summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2008-04-29 14:55:25 +0200
committerJay Berkenbilt <ejb@ql.org>2008-04-29 14:55:25 +0200
commit9a0b88bf7777c153dc46ace22db74ef24d51583a (patch)
treef567ac1cf2bf5071a611eb49323a935b6ac938ff
downloadqpdf-release-qpdf-2.0.tar.zst
update release date to actual daterelease-qpdf-2.0
git-svn-id: svn+q:///qpdf/trunk@599 71b93d88-0707-0410-a8cf-f5a4172ac649
-rw-r--r--Artistic-2.0191
-rw-r--r--ChangeLog3
-rw-r--r--INSTALL216
-rw-r--r--Makefile144
-rw-r--r--README32
-rw-r--r--README.maintainer69
-rw-r--r--TODO68
-rw-r--r--aclocal.m46672
-rw-r--r--autoconf.mk.in30
-rwxr-xr-xconfig.guess1526
-rwxr-xr-xconfig.sub1658
-rw-r--r--configure.ac282
-rw-r--r--doc/stylesheet.css284
-rw-r--r--examples/Makefile1
-rw-r--r--examples/build.mk26
-rw-r--r--examples/examples.testcov19
-rw-r--r--examples/pdf-bookmarks.cc262
-rw-r--r--examples/pdf-mod-info.cc219
-rw-r--r--examples/pdf-npages.cc61
-rw-r--r--examples/qtest/bookmarks.test49
-rw-r--r--examples/qtest/bookmarks/1.pdf1502
-rw-r--r--examples/qtest/bookmarks/2.pdf79
-rw-r--r--examples/qtest/bookmarks/3.pdf1
-rw-r--r--examples/qtest/bookmarks/4.pdfbin0 -> 11561 bytes
-rw-r--r--examples/qtest/bookmarks/5.pdf1573
-rw-r--r--examples/qtest/bookmarks/encrypted.out11
-rw-r--r--examples/qtest/bookmarks/test.-show-open.-lines.out22
-rw-r--r--examples/qtest/bookmarks/test.-show-open.-numbers.out11
-rw-r--r--examples/qtest/bookmarks/test.-show-open..out11
-rw-r--r--examples/qtest/bookmarks/test..-lines.out22
-rw-r--r--examples/qtest/bookmarks/test..-numbers.out11
-rw-r--r--examples/qtest/bookmarks/test...out11
-rw-r--r--examples/qtest/mod-info.test93
-rw-r--r--examples/qtest/mod-info/dump.out11
-rw-r--r--examples/qtest/mod-info/files/1.qdfbin0 -> 6842 bytes
-rw-r--r--examples/qtest/mod-info/files/2.qdf1338
-rw-r--r--examples/qtest/mod-info/files/3.qdfbin0 -> 6245 bytes
-rw-r--r--examples/qtest/mod-info/files/4.qdfbin0 -> 6252 bytes
-rw-r--r--examples/qtest/mod-info/files/empty-info.pdfbin0 -> 5802 bytes
-rw-r--r--examples/qtest/mod-info/files/no-info.pdfbin0 -> 5790 bytes
-rw-r--r--examples/qtest/mod-info/files/source1.pdfbin0 -> 5932 bytes
-rw-r--r--examples/qtest/mod-info/files/source2.pdfbin0 -> 157418 bytes
-rw-r--r--examples/qtest/mod-info/usage.out5
-rw-r--r--examples/qtest/npages.test23
-rw-r--r--examples/qtest/npages/bad1
-rw-r--r--examples/qtest/npages/minimal.pdf79
-rw-r--r--include/qpdf/Buffer.hh32
-rw-r--r--include/qpdf/Pipeline.hh73
-rw-r--r--include/qpdf/Pl_Buffer.hh46
-rw-r--r--include/qpdf/Pl_Count.hh34
-rw-r--r--include/qpdf/Pl_Discard.hh28
-rw-r--r--include/qpdf/Pl_Flate.hh53
-rw-r--r--include/qpdf/Pl_StdioFile.hh49
-rw-r--r--include/qpdf/PointerHolder.hh170
-rw-r--r--include/qpdf/QEXC.hh119
-rw-r--r--include/qpdf/QPDF.hh750
-rw-r--r--include/qpdf/QPDFExc.hh22
-rw-r--r--include/qpdf/QPDFObject.hh20
-rw-r--r--include/qpdf/QPDFObjectHandle.hh221
-rw-r--r--include/qpdf/QPDFTokenizer.hh141
-rw-r--r--include/qpdf/QPDFWriter.hh243
-rw-r--r--include/qpdf/QPDFXRefEntry.hh34
-rw-r--r--include/qpdf/QTC.hh16
-rw-r--r--include/qpdf/QUtil.hh45
-rwxr-xr-xinstall-sh519
-rw-r--r--libqpdf/BitStream.cc45
-rw-r--r--libqpdf/BitWriter.cc30
-rw-r--r--libqpdf/Buffer.cc79
-rw-r--r--libqpdf/MD5.cc441
-rw-r--r--libqpdf/Makefile1
-rw-r--r--libqpdf/PCRE.cc365
-rw-r--r--libqpdf/Pipeline.cc25
-rw-r--r--libqpdf/Pl_ASCII85Decoder.cc131
-rw-r--r--libqpdf/Pl_ASCIIHexDecoder.cc108
-rw-r--r--libqpdf/Pl_Buffer.cc67
-rw-r--r--libqpdf/Pl_Count.cc42
-rw-r--r--libqpdf/Pl_Discard.cc23
-rw-r--r--libqpdf/Pl_Flate.cc198
-rw-r--r--libqpdf/Pl_LZWDecoder.cc229
-rw-r--r--libqpdf/Pl_MD5.cc43
-rw-r--r--libqpdf/Pl_PNGFilter.cc146
-rw-r--r--libqpdf/Pl_QPDFTokenizer.cc179
-rw-r--r--libqpdf/Pl_RC4.cc57
-rw-r--r--libqpdf/Pl_StdioFile.cc48
-rw-r--r--libqpdf/QEXC.cc67
-rw-r--r--libqpdf/QPDF.cc1851
-rw-r--r--libqpdf/QPDFExc.cc20
-rw-r--r--libqpdf/QPDFObject.cc2
-rw-r--r--libqpdf/QPDFObjectHandle.cc637
-rw-r--r--libqpdf/QPDFTokenizer.cc458
-rw-r--r--libqpdf/QPDFWriter.cc2021
-rw-r--r--libqpdf/QPDFXRefEntry.cc61
-rw-r--r--libqpdf/QPDF_Array.cc51
-rw-r--r--libqpdf/QPDF_Bool.cc23
-rw-r--r--libqpdf/QPDF_Dictionary.cc84
-rw-r--r--libqpdf/QPDF_Integer.cc25
-rw-r--r--libqpdf/QPDF_Name.cc46
-rw-r--r--libqpdf/QPDF_Null.cc12
-rw-r--r--libqpdf/QPDF_Real.cc23
-rw-r--r--libqpdf/QPDF_Stream.cc309
-rw-r--r--libqpdf/QPDF_String.cc178
-rw-r--r--libqpdf/QPDF_encryption.cc441
-rw-r--r--libqpdf/QPDF_linearization.cc2103
-rw-r--r--libqpdf/QPDF_optimization.cc490
-rw-r--r--libqpdf/QTC.cc46
-rw-r--r--libqpdf/QUtil.cc198
-rw-r--r--libqpdf/RC4.cc56
-rw-r--r--libqpdf/bits.icc149
-rw-r--r--libqpdf/build.mk73
-rw-r--r--libqpdf/qpdf/BitStream.hh23
-rw-r--r--libqpdf/qpdf/BitWriter.hh24
-rw-r--r--libqpdf/qpdf/MD5.hh73
-rw-r--r--libqpdf/qpdf/PCRE.hh107
-rw-r--r--libqpdf/qpdf/Pl_ASCII85Decoder.hh23
-rw-r--r--libqpdf/qpdf/Pl_ASCIIHexDecoder.hh23
-rw-r--r--libqpdf/qpdf/Pl_LZWDecoder.hh40
-rw-r--r--libqpdf/qpdf/Pl_MD5.hh30
-rw-r--r--libqpdf/qpdf/Pl_PNGFilter.hh62
-rw-r--r--libqpdf/qpdf/Pl_QPDFTokenizer.hh40
-rw-r--r--libqpdf/qpdf/Pl_RC4.hh42
-rw-r--r--libqpdf/qpdf/QPDF_Array.hh24
-rw-r--r--libqpdf/qpdf/QPDF_Bool.hh19
-rw-r--r--libqpdf/qpdf/QPDF_Dictionary.hh35
-rw-r--r--libqpdf/qpdf/QPDF_Integer.hh19
-rw-r--r--libqpdf/qpdf/QPDF_Name.hh22
-rw-r--r--libqpdf/qpdf/QPDF_Null.hh14
-rw-r--r--libqpdf/qpdf/QPDF_Real.hh20
-rw-r--r--libqpdf/qpdf/QPDF_Stream.hh42
-rw-r--r--libqpdf/qpdf/QPDF_String.hh23
-rw-r--r--libqpdf/qpdf/RC4.hh26
-rw-r--r--libtests/Makefile1
-rw-r--r--libtests/ascii85.cc36
-rw-r--r--libtests/bits.cc177
-rw-r--r--libtests/buffer.cc61
-rw-r--r--libtests/build.mk40
-rw-r--r--libtests/flate.cc110
-rw-r--r--libtests/hex.cc36
-rw-r--r--libtests/libtests.testcov18
-rw-r--r--libtests/lzw.cc38
-rw-r--r--libtests/md5.cc74
-rw-r--r--libtests/pcre.cc30
-rw-r--r--libtests/png_filter.cc84
-rw-r--r--libtests/pointer_holder.cc81
-rw-r--r--libtests/qexc.cc65
-rw-r--r--libtests/qtest/ascii85.test22
-rw-r--r--libtests/qtest/ascii85/base85.in43
-rw-r--r--libtests/qtest/ascii85/binary.outbin0 -> 2048 bytes
-rw-r--r--libtests/qtest/bits.test17
-rw-r--r--libtests/qtest/bits/bits.out59
-rw-r--r--libtests/qtest/buffer.test17
-rw-r--r--libtests/qtest/buffer/buffer.out11
-rw-r--r--libtests/qtest/flate.test73
-rw-r--r--libtests/qtest/flate/compressedbin0 -> 147 bytes
-rw-r--r--libtests/qtest/hex.test22
-rw-r--r--libtests/qtest/hex/binary.outbin0 -> 2048 bytes
-rw-r--r--libtests/qtest/hex/hex.in70
-rw-r--r--libtests/qtest/lzw.test17
-rw-r--r--libtests/qtest/lzw/lzw1.inbin0 -> 64355 bytes
-rw-r--r--libtests/qtest/lzw/lzw1.out4299
-rw-r--r--libtests/qtest/md5.test17
-rw-r--r--libtests/qtest/md5/md5.inbin0 -> 250 bytes
-rw-r--r--libtests/qtest/md5/md5.out16
-rw-r--r--libtests/qtest/pcre.test34
-rw-r--r--libtests/qtest/pcre/pcre-unicode-classes.out2
-rw-r--r--libtests/qtest/pcre/pcre.out68
-rw-r--r--libtests/qtest/ph.test17
-rw-r--r--libtests/qtest/ph/ph.out12
-rw-r--r--libtests/qtest/png_filter.test63
-rw-r--r--libtests/qtest/png_filter/in1bin0 -> 3985 bytes
-rw-r--r--libtests/qtest/png_filter/in2bin0 -> 339564 bytes
-rw-r--r--libtests/qtest/png_filter/out1bin0 -> 3188 bytes
-rw-r--r--libtests/qtest/png_filter/out2bin0 -> 282970 bytes
-rw-r--r--libtests/qtest/qexc.test32
-rw-r--r--libtests/qtest/qexc/test0.out2
-rw-r--r--libtests/qtest/qexc/test1.out1
-rw-r--r--libtests/qtest/qexc/test2.out2
-rw-r--r--libtests/qtest/qutil.test17
-rw-r--r--libtests/qtest/qutil/qutil.out30
-rw-r--r--libtests/qtest/rc4.test45
-rw-r--r--libtests/qtest/rc4/test1.in1
-rw-r--r--libtests/qtest/rc4/test1.out1
-rw-r--r--libtests/qtest/rc4/test2.inbin0 -> 8 bytes
-rw-r--r--libtests/qtest/rc4/test2.out1
-rw-r--r--libtests/qtest/rc4/test3.inbin0 -> 8 bytes
-rw-r--r--libtests/qtest/rc4/test3.out1
-rw-r--r--libtests/qtest/rc4/test4.inbin0 -> 10 bytes
-rw-r--r--libtests/qtest/rc4/test4.out1
-rw-r--r--libtests/qtest/rc4/test5.in1
-rw-r--r--libtests/qtest/rc4/test5.outbin0 -> 512 bytes
-rw-r--r--libtests/qutil.cc199
-rw-r--r--libtests/rc4.cc82
-rw-r--r--ltmain.sh6964
-rw-r--r--make/proxy.mk10
-rw-r--r--make/rules.mk63
-rwxr-xr-xmake_dist165
-rw-r--r--manual/Makefile1
-rw-r--r--manual/README3
-rw-r--r--manual/build.mk43
-rw-r--r--manual/common.xsl9
-rw-r--r--manual/fix-qdf.1.in18
-rw-r--r--manual/html.xsl.in8
-rw-r--r--manual/print.xsl.in69
-rw-r--r--manual/qpdf-manual.xml1964
-rw-r--r--manual/qpdf.1.in19
-rw-r--r--manual/zlib-flate.1.in21
-rwxr-xr-xmkinstalldirs161
-rw-r--r--qpdf.spec93
-rw-r--r--qpdf/Makefile1
-rw-r--r--qpdf/build.mk26
-rwxr-xr-xqpdf/fix-qdf352
-rw-r--r--qpdf/qpdf.cc942
-rw-r--r--qpdf/qpdf.testcov117
-rw-r--r--qpdf/qtest/qpdf.test942
-rw-r--r--qpdf/qtest/qpdf/U25A0.1.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.10.check5
-rw-r--r--qpdf/qtest/qpdf/U25A0.11.check5
-rw-r--r--qpdf/qtest/qpdf/U25A0.12.check5
-rw-r--r--qpdf/qtest/qpdf/U25A0.2.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.3.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.4.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.5.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.6.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.7.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.8.check4
-rw-r--r--qpdf/qtest/qpdf/U25A0.9.check5
-rw-r--r--qpdf/qtest/qpdf/U25A0.pdfbin0 -> 67790 bytes
-rw-r--r--qpdf/qtest/qpdf/bad1-recover.out1
-rw-r--r--qpdf/qtest/qpdf/bad1.out1
-rw-r--r--qpdf/qtest/qpdf/bad1.pdf1
-rw-r--r--qpdf/qtest/qpdf/bad10-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad10.out1
-rw-r--r--qpdf/qtest/qpdf/bad10.pdf79
-rw-r--r--qpdf/qtest/qpdf/bad11-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad11.out1
-rw-r--r--qpdf/qtest/qpdf/bad11.pdf104
-rw-r--r--qpdf/qtest/qpdf/bad12-recover.out7
-rw-r--r--qpdf/qtest/qpdf/bad12.out7
-rw-r--r--qpdf/qtest/qpdf/bad12.pdf122
-rw-r--r--qpdf/qtest/qpdf/bad13-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad13.out1
-rw-r--r--qpdf/qtest/qpdf/bad13.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad14-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad14.out1
-rw-r--r--qpdf/qtest/qpdf/bad14.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad15-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad15.out1
-rw-r--r--qpdf/qtest/qpdf/bad15.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad16-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad16.out1
-rw-r--r--qpdf/qtest/qpdf/bad16.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad17-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad17.out1
-rw-r--r--qpdf/qtest/qpdf/bad17.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad18-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad18.out1
-rw-r--r--qpdf/qtest/qpdf/bad18.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad19-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad19.out1
-rw-r--r--qpdf/qtest/qpdf/bad19.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad2-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad2.out1
-rw-r--r--qpdf/qtest/qpdf/bad2.pdf76
-rw-r--r--qpdf/qtest/qpdf/bad20-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad20.out1
-rw-r--r--qpdf/qtest/qpdf/bad20.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad21-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad21.out1
-rw-r--r--qpdf/qtest/qpdf/bad21.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad22-recover.out21
-rw-r--r--qpdf/qtest/qpdf/bad22.out1
-rw-r--r--qpdf/qtest/qpdf/bad22.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad23-recover.out21
-rw-r--r--qpdf/qtest/qpdf/bad23.out1
-rw-r--r--qpdf/qtest/qpdf/bad23.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad24-recover.out2
-rw-r--r--qpdf/qtest/qpdf/bad24.out1
-rw-r--r--qpdf/qtest/qpdf/bad24.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad25-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad25.out1
-rw-r--r--qpdf/qtest/qpdf/bad25.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad26-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad26.out1
-rw-r--r--qpdf/qtest/qpdf/bad26.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad27-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad27.out1
-rw-r--r--qpdf/qtest/qpdf/bad27.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad28-recover.out21
-rw-r--r--qpdf/qtest/qpdf/bad28.out21
-rw-r--r--qpdf/qtest/qpdf/bad28.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad29-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad29.out1
-rw-r--r--qpdf/qtest/qpdf/bad29.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad3-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad3.out1
-rw-r--r--qpdf/qtest/qpdf/bad3.pdf76
-rw-r--r--qpdf/qtest/qpdf/bad30-recover.out6
-rw-r--r--qpdf/qtest/qpdf/bad30.out6
-rw-r--r--qpdf/qtest/qpdf/bad30.pdf93
-rw-r--r--qpdf/qtest/qpdf/bad31-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad31.out9
-rw-r--r--qpdf/qtest/qpdf/bad31.pdf93
-rw-r--r--qpdf/qtest/qpdf/bad32-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad32.out1
-rw-r--r--qpdf/qtest/qpdf/bad32.pdf80
-rw-r--r--qpdf/qtest/qpdf/bad4-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad4.out1
-rw-r--r--qpdf/qtest/qpdf/bad4.pdf77
-rw-r--r--qpdf/qtest/qpdf/bad5-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad5.out1
-rw-r--r--qpdf/qtest/qpdf/bad5.pdf77
-rw-r--r--qpdf/qtest/qpdf/bad6-recover.out6
-rw-r--r--qpdf/qtest/qpdf/bad6.out6
-rw-r--r--qpdf/qtest/qpdf/bad6.pdf122
-rw-r--r--qpdf/qtest/qpdf/bad7-recover.out4
-rw-r--r--qpdf/qtest/qpdf/bad7.out1
-rw-r--r--qpdf/qtest/qpdf/bad7.pdf77
-rw-r--r--qpdf/qtest/qpdf/bad8-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad8.out1
-rw-r--r--qpdf/qtest/qpdf/bad8.pdf104
-rw-r--r--qpdf/qtest/qpdf/bad9-recover.out9
-rw-r--r--qpdf/qtest/qpdf/bad9.out1
-rw-r--r--qpdf/qtest/qpdf/bad9.pdf79
-rw-r--r--qpdf/qtest/qpdf/badlin1.out380
-rw-r--r--qpdf/qtest/qpdf/badlin1.pdfbin0 -> 13103 bytes
-rw-r--r--qpdf/qtest/qpdf/check-ID.pl20
-rw-r--r--qpdf/qtest/qpdf/delete-and-reuse.pdf1573
-rw-r--r--qpdf/qtest/qpdf/delete-and-reuse.qdf1408
-rwxr-xr-xqpdf/qtest/qpdf/diff-encrypted7
-rw-r--r--qpdf/qtest/qpdf/enc-R2,V1,O=master.pdfbin0 -> 17146 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R2,V1,U=view,O=master.pdfbin0 -> 17134 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R2,V1,U=view.pdfbin0 -> 17137 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R2,V1.pdfbin0 -> 17143 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R3,V2,O=master.pdfbin0 -> 17144 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R3,V2,U=view,O=master.pdfbin0 -> 17139 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R3,V2,U=view.pdfbin0 -> 17142 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-R3,V2.pdfbin0 -> 17140 bytes
-rw-r--r--qpdf/qtest/qpdf/enc-base.pdfbin0 -> 16937 bytes
-rwxr-xr-xqpdf/qtest/qpdf/enc-long-password.pdfbin0 -> 17144 bytes
-rw-r--r--qpdf/qtest/qpdf/encrypted-with-images.pdfbin0 -> 50219 bytes
-rw-r--r--qpdf/qtest/qpdf/encrypted1.out578
-rw-r--r--qpdf/qtest/qpdf/fix1.qdf111
-rw-r--r--qpdf/qtest/qpdf/fix1.qdf.out113
-rw-r--r--qpdf/qtest/qpdf/fix2.qdfbin0 -> 1227 bytes
-rw-r--r--qpdf/qtest/qpdf/fix2.qdf.outbin0 -> 1232 bytes
-rw-r--r--qpdf/qtest/qpdf/good1.out6
-rw-r--r--qpdf/qtest/qpdf/good1.pdfbin0 -> 813 bytes
-rw-r--r--qpdf/qtest/qpdf/good1.qdf95
-rw-r--r--qpdf/qtest/qpdf/good10.out8
-rw-r--r--qpdf/qtest/qpdf/good10.pdf80
-rw-r--r--qpdf/qtest/qpdf/good10.qdf100
-rw-r--r--qpdf/qtest/qpdf/good11.out6
-rw-r--r--qpdf/qtest/qpdf/good11.pdf81
-rw-r--r--qpdf/qtest/qpdf/good11.qdf98
-rw-r--r--qpdf/qtest/qpdf/good12.out13
-rw-r--r--qpdf/qtest/qpdf/good12.pdf93
-rw-r--r--qpdf/qtest/qpdf/good12.qdf113
-rw-r--r--qpdf/qtest/qpdf/good13.out9
-rw-r--r--qpdf/qtest/qpdf/good13.pdf101
-rw-r--r--qpdf/qtest/qpdf/good13.qdf139
-rw-r--r--qpdf/qtest/qpdf/good14.out39
-rw-r--r--qpdf/qtest/qpdf/good14.pdf142
-rw-r--r--qpdf/qtest/qpdf/good14.qdf189
-rw-r--r--qpdf/qtest/qpdf/good15.out5
-rw-r--r--qpdf/qtest/qpdf/good15.pdf79
-rw-r--r--qpdf/qtest/qpdf/good15.qdf97
-rw-r--r--qpdf/qtest/qpdf/good16.out6
-rw-r--r--qpdf/qtest/qpdf/good16.pdfbin0 -> 792 bytes
-rw-r--r--qpdf/qtest/qpdf/good16.qdfbin0 -> 1106 bytes
-rw-r--r--qpdf/qtest/qpdf/good17-not-qdf.pdfbin0 -> 9893 bytes
-rw-r--r--qpdf/qtest/qpdf/good17-not-recompressed.pdfbin0 -> 9147 bytes
-rw-r--r--qpdf/qtest/qpdf/good17.out6
-rw-r--r--qpdf/qtest/qpdf/good17.pdf1550
-rw-r--r--qpdf/qtest/qpdf/good17.qdf1523
-rw-r--r--qpdf/qtest/qpdf/good18.out6
-rw-r--r--qpdf/qtest/qpdf/good18.pdf1538
-rw-r--r--qpdf/qtest/qpdf/good18.qdf1343
-rw-r--r--qpdf/qtest/qpdf/good19.out6
-rw-r--r--qpdf/qtest/qpdf/good19.pdfbin0 -> 1032 bytes
-rw-r--r--qpdf/qtest/qpdf/good19.qdfbin0 -> 1105 bytes
-rw-r--r--qpdf/qtest/qpdf/good2.out6
-rw-r--r--qpdf/qtest/qpdf/good2.pdf80
-rw-r--r--qpdf/qtest/qpdf/good2.qdf95
-rw-r--r--qpdf/qtest/qpdf/good20.out6
-rw-r--r--qpdf/qtest/qpdf/good20.pdf901
-rw-r--r--qpdf/qtest/qpdf/good20.qdf1075
-rw-r--r--qpdf/qtest/qpdf/good3.out6
-rw-r--r--qpdf/qtest/qpdf/good3.pdf80
-rw-r--r--qpdf/qtest/qpdf/good3.qdf95
-rw-r--r--qpdf/qtest/qpdf/good4.out6
-rw-r--r--qpdf/qtest/qpdf/good4.pdf83
-rw-r--r--qpdf/qtest/qpdf/good4.qdf95
-rw-r--r--qpdf/qtest/qpdf/good5.out5
-rw-r--r--qpdf/qtest/qpdf/good5.pdf83
-rw-r--r--qpdf/qtest/qpdf/good5.qdf96
-rw-r--r--qpdf/qtest/qpdf/good6.out5
-rw-r--r--qpdf/qtest/qpdf/good6.pdf79
-rw-r--r--qpdf/qtest/qpdf/good6.qdf96
-rw-r--r--qpdf/qtest/qpdf/good7-not-normalized.qdf95
-rw-r--r--qpdf/qtest/qpdf/good7.out5
-rw-r--r--qpdf/qtest/qpdf/good7.pdf79
-rw-r--r--qpdf/qtest/qpdf/good7.qdf97
-rw-r--r--qpdf/qtest/qpdf/good8.out5
-rw-r--r--qpdf/qtest/qpdf/good8.pdf79
-rw-r--r--qpdf/qtest/qpdf/good8.qdf96
-rw-r--r--qpdf/qtest/qpdf/good9.out5
-rw-r--r--qpdf/qtest/qpdf/good9.pdf81
-rw-r--r--qpdf/qtest/qpdf/good9.qdf97
-rw-r--r--qpdf/qtest/qpdf/heifer.out4
-rw-r--r--qpdf/qtest/qpdf/heifer.pdfbin0 -> 93593 bytes
-rw-r--r--qpdf/qtest/qpdf/heifer.qdf1349
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.1.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.10.check5
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.11.check5
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.12.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.2.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.3.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.4.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.5.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.6.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.7.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.8.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.9.check4
-rw-r--r--qpdf/qtest/qpdf/hybrid-xref.pdf1538
-rw-r--r--qpdf/qtest/qpdf/inline-images.1.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.10.check5
-rw-r--r--qpdf/qtest/qpdf/inline-images.11.check5
-rw-r--r--qpdf/qtest/qpdf/inline-images.12.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.2.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.3.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.4.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.5.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.6.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.7.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.8.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.9.check4
-rw-r--r--qpdf/qtest/qpdf/inline-images.pdfbin0 -> 300684 bytes
-rw-r--r--qpdf/qtest/qpdf/lin-delete-and-reuse.pdfbin0 -> 13382 bytes
-rw-r--r--qpdf/qtest/qpdf/lin-special.1.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.10.check5
-rw-r--r--qpdf/qtest/qpdf/lin-special.11.check5
-rw-r--r--qpdf/qtest/qpdf/lin-special.12.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.2.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.3.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.4.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.5.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.6.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.7.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.8.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.9.check4
-rw-r--r--qpdf/qtest/qpdf/lin-special.disable.expbin0 -> 3138 bytes
-rw-r--r--qpdf/qtest/qpdf/lin-special.generate.expbin0 -> 2757 bytes
-rw-r--r--qpdf/qtest/qpdf/lin-special.pdf354
-rw-r--r--qpdf/qtest/qpdf/lin-special.preserve.expbin0 -> 3138 bytes
-rw-r--r--qpdf/qtest/qpdf/lin0.out1
-rw-r--r--qpdf/qtest/qpdf/lin0.pdf79
-rw-r--r--qpdf/qtest/qpdf/lin1.out378
-rw-r--r--qpdf/qtest/qpdf/lin1.pdfbin0 -> 13103 bytes
-rw-r--r--qpdf/qtest/qpdf/lin2.out378
-rw-r--r--qpdf/qtest/qpdf/lin2.pdfbin0 -> 13103 bytes
-rw-r--r--qpdf/qtest/qpdf/lin3.out318
-rw-r--r--qpdf/qtest/qpdf/lin3.pdfbin0 -> 16937 bytes
-rw-r--r--qpdf/qtest/qpdf/lin4.out353
-rw-r--r--qpdf/qtest/qpdf/lin4.pdfbin0 -> 13055 bytes
-rw-r--r--qpdf/qtest/qpdf/lin5.out318
-rw-r--r--qpdf/qtest/qpdf/lin5.pdfbin0 -> 27464 bytes
-rw-r--r--qpdf/qtest/qpdf/lin6.out592
-rw-r--r--qpdf/qtest/qpdf/lin6.pdfbin0 -> 24824 bytes
-rw-r--r--qpdf/qtest/qpdf/lin7.out292
-rw-r--r--qpdf/qtest/qpdf/lin7.pdfbin0 -> 27408 bytes
-rw-r--r--qpdf/qtest/qpdf/lin8.out568
-rw-r--r--qpdf/qtest/qpdf/lin8.pdfbin0 -> 24875 bytes
-rw-r--r--qpdf/qtest/qpdf/lin9.out104
-rw-r--r--qpdf/qtest/qpdf/lin9.pdfbin0 -> 3316 bytes
-rw-r--r--qpdf/qtest/qpdf/misc-1.out15
-rw-r--r--qpdf/qtest/qpdf/misc-1.pdfbin0 -> 18204 bytes
-rw-r--r--qpdf/qtest/qpdf/misc-2.out26
-rw-r--r--qpdf/qtest/qpdf/misc-2.pdfbin0 -> 16022 bytes
-rw-r--r--qpdf/qtest/qpdf/misc-3.out14
-rw-r--r--qpdf/qtest/qpdf/misc-3.pdf127
-rwxr-xr-xqpdf/qtest/qpdf/multiple-mods.pdfbin0 -> 60960 bytes
-rw-r--r--qpdf/qtest/qpdf/object-stream.1.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.10.check5
-rw-r--r--qpdf/qtest/qpdf/object-stream.11.check5
-rw-r--r--qpdf/qtest/qpdf/object-stream.12.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.2.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.3.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.4.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.5.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.6.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.7.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.8.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.9.check4
-rw-r--r--qpdf/qtest/qpdf/object-stream.disable.expbin0 -> 1250 bytes
-rw-r--r--qpdf/qtest/qpdf/object-stream.generate.expbin0 -> 1526 bytes
-rw-r--r--qpdf/qtest/qpdf/object-stream.pdfbin0 -> 792 bytes
-rw-r--r--qpdf/qtest/qpdf/object-stream.preserve.expbin0 -> 1526 bytes
-rw-r--r--qpdf/qtest/qpdf/old-and-complex.pdfbin0 -> 335662 bytes
-rw-r--r--qpdf/qtest/qpdf/p1-a-p2-a.pdf138
-rw-r--r--qpdf/qtest/qpdf/p1-a-p2-b.pdf138
-rw-r--r--qpdf/qtest/qpdf/p1-a.pdf95
-rw-r--r--qpdf/qtest/qpdf/p1-b.pdf95
-rw-r--r--qpdf/qtest/qpdf/show-page-1-content-filtered.out1
-rw-r--r--qpdf/qtest/qpdf/show-page-1-content-normalized.out8
-rw-r--r--qpdf/qtest/qpdf/show-page-1-content-raw.outbin0 -> 61 bytes
-rw-r--r--qpdf/qtest/qpdf/show-page-1-image.outbin0 -> 39109 bytes
-rw-r--r--qpdf/qtest/qpdf/show-page-1.out1
-rw-r--r--qpdf/qtest/qpdf/show-pages-images.out11
-rw-r--r--qpdf/qtest/qpdf/show-pages.out6
-rw-r--r--qpdf/qtest/qpdf/show-unfilterable.out1
-rw-r--r--qpdf/qtest/qpdf/show-xref-by-id-filtered.outbin0 -> 52 bytes
-rw-r--r--qpdf/qtest/qpdf/show-xref-by-id.out2
-rw-r--r--qpdf/qtest/qpdf/show-xref.out12
-rw-r--r--qpdf/qtest/qpdf/test4-1.pdf126
-rw-r--r--qpdf/qtest/qpdf/test4-1.qdf145
-rw-r--r--qpdf/qtest/qpdf/test4-2.out1
-rw-r--r--qpdf/qtest/qpdf/test4-2.pdf104
-rw-r--r--qpdf/qtest/qpdf/test4-3.out1
-rw-r--r--qpdf/qtest/qpdf/test4-3.pdf109
-rw-r--r--qpdf/qtest/qpdf/test4-4.pdf123
-rw-r--r--qpdf/qtest/qpdf/test4-4.qdf145
-rw-r--r--qpdf/test_driver.cc323
-rw-r--r--qtest/QTC/perl/QTC.pm26
-rw-r--r--qtest/README.txt3
-rwxr-xr-xqtest/bin/qtest-driver798
-rw-r--r--qtest/module/TestDriver.pm1566
-rw-r--r--zlib-flate/Makefile1
-rw-r--r--zlib-flate/build.mk22
-rw-r--r--zlib-flate/qtest/1.compressedbin0 -> 193 bytes
-rw-r--r--zlib-flate/qtest/1.uncompressed5
-rw-r--r--zlib-flate/qtest/zf.test26
-rw-r--r--zlib-flate/zlib-flate.cc92
531 files changed, 79083 insertions, 0 deletions
diff --git a/Artistic-2.0 b/Artistic-2.0
new file mode 100644
index 00000000..bb2cfbd2
--- /dev/null
+++ b/Artistic-2.0
@@ -0,0 +1,191 @@
+Artistic License 2.0
+
+Copyright (c) 2000-2006, The Perl Foundation.
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+Preamble
+
+This license establishes the terms under which a given free software
+Package may be copied, modified, distributed, and/or
+redistributed. The intent is that the Copyright Holder maintains some
+artistic control over the development of that Package while still
+keeping the Package available as open source and free software.
+
+You are always permitted to make arrangements wholly outside of this
+license directly with the Copyright Holder of a given Package. If the
+terms of this license do not permit the full use that you propose to
+make of the Package, you should contact the Copyright Holder and seek
+a different licensing arrangement.
+
+Definitions
+
+ "Copyright Holder" means the individual(s) or organization(s) named
+ in the copyright notice for the entire Package.
+
+ "Contributor" means any party that has contributed code or other
+ material to the Package, in accordance with the Copyright Holder's
+ procedures.
+
+ "You" and "your" means any person who would like to copy,
+ distribute, or modify the Package.
+
+ "Package" means the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection and/or of
+ those files. A given Package may consist of either the Standard
+ Version, or a Modified Version.
+
+ "Distribute" means providing a copy of the Package or making it
+ accessible to anyone else, or in the case of a company or
+ organization, to others outside of your company or organization.
+
+ "Distributor Fee" means any fee that you charge for Distributing
+ this Package or providing support for this Package to another
+ party. It does not mean licensing fees.
+
+ "Standard Version" refers to the Package if it has not been
+ modified, or has been modified only in ways explicitly requested by
+ the Copyright Holder.
+
+ "Modified Version" means the Package, if it has been changed, and
+ such changes were not explicitly requested by the Copyright Holder.
+
+ "Original License" means this Artistic License as Distributed with
+ the Standard Version of the Package, in its current version or as
+ it may be modified by The Perl Foundation in the future.
+
+ "Source" form means the source code, documentation source, and
+ configuration files for the Package.
+
+ "Compiled" form means the compiled bytecode, object code, binary,
+ or any other form resulting from mechanical transformation or
+ translation of the Source form.
+
+Permission for Use and Modification Without Distribution
+
+(1) You are permitted to use the Standard Version and create and use
+Modified Versions for any purpose without restriction, provided that
+you do not Distribute the Modified Version.
+
+Permissions for Redistribution of the Standard Version
+
+(2) You may Distribute verbatim copies of the Source form of the
+Standard Version of this Package in any medium without restriction,
+either gratis or for a Distributor Fee, provided that you duplicate
+all of the original copyright notices and associated disclaimers. At
+your discretion, such verbatim copies may or may not include a
+Compiled form of the Package.
+
+(3) You may apply any bug fixes, portability changes, and other
+modifications made available from the Copyright Holder. The resulting
+Package will still be considered the Standard Version, and as such
+will be subject to the Original License.
+
+Distribution of Modified Versions of the Package as Source
+
+(4) You may Distribute your Modified Version as Source (either gratis
+or for a Distributor Fee, and with or without a Compiled form of the
+Modified Version) provided that you clearly document how it differs
+from the Standard Version, including, but not limited to, documenting
+any non-standard features, executables, or modules, and provided that
+you do at least ONE of the following:
+
+ (a) make the Modified Version available to the Copyright Holder of
+ the Standard Version, under the Original License, so that the
+ Copyright Holder may include your modifications in the Standard
+ Version.
+
+ (b) ensure that installation of your Modified Version does not
+ prevent the user installing or running the Standard Version. In
+ addition, the Modified Version must bear a name that is different
+ from the name of the Standard Version.
+
+ (c) allow anyone who receives a copy of the Modified Version to
+ make the Source form of the Modified Version available to others
+ under
+
+ (i) the Original License or
+
+ (ii) a license that permits the licensee to freely copy, modify
+ and redistribute the Modified Version using the same licensing
+ terms that apply to the copy that the licensee received, and
+ requires that the Source form of the Modified Version, and of
+ any works derived from it, be made freely available in that
+ license fees are prohibited but Distributor Fees are allowed.
+ Distribution of Compiled Forms of the Standard Version or
+ Modified Versions without the Source
+
+(5) You may Distribute Compiled forms of the Standard Version without
+the Source, provided that you include complete instructions on how to
+get the Source of the Standard Version. Such instructions must be
+valid at the time of your distribution. If these instructions, at any
+time while you are carrying out such distribution, become invalid, you
+must provide new instructions on demand or cease further
+distribution. If you provide valid instructions or cease distribution
+within thirty days after you become aware that the instructions are
+invalid, then you do not forfeit any of your rights under this
+license.
+
+(6) You may Distribute a Modified Version in Compiled form without the
+Source, provided that you comply with Section 4 with respect to the
+Source of the Modified Version.
+
+Aggregating or Linking the Package
+
+(7) You may aggregate the Package (either the Standard Version or
+Modified Version) with other packages and Distribute the resulting
+aggregation provided that you do not charge a licensing fee for the
+Package. Distributor Fees are permitted, and licensing fees for other
+components in the aggregation are permitted. The terms of this license
+apply to the use and Distribution of the Standard or Modified Versions
+as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with
+other works, to embed the Package in a larger work of your own, or to
+build stand-alone binary or bytecode versions of applications that
+include the Package, and Distribute the result without restriction,
+provided the result does not expose a direct interface to the Package.
+
+Items That are Not Considered Part of a Modified Version
+
+(9) Works (including, but not limited to, modules and scripts) that
+merely extend or make use of the Package, do not, by themselves, cause
+the Package to be a Modified Version. In addition, such works are not
+considered parts of the Package itself, and are not subject to the
+terms of this license.
+
+General Provisions
+
+(10) Any use, modification, and distribution of the Standard or
+Modified Versions is governed by this Artistic License. By using,
+modifying or distributing the Package, you accept this license. Do not
+use, modify, or distribute the Package, if you do not accept this
+license.
+
+(11) If your Modified Version has been derived from a Modified Version
+made by someone other than you, you are nevertheless required to
+ensure that your Modified Version complies with the requirements of
+this license.
+
+(12) This license does not grant you the right to use any trademark,
+service mark, tradename, or logo of the Copyright Holder.
+
+(13) This license includes the non-exclusive, worldwide,
+free-of-charge patent license to make, have made, use, offer to sell,
+sell, import and otherwise transfer the Package with respect to any
+patent claims licensable by the Copyright Holder that are necessarily
+infringed by the Package. If you institute patent litigation
+(including a cross-claim or counterclaim) against any party alleging
+that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the
+date that such litigation is filed.
+
+(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
+HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
+PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
+HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
+OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000..6e527002
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+2008-04-26 Jay Berkenbilt <ejb@ql.org>
+
+ * 2.0: initial public release
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 00000000..afe32aaf
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,216 @@
+These instructions based on the generic INSTALL file from automake
+1.10. However, qpdf does not use automake, so not all of that file
+applies.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+ You can also define the variable DESTDIR when you run make install
+to install the package in a separate subdirectory. This is useful for
+packaging.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..5f3db8b7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,144 @@
+
+# This makefile is inspired by abuild (http://www.abuild.org), which
+# was used during the development of qpdf. The goal here is to have a
+# non-recursive build with all the proper dependencies so we can start
+# the build from anywhere and get the right stuff. Each directory has
+# a build.mk that is included from here and is written from this
+# directory's perspective. Each directory also has a proxy Makefile
+# that allows you to start the build from any directory and get
+# reasonable semantics for the all, check, and clean targets.
+
+# Our "build items" are directories. They are listed here such that
+# no item precedes any item it depends on. Therefore, each item can
+# safely reference variables set in its predecessors.
+
+# For each build item B, you can run make build_B, make check_B, or
+# make clean_B to build, test, or clean B. Full dependencies are
+# represented across all the items, so it is possible to start
+# anywhere. From the top level, the "all", "check", and "clean"
+# targets build, test, or clean everything.
+
+# Although this is not a GNU package and does not use automake, you
+# can still run make clean to remove everything that is compiled, make
+# distclean to remove everything that is generated by the end user,
+# and make maintainer-clean to remove everything that is generated
+# including things distributed with the source distribution. You can
+# pass CLEAN=1 to prevent this Makefile from complaining if
+# ./configure has not been run.
+
+# The install target works as usual and obeys --prefix and so forth
+# passed to ./configure. You can also pass DESTDIR=/dir to make
+# install to install in a separate location. This is useful for
+# packagers.
+
+BUILD_ITEMS = manual libqpdf zlib-flate libtests qpdf examples
+OUTPUT_DIR = build
+ALL_TARGETS =
+
+.PHONY: default
+default: all
+
+CLEAN ?=
+ifneq ($(CLEAN),1)
+ifeq ($(words $(wildcard autoconf.mk)),0)
+DUMMY := $(shell echo 1>&2)
+DUMMY := $(shell echo 1>&2 Please run ./configure before running $(MAKE))
+DUMMY := $(shell echo 1>&2)
+$(error unable to continue with build)
+endif
+
+autoconf.mk:
+
+include autoconf.mk
+
+endif
+
+# Prevent gnu make from trying to rebuild .dep files
+$(foreach B,$(BUILD_ITEMS),$(eval \
+ $(B)/$(OUTPUT_DIR)/%.dep: ;))
+
+# Prevent gnu make from trying to rebuild .mk files
+$(foreach B,$(BUILD_ITEMS),$(eval \
+ $(B)/%.mk: ;))
+%.mk: ;
+make/%.mk: ;
+
+include make/rules.mk
+
+DUMMY := $(shell mkdir $(foreach B,$(BUILD_ITEMS),$(B)/$(OUTPUT_DIR)) 2>/dev/null)
+
+include $(foreach B,$(BUILD_ITEMS),$(B)/build.mk)
+
+ALL_TARGETS = $(foreach B,$(BUILD_ITEMS),$(TARGETS_$(B)))
+
+TEST_ITEMS = $(foreach D,\
+ $(wildcard $(foreach B,$(BUILD_ITEMS),$(B)/qtest)),\
+ $(subst /,,$(dir $(D))))
+
+TEST_TARGETS = $(foreach B,$(TEST_ITEMS),check_$(B))
+
+CLEAN_TARGETS = $(foreach B,$(BUILD_ITEMS),clean_$(B))
+
+# For test suitse
+export QPDF_BIN = $(abspath qpdf/$(OUTPUT_DIR)/qpdf)
+export SKIP_TEST_COMPARE_IMAGES
+
+clean: $(CLEAN_TARGETS)
+
+.PHONY: $(CLEAN_TARGETS)
+$(foreach B,$(BUILD_ITEMS),$(eval \
+ clean_$(B): ; \
+ $(RM) -r $(B)/$(OUTPUT_DIR)))
+
+distclean: clean
+ $(RM) -r autoconf.mk autom4te.cache config.log config.status libtool
+ $(RM) manual/html.xsl
+ $(RM) manual/print.xsl
+ $(RM) doc/*.1
+
+maintainer-clean: distclean
+ $(RM) configure doc/qpdf-manual.*
+
+.PHONY: $(TEST_TARGETS)
+$(foreach B,$(TEST_ITEMS),$(eval \
+ check_$(B): $(TARGETS_$(B))))
+
+.PHONY: $(foreach B,$(BUILD_ITEMS),build_$(B))
+$(foreach B,$(BUILD_ITEMS),$(eval \
+ build_$(B): $(TARGETS_$(B))))
+
+.PHONY: all
+all: $(ALL_TARGETS) ;
+
+check: $(TEST_TARGETS)
+
+install_docs::
+install: all
+ ./mkinstalldirs $(DESTDIR)$(libdir)
+ ./mkinstalldirs $(DESTDIR)$(bindir)
+ ./mkinstalldirs $(DESTDIR)$(includedir)/qpdf
+ ./mkinstalldirs $(DESTDIR)$(docdir)
+ ./mkinstalldirs $(DESTDIR)$(mandir)/man1
+ $(LIBTOOL) --mode=install install -s -c \
+ libqpdf/$(OUTPUT_DIR)/libqpdf.la \
+ $(DESTDIR)$(libdir)/libqpdf.la
+ $(LIBTOOL) --finish $(DESTDIR)$(libdir)
+ $(LIBTOOL) --mode=install install -s -c \
+ qpdf/$(OUTPUT_DIR)/qpdf \
+ $(DESTDIR)$(bindir)/qpdf
+ $(LIBTOOL) --mode=install install -s -c \
+ zlib-flate/$(OUTPUT_DIR)/zlib-flate \
+ $(DESTDIR)$(bindir)/zlib-flate
+ cp qpdf/fix-qdf $(DESTDIR)$(bindir)
+ cp include/qpdf/*.hh $(DESTDIR)$(includedir)/qpdf
+ cp doc/stylesheet.css $(DESTDIR)$(docdir)
+ cp doc/qpdf-manual.html $(DESTDIR)$(docdir)
+ cp doc/qpdf-manual.pdf $(DESTDIR)$(docdir)
+ cp doc/*.1 $(DESTDIR)$(mandir)/man1
+
+QTEST=$(abspath qtest/bin/qtest-driver)
+$(TEST_TARGETS):
+ @echo running qtest-driver for $(subst check_,,$@)
+ @(cd $(subst check_,,$@)/$(OUTPUT_DIR); \
+ TC_SRCS="$(foreach T,$(TC_SRCS_$(subst check_,,$@)),../../$(T))" \
+ $(QTEST) -bindirs .:.. -datadir ../qtest -covdir ..)
diff --git a/README b/README
new file mode 100644
index 00000000..ea947b9f
--- /dev/null
+++ b/README
@@ -0,0 +1,32 @@
+This is the QPDF package. Information about it can be found at
+http://qpdf.qbilt.org.
+
+QPDF is copyright (c) 2005-2008 Jay Berkenbilt
+
+This software may be distributed under the terms of version 2 of the
+Artistic License which may be found in the source distribution as
+"Artistic-2.0". It is provided "as is" without express or implied
+warranty.
+
+To install this software, you can run
+
+./configure
+make
+make install
+
+For more detailed information, see the "INSTALL" in this directory.
+
+The QPDF package provides some executables and a software library. A
+user's manual can be found in the "doc" directory. The docbook
+sources to the user's manual can be found in the "manual" directory.
+
+The software library is just libqpdf, and all the header files are in
+the qpdf subdirectory. If you link with -lqpdf and your system does
+not know how to read libtool .la files, then you will also need to
+link with -lpcre and -lz.
+
+To learn about using the library, please read comments in the header
+files in include/qpdf, especially QPDF.hh, QPDFObjectHandle.hh, and
+QPDFWriter.hh. You can also study the code of qpdf/qpdf.cc, which
+exercises most of the public interface. There are additional example
+programs in the examples directory.
diff --git a/README.maintainer b/README.maintainer
new file mode 100644
index 00000000..49e6a175
--- /dev/null
+++ b/README.maintainer
@@ -0,0 +1,69 @@
+Release Reminders
+=================
+
+ * To create a source release, do an export from the version control
+ system to a directory called qpdf-version. From the parent of that
+ directory, run make_dist with the directory as an argument. For
+ internally testing releases, you can run make_dist with the
+ --no-tests option.
+
+ * Make sure version numbers are consistent in the following
+ locations:
+
+ configure.ac
+ qpdf.spec
+ qpdf/qpdf.cc
+ manual/qpdf-manual.xml
+
+ make_dist does this automatically.
+
+ * Each year, update copyright notices. Just search for Copyright.
+ Last updated: 2008.
+
+ * To construct a source distribution from a pristine checkout,
+ make_release does the following.
+
+ autoconf
+ ./configure --enable-doc-maintenance
+ make build_manual
+ make distclean
+
+ * Remember to update documentation in the "files" subdirectory of the
+ website on sourceforge.net.
+
+General Build Stuff
+===================
+
+QPDF supports autoconf and libtool but does not use automake. In
+addition, there is no header file generated by autoconf. The only
+file distributed with the qpdf source distribution that is not a
+controlled file is "configure", and it is generated by just running
+"autoconf". There is no need to run autoreconf, automake, autoheader,
+aclocal, or any other autotools programs beyond autoconf.
+
+A small handful of additional files have been taken from autotools
+programs. These should probably be updated from time to time.
+
+ * config.guess, config.sub, ltmain.sh: these were created by running
+ libtoolize -c. To update, run libtoolize -f -c or remove the files
+ and rerun libtoolize.
+
+ * Other files copied as indicated:
+
+ cp /usr/share/aclocal/libtool.m4 aclocal.m4
+ cp /usr/share/automake-1.10/install-sh .
+ cp /usr/share/automake-1.10/mkinstalldirs .
+
+The entire contents of aclocal.m4 came from libtool.m4. If we had
+some additional local parts, we could manually combine them or we
+could run aclocal. For now, the simple copy statement above is
+sufficient.
+
+If building or editing documentation, configure with
+--enable-doc-maintenance. This will ensure that all tools or files
+required to validate and build documentation are available.
+
+If you want to run make maintainer-clean or make distclean and you
+haven't run ./configure, you can pass CLEAN=1 to make on the command
+line to prevent it from complaining about configure not having been
+run.
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..d705187e
--- /dev/null
+++ b/TODO
@@ -0,0 +1,68 @@
+General
+=======
+
+ * See whether we can do anything with /V > 3 in the encryption
+ dictionary. (V = 4 is Crypt Filters.)
+
+ * The second xref stream for linearized files has to be padded only
+ because we need file_size as computed in pass 1 to be accurate. If
+ we were not allowing writing to a pipe, we could seek back to the
+ beginning and fill in the value of /L in the linearization
+ dictionary as an optimization to alleviate the need for this
+ padding. Doing so would require us to pad the /L value
+ individually and also to save the file descriptor and determine
+ whether it's seekable. This is probably not worth bothering with.
+
+ * The whole xref handling code in the QPDF object allows the same
+ object with more than one generation to coexist, but a lot of logic
+ assumes this isn't the case. Anything that creates mappings only
+ with the object number and not the generation is this way,
+ including most of the interaction between QPDFWriter and QPDF. If
+ we wanted to allow the same object with more than one generation to
+ coexist, which I'm not sure is allowed, we could fix this by
+ changing xref_table. Alternatively, we could detect and disallow
+ that case. In fact, it appears that Adobe reader and other PDF
+ viewing software silently ignores objects of this type, so this is
+ probably not a big deal.
+
+ * Pl_PNGFilter is only partially implemented. If we ever decoded
+ images, we'd have to finish implementing it along with the other
+ filter decode parameters and types. For just handling xref
+ streams, there's really no need as it wouldn't make sense to use
+ any kind of predictor other than 12 (PNG UP filter).
+
+ * If we ever want to have check mode check the integrity of the free
+ list, this can be done by looking at the code from prior to the
+ object stream support of 4/5/2008. It's in an if (0) block and
+ there's a comment about it. There's also something about it in
+ qpdf.test -- search for "free table". On the other hand, the value
+ of doing this seems very low since no viewer seems to care, so it's
+ probably not worth it.
+
+ * Embedded files streams: figure out why running qpdf over the pdf
+ 1.7 spec results in a file that crashes acrobat reader when you try
+ to save nested documents.
+
+ * QPDFObjectHandle::getPageImages() doesn't notice images in
+ inherited resource dictionaries. See comments in that function.
+
+Splitting by Pages
+==================
+
+Although qpdf does not currently support splitting a file into pages,
+the work done for linearization covers almost all the work. To do
+page splitting. If this functionality is needed, study
+obj_user_to_objects and object_to_obj_users created in
+QPDF_optimization for ideas. It's quite possible that the information
+computed by calculateLinearizationData is actually sufficient to do
+page splitting in many circumstances. That code knows which objects
+are used by which pages, though it doesn't do anything page-specific
+with outlines, thumbnails, page labels, or anything else.
+
+Another approach would be to traverse only pages that are being output
+taking care not to traverse into the pages tree, and then to fabricate
+a new pages tree.
+
+Either way, care must be taken to handle other things such as
+outlines, page labels, thumbnails, threads, etc. in a sensible way.
+This may include simply omitting information other than page content.
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 00000000..cfa57323
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,6672 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007,
+## 2008 Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+##
+## This file is free software; the Free Software Foundation gives
+## unlimited permission to copy and/or distribute it, with or without
+## modifications, as long as this notice is preserved.
+
+# serial 52 Debian 1.5.26-1 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+ [],
+ [m4_define([AC_PROVIDE_IFELSE],
+ [m4_ifdef([AC_PROVIDE_$1],
+ [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [AC_LIBTOOL_CXX],
+ [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+ ])])
+dnl And a similar setup for Fortran 77 support
+ AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [AC_LIBTOOL_F77],
+ [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+ AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [ifdef([AC_PROG_GCJ],
+ [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([A][M_PROG_GCJ],
+ [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([LT_AC_PROG_GCJ],
+ [define([LT_AC_PROG_GCJ],
+ defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ AC_PATH_MAGIC
+ fi
+ ;;
+esac
+
+_LT_REQUIRED_DARWIN_CHECKS
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+ [AC_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+AC_DEFUN([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+AC_DEFUN([_LT_COMPILER_BOILERPLATE],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+AC_DEFUN([_LT_LINKER_BOILERPLATE],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# --------------------------
+# Check for some things on darwin
+AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "${LT_MULTI_MODULE}"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ echo "int foo(void){return 1;}" > conftest.c
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib ${wl}-single_module conftest.c
+ if test -f libconftest.dylib; then
+ lt_cv_apple_cc_single_mod=yes
+ rm -rf libconftest.dylib*
+ fi
+ rm conftest.c
+ fi])
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[0123]])
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ darwin*)
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[[012]]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+ else
+ _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}"
+ fi
+ if test "$DSYMUTIL" != ":"; then
+ _lt_dsymutil="~$DSYMUTIL \$lib || :"
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+[$]*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+ ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$5], , :, [$5])
+else
+ ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $rm -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$4], , :, [$4])
+else
+ ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# ------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ---------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}]
+EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# ----------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_AC_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+m4_if($1,[],[
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary.
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+ else
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+ lt_foo="";
+ lt_count=0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo="/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ sys_lib_search_path_spec=`echo $lt_search_path_spec`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[123]]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+AC_CACHE_VAL([lt_cv_sys_lib_search_path_spec],
+[lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec"])
+sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+AC_CACHE_VAL([lt_cv_sys_lib_dlsearch_path_spec],
+[lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec"])
+sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_ARG_WITH([tags],
+ [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+ [include additional configurations @<:@automatic@:>@])],
+ [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ AC_MSG_WARN([output file `$ofile' does not exist])
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+ else
+ AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+ "") ;;
+ *) AC_MSG_ERROR([invalid tag name: $tagname])
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ AC_MSG_ERROR([tag name \"$tagname\" already exists])
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_LIBTOOL_LANG_CXX_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+ AC_LIBTOOL_LANG_F77_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+ AC_LIBTOOL_LANG_GCJ_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+ AC_LIBTOOL_LANG_RC_CONFIG
+ ;;
+
+ *)
+ AC_MSG_ERROR([Unsupported tag name: $tagname])
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ AC_MSG_ERROR([unable to update list of available tagged configurations.])
+ fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 DLLs
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+ [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+# set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+ [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+ [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognize shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognize a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+ [AC_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# it is assumed to be `libltdl'. LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!). If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case $enable_ltdl_convenience in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, lt_dlinit,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ LTDLINCL=
+ fi
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ------------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+ [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+ [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+ [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# -------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF
+
+# Report which library types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_dirs, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ AC_PROG_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+ if test "$GXX" = yes ; then
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+ _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+ fi
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ freebsd[[12]]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ freebsd-elf*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*) ;;
+ *)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ interix[[3-9]]*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+ _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+ _LT_AC_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+ _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+_LT_AC_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_AC_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_AC_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_AC_TAGVAR(predep_objects,$1)=
+ _LT_AC_TAGVAR(postdep_objects,$1)=
+ _LT_AC_TAGVAR(postdeps,$1)=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ #
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+esac
+])
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="\
+ program t
+ end
+"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# -------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars. Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ _LT_AC_TAGVAR(compiler, $1) \
+ _LT_AC_TAGVAR(CC, $1) \
+ _LT_AC_TAGVAR(LD, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+ _LT_AC_TAGVAR(old_archive_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+ _LT_AC_TAGVAR(predep_objects, $1) \
+ _LT_AC_TAGVAR(postdep_objects, $1) \
+ _LT_AC_TAGVAR(predeps, $1) \
+ _LT_AC_TAGVAR(postdeps, $1) \
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+ _LT_AC_TAGVAR(compiler_lib_search_dirs, $1) \
+ _LT_AC_TAGVAR(archive_cmds, $1) \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(postinstall_cmds, $1) \
+ _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+ _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+ _LT_AC_TAGVAR(no_undefined_flag, $1) \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+ _LT_AC_TAGVAR(hardcode_automatic, $1) \
+ _LT_AC_TAGVAR(module_cmds, $1) \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+ _LT_AC_TAGVAR(fix_srcfile_path, $1) \
+ _LT_AC_TAGVAR(exclude_expsyms, $1) \
+ _LT_AC_TAGVAR(include_expsyms, $1); do
+
+ case $var in
+ _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(module_cmds, $1) | \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\[$]0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+ ;;
+ esac
+
+ifelse([$1], [],
+ [cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ AC_MSG_NOTICE([creating $ofile])],
+ [cfgfile="$ofile"])
+
+ cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The directories searched by this compiler when creating a shared
+# library
+compiler_lib_search_dirs=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_dirs, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+])
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([LT_AC_PROG_SED])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux* | k*bsd*-gnu)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDGIRSTW]]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler.
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd* | netbsdelf*-gnu)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ icc* | ecc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Sun\ F*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_pic_works, $1),
+ [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+ ;;
+ linux* | k*bsd*-gnu)
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+ _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+],[
+ runpath_var=
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)=
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+ _LT_AC_TAGVAR(module_cmds, $1)=
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_AC_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ _LT_CC_BASENAME([$compiler])
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ interix[[3-9]]*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | k*bsd*-gnu)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ *)
+ tmp_sharedflag='-shared' ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=no
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ # see comment about different semantics on the GNU ld section
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ bsdi[[45]]*)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'. GCC discards it without `$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_AC_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $rm conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+
+# Cheap backport of AS_EXECUTABLE_P and required macros
+# from Autoconf 2.59; we should not use $as_executable_p directly.
+
+# _AS_TEST_PREPARE
+# ----------------
+m4_ifndef([_AS_TEST_PREPARE],
+[m4_defun([_AS_TEST_PREPARE],
+[if test -x / >/dev/null 2>&1; then
+ as_executable_p='test -x'
+else
+ as_executable_p='test -f'
+fi
+])])# _AS_TEST_PREPARE
+
+# AS_EXECUTABLE_P
+# ---------------
+# Check whether a file is executable.
+m4_ifndef([AS_EXECUTABLE_P],
+[m4_defun([AS_EXECUTABLE_P],
+[AS_REQUIRE([_AS_TEST_PREPARE])dnl
+$as_executable_p $1[]dnl
+])])# AS_EXECUTABLE_P
+
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])
diff --git a/autoconf.mk.in b/autoconf.mk.in
new file mode 100644
index 00000000..eb213ff2
--- /dev/null
+++ b/autoconf.mk.in
@@ -0,0 +1,30 @@
+PACKAGE_TARNAME=@PACKAGE_TARNAME@
+PACKAGE_VERSION=@PACKAGE_VERSION@
+top_builddir=@top_builddir@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+mandir=@mandir@
+docdir=@docdir@
+htmldir=@htmldir@
+pdfdir=@pdfdir
+CC=@CC@
+CFLAGS=@CFLAGS@
+LDFLAGS=@LDFLAGS@
+LIBS=@LIBS@
+CPPFLAGS=@CPPFLAGS@
+CXX=@CXX@
+CXXFLAGS=@CXXFLAGS@
+GENDEPS=@GENDEPS@
+LIBTOOL=@LIBTOOL@
+DOCBOOKX_DTD=@DOCBOOKX_DTD@
+FOP=@FOP@
+XSLTPROC=@XSLTPROC@
+XMLLINT=@XMLLINT@
+BUILD_HTML=@BUILD_HTML@
+BUILD_PDF=@BUILD_PDF@
+VALIDATE_DOC=@VALIDATE_DOC@
+SKIP_TEST_COMPARE_IMAGES=@SKIP_TEST_COMPARE_IMAGES@
diff --git a/config.guess b/config.guess
new file mode 100755
index 00000000..f32079ab
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/config.sub
new file mode 100755
index 00000000..6759825a
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1658 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 00000000..b1c5e567
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,282 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl This config.in requires autoconf 2.5 or greater.
+
+AC_PREREQ(2.59)
+AC_INIT(qpdf,2.0)
+
+dnl No AC_CONFIG_HEADERS. If this changes, update README.maintainer.
+AC_CONFIG_FILES([autoconf.mk])
+AC_CONFIG_FILES([manual/html.xsl manual/print.xsl])
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_HEADER_STDC
+AC_PROG_LIBTOOL
+
+AC_CHECK_HEADER(zlib.h,,[MISSING_ZLIB_H=1; MISSING_ANY=1])
+AC_SEARCH_LIBS(deflate,z zlib,,[MISSING_ZLIB=1; MISSING_ANY=1])
+AC_CHECK_HEADER(pcre.h,,[MISSING_PCRE_H=1; MISSING_ANY=1])
+AC_SEARCH_LIBS(pcre_compile,pcre,,[MISSING_PCRE=1; MISSING_ANY=1])
+
+AC_MSG_CHECKING(for gnu make >= 3.81)
+make_okay=0
+if make --version >/dev/null 2>&1; then
+ v=`make --version | grep 'GNU Make' | sed -e 's/.*Make //'`
+ maj=`echo $v | cut -d. -f 1`
+ min=`echo $v | cut -d. -f 2`
+ if test $maj -gt 3 -o '(' $maj -eq 3 -a $min -ge 81 ')'; then
+ make_okay=1
+ fi
+fi
+if test "$make_okay" = "1"; then
+ AC_MSG_RESULT(yes)
+else
+ dnl Don't set MISSING_ANY=1 -- maybe user calls make something else
+ MISSING_MAKE_381=1
+ ISSUE_WARNINGS=1
+ AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(GENDEPS)
+GENDEPS=0
+AC_MSG_CHECKING(for whether $CC supports -MD -MF x.dep -MP)
+oCFLAGS=$CFLAGS
+rm -f x.dep
+CFLAGS="$CFLAGS -MD -MF x.dep -MP"
+AC_TRY_COMPILE([#include <stdio.h>], [FILE* a = stdout],
+ qpdf_DEPFLAGS=yes,
+ qpdf_DEPFLAGS=no)
+CFLAGS=$oCFLAGS
+if test "$qpdf_DEPFLAGS" = "yes"; then
+ if ! grep stdio.h x.dep >/dev/null 2>&1; then
+ qpdf_DEPFLAGS=no
+ fi
+fi
+rm -f x.dep
+if test "$qpdf_DEPFLAGS" = "yes"; then
+ AC_MSG_RESULT(yes)
+ GENDEPS=1
+else
+ AC_MSG_RESULT(no)
+fi
+
+qpdf_USE_WALL=0
+AC_MSG_CHECKING(for whether $CC supports -Wall)
+oCFLAGS=$CFLAGS
+CFLAGS="$CFLAGS -Wall"
+AC_TRY_COMPILE([], [int a = 1; int b = a; a = b;],
+ qpdf_USE_WALL=1,
+ qpdf_USE_WALL=0)
+if test "$qpdf_USE_WALL" = "1"; then
+ AC_MSG_RESULT(yes)
+ CXXFLAGS="$CXXFLAGS -Wall"
+else
+ AC_MSG_RESULT(no)
+ CFLAGS=$oCFLAGS
+fi
+
+AC_MSG_CHECKING(for whether to use -Werror)
+AC_ARG_ENABLE(werror,
+ AS_HELP_STRING([--enable-werror],
+ [whether to use werror (default is yes if -Wall works)]),
+ [if test "$enableval" = "yes"; then
+ qpdf_USE_WERROR=1;
+ else
+ qpdf_USE_WERROR=0;
+ fi], [qpdf_USE_WERROR=$qpdf_USE_WALL])
+if test "$qpdf_USE_WERROR" = "1"; then
+ AC_MSG_RESULT(yes)
+ CFLAGS="$CFLAGS -Werror"
+ CXXFLAGS="$CXXFLAGS -Werror"
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(SKIP_TEST_COMPARE_IMAGES)
+AC_ARG_ENABLE(test-compare-images,
+ AS_HELP_STRING([--enable-test-compare-images],
+ [whether to compare images in test suite; enabled by default, enabling requires ghostscript and tiffcmp to be available]),
+ [if test "$enableval" = "no"; then
+ SKIP_TEST_COMPARE_IMAGES=1
+ else
+ SKIP_TEST_COMPARE_IMAGES=0
+ fi],
+ [SKIP_TEST_COMPARE_IMAGES=0])
+
+AC_ARG_WITH(docbook-xsl,
+ AS_HELP_STRING([--with-docbook-xsl=DIR],
+ [location of docbook 4.x xml stylesheets]),
+ [DOCBOOK_XSL=$withval],
+ [DOCBOOK_XSL=/usr/share/xml/docbook/stylesheet/nwalsh])
+
+DOCBOOK_XHTML=
+AC_SUBST(DOCBOOK_XHTML)
+AC_MSG_CHECKING(for xml to xhtml docbook stylesheets)
+if test -f "$DOCBOOK_XSL/xhtml/docbook.xsl"; then
+ DOCBOOK_XHTML="$DOCBOOK_XSL/xhtml/docbook.xsl"
+ AC_MSG_RESULT($DOCBOOK_XHTML)
+else
+ AC_MSG_RESULT(no)
+fi
+DOCBOOK_FO=
+AC_SUBST(DOCBOOK_FO)
+AC_MSG_CHECKING(for xml to fo docbook stylesheets)
+if test -f "$DOCBOOK_XSL/fo/docbook.xsl"; then
+ DOCBOOK_FO="$DOCBOOK_XSL/fo/docbook.xsl"
+ AC_MSG_RESULT($DOCBOOK_FO)
+else
+ AC_MSG_RESULT(no)
+fi
+
+DOCBOOKX_DTD=
+AC_SUBST(DOCBOOKX_DTD)
+AC_ARG_WITH(docbookx-dtd,
+ AS_HELP_STRING([--with-docbookx-dtd=FILE],
+ [location of docbook 4.x xml DTD]),
+ [DOCBOOKX_DTD=$withval],
+ [DOCBOOKX_DTD=/usr/share/xml/docbook/schema/dtd/4/docbookx.dtd])
+AC_MSG_CHECKING(for docbook 4.x xml DTD)
+if test -f "$DOCBOOKX_DTD"; then
+ AC_MSG_RESULT($DOCBOOKX_DTD)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_CHECK_PROG(FOP,fop,fop,[])
+AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,[])
+AC_CHECK_PROG(XMLLINT,xmllint,xmllint,[])
+
+AC_ARG_ENABLE(doc-maintenance,
+ AS_HELP_STRING([--enable-doc-maintenance],
+ [if set, enables all documentation options]),
+ [if test "$enableval" = "yes"; then
+ doc_default=1;
+ else
+ doc_default=0;
+ fi],
+ [doc_default=0])
+
+BUILD_HTML=0
+AC_SUBST(BUILD_HTML)
+AC_ARG_ENABLE(html-doc,
+ AS_HELP_STRING([--enable-html-doc],
+ [whether to build HTML documents]),
+ [if test "$enableval" = "yes"; then
+ BUILD_HTML=1;
+ else
+ BUILD_HTML=0;
+ fi],
+ [BUILD_HTML=$doc_default])
+BUILD_PDF=0
+AC_SUBST(BUILD_PDF)
+AC_ARG_ENABLE(pdf-doc,
+ AS_HELP_STRING([--enable-pdf-doc],
+ [whether to build PDF documents]),
+ [if test "$enableval" = "yes"; then
+ BUILD_PDF=1;
+ else
+ BUILD_PDF=0;
+ fi],
+ [BUILD_PDF=$doc_default])
+VALIDATE_DOC=0
+AC_SUBST(VALIDATE_DOC)
+AC_ARG_ENABLE(validate-doc,
+ AS_HELP_STRING([--enable-validate-doc],
+ [whether to validate xml document source]),
+ [if test "$enableval" = "yes"; then
+ VALIDATE_DOC=1;
+ else
+ VALIDATE_DOC=0;
+ fi],
+ [VALIDATE_DOC=$doc_default])
+
+if test "$VALIDATE_DOC" = "1"; then
+ if test "$XMLLINT" = ""; then
+ MISSING_XMLLINT=1
+ MISSING_ANY=1
+ fi
+fi
+if test "$BUILD_HTML" = "1"; then
+ if test "$XSLTPROC" = ""; then
+ MISSING_XSLTPROC=1
+ MISSING_ANY=1
+ fi
+ if test "$DOCBOOK_XHTML" = ""; then
+ MISSING_DOCBOOK_XHTML=1
+ MISSING_ANY=1
+ fi
+fi
+if test "$BUILD_PDF" = "1"; then
+ if test "$XSLTPROC" = ""; then
+ MISSING_XSLTPROC=1
+ MISSING_ANY=1
+ fi
+ if test "$DOCBOOK_FO" = ""; then
+ MISSING_DOCBOOK_FO=1
+ MISSING_ANY=1
+ fi
+ if test "$FOP" = ""; then
+ MISSING_FOP=1
+ MISSING_ANY=1
+ fi
+fi
+
+
+if test "$MISSING_ANY" = "1"; then
+ ISSUE_WARNINGS=1
+fi
+if test "$ISSUE_WARNINGS" = "1"; then
+ echo ""
+ echo ""
+fi
+
+if test "$MISSING_MAKE_381" = "1"; then
+ AC_MSG_WARN(gnu make >= 3.81 is required)
+fi
+
+if test "$MISSING_ZLIB_H" = "1"; then
+ AC_MSG_WARN(unable to find required header zlib.h)
+fi
+
+if test "$MISSING_ZLIB" = "1"; then
+ AC_MSG_WARN(unable to find required library z (or zlib))
+fi
+
+if test "$MISSING_PCRE_H" = "1"; then
+ AC_MSG_WARN(unable to find required header pcre.h)
+fi
+
+if test "$MISSING_PCRE" = "1"; then
+ AC_MSG_WARN(unable to find required library pcre)
+fi
+
+if test "$MISSING_DOCBOOK_FO" = "1"; then
+ AC_MSG_WARN(docbook fo stylesheets are required to build PDF documentation)
+fi
+
+if test "$MISSING_DOCBOOK_XHTML" = "1"; then
+ AC_MSG_WARN(docbook xhmtl stylesheets are required to build HTML documentation)
+fi
+
+if test "$MISSING_FOP" = "1"; then
+ AC_MSG_WARN(apache fop is required to build PDF documentation)
+fi
+
+if test "$MISSING_XMLLINT" = "1"; then
+ AC_MSG_WARN(xmllint is required to validate documentation)
+fi
+
+if test "$MISSING_XSLTPROC" = "1"; then
+ AC_MSG_WARN(xsltproc is required to build documentation)
+fi
+
+if test "$ISSUE_WARNINGS" = "1"; then
+ echo ""
+ echo ""
+fi
+
+if test "$MISSING_ANY" = "1"; then
+ AC_MSG_ERROR(some required prerequisites were not found)
+fi
+
+AC_OUTPUT()
diff --git a/doc/stylesheet.css b/doc/stylesheet.css
new file mode 100644
index 00000000..abaf226f
--- /dev/null
+++ b/doc/stylesheet.css
@@ -0,0 +1,284 @@
+/**************************************************************/
+/* Custom style-sheet for the QPDF manual in HTML form. */
+/**************************************************************/
+
+/*
+ * This file is the CSS for the QPDF manual. It is based heavily on
+ * the CSS for the Subversion book. That file contains the following
+ * copyright and attribution:
+ *
+ * Copyright (c) 2003-2007
+ * Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato.
+ *
+ * This work is licensed under the Creative Commons Attribution License.
+ * To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by/2.0/ or send a letter to
+ * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305,
+ * USA.
+ */
+
+body
+{
+ background: white;
+ margin: 0.5in;
+}
+
+p, li, ul, ol, dd, dt
+{
+ font-style: normal;
+ font-weight: normal;
+ color: black;
+}
+
+tt, pre
+{
+ font-family: courier new,courier,fixed;
+}
+
+a
+{
+ color: blue;
+ text-decoration: underline;
+}
+
+a:hover
+{
+ background: rgb(75%,75%,100%);
+ color: blue;
+ text-decoration: underline;
+}
+
+a:visited
+{
+ color: purple;
+ text-decoration: underline;
+}
+
+img
+{
+ border: none;
+}
+
+h1.title
+{
+ font-size: 250%;
+ font-style: normal;
+ font-weight: bold;
+ color: black;
+}
+
+h2.subtitle
+{
+ font-size: 150%;
+ font-style: italic;
+ color: black;
+}
+
+h2.title
+{
+ font-size: 150%;
+ font-style: normal;
+ font-weight: bold;
+ color: black;
+}
+
+h3.title
+{
+ font-size: 125%;
+ font-style: normal;
+ font-weight: bold;
+ color: black;
+}
+
+h4.title
+{
+ font-size: 100%;
+ font-style: normal;
+ font-weight: bold;
+ color: black;
+}
+
+.toc b
+{
+ font-size: 125%;
+ font-style: normal;
+ font-weight: bold;
+ color: black;
+}
+
+.screen, .programlisting, .literal
+{
+ font-family: courier new,courier,fixed;
+ font-style: normal;
+ font-weight: normal;
+}
+
+.command, .option, .type
+{
+ font-family: courier new,courier,fixed;
+ font-style: normal;
+ font-weight: normal;
+}
+
+.filename
+{
+ font-family: arial,helvetica,sans-serif;
+ font-style: italic;
+}
+
+.property
+{
+ font-family: arial,helvetica,sans-serif;
+ font-weight: bold;
+}
+
+.classname
+{
+ font-family: arial,helvetica,sans-serif;
+ font-weight: bold;
+ font-style: italic;
+}
+
+.varname, .function, .envar
+{
+ font-family: arial,helvetica,sans-serif;
+ font-style: italic;
+}
+
+.replaceable
+{
+ font-style: italic;
+ font-size: 100%;
+}
+
+.figure, .example, .table
+{
+ margin: 0.125in 0.25in;
+}
+
+.table table
+{
+ border-width: 1px;
+ border-style: solid;
+ border-color: black;
+ border-spacing: 0;
+ background: rgb(240,240,240);
+}
+
+.table td
+{
+ border: none;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 2px;
+}
+
+.table th
+{
+ background: rgb(180,180,180);
+ border: none;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 2px;
+}
+
+.table p.title, .figure p.title, .example p.title
+{
+ text-align: left !important;
+ font-size: 100% !important;
+}
+
+.author, .pubdate
+{
+ margin: 0;
+ font-size: 100%;
+ font-style: italic;
+ font-weight: normal;
+ color: black;
+}
+
+.preface div.author, .preface .pubdate
+{
+ font-size: 80%;
+}
+
+.sidebar
+{
+ border-top: dotted 1px black;
+ border-left: dotted 1px black;
+ border-right: solid 2px black;
+ border-bottom: solid 2px black;
+ background: rgb(240,220,170);
+ padding: 0 0.12in;
+ margin: 0.25in;
+}
+
+.note .programlisting, .note .screen,
+.tip .programlisting, .tip .screen,
+.warning .programlisting, .warning .screen,
+.sidebar .programlisting, .sidebar .screen
+{
+ border: none;
+ background: none;
+}
+
+.sidebar p.title
+{
+ text-align: center;
+ font-size: 125%;
+}
+
+.note
+{
+ border: black solid 1px;
+ background: url(./images/note.png) no-repeat rgb(252,246,220);
+ margin: 0.125in 0;
+ padding: 0 55px;
+}
+
+.tip
+{
+ border: black solid 1px;
+ background: url(./images/tip.png) no-repeat rgb(224,244,255);
+ margin: 0.125in 0;
+ padding: 0 55px;
+}
+
+.warning
+{
+ border: black solid 1px;
+ background: url(./images/warning.png) no-repeat rgb(255,210,210);
+ margin: 0.125in 0;
+ padding: 0 55px;
+}
+
+/*
+.note .title, .tip .title, .warning .title
+{
+ display: none;
+}
+*/
+
+.programlisting, .screen
+{
+ font-size: 90%;
+ color: black;
+ margin: 1em 0.25in;
+ padding: 0.5em;
+ background: rgb(240,240,240);
+ border-top: black dotted 1px;
+ border-left: black dotted 1px;
+ border-right: black solid 2px;
+ border-bottom: black solid 2px;
+}
+
+.navheader, .navfooter
+{
+ border: black solid 1px;
+ background: rgb(180,180,200);
+}
+
+.navheader hr, .navfooter hr
+{
+ display: none;
+}
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 00000000..90899055
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1 @@
+include ../make/proxy.mk
diff --git a/examples/build.mk b/examples/build.mk
new file mode 100644
index 00000000..eab2744c
--- /dev/null
+++ b/examples/build.mk
@@ -0,0 +1,26 @@
+BINS_examples = pdf-bookmarks pdf-mod-info pdf-npages
+
+TARGETS_examples = $(foreach B,$(BINS_examples),examples/$(OUTPUT_DIR)/$(B))
+
+$(TARGETS_examples): $(TARGETS_qpdf)
+
+INCLUDES_examples = include
+
+TC_SRCS_examples = $(wildcard examples/*.cc)
+
+# -----
+
+$(foreach B,$(BINS_examples),$(eval \
+ OBJS_$(B) = $(call src_to_obj,examples/$(B).cc)))
+
+ifeq ($(GENDEPS),1)
+-include $(foreach B,$(BINS_examples),$(call obj_to_dep,$(OBJS_$(B))))
+endif
+
+$(foreach B,$(BINS_examples),$(eval \
+ $(OBJS_$(B)): examples/$(OUTPUT_DIR)/%.o: examples/$(B).cc ; \
+ $(call compile,examples/$(B).cc,$(INCLUDES_examples))))
+
+$(foreach B,$(BINS_examples),$(eval \
+ examples/$(OUTPUT_DIR)/$(B): $(OBJS_$(B)) ; \
+ $(call makebin,$(OBJS_$(B)),$$@)))
diff --git a/examples/examples.testcov b/examples/examples.testcov
new file mode 100644
index 00000000..5a19b7c5
--- /dev/null
+++ b/examples/examples.testcov
@@ -0,0 +1,19 @@
+pdf-bookmarks lines 0
+pdf-bookmarks numbers 0
+pdf-bookmarks none 0
+pdf-bookmarks has count 0
+pdf-bookmarks no count 0
+pdf-bookmarks open 0
+pdf-bookmarks closed 0
+pdf-bookmarks dest 0
+pdf-bookmarks targets 0
+pdf-mod-info --dump 0
+pdf-mod-info no in file 0
+pdf-mod-info in-place 0
+pdf-mod-info -key 0
+pdf-mod-info usage wrong val 0
+pdf-mod-info -val 0
+pdf-mod-info usage junk 0
+pdf-mod-info no keys 0
+pdf-mod-info has info 0
+pdf-mod-info file no info 0
diff --git a/examples/pdf-bookmarks.cc b/examples/pdf-bookmarks.cc
new file mode 100644
index 00000000..98bff7fe
--- /dev/null
+++ b/examples/pdf-bookmarks.cc
@@ -0,0 +1,262 @@
+#include <iostream>
+#include <string.h>
+#include <qpdf/QPDF.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/QTC.hh>
+
+static char const* whoami = 0;
+static enum { st_none, st_numbers, st_lines } style = st_none;
+static bool show_open = false;
+static bool show_targets = false;
+static std::map<int, int> page_map;
+
+void usage()
+{
+ std::cerr << "Usage: " << whoami << " [options] file.pdf [password]"
+ << std::endl
+ << "Options:" << std::endl
+ << " -numbers give bookmarks outline-style numbers"
+ << std::endl
+ << " -lines draw lines to show bookmark hierarchy"
+ << std::endl
+ << " -show-open indicate whether a bookmark is initially open"
+ << std::endl
+ << " -show-targets show target if possible"
+ << std::endl;
+ exit(2);
+}
+
+void print_lines(std::vector<int>& numbers)
+{
+ for (unsigned int i = 0; i < numbers.size() - 1; ++i)
+ {
+ if (numbers[i])
+ {
+ std::cout << "| ";
+ }
+ else
+ {
+ std::cout << " ";
+ }
+ }
+}
+
+void generate_page_map(QPDF& qpdf)
+{
+ std::vector<QPDFObjectHandle> pages = qpdf.getAllPages();
+ int n = 0;
+ for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
+ iter != pages.end(); ++iter)
+ {
+ QPDFObjectHandle& oh = *iter;
+ page_map[oh.getObjectID()] = ++n;
+ }
+}
+
+void extract_bookmarks(QPDFObjectHandle outlines, std::vector<int>& numbers)
+{
+ if (outlines.hasKey("/Title"))
+ {
+ // No default so gcc will warn on missing tag
+ switch (style)
+ {
+ case st_none:
+ QTC::TC("examples", "pdf-bookmarks none");
+ break;
+
+ case st_numbers:
+ QTC::TC("examples", "pdf-bookmarks numbers");
+ for (std::vector<int>::iterator iter = numbers.begin();
+ iter != numbers.end(); ++iter)
+ {
+ std::cout << *iter << ".";
+ }
+ std::cout << " ";
+ break;
+
+ case st_lines:
+ QTC::TC("examples", "pdf-bookmarks lines");
+ print_lines(numbers);
+ std::cout << "|" << std::endl;
+ print_lines(numbers);
+ std::cout << "+-+ ";
+ break;
+ }
+
+ if (show_open)
+ {
+ if (outlines.hasKey("/Count"))
+ {
+ QTC::TC("examples", "pdf-bookmarks has count");
+ int count = outlines.getKey("/Count").getIntValue();
+ if (count > 0)
+ {
+ // hierarchy is open at this point
+ QTC::TC("examples", "pdf-bookmarks open");
+ std::cout << "(v) ";
+ }
+ else
+ {
+ QTC::TC("examples", "pdf-bookmarks closed");
+ std::cout << "(>) ";
+ }
+ }
+ else
+ {
+ QTC::TC("examples", "pdf-bookmarks no count");
+ std::cout << "( ) ";
+ }
+ }
+
+ if (show_targets)
+ {
+ QTC::TC("examples", "pdf-bookmarks targets");
+ std::string target = "unknown";
+ // Only explicit destinations supported for now
+ if (outlines.hasKey("/Dest"))
+ {
+ QTC::TC("examples", "pdf-bookmarks dest");
+ QPDFObjectHandle dest = outlines.getKey("/Dest");
+ if ((dest.isArray()) && (dest.getArrayNItems() > 0))
+ {
+ QPDFObjectHandle first = dest.getArrayItem(0);
+ int object_id = first.getObjectID();
+ if (page_map.count(object_id))
+ {
+ target = QUtil::int_to_string(page_map[object_id]);
+ }
+ }
+
+ std::cout << "[ -> " << target << " ] ";
+ }
+ }
+
+ std::cout << outlines.getKey("/Title").getUTF8Value() << std::endl;
+ }
+
+ if (outlines.hasKey("/First"))
+ {
+ numbers.push_back(0);
+ QPDFObjectHandle child = outlines.getKey("/First");
+ while (1)
+ {
+ ++(numbers.back());
+ bool has_next = child.hasKey("/Next");
+ if ((style == st_lines) && (! has_next))
+ {
+ numbers.back() = 0;
+ }
+ extract_bookmarks(child, numbers);
+ if (has_next)
+ {
+ child = child.getKey("/Next");
+ }
+ else
+ {
+ break;
+ }
+ }
+ numbers.pop_back();
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ if ((whoami = strrchr(argv[0], '/')) == NULL)
+ {
+ whoami = argv[0];
+ }
+ else
+ {
+ ++whoami;
+ }
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
+ {
+ std::cout << whoami << " version 1.5" << std::endl;
+ exit(0);
+ }
+
+ int arg;
+ for (arg = 1; arg < argc; ++arg)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (strcmp(argv[arg], "-numbers") == 0)
+ {
+ style = st_numbers;
+ }
+ else if (strcmp(argv[arg], "-lines") == 0)
+ {
+ style = st_lines;
+ }
+ else if (strcmp(argv[arg], "-show-open") == 0)
+ {
+ show_open = true;
+ }
+ else if (strcmp(argv[arg], "-show-targets") == 0)
+ {
+ show_targets = true;
+ }
+ else
+ {
+ usage();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (arg >= argc)
+ {
+ usage();
+ }
+
+ char const* filename = argv[arg++];
+ char const* password = "";
+
+ if (arg < argc)
+ {
+ password = argv[arg++];
+ }
+ if (arg != argc)
+ {
+ usage();
+ }
+
+ try
+ {
+ QPDF qpdf;
+ qpdf.processFile(filename, password);
+
+ QPDFObjectHandle root = qpdf.getRoot();
+ if (root.hasKey("/Outlines"))
+ {
+ std::vector<int> numbers;
+ if (show_targets)
+ {
+ generate_page_map(qpdf);
+ }
+ extract_bookmarks(root.getKey("/Outlines"), numbers);
+ }
+ else
+ {
+ std::cout << filename << " has no bookmarks" << std::endl;
+ }
+ }
+ catch (std::exception &e)
+ {
+ std::cerr << whoami << " processing file " << filename << ": "
+ << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/examples/pdf-mod-info.cc b/examples/pdf-mod-info.cc
new file mode 100644
index 00000000..cd2bd034
--- /dev/null
+++ b/examples/pdf-mod-info.cc
@@ -0,0 +1,219 @@
+// Author: Vitaliy Pavlyuk
+
+#include <qpdf/QPDF.hh>
+#include <qpdf/QPDFWriter.hh>
+#include <qpdf/QPDFObjectHandle.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/QTC.hh>
+#include <iostream>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char const* version = "1.1";
+static char const* whoami = 0;
+
+void usage()
+{
+ std::cerr
+ << "Usage: " << whoami
+ << " -in in_file [-out out_file] [-key key [-val val]?]+\n"
+ << "Modifies/Adds/Removes PDF /Info entries in the in_file\n"
+ << "and stores the result in out_file\n"
+ << "Special mode: " << whoami << " --dump file\n"
+ << "dumps all /Info entries to stdout\n";
+ exit(2);
+}
+
+void dumpInfoDict(QPDF& pdf,
+ std::ostream& os = std::cout,
+ std::string const& sep = ":\t")
+{
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ if (trailer.hasKey("/Info"))
+ {
+ QPDFObjectHandle info = trailer.getKey("/Info");
+ std::set<std::string> keys = info.getKeys();
+ for (std::set<std::string>::const_iterator it = keys.begin();
+ keys.end() != it; ++it)
+ {
+ QPDFObjectHandle elt = info.getKey(*it);
+ std::string val;
+ if (false) {}
+ else if (elt.isString())
+ {
+ val = elt.getStringValue();
+ }
+ else if (elt.isName())
+ {
+ val = elt.getName();
+ }
+ else // according to PDF Spec 1.5, shouldn't happen
+ {
+ val = elt.unparseResolved();
+ }
+ os << it->substr(1) << sep << val << std::endl; // skip '/'
+ }
+ }
+}
+
+void pdfDumpInfoDict(char const* fname)
+{
+ try
+ {
+ QPDF pdf;
+ pdf.processFile(fname);
+ dumpInfoDict(pdf);
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+
+ bool static_id = false;
+ std::map<std::string, std::string> Keys;
+
+ if ((whoami = strrchr(argv[0], '/')) == NULL)
+ {
+ whoami = argv[0];
+ }
+ else
+ {
+ ++whoami;
+ }
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if ((argc == 2) && (! strcmp(argv[1], "--version")) )
+ {
+ std::cout << whoami << " version " << version << std::endl;
+ exit(0);
+ }
+ if ((argc == 4) && (! strcmp(argv[1], "--dump")) &&
+ (strcmp(argv[2], "-in") == 0) )
+ {
+ QTC::TC("examples", "pdf-mod-info --dump");
+ pdfDumpInfoDict(argv[3]);
+ exit(0);
+ }
+
+ char* fl_in = 0;
+ char* fl_out = 0;
+ char* cur_key = 0;
+
+ for (int i = 1; i < argc; ++i)
+ {
+ if ((! strcmp(argv[i], "-in")) && (++i < argc))
+ {
+ fl_in = argv[i];
+ }
+ else if ((! strcmp(argv[i], "-out")) && (++i < argc))
+ {
+ fl_out = argv[i];
+ }
+ else if (! strcmp(argv[i], "--static-id")) // don't document
+ {
+ static_id = true; // this should be used in test suites only
+ }
+ else if ((! strcmp(argv[i], "-key")) && (++i < argc))
+ {
+ QTC::TC("examples", "pdf-mod-info -key");
+ cur_key = argv[i];
+ Keys[cur_key] = "";
+ }
+ else if ((! strcmp(argv[i], "-val")) && (++i < argc))
+ {
+ if (cur_key == 0)
+ {
+ QTC::TC("examples", "pdf-mod-info usage wrong val");
+ usage();
+ }
+ QTC::TC("examples", "pdf-mod-info -val");
+ Keys[cur_key] = argv[i];
+ cur_key = 0;
+ }
+ else
+ {
+ QTC::TC("examples", "pdf-mod-info usage junk");
+ usage();
+ }
+ }
+ if (! fl_in)
+ {
+ QTC::TC("examples", "pdf-mod-info no in file");
+ usage();
+ }
+ if (! fl_out)
+ {
+ QTC::TC("examples", "pdf-mod-info in-place");
+ fl_out = fl_in;
+ }
+ if (Keys.size() == 0)
+ {
+ QTC::TC("examples", "pdf-mod-info no keys");
+ usage();
+ }
+
+ try
+ {
+ QPDF file;
+ file.processFile(fl_in);
+
+ QPDFObjectHandle filetrailer = file.getTrailer();
+ QPDFObjectHandle fileinfo;
+
+ for (std::map<std::string, std::string>::const_iterator it =
+ Keys.begin(); Keys.end() != it; ++it)
+ {
+ if (! fileinfo.isInitialized())
+ {
+ if (filetrailer.hasKey("/Info"))
+ {
+ QTC::TC("examples", "pdf-mod-info has info");
+ fileinfo = filetrailer.getKey("/Info");
+ }
+ else
+ {
+ QTC::TC("examples", "pdf-mod-info file no info");
+ std::map<std::string, QPDFObjectHandle> vacant;
+ fileinfo = fileinfo.newDictionary(vacant);
+ filetrailer.replaceKey("/Info", fileinfo);
+ }
+ }
+ if (it->second == "")
+ {
+ fileinfo.removeKey(it->first);
+ }
+ else
+ {
+ QPDFObjectHandle elt = fileinfo.newString(it->second);
+ elt.makeDirect();
+ fileinfo.replaceKey(it->first, elt);
+ }
+ }
+ std::string fl_tmp = fl_out;
+ fl_tmp += ".tmp";
+ QPDFWriter w(file, fl_tmp.c_str());
+ w.setStreamDataMode(QPDFWriter::s_preserve);
+ w.setLinearization(true);
+ w.setStaticID(static_id);
+ w.write();
+ QUtil::os_wrapper("rename " + fl_tmp + " " + std::string(fl_out),
+ rename(fl_tmp.c_str(), fl_out));
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/examples/pdf-npages.cc b/examples/pdf-npages.cc
new file mode 100644
index 00000000..53074d05
--- /dev/null
+++ b/examples/pdf-npages.cc
@@ -0,0 +1,61 @@
+
+
+#include <iostream>
+#include <string.h>
+
+#include <qpdf/QPDF.hh>
+
+static char const* whoami = 0;
+
+void usage()
+{
+ std::cerr << "Usage: " << whoami << " filename" << std::endl
+ << "Prints the number of pages in filename" << std::endl;
+ exit(2);
+}
+
+int main(int argc, char* argv[])
+{
+ if ((whoami = strrchr(argv[0], '/')) == NULL)
+ {
+ whoami = argv[0];
+ }
+ else
+ {
+ ++whoami;
+ }
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
+ {
+ std::cout << whoami << " version 1.3" << std::endl;
+ exit(0);
+ }
+
+ if (argc != 2)
+ {
+ usage();
+ }
+ char const* filename = argv[1];
+
+ try
+ {
+ QPDF pdf;
+ pdf.processFile(filename);
+ QPDFObjectHandle root = pdf.getRoot();
+ QPDFObjectHandle pages = root.getKey("/Pages");
+ QPDFObjectHandle count = pages.getKey("/Count");
+ std::cout << count.getIntValue() << std::endl;
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << whoami << ": " << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/examples/qtest/bookmarks.test b/examples/qtest/bookmarks.test
new file mode 100644
index 00000000..4cf4abcf
--- /dev/null
+++ b/examples/qtest/bookmarks.test
@@ -0,0 +1,49 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("bookmarks");
+
+require TestDriver;
+
+my $td = new TestDriver('pdf-bookmarks');
+
+foreach my $show ("", " -show-open")
+{
+ foreach my $style ("", " -lines", " -numbers")
+ {
+ my $out = "test.$show.$style.out";
+ $out =~ s/ //g;
+ $td->runtest("show:$show, style:$style",
+ {$td->COMMAND => "pdf-bookmarks $show $style 1.pdf"},
+ {$td->FILE => $out, $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+ }
+}
+$td->runtest("no bookmarks",
+ {$td->COMMAND => "pdf-bookmarks 2.pdf"},
+ {$td->STRING => "2.pdf has no bookmarks\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("bad",
+ {$td->COMMAND => "pdf-bookmarks 3.pdf"},
+ {$td->STRING => "pdf-bookmarks processing file 3.pdf: " .
+ "3.pdf: offset 0: not a PDF file\n",
+ $td->EXIT_STATUS => 2},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("encrypted, targets",
+ {$td->COMMAND => "pdf-bookmarks -show-targets 4.pdf user"},
+ {$td->FILE => "encrypted.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("bookmarks deleted",
+ {$td->COMMAND => "pdf-bookmarks 5.pdf user"},
+ {$td->STRING => "5.pdf has no bookmarks\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->report(10);
diff --git a/examples/qtest/bookmarks/1.pdf b/examples/qtest/bookmarks/1.pdf
new file mode 100644
index 00000000..2003cf97
--- /dev/null
+++ b/examples/qtest/bookmarks/1.pdf
@@ -0,0 +1,1502 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels << /Nums [
+ 0 << /P () >>
+ 2 << /S /r /St 1 >>
+ 7 << /P () >>
+ 9 << /S /r /St 6 >>
+ 11 << /P () >>
+ 12 << /S /D /St 2 >>
+ 15 << /S /D /St 6 >>
+ 19 << /P () >>
+ 20 << /S /D /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+95 0 obj
+<<
+ /Type /Outlines
+ /First 97 0 R
+ /Last 96 0 R
+ /Count 6
+>>
+endobj
+
+96 0 obj
+<<
+ /Type /Outline
+ /Title (Isis 1 -> 5: /XYZ null null null)
+ /Parent 95 0 R
+ /Count 4
+ /Prev 97 0 R
+ /First 98 0 R
+ /Last 99 0 R
+ /Dest [ 8 0 R /XYZ null null null ]
+>>
+endobj
+
+97 0 obj
+<<
+ /Type /Outline
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Parent 95 0 R
+ /Next 96 0 R
+ /Dest [ 18 0 R /XYZ 66 756 3 ]
+>>
+endobj
+
+98 0 obj
+<<
+ /Type /Outline
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Parent 96 0 R
+ /Next 99 0 R
+ /First 100 0 R
+ /Last 101 0 R
+ /Count -3
+ /Dest [ 14 0 R /Fit ]
+>>
+endobj
+
+99 0 obj
+<<
+ /Type /Outline
+ /Title (Sandy 1.2 -> 13: /FitH 792)
+ /Parent 96 0 R
+ /Prev 98 0 R
+ /First 105 0 R
+ /Last 106 0 R
+ /Count 2
+ /Dest [ 16 0 R /FitH 792 ]
+>>
+endobj
+
+100 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Parent 98 0 R
+ /Next 101 0 R
+ /First 102 0 R
+ /Last 103 0 R
+ /Count -2
+ /Dest [ 15 0 R /FitV 100 ]
+>>
+endobj
+
+101 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Parent 98 0 R
+ /Prev 100 0 R
+ /First 104 0 R
+ /Last 104 0 R
+ /Count 1
+ /Dest [ 15 0 R /XYZ null null null ]
+>>
+endobj
+
+102 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Parent 100 0 R
+ /Next 103 0 R
+ /Dest [ 21 0 R /XYZ null null null ]
+>>
+endobj
+
+103 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Parent 100 0 R
+ /Prev 102 0 R
+ /Dest [ 22 0 R /XYZ null null null ]
+>>
+endobj
+
+104 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Parent 101 0 R
+ /Dest [ 25 0 R /XYZ null null null ]
+>>
+endobj
+
+105 0 obj
+<<
+ /Type /Outline
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Parent 99 0 R
+ /Next 106 0 R
+ /Dest [ 4 0 R /FitR 66 714 180 770 ]
+>>
+endobj
+
+106 0 obj
+<<
+ /Type /Outline
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Parent 99 0 R
+ /Prev 105 0 R
+ /Dest [ 3 0 R /XYZ null null null ]
+>>
+endobj
+
+xref
+0 107
+0000000000 65535 f
+0000000025 00000 n
+0000000434 00000 n
+0000000830 00000 n
+0000001035 00000 n
+0000001240 00000 n
+0000001445 00000 n
+0000001650 00000 n
+0000001855 00000 n
+0000002060 00000 n
+0000002265 00000 n
+0000002471 00000 n
+0000002678 00000 n
+0000002885 00000 n
+0000003092 00000 n
+0000003299 00000 n
+0000003506 00000 n
+0000003713 00000 n
+0000003920 00000 n
+0000004127 00000 n
+0000004334 00000 n
+0000004541 00000 n
+0000004748 00000 n
+0000004955 00000 n
+0000005162 00000 n
+0000005369 00000 n
+0000005576 00000 n
+0000005783 00000 n
+0000005990 00000 n
+0000006197 00000 n
+0000006404 00000 n
+0000006611 00000 n
+0000006818 00000 n
+0000007037 00000 n
+0000007140 00000 n
+0000007160 00000 n
+0000007279 00000 n
+0000007338 00000 n
+0000007441 00000 n
+0000007484 00000 n
+0000007587 00000 n
+0000007630 00000 n
+0000007733 00000 n
+0000007776 00000 n
+0000007879 00000 n
+0000007922 00000 n
+0000008025 00000 n
+0000008068 00000 n
+0000008171 00000 n
+0000008214 00000 n
+0000008317 00000 n
+0000008360 00000 n
+0000008463 00000 n
+0000008507 00000 n
+0000008610 00000 n
+0000008654 00000 n
+0000008758 00000 n
+0000008802 00000 n
+0000008906 00000 n
+0000008950 00000 n
+0000009054 00000 n
+0000009098 00000 n
+0000009202 00000 n
+0000009246 00000 n
+0000009350 00000 n
+0000009394 00000 n
+0000009498 00000 n
+0000009542 00000 n
+0000009646 00000 n
+0000009690 00000 n
+0000009794 00000 n
+0000009838 00000 n
+0000009942 00000 n
+0000009986 00000 n
+0000010090 00000 n
+0000010134 00000 n
+0000010238 00000 n
+0000010282 00000 n
+0000010386 00000 n
+0000010430 00000 n
+0000010534 00000 n
+0000010578 00000 n
+0000010682 00000 n
+0000010726 00000 n
+0000010830 00000 n
+0000010874 00000 n
+0000010978 00000 n
+0000011022 00000 n
+0000011126 00000 n
+0000011170 00000 n
+0000011274 00000 n
+0000011318 00000 n
+0000011422 00000 n
+0000011466 00000 n
+0000011570 00000 n
+0000011590 00000 n
+0000011677 00000 n
+0000011873 00000 n
+0000012019 00000 n
+0000012194 00000 n
+0000012377 00000 n
+0000012568 00000 n
+0000012778 00000 n
+0000012947 00000 n
+0000013116 00000 n
+0000013269 00000 n
+0000013438 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 107
+>>
+startxref
+13603
+%%EOF
diff --git a/examples/qtest/bookmarks/2.pdf b/examples/qtest/bookmarks/2.pdf
new file mode 100644
index 00000000..a7e01f91
--- /dev/null
+++ b/examples/qtest/bookmarks/2.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/examples/qtest/bookmarks/3.pdf b/examples/qtest/bookmarks/3.pdf
new file mode 100644
index 00000000..a1c0d954
--- /dev/null
+++ b/examples/qtest/bookmarks/3.pdf
@@ -0,0 +1 @@
+potato salad
diff --git a/examples/qtest/bookmarks/4.pdf b/examples/qtest/bookmarks/4.pdf
new file mode 100644
index 00000000..9d25f2f7
--- /dev/null
+++ b/examples/qtest/bookmarks/4.pdf
Binary files differ
diff --git a/examples/qtest/bookmarks/5.pdf b/examples/qtest/bookmarks/5.pdf
new file mode 100644
index 00000000..53a89ae5
--- /dev/null
+++ b/examples/qtest/bookmarks/5.pdf
@@ -0,0 +1,1573 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels 107 0 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+95 0 obj
+<<
+ /Type /Outlines
+ /First 96 0 R
+ /Last 97 0 R
+ /Count 6
+>>
+endobj
+
+96 0 obj
+<<
+ /Type /Outline
+ /Title (Isís 1 -> 5: /XYZ null null null)
+ /Parent 95 0 R
+ /Count 4
+ /Next 97 0 R
+ /First 98 0 R
+ /Last 99 0 R
+ /Dest [ 8 0 R /XYZ null null null ]
+>>
+endobj
+
+97 0 obj
+<<
+ /Type /Outline
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Parent 95 0 R
+ /Prev 96 0 R
+ /Dest [ 18 0 R /XYZ 66 756 3 ]
+>>
+endobj
+
+98 0 obj
+<<
+ /Type /Outline
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Parent 96 0 R
+ /Next 99 0 R
+ /First 100 0 R
+ /Last 101 0 R
+ /Count -3
+ /Dest [ 14 0 R /Fit ]
+>>
+endobj
+
+99 0 obj
+<<
+ /Type /Outline
+ % /Title (Sandy (Sandy [Greek]) 1.2 -> 13: /FitH 792)
+ /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
+ /Parent 96 0 R
+ /Prev 98 0 R
+ /First 105 0 R
+ /Last 106 0 R
+ /Count 2
+ /Dest [ 16 0 R /FitH 792 ]
+>>
+endobj
+
+100 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Parent 98 0 R
+ /Next 101 0 R
+ /First 102 0 R
+ /Last 103 0 R
+ /Count -2
+ /Dest [ 15 0 R /FitV 100 ]
+>>
+endobj
+
+101 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Parent 98 0 R
+ /Prev 100 0 R
+ /First 104 0 R
+ /Last 104 0 R
+ /Count 1
+ /Dest [ 15 0 R /XYZ null null null ]
+>>
+endobj
+
+102 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Parent 100 0 R
+ /Next 103 0 R
+ /Dest [ 21 0 R /XYZ null null null ]
+>>
+endobj
+
+103 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Parent 100 0 R
+ /Prev 102 0 R
+ /Dest [ 22 0 R /XYZ null null null ]
+>>
+endobj
+
+104 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Parent 101 0 R
+ /Dest [ 25 0 R /XYZ null null null ]
+>>
+endobj
+
+105 0 obj
+<<
+ /Type /Outline
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Parent 99 0 R
+ /Next 106 0 R
+ /Dest [ 4 0 R /FitR 66 714 180 770 ]
+>>
+endobj
+
+106 0 obj
+<<
+ /Type /Outline
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Parent 99 0 R
+ /Prev 105 0 R
+ /Dest [ 3 0 R /XYZ null null null ]
+>>
+endobj
+
+107 0 obj
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /r /St 1 >>
+ 7 << /P () >>
+ 9 << /S /r /St 6 >>
+ 11 << /P () >>
+ 12 << /S /D /St 2 >>
+ 15 << /S /D /St 6 >>
+ 19 << /P () >>
+ 20 << /S /D /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endobj
+
+xref
+0 108
+0000000000 65535 f
+0000000025 00000 n
+0000000145 00000 n
+0000000541 00000 n
+0000000746 00000 n
+0000000951 00000 n
+0000001156 00000 n
+0000001361 00000 n
+0000001566 00000 n
+0000001771 00000 n
+0000001976 00000 n
+0000002182 00000 n
+0000002389 00000 n
+0000002596 00000 n
+0000002803 00000 n
+0000003010 00000 n
+0000003217 00000 n
+0000003424 00000 n
+0000003631 00000 n
+0000003838 00000 n
+0000004045 00000 n
+0000004252 00000 n
+0000004459 00000 n
+0000004666 00000 n
+0000004873 00000 n
+0000005080 00000 n
+0000005287 00000 n
+0000005494 00000 n
+0000005701 00000 n
+0000005908 00000 n
+0000006115 00000 n
+0000006322 00000 n
+0000006529 00000 n
+0000006748 00000 n
+0000006851 00000 n
+0000006871 00000 n
+0000006990 00000 n
+0000007049 00000 n
+0000007152 00000 n
+0000007195 00000 n
+0000007298 00000 n
+0000007341 00000 n
+0000007444 00000 n
+0000007487 00000 n
+0000007590 00000 n
+0000007633 00000 n
+0000007736 00000 n
+0000007779 00000 n
+0000007882 00000 n
+0000007925 00000 n
+0000008028 00000 n
+0000008071 00000 n
+0000008174 00000 n
+0000008218 00000 n
+0000008321 00000 n
+0000008365 00000 n
+0000008469 00000 n
+0000008513 00000 n
+0000008617 00000 n
+0000008661 00000 n
+0000008765 00000 n
+0000008809 00000 n
+0000008913 00000 n
+0000008957 00000 n
+0000009061 00000 n
+0000009105 00000 n
+0000009209 00000 n
+0000009253 00000 n
+0000009357 00000 n
+0000009401 00000 n
+0000009505 00000 n
+0000009549 00000 n
+0000009653 00000 n
+0000009697 00000 n
+0000009801 00000 n
+0000009845 00000 n
+0000009949 00000 n
+0000009993 00000 n
+0000010097 00000 n
+0000010141 00000 n
+0000010245 00000 n
+0000010289 00000 n
+0000010393 00000 n
+0000010437 00000 n
+0000010541 00000 n
+0000010585 00000 n
+0000010689 00000 n
+0000010733 00000 n
+0000010837 00000 n
+0000010881 00000 n
+0000010985 00000 n
+0000011029 00000 n
+0000011133 00000 n
+0000011177 00000 n
+0000011281 00000 n
+0000011301 00000 n
+0000011388 00000 n
+0000011584 00000 n
+0000011730 00000 n
+0000011905 00000 n
+0000012258 00000 n
+0000012449 00000 n
+0000012659 00000 n
+0000012828 00000 n
+0000012997 00000 n
+0000013150 00000 n
+0000013319 00000 n
+0000013484 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 108
+>>
+startxref
+13801
+%%EOF
+
+% 1. Delete page labels
+xref
+0 1
+0000000107 65535 f
+107 1
+0000000000 00001 f
+trailer << /Root 1 0 R /Size 108 /Prev 13801 >>
+startxref
+16059
+%%EOF
+
+% 2. Delete outlines, reuse page labels.
+
+107 1 obj
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /D /St 1 >>
+ 7 << /P () >>
+ 9 << /S /R /St 6 >>
+ 11 << /P () >>
+ 12 << /S /r /St 2 >>
+ 15 << /S /r /St 6 >>
+ 19 << /P () >>
+ 20 << /S /R /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endobj
+
+% Reuse object 1 with the same generation number. Leave outlines
+% there pointing to a deleted object.
+1 0 obj
+<<
+ /PageLabels 107 1 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+xref
+0 2
+0000000095 65535 f
+0000016648 00000 n
+95 13
+0000000096 00001 f
+0000000097 00001 f
+0000000098 00001 f
+0000000099 00001 f
+0000000100 00001 f
+0000000101 00001 f
+0000000102 00001 f
+0000000103 00001 f
+0000000104 00001 f
+0000000105 00001 f
+0000000106 00001 f
+0000000000 00001 f
+0000016227 00001 n
+trailer << /Size 108 /Prev 16059 /Root 1 0 R >>
+startxref
+16768
+%%EOF
diff --git a/examples/qtest/bookmarks/encrypted.out b/examples/qtest/bookmarks/encrypted.out
new file mode 100644
index 00000000..4ad63b76
--- /dev/null
+++ b/examples/qtest/bookmarks/encrypted.out
@@ -0,0 +1,11 @@
+[ -> 6 ] Isís 1 -> 5: /XYZ null null null
+[ -> 12 ] Amanda 1.1 -> 11: /Fit
+[ -> 13 ] Isosicle 1.1.1 -> 12: /FitV 100
+[ -> 19 ] Isosicle 1.1.1.1 -> 18: /XYZ null null null
+[ -> 20 ] Isosicle 1.1.1.2 -> 19: /XYZ null null null
+[ -> 13 ] Isosicle 1.1.2 -> 12: /XYZ null null null
+[ -> 23 ] Isosicle 1.1.2.1 -> 22: /XYZ null null null
+[ -> 14 ] Sandy ÷Σανδι÷ 1.2 -> 13: /FitH 792
+[ -> 2 ] Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+[ -> 1 ] Trepsicle 1.2.2 -> 0: /XYZ null null null
+[ -> 16 ] Trepak 2 -> 15: /XYZ 66 756 3
diff --git a/examples/qtest/bookmarks/test.-show-open.-lines.out b/examples/qtest/bookmarks/test.-show-open.-lines.out
new file mode 100644
index 00000000..ea66669c
--- /dev/null
+++ b/examples/qtest/bookmarks/test.-show-open.-lines.out
@@ -0,0 +1,22 @@
+|
++-+ ( ) Trepak 2 -> 15: /XYZ 66 756 3
+|
++-+ (v) Isis 1 -> 5: /XYZ null null null
+ |
+ +-+ (>) Amanda 1.1 -> 11: /Fit
+ | |
+ | +-+ (>) Isosicle 1.1.1 -> 12: /FitV 100
+ | | |
+ | | +-+ ( ) Isosicle 1.1.1.1 -> 18: /XYZ null null null
+ | | |
+ | | +-+ ( ) Isosicle 1.1.1.2 -> 19: /XYZ null null null
+ | |
+ | +-+ (v) Isosicle 1.1.2 -> 12: /XYZ null null null
+ | |
+ | +-+ ( ) Isosicle 1.1.2.1 -> 22: /XYZ null null null
+ |
+ +-+ (v) Sandy 1.2 -> 13: /FitH 792
+ |
+ +-+ ( ) Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+ |
+ +-+ ( ) Trepsicle 1.2.2 -> 0: /XYZ null null null
diff --git a/examples/qtest/bookmarks/test.-show-open.-numbers.out b/examples/qtest/bookmarks/test.-show-open.-numbers.out
new file mode 100644
index 00000000..3680c2d4
--- /dev/null
+++ b/examples/qtest/bookmarks/test.-show-open.-numbers.out
@@ -0,0 +1,11 @@
+1. ( ) Trepak 2 -> 15: /XYZ 66 756 3
+2. (v) Isis 1 -> 5: /XYZ null null null
+2.1. (>) Amanda 1.1 -> 11: /Fit
+2.1.1. (>) Isosicle 1.1.1 -> 12: /FitV 100
+2.1.1.1. ( ) Isosicle 1.1.1.1 -> 18: /XYZ null null null
+2.1.1.2. ( ) Isosicle 1.1.1.2 -> 19: /XYZ null null null
+2.1.2. (v) Isosicle 1.1.2 -> 12: /XYZ null null null
+2.1.2.1. ( ) Isosicle 1.1.2.1 -> 22: /XYZ null null null
+2.2. (v) Sandy 1.2 -> 13: /FitH 792
+2.2.1. ( ) Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+2.2.2. ( ) Trepsicle 1.2.2 -> 0: /XYZ null null null
diff --git a/examples/qtest/bookmarks/test.-show-open..out b/examples/qtest/bookmarks/test.-show-open..out
new file mode 100644
index 00000000..46667ef7
--- /dev/null
+++ b/examples/qtest/bookmarks/test.-show-open..out
@@ -0,0 +1,11 @@
+( ) Trepak 2 -> 15: /XYZ 66 756 3
+(v) Isis 1 -> 5: /XYZ null null null
+(>) Amanda 1.1 -> 11: /Fit
+(>) Isosicle 1.1.1 -> 12: /FitV 100
+( ) Isosicle 1.1.1.1 -> 18: /XYZ null null null
+( ) Isosicle 1.1.1.2 -> 19: /XYZ null null null
+(v) Isosicle 1.1.2 -> 12: /XYZ null null null
+( ) Isosicle 1.1.2.1 -> 22: /XYZ null null null
+(v) Sandy 1.2 -> 13: /FitH 792
+( ) Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+( ) Trepsicle 1.2.2 -> 0: /XYZ null null null
diff --git a/examples/qtest/bookmarks/test..-lines.out b/examples/qtest/bookmarks/test..-lines.out
new file mode 100644
index 00000000..a6de7db5
--- /dev/null
+++ b/examples/qtest/bookmarks/test..-lines.out
@@ -0,0 +1,22 @@
+|
++-+ Trepak 2 -> 15: /XYZ 66 756 3
+|
++-+ Isis 1 -> 5: /XYZ null null null
+ |
+ +-+ Amanda 1.1 -> 11: /Fit
+ | |
+ | +-+ Isosicle 1.1.1 -> 12: /FitV 100
+ | | |
+ | | +-+ Isosicle 1.1.1.1 -> 18: /XYZ null null null
+ | | |
+ | | +-+ Isosicle 1.1.1.2 -> 19: /XYZ null null null
+ | |
+ | +-+ Isosicle 1.1.2 -> 12: /XYZ null null null
+ | |
+ | +-+ Isosicle 1.1.2.1 -> 22: /XYZ null null null
+ |
+ +-+ Sandy 1.2 -> 13: /FitH 792
+ |
+ +-+ Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+ |
+ +-+ Trepsicle 1.2.2 -> 0: /XYZ null null null
diff --git a/examples/qtest/bookmarks/test..-numbers.out b/examples/qtest/bookmarks/test..-numbers.out
new file mode 100644
index 00000000..7ff9e2aa
--- /dev/null
+++ b/examples/qtest/bookmarks/test..-numbers.out
@@ -0,0 +1,11 @@
+1. Trepak 2 -> 15: /XYZ 66 756 3
+2. Isis 1 -> 5: /XYZ null null null
+2.1. Amanda 1.1 -> 11: /Fit
+2.1.1. Isosicle 1.1.1 -> 12: /FitV 100
+2.1.1.1. Isosicle 1.1.1.1 -> 18: /XYZ null null null
+2.1.1.2. Isosicle 1.1.1.2 -> 19: /XYZ null null null
+2.1.2. Isosicle 1.1.2 -> 12: /XYZ null null null
+2.1.2.1. Isosicle 1.1.2.1 -> 22: /XYZ null null null
+2.2. Sandy 1.2 -> 13: /FitH 792
+2.2.1. Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+2.2.2. Trepsicle 1.2.2 -> 0: /XYZ null null null
diff --git a/examples/qtest/bookmarks/test...out b/examples/qtest/bookmarks/test...out
new file mode 100644
index 00000000..31a1cf45
--- /dev/null
+++ b/examples/qtest/bookmarks/test...out
@@ -0,0 +1,11 @@
+Trepak 2 -> 15: /XYZ 66 756 3
+Isis 1 -> 5: /XYZ null null null
+Amanda 1.1 -> 11: /Fit
+Isosicle 1.1.1 -> 12: /FitV 100
+Isosicle 1.1.1.1 -> 18: /XYZ null null null
+Isosicle 1.1.1.2 -> 19: /XYZ null null null
+Isosicle 1.1.2 -> 12: /XYZ null null null
+Isosicle 1.1.2.1 -> 22: /XYZ null null null
+Sandy 1.2 -> 13: /FitH 792
+Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770
+Trepsicle 1.2.2 -> 0: /XYZ null null null
diff --git a/examples/qtest/mod-info.test b/examples/qtest/mod-info.test
new file mode 100644
index 00000000..83cc3ba0
--- /dev/null
+++ b/examples/qtest/mod-info.test
@@ -0,0 +1,93 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+use File::Copy;
+
+chdir("mod-info");
+
+require TestDriver;
+
+my $td = new TestDriver('pdf-mod-info');
+
+my $prg = "pdf-mod-info";
+my $qpdf = $ENV{'QPDF_BIN'} or die;
+
+cleanup();
+
+$td->runtest("usage #1",
+ {$td->COMMAND => "$prg -in target.pdf"},
+ {$td->FILE => "usage.out",
+ $td->EXIT_STATUS => 2});
+
+$td->runtest("usage #2",
+ {$td->COMMAND => "$prg -key abc -val def"},
+ {$td->FILE => "usage.out",
+ $td->EXIT_STATUS => 2});
+
+$td->runtest("usage #3",
+ {$td->COMMAND => "$prg -key abc -val def abc"},
+ {$td->FILE => "usage.out",
+ $td->EXIT_STATUS => 2});
+
+$td->runtest("usage #4",
+ {$td->COMMAND => "$prg -in source1.pdf -key /date -val 01/01/01 -val 12/12/12"},
+ {$td->FILE => "usage.out",
+ $td->EXIT_STATUS => 2});
+
+$td->runtest("dump #1",
+ {$td->COMMAND => "$prg --dump -in files/source1.pdf"},
+ {$td->FILE => "dump.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("dump #2",
+ {$td->COMMAND => "$prg --dump -in files/no-info.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("dump #3",
+ {$td->COMMAND => "$prg --dump -in files/empty-info.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+
+run_and_cmp("modify Subject",
+ "$prg -in files/source1.pdf -out out.pdf -key /Subject " .
+ "-val \"Export Business\"",
+ "", "out.pdf", "files/1.qdf");
+
+run_and_cmp("add Subject, remove Producer, modify CreationDate",
+ "$prg -in files/source2.pdf -out out.pdf -key /Subject " .
+ "-val \"Tammlin\" -key /Producer -key /CreationDate -val 12/12",
+ "", "out.pdf", "files/2.qdf");
+
+run_and_cmp("add Subject (empty-info file)",
+ "$prg -in files/empty-info.pdf -out out.pdf -key /Subject " .
+ "-val Tammlin",
+ "", "out.pdf", "files/3.qdf");
+
+copy("files/no-info.pdf", "no-info.pdf") or die "can't copy no-info: $!";
+run_and_cmp("in-place Producer added (no-info file)",
+ "$prg -in no-info.pdf -key /Producer -val \"Obivan Kinobi\"",
+ "", "no-info.pdf", "files/4.qdf");
+
+cleanup();
+
+$td->report(15);
+
+sub cleanup
+{
+ unlink (<*.pdf>);
+}
+
+sub run_and_cmp
+{
+ my ($dsc, $cmd, $out, $fout, $fexp) = @_;
+ $td->runtest($dsc,
+ {$td->COMMAND => "$cmd --static-id"},
+ {$td->STRING => $out,
+ $td->EXIT_STATUS => 0});
+ $td->runtest("$dsc output",
+ {$td->COMMAND => "$qpdf --static-id -qdf $fout -"},
+ {$td->FILE => $fexp,
+ $td->EXIT_STATUS => 0});
+}
diff --git a/examples/qtest/mod-info/dump.out b/examples/qtest/mod-info/dump.out
new file mode 100644
index 00000000..a453f9dd
--- /dev/null
+++ b/examples/qtest/mod-info/dump.out
@@ -0,0 +1,11 @@
+Author: Yours Truly
+ContentTemperature: 100F
+CreationDate: D:20040212104653-05'00'
+Creator: Adobe Acrobat 6.0
+FormerlyKnownAs: target/branch/leaf/leaf.pdf
+Keywords: 40, 128, public, encryption, ignition, primarily prime
+ModDate: D:20040212112832-05'00'
+Producer: Adobe Acrobat 6.0 Image Conversion Plug-in
+Subject: Of The Matter
+Title: My New Car Title
+VeryImportantNote: pordofor stands for portable document format
diff --git a/examples/qtest/mod-info/files/1.qdf b/examples/qtest/mod-info/files/1.qdf
new file mode 100644
index 00000000..2b63f6ae
--- /dev/null
+++ b/examples/qtest/mod-info/files/1.qdf
Binary files differ
diff --git a/examples/qtest/mod-info/files/2.qdf b/examples/qtest/mod-info/files/2.qdf
new file mode 100644
index 00000000..63be2439
--- /dev/null
+++ b/examples/qtest/mod-info/files/2.qdf
@@ -0,0 +1,1338 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Metadata 3 0 R
+ /Pages 5 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /CreationDate (12/12)
+ /Creator (Writer)
+ /ModDate (D:20041221113239-05'00')
+ /Subject (Tammlin)
+>>
+endobj
+
+3 0 obj
+<<
+ /Subtype /XML
+ /Type /Metadata
+ /Length 4 0 R
+>>
+stream
+<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
+<?adobe-xap-filters esc="CRLF"?>
+<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'>
+<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
+<rdf:Description rdf:about='uuid:d8434ae3-1ef1-4c46-8276-e1d75853ad75' xmlns:pdf='http://ns.adobe.com/pdf/1.3/' pdf:Producer='OpenOffice.org 1.1.2'></rdf:Description>
+<rdf:Description rdf:about='uuid:d8434ae3-1ef1-4c46-8276-e1d75853ad75' xmlns:xap='http://ns.adobe.com/xap/1.0/' xap:CreateDate='2004-12-21T09:50:20-05:00' xap:CreatorTool='Writer' xap:ModifyDate='2004-12-21T11:32:39-05:00' xap:MetadataDate='2004-12-21T11:32:39-05:00'></rdf:Description>
+<rdf:Description rdf:about='uuid:d8434ae3-1ef1-4c46-8276-e1d75853ad75' xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/' xapMM:DocumentID='uuid:3cc807c7-0bed-463b-9bdf-c902541aab4b'/>
+<rdf:Description rdf:about='uuid:d8434ae3-1ef1-4c46-8276-e1d75853ad75' xmlns:dc='http://purl.org/dc/elements/1.1/' dc:format='application/pdf'/>
+</rdf:RDF>
+</x:xmpmeta>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xpacket end='w'?>
+endstream
+endobj
+
+%QDF: ignore_newline
+4 0 obj
+3154
+endobj
+
+5 0 obj
+<<
+ /Count 1
+ /Kids [
+ 6 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+6 0 obj
+<<
+ /Annots 7 0 R
+ /Contents 8 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 5 0 R
+ /Resources 10 0 R
+ /Type /Page
+>>
+endobj
+
+7 0 obj
+[
+ 11 0 R
+]
+endobj
+
+%% Contents for page 1
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+0 w
+q 0 -0.1 612.1 792.1 re W* n
+q 0 0 0 rg
+BT
+90.1 615.3 Td /F1 80 Tf (abcd) Tj
+151.2 0 Td (-) Tj
+26.6 0 Td (efghjk-) Tj
+ET
+Q
+q 0 0 0 rg
+BT
+90.1 504.8 Td /F1 80 Tf (mn) Tj
+102.4 0 Td ( ) Tj
+20 0 Td (o) Tj
+40.1 0 Td (p) Tj
+39.9 0 Td (-) Tj
+26.8 0 Td (q) Tj
+ET
+Q
+q 0 0 0 rg
+BT
+90.1 394.3 Td /F1 80 Tf (rs) Tj
+58.7 0 Td (tu) Tj
+62.1 0 Td (v) Tj
+40.1 0 Td (w) Tj
+57.8 0 Td ( ) Tj
+20.1 0 Td (xyz) Tj
+ET
+Q
+Q
+endstream
+endobj
+
+9 0 obj
+404
+endobj
+
+10 0 obj
+<<
+ /Font 12 0 R
+ /ProcSet [
+ /PDF
+ ]
+>>
+endobj
+
+11 0 obj
+<<
+ /APEX:Id (353)
+ /APEX:Label (1)
+ /APEX:LabelAp 13 0 R
+ /F 4
+ /Rect [
+ 63.461945
+ 339.112457
+ 525.003418
+ 700.653259
+ ]
+ /Subtype /APEX:Zone
+ /Type /Annot
+>>
+endobj
+
+12 0 obj
+<<
+ /F1 15 0 R
+>>
+endobj
+
+13 0 obj
+<<
+ /BBox [
+ 0.0
+ 0.0
+ 9.199997
+ 12.399994
+ ]
+ /FormType 1
+ /Resources <<
+ /Font 16 0 R
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Subtype /Form
+ /Type /XObject
+ /Length 14 0 R
+>>
+stream
+0 0 1 rg
+0 0 9.2 12.4 re
+f
+BT
+1 g
+/LABELFONT 12 Tf
+1 2.32 TD
+(1)Tj
+ET
+endstream
+endobj
+
+14 0 obj
+70
+endobj
+
+15 0 obj
+<<
+ /BaseFont /NimbusRomanNo9L-Regu
+ /FirstChar 0
+ /FontDescriptor 17 0 R
+ /LastChar 255
+ /Subtype /Type1
+ /ToUnicode 18 0 R
+ /Type /Font
+ /Widths [
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 250
+ 333
+ 408
+ 500
+ 500
+ 833
+ 778
+ 333
+ 333
+ 333
+ 500
+ 564
+ 250
+ 333
+ 250
+ 278
+ 500
+ 500
+ 500
+ 500
+ 500
+ 500
+ 500
+ 500
+ 500
+ 500
+ 278
+ 278
+ 564
+ 564
+ 564
+ 444
+ 921
+ 722
+ 662
+ 667
+ 718
+ 611
+ 556
+ 722
+ 715
+ 329
+ 389
+ 700
+ 611
+ 883
+ 722
+ 722
+ 552
+ 722
+ 662
+ 556
+ 611
+ 722
+ 722
+ 944
+ 722
+ 722
+ 611
+ 333
+ 278
+ 333
+ 469
+ 500
+ 333
+ 444
+ 500
+ 444
+ 500
+ 444
+ 333
+ 500
+ 500
+ 278
+ 278
+ 500
+ 278
+ 778
+ 500
+ 500
+ 500
+ 500
+ 344
+ 389
+ 278
+ 500
+ 500
+ 722
+ 500
+ 500
+ 444
+ 480
+ 200
+ 480
+ 541
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 333
+ 500
+ 500
+ 167
+ 500
+ 500
+ 500
+ 500
+ 180
+ 444
+ 500
+ 333
+ 333
+ 556
+ 556
+ 0
+ 500
+ 500
+ 500
+ 250
+ 0
+ 453
+ 350
+ 333
+ 444
+ 444
+ 500
+ 1000
+ 1000
+ 0
+ 444
+ 0
+ 333
+ 333
+ 333
+ 333
+ 333
+ 333
+ 333
+ 333
+ 0
+ 333
+ 333
+ 0
+ 333
+ 333
+ 333
+ 1000
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 889
+ 0
+ 276
+ 0
+ 0
+ 0
+ 0
+ 611
+ 722
+ 889
+ 310
+ 0
+ 0
+ 0
+ 0
+ 0
+ 667
+ 0
+ 0
+ 0
+ 278
+ 0
+ 0
+ 278
+ 500
+ 722
+ 500
+ 0
+ 0
+ 0
+ 0
+ ]
+>>
+endobj
+
+16 0 obj
+<<
+ /LABELFONT 20 0 R
+>>
+endobj
+
+17 0 obj
+<<
+ /Ascent 1098
+ /CapHeight 1098
+ /Descent -281
+ /Flags 4
+ /FontBBox [
+ -168
+ -281
+ 1030
+ 1098
+ ]
+ /FontFile 21 0 R
+ /FontName /NimbusRomanNo9L-Regu
+ /ItalicAngle 0
+ /StemV 80
+ /Type /FontDescriptor
+>>
+endobj
+
+18 0 obj
+<<
+ /Length 19 0 R
+>>
+stream
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo <<
+ /Registry (Adobe)
+ /Ordering (UCS)
+ /Supplement 0
+>> def
+/CMapName /Adobe-Identity-UCS def
+/CMapType 2 def
+1 begincodespacerange
+<00> <FF>
+endcodespacerange
+100 beginbfchar
+<20> <00A0>
+<21> <0021>
+<22> <0022>
+<23> <0023>
+<24> <0024>
+<25> <0025>
+<26> <0026>
+<27> <2019>
+<28> <0028>
+<29> <0029>
+<2A> <002A>
+<2B> <002B>
+<2C> <002C>
+<2D> <00AD>
+<2E> <002E>
+<2F> <002F>
+<30> <0030>
+<31> <0031>
+<32> <0032>
+<33> <0033>
+<34> <0034>
+<35> <0035>
+<36> <0036>
+<37> <0037>
+<38> <0038>
+<39> <0039>
+<3A> <003A>
+<3B> <003B>
+<3C> <003C>
+<3D> <003D>
+<3E> <003E>
+<3F> <003F>
+<40> <0040>
+<41> <0041>
+<42> <0042>
+<43> <0043>
+<44> <0044>
+<45> <0045>
+<46> <0046>
+<47> <0047>
+<48> <0048>
+<49> <0049>
+<4A> <004A>
+<4B> <004B>
+<4C> <004C>
+<4D> <004D>
+<4E> <004E>
+<4F> <004F>
+<50> <0050>
+<51> <0051>
+<52> <0052>
+<53> <0053>
+<54> <0054>
+<55> <0055>
+<56> <0056>
+<57> <0057>
+<58> <0058>
+<59> <0059>
+<5A> <005A>
+<5B> <005B>
+<5C> <005C>
+<5D> <005D>
+<5E> <005E>
+<5F> <005F>
+<60> <2018>
+<61> <0061>
+<62> <0062>
+<63> <0063>
+<64> <0064>
+<65> <0065>
+<66> <0066>
+<67> <0067>
+<68> <0068>
+<69> <0069>
+<6A> <006A>
+<6B> <006B>
+<6C> <006C>
+<6D> <006D>
+<6E> <006E>
+<6F> <006F>
+<70> <0070>
+<71> <0071>
+<72> <0072>
+<73> <0073>
+<74> <0074>
+<75> <0075>
+<76> <0076>
+<77> <0077>
+<78> <0078>
+<79> <0079>
+<7A> <007A>
+<7B> <007B>
+<7C> <007C>
+<7D> <007D>
+<7E> <007E>
+<A1> <00A1>
+<A2> <00A2>
+<A3> <00A3>
+<A4> <2215>
+<A5> <00A5>
+endbfchar
+49 beginbfchar
+<A6> <0192>
+<A7> <00A7>
+<A8> <00A4>
+<A9> <0027>
+<AA> <201C>
+<AB> <00AB>
+<AC> <2039>
+<AD> <203A>
+<AE> <FB01>
+<AF> <FB02>
+<B1> <2013>
+<B2> <2020>
+<B3> <2021>
+<B4> <2219>
+<B6> <00B6>
+<B7> <2022>
+<B8> <201A>
+<B9> <201E>
+<BA> <201D>
+<BB> <00BB>
+<BC> <2026>
+<BD> <2030>
+<BF> <00BF>
+<C1> <0060>
+<C2> <00B4>
+<C3> <02C6>
+<C4> <02DC>
+<C5> <02C9>
+<C6> <02D8>
+<C7> <02D9>
+<C8> <00A8>
+<CA> <02DA>
+<CB> <00B8>
+<CD> <02DD>
+<CE> <02DB>
+<CF> <02C7>
+<D0> <2014>
+<E1> <00C6>
+<E3> <00AA>
+<E8> <0141>
+<E9> <00D8>
+<EA> <0152>
+<EB> <00BA>
+<F1> <00E6>
+<F5> <0131>
+<F8> <0142>
+<F9> <00F8>
+<FA> <0153>
+<FB> <00DF>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+endstream
+endobj
+
+19 0 obj
+2311
+endobj
+
+20 0 obj
+<<
+ /BaseFont /Courier-Oblique
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+21 0 obj
+<<
+ /Length1 1346
+ /Length2 145230
+ /Length3 0
+ /Length 22 0 R
+>>
+stream
+%!PS-AdobeFont-1.0: NimbusRomanNo9L-Regu 1.06
+%%Title: NimbusRomanNo9L-Regu
+%%CreationDate: Thu Aug 5 23:43:46 2004
+%%Creator: frob
+%%DocumentSuppliedResources: font NimbusRomanNo9L-Regu
+% Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development; Cyri
+% Generated by FontForge 20040703 (http://fontforge.sf.net/)
+%%EndComments
+FontDirectory/NimbusRomanNo9L-Regu known{/NimbusRomanNo9L-Regu findfont dup/UniqueID known{dup
+/UniqueID get 4162059 eq exch/FontType get 1 eq and}{pop false}ifelse
+{save true}{false}ifelse}{false}ifelse
+11 dict begin
+/FontType 1 def
+/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def
+/FontName /NimbusRomanNo9L-Regu def
+/FontBBox {-168 -281 1031 1098 }readonly def
+/UniqueID 4162059 def
+/PaintType 0 def
+/FontInfo 10 dict dup begin
+ /version (1.06) readonly def
+ /Notice (Copyright \050URW\051++,Copyright 1999 by \050URW\051++ Design & Development; Cyrillic glyphs added by Valek Filippov \050C\051 2001; Numero, infinity and Omega made by Dmitry 40in \050C\051 2001) readonly def
+ /FullName (Nimbus Roman No9 L Regular) readonly def
+ /FamilyName (Nimbus Roman No9 L) readonly def
+ /Weight (Regular) readonly def
+ /FSType 0 def
+ /ItalicAngle 0 def
+ /isFixedPitch false def
+ /UnderlinePosition -100 def
+ /UnderlineThickness 50 def
+end readonly def
+/Encoding StandardEncoding def
+currentdict end
+currentfile eexec
+o4…>£ö‰à‡Ã¬`0˜šB‰ÆCTà£ÿ&5.
+
+Svî‹ik úˆœkA¦ ëÙ£¨7ñ¢F`üôƒ$àyJU4ú¢ßÊÀºNLŸõ·^¼§“
+ÈVöÙ.èÐ+´¢Y¼ÂÒÒ4Û³\ºs‰mã'v­Í½=@R3GIJ¯z°ÉvŸô®N1€§ÍŒdð²Õ°¾©f~žð ÷e:^ŒÑ/’:0部Ï(}æÄl^?ô¬ˆ¬–2¾-ª*Йu3KÛ65g*ß Jµ(Ø]»<ßMÓ¶»Áͺ
+Õ#!v'«Ë…ˆÕ:m(Üî^¾ä^¹Û ç ïòô±mzTG´ó9‹~^¥ê@ªs?;†V¤lñ1ë ¢¹`vóQ¦L¼aïÔÒXîìj¶p¤¾¸ô›êÌâ†`Mïÿ `ÔjïýQhì|?M'ÒÑÇUHÑêäçj=¶Î^ý+t‰í½òLÒ©u¿¸ÖŠ$£ÇV´®Z‹ ýÆ8=˜Ýh^I|ùR2Ž‘…š•šiTéMBí"² Ï,0\ ïm`Æ3ßõi6ç\8s'‘kÂ##
+h
+ æ·³•¬¼é˜yÜ0'ϳ¿°mdc0ßüXjr<‡ûò±?¨µ[A¯)µAQ³Í_&&SãÿÖ,z èô/’˜ÖW—ŒxDC?Ó̶`{‰4dKšNVh3Cø8Dù%3ËšÿJ§tàiqNâeÓÓ
+[}ƒi}“ðñš"Ž&`b·a)—Ð%v•nÅÒjQ}¼áÜŸª%œ¿ž¾¸ž]y¨ZìªÒ¨p¯žT¦æ0çD9‘(§pv±M
+6_rókß¼o÷%ŒßþÀ™8—Ÿ×G# 9¡–qöÁß<ê–Evy$„
+Iè#"Lbûþ:çT­Ì£*fë}tÊËý‚àgxÀ½yW¨ŸGûŸñxVVÀF0ɘévǦ>—;ê 4ò¯ÖwÇÅsž¢ßOüðEó©ÃÌhiåEº¢/17ñ¥±²YY$ãd5x:¥8/);
+
+ÓØ-°‰
+P–Ѽ+IEs›´PŒ›<Jõ!‘­ŒuïÍckäëËM v®Óƒ¨ zÕQ³N¼÷ŠwÉÂXÖþüxÀœ>7f†’ª&ûµÍÿ8òùؽO]ŠÐèÕž²ÜV}_ˆ2ôR•5‡É:8`”ĺ1îÅÅIŽ^Å8 £‰Rs¹L‰‹˜8¶ÞÏn$û4ÉüWf“î=p.‰ Õz|ÝìçU¸­¤ƒrî½~Hø Ö&žn¤×òãT¹<•å³EÉ“ì‘ÏßoƒmWàô‰ Œ2‹U÷¨_íѨÅÊï>:Yúož;-kGˆû¹p#Ùõçœd¬Ý¢0Že³E£¥Ñv®®0ÎFä!øNì˜]ˆì¹œ ë)Ä€8”êéýó‚ç¬8ìÝzKú•¶ËG¢’7uÉôpž©$ú|kS5vβâŒR*ù
+´mZ\ÉZp4ü0e ' f¢®‘¯…(#)B:ÉÅð Y¡±îвAì]rÛ›®ÑNUÁöñ£Ù <ÿL¾NÅÓ¢q±Žõ¯åWrÄ ƒ´¸+Å’¸0±““È{ãQi¢}”ˆÀBú“ }íáÿ*²ÕPª†ÒdΆ"%î^v“`-œøï—<[ª¦_ G¤€èÞ¾ äeÐÇNtœ]Ê%ê&ë9α©­å˜d´]}B‚W üÆlýv—¾æç8Ä—Ct#ÝÝ[ó{Ì·´)§±ãl{#é¿óŸèÖh{‘üUå‘S ésh¡Z3ÆK%æÊs—²Ûè¼±˜Î ¯ÎsWª|Œ¦”ë|fFýÁEäß=åw|±Â¶˜õžŸ¤x¼†HŸ'ÙG^aš––2]bϽ¸Ó÷bÁ*á±;çþþi½¯B´å¶€@3æÃ̾µàuÂT¦ ¦5GîIÔ—4uIwŽ âOÙ6QH0¼
+ÝÒ“
+ŽJ;;Ä¥úê#ý _µ‚Bˆ°‰´>.îˆyÀå½Þ oÍ ÷ÆÏ퇜‡·ÜñÙú¨ Í•².B±ÇQ¢” u[²Û¹5G âîqUÎÁ‚rœÚ×”}lô¨¶œwãÓã`½È£r`3dq„×&xwT
+ølÄRY+R“‰¤”—fÀÄþÎ}„Hÿ$4pm›æ1<úlÒ4eÕ†ª«¾J#0 ì,øé÷M„³ë^Ö~UÒÂ
+:j`-µ{ k
+m"庖Ö/²®x°B‹Fd8©ùÚªû ÅÓD[L€aÃÌ@ñ‰¡È&ïJšRñ’ü“»RîÇ,âŠCuØ`ªMxÌAVl¯àÞ¦QȈèÅòÖ\²Î®›%œµË# }ù‡AÊ5j¯k9†PâÖ‹?u&†[km»…Yý¹|¡d°Ñ
+sxôú6÷k®/£¼‰½rU„™Š³ ŽsçmëÔ`Ž æ6pr:Úi—š"!yÐàÓÒ–Ÿ„w±’FTä|`²_<êTÛíE¤˜Úº<ƒ ¸ìîdß°žC;:ûBœj9rÍT¼V\¨¸<ID”Ó;ÞÕ´…†-?`†çšÂGEU—Žjk£c.²c® ƒHO(FÀÀ”®K¶2FŸc¿;öÛÂdŒes
+8"ÜcÃÉ»–Á-õ(É^È!Ëž*eÂ8´Ïþ õø*^øÄ'”+>Zâo1EœT©/Ú’ÖNx¿¥¶ ]b¬WP¼ J b ¬0 `ò/ò9²Î¼CÔ·y{|ˆO${–9AÈ£Õ‘*7Í(þ•a¶F‚B—âQÜ¥ýÅÕ–‚€Hô ”Mç½
+×Oãõ´~\EfqÑ·¯ oÛoÒL9 ÆøóXQÙ÷ßCÄ0¿ââËÒS/ílAÓ‡þ\¹¼*‰®® †Óõ7…^IüŽÈQ“æløYü³õF˜¯¤G:E|â±õVTG78{ ï3õŒâ¸ã0ïÕ"7·Šû"g
+V3ÀTÜÏÁ/\ÂddAËæDÆV®Þ T³ÞÉ´éâÜK;Öªõ/«rØ-ʈêî Ô±¤®;:þ‰6Tò 
+¯$6âà¼Â}¨dúÏŠå©OéÕ/1‡ßÙå¢,÷¾—´Ú¢GÄFì Uqf€0YÆÈ9\°ŸÙdUIg=_>H‘jL6ŸPÈÄ—CcÙ4±}–ÚÌ+ö7ÍLæÖå +Ê‚ÀÃ>@<ü‘nzFUàô+š:©ÆÐ_ókÞ¿ðía|j”ÚGAe%úWÃêÌÓC^ž»Ô!Q>]¯R6Ùø áeÐàfõîßaýôàimÆÉœ:Œñ±_6.GZ€¯Þþ£Ë79Ùÿ­¦ºAf—ÞØwÇ?C›! 0‰4«‚ƒ‚,øRàÿÁiÉ+$…ÿ ÅMIA,p¼ôÕ˼~VÓ]‚Ç×-´<†5(Ûrñ˜›»÷ÇÛUo‚gÚÉhðTxm¼îdþ‹:ïu\equµeÒ´¢Q<s|†¾%
+k2ðJBQy—ÿ~Ö”ûyÍŒdÑß”wgôÚø2n´BÖæFì2£È‚î'ç4ækV"˜?ú9‹øçð oö;c}™…òbx=lüœæ ïNõû1dì9ì°Šã›ûjð«²êÑ ­¨(Gßü@ìvR›7ëã¾­qÉLÚÅÙy¶ŠàŒŠ£¾…u<~Õ.‹„Sg Ý¡Þ¯§ªË6kQß*Œ4½tâ7oèÐÏÒ;7éîðªãÔ^]¥k»z3:0÷ (¥. þ{TU³‡&¡” Dì¢t±vEau¹:o!矎·`>$`¡Å <­ó‡¸Çípï(ÓW„Ì.¸3Ë'ØS€Ü·® »nÔ”úXï˜^…q Xà7­4ÜÓÙQíÝè¥r•àø§Æ‹¥G?~ýÍ3üB±O$ïíGÒS·û{
+öÏCêǸR¦Gr…ÍßzÙú%‹Q+˜p…´?‹æ£)—;F%œ8€0*­+gÖ‚@ŸŒÁ³ûÜ}<qÛMX¨*É
+÷°‰2ÑÃ`/Åc
+GšŠ&^Ð Iž"¸ËÒŽÆþˆ’Èç4GÓ!
+$ß)ÍìWñŠ&ÿ*?í’ÇmYî=<MܯOAQní¦¬ã‘‡Z:y£‘=n“CQxˆ&^W×Uqɡ¢Se¨]Õ°y,«Y´8º.9Ìß³GŒ´ÕÛó}=bW± ílEƒËáô.Æ4ù:JòÀLU„1J©Y¼1¸±X˹yÅrª¶µ—þÏqœ_R€‹‡ž¶ ÎzJ+úrÝæð;ü/Çb}z7Ka8ïÿâŸÏ“­gêØ@ªpÉš|ïIÀxZ‚oß‹ûð'l!,ÝÀT9^‚Ú¼B|“BnF©l
+õ+¨ÇÊ©ö`—<ªä[?¾wm’Ž²tR^ÇŒ`ñG] _–…é¨øgxÆßtÚ$|ÇD²ãì.W»œ¶‘˜q)’ÌCË‘sê=ÐÁ¶Ú¿ËéJCö/¡Ý¾¤mŸ €QļU¥Á}x„; Dèq•ˆ™ÐþI.Í"F,'µâŠÐ£_µauì¢übêÚ²BøÍâ'I'fn­ÓDÈ+œ·Anš¨†’ªDÞ×á¤î•Ðù`„m(˜ kM:T6’ÈÅÛqÑ<‹£V¢I±iÔóÕ¾lÔ\ÌíÀ{ŸÆbNöt·‹ËFgã!ß![$ÀÁëƒk §Ú9(VXØÞåXÕncŸþ9æþ±Ûz`iŠš#SÏmy‹2W¢œ8rä`²·›šë°¶­¹^ˆ‘ý‹Ùž˜eæ¶V”RŸÔû#±>G­æ5y»`tì‹ú)qíÂ#¼«¦ÜM¿r}z¼xádô¿â¸š>gPsÀh 1¨Ï rAé Dª
+’AÐFƳƒ÷H‰Ãt^Ý÷ ›j&:€mVO¿oµÈªÜ)Œ³×7É—QSFûõVÐ=¶#?Þm ‡Ü#!x ~ù f£÷l›m¡‰@XôyuXÍN¶`éâÈyÓܽkºgÞGƒ¦9¦Ú‘éÐÒ uùS<–stÍ:tñ_ÒšGž÷[!š—?Mi 1èöâ~œLîzJ[
+ÎIÌC†/¨Ê¢+›q;l=‘Ö<èãŒó?ÅÕ’
+B,p%ЀDý§àmàÌ
+§@˜¼BâÓ? ‹žù7Ò¿§å‚°Pè ç8±c©wÙ¶R=‚í>pomƒ Ó|6fWáùÑ6$Q˜"AšœŽ¾3
+Ú»­_EÙjè“[²•U ~ydæ†ûž€bÑ»{Lõvòvß'î³2X²f–‰Ò‚ÁnSâ_~¸¦g†o‰3‹û7{|ó›ýÂI[¤uØL0ÈncüÝ$Z0Z9$óŒAÌsÁÉöh“ºŽãa¡à™½o["´òÉHl[¿ùŽóÈÊò$U‹ÐÂýÄŸ”á0üžð´\àžòp=bô )÷àh|àiÛœzN ý4n`Ïn²;Àõ6(ãTËЀaóUUål+Küd¼ÏjJ3(I=»b>òèæô.yEÞè:B›V;þŒ¦sÌX´Æ¢4DÂ7µ<¦[…÷­d!þYæÿlg÷²ZùŽ©ç–\N¾qslúsù‘jm‰ý‘³8ÿ›ƒ7–o×Ûi†zÔJDñn¥hkÌ©^
+OŠ?oóWÏÊ÷?•÷'úqïBq¡Áµ­‚ç÷„à˜–eí—mãa½we¯@Ô† ¾ˆ
+ûDóßý”•ê}MQ¨ìÝä¿°8®–0‘Ï\ªôf3R(|L{ãKùrFp`TÙÛÆ&(¢J/Ãk )NÔˆVÉXw²çTaÒ‰ fÄy‰J¹i·x­ I/%Ínt_2”ß–êÕó×kTÄ/^J´rð6ÓTcwÉ©¾Ü¹äÎ@t‰?‹yî^ïEÃ
+Òj湆ô³¤oòiª·.¼R#6!0騱®ÊÖ n{’@W´ÕùýAjÖ¢=H¥Ì\Ÿhpñ‘;íaá»»3`v_êÚŽïR1â
+µS‚EòÍóëÔÒ=\Žî)šdU2™ ¾Ü¨䔜º7ë <×CxžCR:œUQfÀ3»ÇäH¶ãYK……¯îè·Ñ¹Ì6„Á&\‘
+ò—Íî=©§Ä’n_Y\­õW,üäx– s~¿lÏÂî¯Iy‹—Ö+³=r‘0òÖM¶xÜ`p> (dLÓÿŠª kiÇð†ù&ºVÂUó8˜¤¢`P•g*÷Q„AFÇÚ¦Ý]y‚›Ìg¨é)iji¹ŠŽá)nïÄÌ!º‰aåhz«b3ˆ,‘å3’=?Ò ©òçËMRVç*6ýßšâb6¬ýêh¸'Æ¥‘ªö¾º$Ó7„xâ ¥Üw›Dç –#h÷ÁV‰ÍD1‡ÿ#O£…ÃÅÕŽ ¿üªæŒ*ÛZ\<ʨ6è²Ö%
+‘D í´Þ)ª^×úhX)¤{ätFNiÐPðM-\|1îQ]n3G’®ÂÅp t“È…›}`-¼!*õ²º­ÎužÙ«¼ì’{Û/÷Æçå°&ÐxíÚQyr{Tº¼ÉWÏÐG^µÀ·©PÄ ‰*¨,‡gÙÌ’t‘BUeöÖöCÝo„Ú¹cõ!1F‡”lŠçFø,ÅÝ’óõoƒî®°vR>À2)H¦–¥ºÐ­äl¤KìrvX𳧅ñ
+ãœÙô•'¬¿\õp¢MydÂŒKé{Rp1ªÏÚ½ÝÌÐ::q8°K¿ ùdy¯»Ù6ÎY³mÇWVþÌjG]î#C÷Üâ?FZüªŽ¨f’dE9•UX';î3ºî ˜¹µí©+àïpœ{­¿]bZú)’½¯´31ß a F?•¨¬Õ`Jæ£ɹu«]-…S|Ák|$ùÅî©õiñâ åzUoÑ[Tk¢£Jq71±r¿g+KùtÏ"ó@Ù‡×Ã2A3¦9ÂÔíÜ 8þ` qO](ÚƒW[SúõÆ
+q5]AŸY«Û\a⼎1Y:T¬ùn\‘Î#PÅîIðÁ=YÃq½öPçxû\.ß”V˜úÁgEù‚ÈÌNÛØñ)Ù…¡?4ÄâªÏà’*<Õ×ß4um›[–5`²×¦üs¶À²yØ–ôæ‡bw¦Hý
+ž×ñÝéÓ°Žµr²¹x%ôAüm9Œà_Õ~HƒoÇaËT¸°êÓÁÚ›!N A%ѹ 4Øâ! Œ¼>ÃEÁšÜkãýU‘qµZÏÉXdÈé¼¥,{žSÙDèƒÑ¼^`ÍËO<e:Ç×xOk”‘fãðUÛµ ²¥–©y 1ßß\Yës8磩}ðG‘.³ “¯ÖˆGâ²h|E¨ŸZßhŽõU³oM²eñN+ò Ð;À ÈüW€…ÜHÀ›2›îç3Ït?0¡-¦"E~s#žz!{ì¢O@¹¢Í¬bÜsq?ÂH»Ð‰±ˆI~ ÆîtwÄ? oÁy›’ÌÐÐ&b‰Ç¼ÞÅY¸*ÆS—œàrrëûN†{Lú®cœOj·’øÁ1 …°k¼•6Á}rTÿœ+>±7w(Cã2ŽB}¹M1û§ì<ÝO7´db¢*ZíU8Ô`ÓÜ‹¾ñ~íýÎEPÒã0âŽÜËNÕÎ~À@p¼
+Áòµˆ»Èó Vˆ º/寿Hü„?VfY„CÜ? §B]«W1 ¼Þj¬ð,
+ûo³.ü5ÂUsj”‡m¤lQ³êÅèb¿Í CTky¨u3Öºö±Üùl-/n¨†ÔøðvÜíL¥@‚ K΄mÙûQºí8D¸ÙZŸdÚ¹¤kÕsß(R`_Öx©‚Ý£%ÔÓK0Ê/ÌF«ÔAŒ¡?Í7‰»@I§fÙÈZ ø}¬@‚SŸ»Ø\à¿@<!«!évC¬Á,Âoˆö
+›JÇ]ý#€Jδښ€[•Í8ÌCÃTûKrT”0¥q›´ðî½WîãÉžâÑÒIý½,e )¨¤Ð…Cªÿtó†\½ó¸ž³u8£ºØgºaTˆBƒtÄÏŸÑXhí ¯(Ü*Òü¿,ÜPüìK]cÒ7mL!zzË<˜+®Að9>Çåu¹Ëmð¼ï ¬
+àÒ”Ó…-hrn€MågÛÓJÅé¬9hYþí r€@ùYἜ>f»”¥ë
+vlhœT_Ý#â,°%Õ|lxóAÀTl½çóqæ»”XÜmš…βz|j}oÆC›œv6˜øŸó[žc$ÕJ¬û"ìaï}Ùt›U^ØÈ
+¹A"£KDÃ%’ºµÇ
+JÕˆ¦IÚÝÕžzñ ÈÞë¯ß z+7FŽd#àB½êÅí¢ûiüé^í¾ëËA© 0ÅØL¤£6OÛ5ª Ûšja Xªo(-áÆü—c{7íUäÖYòè¦WLuꤩtuÿ›åm×Bt °T‡È°n1àWcà³äR€²\Ö-ÜÈ|‰?ìâ1‚5«½Þzmây—Oœ~kZzäðt‚
+Ü ìÃ
+WÞÒã&tøÐè$ÎFnýûÒ½‚±·³Ë׸‚ùmËï”ÊÉÁÔ­
+MòIÈáÒ˜ÛÞ”ÔAå;>ßg7Âä*÷]{ 9îF&ùtYu+íI+¸}ÛÈ@D_7žnéÉ.¯£ïZŒ¿·Þœ Å_;Lò} ^|¹
+ß0ô¦ÀãŽÛ9ÚEZ#‹»‰h}ÅbÙð€˜ÿm05Ñ*\1»âŒ¥@±Ö¼—§ßVû³Œˆ¶k›ÌòZÙ`¶ðç6à¿C1ŠÈsèâëwÂù~à*Ùp´Þã%{íñ‡t V¯u;ûwP“>-_¦ýCãW4(.…k¢ÇþUì4!ñmÐ>¨ovòÎI}Êéa˜õœÒ#cã2°t`?çÔ‡ÞÀE›¹t¦ä%ðÉ_°oÓ:n½RµYAɾ¸rÂ@&ÍÌŒØ$ä¼aÉ:{AÊÎß&ë®*•y }NôBù‚Q€SêÞ=q«U•»[Á”ŸŽsn¬c¢%&8äLáª0æu 0ׯj¿WÞªtÝÂŒ„ ~< ­DºEÅ€5ï»°0¬Ù÷Ù@Î%Cå#ÍfçÃ*)p³ñŸ´`‚ p”µñÙô ùèïßøL Œ+ßë ØJ"rpÑ?öyÆáÏvŸŽyp±óc¹èË_á†{|%f ÓûuZúž§±UûD0 •O1Ø°L0íœ Û´ ®À¯ 4ÒÇOMÈM)¢íÑ}áPúÆ_Û«cÊ;j™>®x{+u ÏëD䩦3hÁÔžsaÚXûÂošò2¾R#0ÅÁ >ã1<ýùø4‘‹ô­Qf°«F¼õê|¦IN$i.†@ )ÀB4®b^ðü\‹;©–. wíFT5cŒ’Yîôã6Üùð„D |+⩾ۓK‰ÉÂÅÿøݯÑU3’ÐiظH´\L˜7‹ #eŒäùT?jëžj5Rv¢v¨ ólðÑçAlö‡€zlþ!Žê—Ó–îW/‰»¥.‰óh+,ÜÐœ¨âöTSòDÊò'·”0¡è«EIcϳ‹L¸5É;üã[êŽß%Ni—óÛŒÍÞE±j9¶®ë¬]‰±ì0ÛÓ'¶L(­{š<<žøÄe
+ê0:Θs„"»ƒö\
+ß$o éDÙšb°¡ñL[ˆÑx4±¥D±/“t’\k)ÔCµó?ðl¢ µd'5¸Öß ‹˜Ä•&IBo½Fû´D>†
+`³’m=)žŸõ²
+&ÅÌÄ«cDsÈ£šÓ€ØԦȉ ׇ}ãÁÄ]¸oQ^J4P Ðßr¶Ö1Òt am½j”‚ßEŠöd\FH×jt!v%à¤ÈY=ép²Èƒþ`ó-“ï¯ïa¿ý™<¤ÉåŠÂ
+¸y€;_NF`ç6Ù‡îýF˜–G‚…1†}ÀYæv=CA­¦¦óUp³6·¾„1gtvªàL:昃6/‚§7»5u¤'ï\ÖéaõxÔ/º@¤Ÿ[ŠÆ—ti„?>Z˜êaG.
+OëóØÒŃ˜.¡–Î,É‚QëUH…>Ñ-ÖÁ½6$£svŸ.ÝV‹>œx¶ÅRGÄûçTh:Re¶ô!?ýxˆ!±L#Å¿<YCîM`’넨tmº½È@ÄÑkÛÑ~ JÂm¼+Îò
+ ‹üG
+µ*2Ãõ§ YvÓ‹é+çéÕê¦Í^.žr5ç÷Æ3(N'¿x뙨è #èåŠw,4—N'_#>¶¿>§*†­ä‰ù,• PôM0%ÐEe}G\”]ûž¢ÊÅöÍ›4öÐI´ãX¾oÎä’ÀÐ3±!KÝè±|$Ú§
+Õ°RñX‰6Ç»0í‰3@skO»HßæŽVîB÷þÈí#«Zaˆ9A8ð41‹”~Z^gïA¸3oã—)üé±<¨®y§Û—qe$Ñê,W»MÜêáœ@~8ºñ8”)mºVËiM'V`V4{ú3mK^žƒ-
+“Ö.Êwj*t¢M‡eö®NMI¢ë|Í”}Ø*ü'`š¢|=xDϳí@–´÷OŽÂO–Ëik±P9W¹Ëò1àLåR#GË÷¼™ a—E9i•Ÿ,Ð~°dú
+
+Ä% )C¹fƒ.AF´‚±¯eÀ…Šw{ÕhV“²iÈZ'Cê‘M}﵃êÖƒ.[¾óS:ŠÙ·Y­_3©ÙUÎÕYäˆèø›»Ñ_ž/Ý«*4+ã,FIwœ¯ßoF¢Ù«þ|Û^å±òhrÉ|¾ÄM›Kz<
+E({¯Èñ‚×Í"‰µ|ýlÿÁóp!2ö»sÊI åËØzeX‘ƒ¼‚ΖÃGh:¦^ÊóIeÓ½¡œîè$SLÁ‰úºS`¹‚~nÄDHH+\°2Îíá­2êÕŸK>³õ »£+ž¶ã<¡SëqÆæë_F3œölsò\hfßà)Nb>èewÆfþ)¦âª+ÙRñ Ç)ªõ³;© €´ Þ]qZÞoà 4ÐwäîíPÀD8¥óQÎrqý‰Û£Em…Sê¨TgHê0ÁÄþU\–‹-ÄŽz0ÞEl
+ ù_óA-CDÍ*µ°æIå”I }·ïy½×Ì–ú’ÒV5¹í|x=8*$ßIÁà ,^mŸ;ØOy¿·†'ýþIÆ,•3oÀ`%’´Æ°r ЕMTƒãÎiÈEN]  †GMÕÂÔxÛ* ž±º üjÁ+z²îóî–ʵÑ“Æ]¸ÇÕBð©øWw!9aE•þLÉq¾øÔ½ti€Š+ü7šH¡
+7.“ôª´BɦaapÅ\ãZ°ÀZÖÐdCï6Zðfö¸z+ãæPCw—‚ŽàgÙо1cE äLöa’ƒÚmZw°Ä8!ðDG×âã(a‘öÄd=âpR÷ø—Q½&‘VÐ:Ö ™WdõìµéÇœÊ)ÓyL^Ñ”Å%]ÚV¶fÚ½ ˜æQOŒèËg¼wÿ›<Àà­Ë0Ù , ™ ¸Æûø²¨M\Ã+TE±¥:§ .™bŠêÑŽƒƒ2¬}¦Ýzí*³&[­BCÉÔîË®a×êt™jƒ—ù3ùL[Tmý¹ÿ±öä>g”±’
+a6ÖáTw@H*ž¤cz,vÚdºl¸–0„ˆáÒ!Ñ´ôŠ„¡cÏì,áC—ÇÜXà}”±xç)»C*À•Ògv2nÎ(h 8†zñXôüU4§šrñÒú‚Çúù+Þtf>•#.¥êÄfç2– TŒÐuËÖÝÝ» òCÒÚ2rœðûßolâ+0ÛU æ ¹êghÅw5­¼ñZ+ ÐLÐ-`†3‚*wí©g(¸äÜ©øÑ£Uc ßög >
+AÑ´¶þi†Ö4UÖnm1q•,yÆ5Šb)‹ ßvÊ]?(fÂgûT‚ç …ÑO ?†Ù1G"Iˆ¢cíŠ2ŠN{M@ì¼4n<!M[}°¤`s
+«¶31& ^òG]³œ–ãŠua<†ñ*˜vNtœTsC"öÌ;›0)šô“,„¿7}#ÊPH*ã¯%)2$àÔ)޼ū:*9ã8yÐXhå1Cr%Ý«ßþ•®Ùñ̳‰ª¸O¹3ãÇÄ,[åtʉFÉeÚDz·n… ÿÕ[wÅ¢­,Ú°yQðáõ)Gž^«Ü”úŸ“¶úݧ`ƒõŠÇ´±¾áu€•Z¦}Õø–ô¼=–€ƒ8Uif¥ºÜÐ5S¥–Se6XAÈõÞ¡ð‹ZTÜZuÚõ¬\+“pIL¸šS°Ÿm°Ú^þZ]©$Ì¿ƒè¶ ùêmµ=æöÚÓ=N¦ ™ôͧû,Õ´‹™Ü*JJ¡0ÆÊ<HsðA³W÷˜rWYbì r`ŸD_t
+ &.ýÖÊ^Bn3ÚŽÊU“©x¦
+e;àSgä}&'C&{Ç­üÖY¥!R‡O|$%|H3bbþ¥9¤UkŸHy¤Forš"qˆ?¡`Ì8S5MQ®©›«nÝ‹
+Á@^¥¹×‰$$·¶¾y9>¶H[–š)…åùP_ZõÎhÔuè„gÏÒŠ··îÒà²ç™”¤°øçq<&˨ܴ±¹ aôcˆA†1RmÍ
+kf¥BÞ¿ÎÞ©´V·Hx-aDpJÓ(‡Ðxç÷Ü×ß4#ép>’;0 (fa ½ò¶RIMŒwë[ªª~YP®QlUçBõ˜±`¶¨ü5¸†³˜"•]ï縵9ˆêm—æ9†Š¿ ¡Ç"1ðÄè^$eË,Èú gÀãQs} M’ÓíúH ! >P˜ï¾S>ΚôÙ‰åIÒ»= ·‘fšÛÎX;=ˆžï߸ão4âð c<ÕY`B3¿Åú×:_€^úH౤Ps±ÖFTPyøn€è¨Ëûøû•d÷Ní· `h›f¬Þ˯A‹ëݸÖAÔ\$íP¿qÓ´
+ÒbXxÖ¨Ÿ–\ô*ª™KIÊ5hžÛ2^Oçï&+w1H¢:L0›cYE(€ñ|mæ!SLZV´2Åñ!Ic#qvÇàDÃ%–€ñ‰x*X/_Éy®Ë·Ä
+Ea˜È·A…aa{uŸ#Ì£!%š­X­¿[ÿ1=¿"{¥²ÊÆ÷*w\ŠiXª†€í£s'äè8ǵ-!‹F5¸þ{ þ—&0<òÑ´¯Ò6hs§þõö@xt”Š<c?Dt]‡T̽Š°Ì]ðÓ{i¾²˜yµûéÝ8U¼]IŒÒ*ÁúU®òÛeyT‰›òg¤ba`~°d÷×Ã;4•þã8(/FªˆQÔ%^'%4µÖJ^xUa Wâ^ ¿&rAA]èJ¸—ˆt‰Sd©¸€Ì“z-ŽðèGÿÇŸ«¤óí©(Ÿª c³
+Á$þŇäâ)²{2ÏÂr¾"^Ú‡·^Œ3ûà3[HÀm¿6‘M…º€¶ˆÀG"£[Í|ü.]SŒyœÎkZéc|±œÿ«Gë>µÁÕÆâgŘ07»nžÀ
+°¯Þ‚Kt4:,“¶EïÒl…®ˆ«|lFêwÂøb¼+È+æš­[ö+ƒ¦W¯gnHeñã+
+ì÷ijP‚,«ÖiUœ÷š'ü8e¿b‘7^(‹AèT«ª‘‘Ô}ö¢n1ò9¾ˆ<Q›cªYä¢ÝqÊáD_ ·õ›ZG9§×‘2E„/Ô{|¦Ë¿}ÝÖ SD5 œÿÿì”!]/lwœµ“³?8ˆ}ZçÛ@ž9ܸyEFTãZ–ÒuUaZëhs¹«‡ •v€aŒ’;«²ÅXÕxÁbI#Pw¨)MìbïÄ•l/¸_–|ˎѺÿÂHÎyc„¯·–§Tcp=h¦é±B¹ÿÔ-… Ó‹H$ËZ#~‰»ÌÃ3}t7ÄýÏcíg&ªâ.|b§§H¦<n*Ĥnïà—Ãt ÁlÝÛÅÎRmÞ_Øß×âÞ–ö‡ªj¡EÙØš–2Xë¨ráu˜(¨±‘Ïⶂ|î¾°×í?ºBÈ6±ÿôÓÓ¥Bf­Ë™dc’Ön‹·Ö•JÑxJ¾ßEµÌQí
+•å—½>•oˆNë!’f)pK¼…ÖÚ\÷ÔïºIÔyg{Ô“øB¯U#0‘9¸ÛL'&W³gF$<bV0wbÁSµjV£'c»-c½w? €ÖÕZDÇ‘þPÎÃ^5vA!FÎ…V/-Dø2g2Ÿø`zâ(Ž°Æ`÷ý|/醣BÈ
+s+#N|zÀQÊÍ€'ñ9^™Õp.·}zŽÀJ¶‹R LyªOÅéáªÅˆÓ†t½}.”ƒÜ ·kz§Ae;¬Írš“ÐÒ^ß@G»gÓ}ðQu–Tf‹ÙyÐá‹÷‚‘µ
+—&xf¤Ç¹ð ?I’˜ºsµÕÏ¡R¦ž5„$ô ss©¯(?Þž’ž çN HÀÙ‡ÓåAaÐoïÕRMìãFs½v1æ^çÛcèB©#!Ž>Ôë²= Uë€@~Ìeª®?Q[„/×fQM/ˆó®Ù G\¡ïlð´ÇÑ}!U_˜ÕÎÖHk)+4$AZn%†(ã[ê¿/¦º ÂòæÞŽKâ2ñ‹ÜÖ
+ùÇ¢kàÆIäþÎvo«ùLi¦t¾›ýEÇŸe“Iãl|áÈ>bS…ãŠpBa÷¡ú«*—“"A ÁÑ‚¿c
+¨ 2£öÇ2ø(UqÈ/äéK úµr>g
+Þ3¤¨¡6‘«Nç9¦ûÏ–mqœ÷r•â
+|®ŽˆK{~ÝB€Ô·$CUUvÅÿ)k. uÚÀ!z7‹\ì‰L8‰)‹]:L,Û Þ¶2e†!íå"d´BI×Äâ
+^§•\Û.ôgÍÍJ²?|EÐë¸ÖG)úØ뙳ÊÝ@j~ÐãÚJsÁ^ ¦Õ~âíÓ~¾å¹D„Ó˜ÀDË2øš~vèªÌì¬È³"˜ Êü²a)XÝ´
+ˆó fƒSÝS‡Â›ˆÆY½{ÌÏä(ù¸ŒÞ¼ñ”nÇt5 Ía¯èuœNàëbÍ€_Ö˜ü°…à‰!C£nŠ#}, Gú¨÷=æ3‚0<dïzKƉÝÔcÜlù
+€b÷º†-±r²‡¸åæIÚ,mŸL¼èë1é#pÚé[4ðÆ…¡‹š'J«Í% Ù_Ô]ø„S]$Õ×Pnµ<ë©*w¯V§¨ÞPNç5ê¨"6·ƒÕ»ƒ“ĺA…vUÂõ’†?LX—EtCµÕZ*rMÎCŸúnúÖëv £¦ºõö
+Õ tyTkoµÊÇâ”>•Â §ÎÖ!yXêúí,øÒoo¸W˜‘Cî´¾"¬ØÏÊ׬Ί›AžX‹Aïz|ln\“¬pƒ5ª¯Vä=iXjIø±!û4é6ºfÞMŠ¬ ­8?›MHlÐôÃ
+³‘èvEÄ„9»ºÖKœˆ¤ )ÜÉd;‹u¥
+¹î^æn9.™_½SI~¦¼áŽ*í–ú >2ëp0qäÓÂ#ŽÎ
+ÜŽÀœþ9é9Pèá’ñ8õ^;‹ »èJ´iR)¡=þh@HÄ B ù†pên‰{ޔџnÆQDE£ßôVUÜ)†Ø+Ô×ö)F-.©Ù_¿«Ÿj”ú
+î ZsAo™Å.Õý€», 5͉ò¶ò=èÙD„g¶–&áŒRJïÆï3±ôðÑB©?Ø›ìùT"¢¼º^vÆ—¢V^y[©­½Ð“•“ØÝP¯´ß‚}óÄ,G^ŽÜƒ3Da7«OXÊ¡M‹å¾a¤}j_s—%Íe äËCW½a×Ë–,N¦³—.6šÒ
+RUö+&ãj
+…!ÏgÄ‘›¾ÕÑT[”²jcŽа[¸n±¾ƒVA‚kG\+Mrèf|Ͼ|¶¾ì:,„®8ŽV8´­ð@„§guÏ¥%m¿ìI2‚E &Ù¶s–ÅäWô¥kA®ñCÉÞ¢Ìæ[FF·á¬ By±M`€«•vÊ®.¶Cƒ·'BÅõ\ÉÇêDqdc}ä¹0›k_éÊÓÄ#™‹ïxº9S'”Ô(óá‰î{¯d¥n¦âÓÓ÷1Æ}êÝí’~Œ¸¾Óõ¾(§B g\Ìçd®škøÁû4EU}Œ|ìÆ”ïIÚz*‚üó1xühâüÈÕÛÁkDÔÃ2îðÖ{“ë&#ך“­3pA˜c(Ö0 $Ôiű {ésì,+C_Ò%g‘zoz¥Ü²@'\ñ^¢M£Ä‰Ê[£Åáîjìq/Û_­7ü{u¹¢¤b^I –.©ÅV›³Æö®sõXãøv~ÈåÏÈ]íúvz ƒWq>:·Zo§¹cÈE째6^øƆBÆåñß<Ó "ŸîE¸Á‡>Ù7Ë0mâøÕ,¼·0‰ú+]¶Rn{IåE«Àuæô#ÕD ¤Nh6 ö‚ð_j 7L=û”ÔK…)YhÐΧ2±j³Fmt#àô?&íúéÏx×Rð,5xðÍŒh¸HRq%Øz>b.3;F> g#eL¶ü|áQiØ~Åñ™üÊ9g3qè6Ÿ³X­äõ¡}ë÷°f¹çÃÁíÛókü*wË]Kï.¬7éós}™C„ùu}Ecuê¸u9ÖHÅÓ'¡é˜Ãªê•ÄŸÑ:æ †/,¦à%…µVò—¦k.,„lH[
+ åp¬C9òðçŽ0²­9ŠàhÆ;-åÏ;13røÐý$U&
+ßW™'‘×JÛ™ç]µ·õ©3a†)»W?
+ßõŽm‰ë´HvõʱãÜmücƒw´–Re¡êöððˆÄÂ…•˜/wìP3‡sšMâÖ T×
+&½Nþk·G£ ·þM$³‘EWwlC¬M9»›’Æy çÛ®éFâ›…î÷K÷
+µjNßJà:Û#Ã=RE%¬+ª–žÚÌ›(uÏ”@;#²·ˆx«c¼IÒ¦¯ûG~Ï~Ñl~ µVâ‚êÄ{¾œîÜÃý¼0êõõo§ñšLˤ“¶ÂXŸ
+ÌQšû¹¹´#%œnáÙD{௱>}ZÞ¾c'7øo$W¼4è–úŽhQ¾ŽÀ¤² T®mþžš7ÈËÆá‹D}Ò_²hÉøA9¯UÝe3Uj(‚æqËš”d‘
+²8`×\æ—Nn!y–uܶ–¸k€Š[1·\6lË_…‘6¹Â¼\¶ñŠÒ¸‡,Ùå[.:åã#Ìïkź¤ë2°hJ)Ù7Ôœr4§?ÇðVßW./؆€
+Õ”Bx%o_`ï• ¾Š.v¤{íE"j೓eÏFŸÒÊA Pá4ºKµ&Ƽ\sƒ4œü‘M~-R¢ÍPñÕ`ïLS£Éƒ…:\-ò]ôë¦þ)¶c
+‰iñ%?KmFx€†vMª¿#mØOÄètõô•?RtÙÅ‚±C%CSyHdǪ!À¬ùwQOTb…ù˜+Zí,çÆ …»!3
+«‰‰ñëT
+í£ï¸y×jÙGÔ·#4!ÌÒ]zI=·À"Îòz¨E®@"»¾ ©H>ïµlbèvwŲÍ48©Q²…Ð
+ÿ”Š¯øöKb@ô!{¶ïE@<;€è+î§ÅbUárÞþ[ˆ4¼ü¹­"ŽS`:v-Ëbã É§l2 Ü51Dñu·”“o#,y»RÞå
+T̺1û¯wˆ\èòÔrécÄÿ•wê³¢H ¬&õáî­¬Û¹V=s øwS^°­!×0”fÈ
+
+Ûí]œq–îJÁ»%t•Œ 0Gÿþ£Úí¬!žmÝ2Uâà¥!—@RÇØø’‹TÈžŸÊ!lÜ3èÐ[AEÑå>D @Èò]°OÙáü2¾ô! WI;¸Vˆt;Ü 'Ç((ÌÛ¤Bõɼ'*!gíØÓñ•Žè$¥¾Ã…sQi%uÛŸ³9Hï‘Ì: ß½a>¯|ïcóûi¨-6ð¤Ü’ýGr‡lÙ’»k]ir ªÀA¿¿¸OØæg ÝCõØØñ›†^f¶ž¾ŸwWˆ®˜oKG8r¦Ÿš=a/cеWÐ
+ WEEtUþ»¼8z… Â_1³Ëå­ÔNè‡NTÞ:GÆüx_Ä#Ùä< PÂÈ·K÷Œð‰–3òÎùF ±¤ †ëÿ/ÌþH°@Ô‘=è’_áïv< JöXŒnyy…tEÅ Uj1n2ö{ÁNÍ+ÇQÑÌ™!êe:3p³„É.°Lµ¥1wEÍ 6TÜV•8å£8eÌÈ(,¡‡p[Í. ]硳u´É‡g]rºë®Ç$«2mضˆ ¦ž- ÿá/a"]ç´êOá?T
+÷ÆcÄUŽõ{Ê(nÀ
+UªQJ1]ï$tË×ñ˜B D;„],¨G'Ês2›vAªÔŠDW3†ÞösS0~¤Å]\™ðµ|ðúPðmË=T|»[,öŸâÒp—J³ûýîz3»A@Øã5Kióï t@‰:ËQWc¹ä|(ÏJ¾C›¥å—¦ÀñÀÝNvÈ6ÙVE=®ÄØÒG½—ûì†ýב³8”o ñŽ
+.wâ
+á\7P kÄ «øÿF<(Ü´aƱÃO*¡
+ë²oUZuºø-Ó¢e<úôë®ÈàÉ=‹W7ý_SòE©I ¤§db€1QE,ÂîsãkM2ùÃ"xööÉIKÜþ}JÒÉG°{A-+šÜÑaõ¤ùò·éã±Wø¾aÀpAσÔrÊkÿ,µŽ)¯†nÀ†«B¤j p8¹jChååЄ`Ýô‘_fþ0Ðð4.Zÿ ¸Agí/õõ,yÇ r*.$ {Ö`Ü0´‘(.Û¤ã$‚°*ìFÚõA‚w®¬Ç%š^ó“Ü÷ßSƒD›3¬žsP—µÐx®Æ ÈÈ-¸̺ÀÍ)«|¾ÐŸ¾z„S!ÖatÓõ&Cs‰EºfOÆâ°T‘ÊÙ„B
+§ö £N‹´W( é§ïªÿTۑሪ;ûs‹ÌƉ9‡6œ~kZzäðt†[’osÖÛç8bµ©uv5X÷ƒH¬+÷‹4ÖŒ
+ KÍxly·J—Š¡W»Äø QÛд†-øºû2Ž†7Í=f—d9ùúo'÷cbžï›Ú§Wð³ô’ÈÏx²Ðu×ìkÏ\åfIòOt‡ÙG´K?ËS€ŽEÈ%× pàˆ:Jua'Ìä=ÓQ3Kô™@ý{
+,vEˆ‡©J³-:Jy‰œÁ³ÝØbÓƒuãED»±_ƒ|¯Ô¢©SuåŸ4BÙ<í_›wòÉL!ûñ/¤<°{'‘}b‘íþÙÄ[söîÀ çe¿o+}
+õ.q_€ÃSo‚á.{à Ò:íÜhª.Eç7[³•¡ü¤’ îîÃ^uæCîSÌ‘‘åUÇ9=1ãw:£ã)F[c¨Žb™å?êÈï._23º™;õ¼;ÜpoçLÆŸ‹§¯ßÑvÌ‹ËüâÏ°Rö^ zéûì’Zæ=ë˜ió °S.ÜÉÛg­O\—/ƒ‡½ ºŠH; õ¦n,«° ÂzQãy«^þn–Õƒ)E-•1üŸôV$ ½[­²?A"¶~çU©S»ø©K
+ü…–&Ÿ5þ¸3è(–¡y9a”Ö“ßì j¸ø>™ Vâì ×£yÉ<’1<HM}+G¶¥#|ä{7?ÎeÂoÂUf/†Í%{}®ß …¹ú¸À»ÅXõ6^‰ñö3±ñÞÉ 2ÿ¼qnô#*VÍ“4„ßôÏàõ9ÖK@ô†‘hÍÎbÀ´I±GrÿÎLtzf‚ ¬&ë9ÉÓX|˜#O–럿z2¢kK” :¶GÓEÓT0®*òi1>3‹Îà5þ¥óÑ>ˆN²nÔß»÷ ìRãÑÞÏŒuè\Ó¶ýí€Þ§qÔAïCt–6rE:w‹*|LÎcúE¯>î×=Úᦂ|(õèĈiú¡Ó ÑP+Ïl¬$Ø»ŒcÍã3NeÐ ïÕ¸ë‡Z[„Åq´SpŽ©3c•ˆ:CšhŸ”[ýµé{B&ÜOkSE_ý_˜,ðWw
+f&Þ±ÉÍ’ŒÅ ¸”ÀÅõó‹_Z`s€E{HÛ‡Tª,&°Ý:¾ ›SÎé!l–2 ûLét䚟ò¨¿C«µ_ ÿ.Í®ìÁ•ô7²«^nÉÂZ# Yk7©–È°¼=¨ÂÈŠRDb³fµÒk‹*÷Õ°€|2Y0
+‚ÍC‘ ñšÈ‘øúëa"’3e4I.¡ŠS—¨ÎÁHâÕQjÓµ!ÊzÚ ëþcsgEatßù›]¢FÑR Œf,:Š…vkTŒ!CV)‰ïzÄ ß´‘I`8)ýMY_äIm*R|÷m|’ÍùP¨ÈSÇÀÕæ8W’¦5g ñA¿ ÁÃY¯Å»”¼9ŸÔº·Of]O÷t½F¦UûZ‰Ðž|¡§¾94$ôŠ[cJÌ¡Yïõ¾tmÛ%NJœGÿ0aù7ëCh@–øHk~““ÎÌ >Q¼fJνÓm`…ûbÔÉÛ\×±ˆ9ÿÉ—9Åï õ„¾ºˆŸ¾&Cëž1Ίҗ@iE}ø3ˆÉÉÃBÇ ôXZÿΈ”:  QÅ.3VìQº[ªp7+V
+2×ü±åT]‡vìr¢wÊE°ŠãÞҪʨӺ›Í¶áæ–>n>ДZÎ*”F°óŸWWG¤ÿó²u…E€˜O+{_´UI —A̹hº²§«ð_H0@þ@¼5©¶y_\àɪpbJâ8€ÒU0` ÚL“k­²^«²’ÕW^™zEÿ4£Ä³f÷§™§èÝHû@x/Dö0Èú¶ù%3ůX} •Äü:QIÞµeÞHXg,©0¯0uoôºmá®z7œJôé©uª·á¥®‡t¢„ÿáwQÕ$8½æMBùK‘‹‰¿ÿ+‡ ‡ƒ TpC¦Zs¬8áÚyy‰bàÕ7*änrRìÝ×¥]}eà~•Q4âîú™÷z¥†§úŒP©ä1¾:tÄy®K=å~-ï\SÅÆ“Ë—#u
+¢ôº[çV>—ßN–0LX&dIÿÌ:q˜>
+czNÌ'Àò}?Êx9Ü1`ÉsÎܳߵERà¥Þ ’y62"Ž#ôȹRѲƒ»#á²Ï:#€‡* rª¯T>Å ÷ü ®ûdÌC\ÆÙÛ´@‚âý±Wô™âýËUÁøfŠ©Ù_Œd1οZ [€sží…@Ÿ¹Æ·œ ^ÎÕ!ÌO1uºŒZŠøZÇøž¾ž^ÿ@žžb<ÁR<x)߀Pû€(7'ÙC)YQàð ç'üÉŠ™SWº@¤Pº*ƒ<†Ý
+-¨
+BÁåÑ=¸þ£¸üêgÉ.uÒ¯•oÒŽ¾XŠ@¾xl‡¨wšô²pPZ¸¿K÷ù gõÇZ6óÈ Þèãw(±
+€‹—/Ì,Î’ðÓ©“6´^:Ãõ´w±ÖñGjo—¾˜ª9χÖå”à4П a—fjK']€0ö‚öÃCgûµŸÑbø
+b·%óø5ÝÙÞCæ
+¯{Båé{æ÷>i†GÇþíùº¥û”²Žá?M9èÍã6êë nã´8¢ÁNª•}¢éìSט¼²- P@-j4,œH¬wK‚ÃvºU19ÞzücGIN
+ èS4=–ÒÐ ¬»¡cB⬴€Å¨°rµ’-y*j‡~õ}}ñÞ€Ø]iïG“ jyu~‰ \öl [ÌiÕ¹yÙ& J.=’uتŽY6M2 æ´ÕÞÏ0ÿªüì—Ài½äÓU1ëŒ&¿ @¤Y&OâéÈ3£ÉÖþ0%Ÿ Þ¶Ë ðÔ)ïI»& ú©P³í@çAPŒ–j¯ÓŠ¹™fþȉýW¶˜¡<{òyÒ^¬”øÝ;uË*c`
+cýšhñLvÐçôÚtSþøÉ›T¯ËBºm;|ÃYž‰"uæ±Ö9IS"2øShÔ£ •¥*ƒ%ª»``äФ6Û+Ç [ïk—÷{¢ŽN°ÉÝÏ¢Þ€I1”üõ­u×9ø½9,>“ %&nŒébÞ" H=Ö¨G¶ƒâ™4ÉTû«P¤©*‹ýF¼Œ5r+í8…ï°cÇÔ±HY5´¯,z(¾²t:f‰§¤KÃVQAóâÿ|(Í¿0‚£ó€…‰ãðÐüìÍ‚4wiÁÒ!Á‘ß@cRÞ‘³3>)¿;¹V£):ï'›B ô=Ù4ª
+à_gqÄþ’ö¿½o~n·çXZ>®­+ûv[*Üó.uÙí!!¡2GÄ ŸCð{
+Dú´W
+ðåx›þ&äŒW;Õ_®ÃfýC&-[7©b@?i†‡™ºþA1¾¶ÙrO%–C‚s0ð™É¥‡1ÒHN$œÅpìg) s†ŒÅÉI`=
+~1³Ð†ÝÍæûɘ”&fÅÁ߬Ù:ŠÂ¹jË™ÕF(0šôá4Ù?pJƒÅZÚÜùÁbm vK|²
+Þ_Ñ‘ò×_艽<1_-xÞQÍN°x06ßZóÌí\
+ãã¿y¡˜èX&‹ü¾5˜1iFúÓ¸ ²÷jsÜ:·x-¯–41Ót’w\Å­¸oPo¬<L’µÝ'RÙ`K:2>ÓÜCn'ktâ`ÜZÌým¬ÿrŠ->6lh+*l1t… éár(…çþJ¬
+wë»æ°ŸôªçÉ‚îzú;vÉRvS¹©5°ø.*K¶µ:T 1ã+냮KŸ_vkΕ⩴ þ› ­…Z’JX¦p•Í5
+ûs&‚·†#ýšõÿ$0d"…†—¡<‰>-‚©U·•=Íð[°ƒÉ|@Ðd²ª ~EPz‡¿p1øQÁ,ZÒÖîT?â¤óŸfÿ„Àñ¹N0QmfGí½Ù¬¸€Ä#`{ßGyêç“ÇÀ“” $Ö¥c ¯DgÂï®às$H‰³ÔÔX,Âçä²õ®ËbôÔöW§¤ÔØé5œŸnj̔!¹à`~?$‹1÷ÞUªpTxJÞìÅýŸ£Æ‹}¤Gà·í}$árGÇ<ššÌá.†'Иr(ÛôGMЮ³BòT¥ºÔ¾'_¡OUÉô'ÉúË–,(.Ÿ\" ‡ D¡J€(IS‚ÈìØV™q–«Bè÷? /1f__Êê!$ñ$Ö” ­‡ruÓ1&¹& ¿ Çër¹ÁÒs:ŒR Á¨Të¯Òl|7üü8¾ƒeÿé) ,¦¼az3ÃP:ߟj¦X1X98rýô|yàìŽÀÝÛ ±‡2°Å%YZ¶èÈ=a{zºº‚#:"a£ú7p>ר1r¤j“_»6¤ŽSyp#ý¹·²X½pù)R¿ôúŠªýW‡‚
+VMHîAõ•²uשd„Ú‡çËJ¨cQ³E]€†ea_LÓg*t¸J¹¢¾=ZXdÏy&ÇSY¤S”vÃÇg¯¾Ÿ]KÙc‹UÍÆBE£cûž…Š·wÌ”/2Hh0ù'æ'øjRfÇù&£¥ŽXwý¯É¸(®¢êz’î¹ÉÄ—‰ûÇ–Û/õ+?ý[{ÐÅɸÉmÁèszÈ?R›Yth ›y.s8«1i\_ŽŸ ±X³î&ÿ459>“²Ånj©fæЕ”°é³Yùôxù€^XBcÇ41ˬ{%Ø( ©|¡Nž1Æ*LÇòŪºW¡(ÔÃ|™MœÇÛô„dµ¯-&ém8zä`¹zUug´[$\ß{'YŒ˜ÿÉ»Ž=eZßOPÖ<ƒ½
+ÅãGµ’’IÊFëé{a aè[P¾à+ñmøDöoª^ØÚ ÕyIH†
+Ó·ÖtËìô.¢1ù)f?•ü6ƒ$Ǻ²4ç’8ðàFã‘÷óÁ@b=Gô2×ÿ;b^Í•ëœc*‹øžŸáýšÎT¦Ïm… ûgìèÊl1k«æ»ÖÓ+±-ïbh)Z,Ö­t2õ¦ÔËIòMì_°¿ã° s+©Ääœ^Ú‹¹}Š¥æebQ“ HsÔb_Ëc‰wBÿŽ¶›‘€ÝW‡DM€]ƒûæñz‰ø”«\NNÒÒ¯ª¶²al
+ìK*éΣ}Ý’ó
+˜ô(µônƒ‹ ô…QÖ
+¶—†(b³¹EŽ³_QR¿±~Ì÷ô›© vÍÄæ3XÖ3ã¾^I— >È5b¼iÒlƒ•x†H>Ú×1EÈ~ œEØêO÷`‡Å— ãÈ«á0ÎñÑPþÐ%wö²|ä¹wq=c;5€e)ªòŠÌÍ}ê_KÇeJóGø"Šz<xý¶!DÞú•X(ÛNKÏ9J…Ìò ‘0GîÙƒez<lQGØŠ2ë¦wœ]çÄ‘ŠÁuì…Ø".¸€UvžÂœÜZåjÐ4ü ®÷4ÍÉÅj¡¾P1,|ûÏŠžvçÓˆEܵ
+.U84ßz6ê
+µ^ÃÊó¡Kø¬MóÙ1Šzî ÉwHh½JIbäAm†°D:ÅlxU=ä¯ÖBÛ$>ã^ ºsv£Bš wsœ¼
+xlLâ#¾!«™„ŸÇe_eR;•–ÏòfC“ #þ“‰ÁAÝQß¿À²P3~’<;tõ†nŠªÁÔADQa¿íÄP õXÖš!=ºœ†ÎE ˜Fž;Íå„ËŠ=[VŒGÎÍ®‡ÐKÆ}ž3¶Ÿ¿ÒyO4¯Âž§Út›ý\ÐBéûg£xñ¨”β†HÆ|ìŒÞ÷.£E 4pPfü.ÉéçÛØ}3>V~úÓ+?5Yì&ÔËq¹N3<çÇ’C7[¡´·$«’8(³jdÃÙƒÈ{çiÎ¥`UðµZýxHiÎùá´1Íý/}µ M³w‚I›ñÁçžÔ½ØÒ cŒQóFpÔÕ—&õ…°ôÖ¹¼õÂ8¸nd˜ kšùJ“ªïãƒ|ÎC½Àn"UÀþìYÒôìùf¡5.xæ}ŸB`º²Älán3 pÇ_„Q±÷.IŽÌ–é±ÞzèÉ€¿g—_ùÏd}óûIäXI(™kßJú湈ŠŸ>Ó™ÚîÁåLÏ¡U¨î ¬B®Â4Ï[ÅI¨¦”: ^}Ã@¿Üºª¹X'–ÙdûÆÒè€:*$$2¹A¨–û¢Á”²0ÈŸt"ÂCUãX5;Ì~íð®'ÞAúÙ²Ôh²ÂîÀ¸öN–èn<‰q¦zEµ/¡(´V]w¬?8#vͱ!ï*ßjtª2c]âC^´¸]hyûÌ÷hAƒâkÑûÉ ¢¡˜Šf•µq£i௠•ÎµÍŠ±Ù8ëª8dÖ4sçWVBÁ²P8Û³OvZ­wïõIÑ64´Ÿ°4°Ôt…¥ž³Áºµ ú¡q– Ò8Â~xqP”ž0ª8‘Ç–în—àiÛ‡ÂV€ZyÐGa½åÛ"¹Ý…½•Üå×€‰‚£ˆg’œ•™PÅç<Ê<x ¾¶Ë€RŠŠ´³B±I|ÚÙmlmë“õüÖî³òÄxCÍϹ•Ã“j©g‹¾\ýθªyw‘½)­ ¸ÙЕ¨§éHv’Y…ø†âBä¾F_$ð]R†Ê+¸Ð%FûV©í÷Ìûuˆn=‡´»¢Ö^éÆV=³óí ,ŒÉá|`ÿE]&Nì›Sà\“ƒ&h¼Çó® º)­î-ày4OÀðxqë•E he’À[m|öîa‹¹EV$G)Ä‹QUŽý›ûp¢€¥BÅdù­nü-|SQ
+±4Xw‚/VU‡
+º÷Œ»&|@¸=ô§Õ,`´:Á¿šT²bÏVJÂ1
+D
+ÙJ_?z–L(\'ª#2s0šP?ÕÄ^wˆéêsA'™m2Ô˜¹çL¬Ä±*¤>¨­'UWhëT²à¾·'‹ØSÊ{¬–§©U77$“’
+ oŒÿ¡Ëp ÁµÝ¬"Újfµ³¬Ø Ó­¤»Ü ñWœ¾ùJîlÙAÓ]¯bøšgd‡w‰"ñrq¿ô6Šñ9éLä«/Ò9Çw%;=J«-b·3ÔF\-‡’*ËÙA§çxž’ñËU!ôÖ˜QŒâFi/™¿3‰9eÓé[²]C»Û‰ÍÍ­!Ùr{WG¿Ÿ©ÐÄ8”Û¾³s0Žõ{D`
+ ZÐ\Ð<þsKá4KQÌŒâ{_µmL£¤Qª™»c›-ð*ìýbïÀ¡Öµ'¾Ÿv؇‘¾½‡øS¦Y÷z5ù;dÂRæ ¸¥'ƒdù
+4àêˆÚkQùlÿÙî'¼³” o:Ï{Yd)7
+)E)åõ;¾1 dFÏ:kaÞixšù5,?{ú?#¥+ÚšÍI¹jOfF™§w¾á:ªzâίGoqÈ5õÇ»øº
+ë¾ Ôv86ÖVt¿2â EPe‘¢ûWqtXÌNå°i.ÿjɨÅùÐÊEßU À¿®Sš]Ì•5wãM²£ñHáÁv'C§1ñJ7m—¥S…øW.o1^à¡Gò#ê’ \Î+U7ʧRä>ðǦRMã2½ñ9€„t;bé8z+Nm0÷
+ïŸ
+Žï ÊD§z«曘×zZËÜx_ {1ú¢ ¹]§N•ãDñfqò6sã»bÇjú™ËzV @GÎí]Äþû'üïD>QDxÃýn„D²ÈT<×c¼xk¨ñAT6¾ê
+áéE²€ï¡çˆvÔ“´Ãë×=
+Ë3NJvQ
+÷ÿ\´’¸]¾_LWÞ:ÏâÍÓÑ÷?Óª
+Tþ›³s;µ#d8!‘Œ§¥4Ê«e|Jî™Õy¥ûú¤eF¶’Ù†˜ƒßþÇ1Nö¢?UíyOÑk’Kw)NöÿD0Ÿô+yM; §kSÕ‘ÙõE¬DÍUŠZ¯;ÑÜ®ëÛóöFçeŸWyò M»Dã–H㺭3RCnIe¤¨q5•?¶ 5ˆu­^¶§ 2圆š·±·2’·kðjvf·ÂôaÙ 93ÎæÛm‚g’}¸‰}jà˜ ÍN‰fopNâ-`qWåM1è2¦ñˆUýó¤9SA­Ý2f‹2
+Ùµ˜®FLowa°÷ÙX
+iÏVqþöAÔ¡ž¯Þ'úÐh)ëÛŒšƒ`—æx™ö$Ã…Á CàäÓ,8_üOdÊÇä×)Tq!"¨™(å2µr*ˆY—§¯Ì¢æ9‰f¢Ãòéê3B¼µUè@«¨×ÂØ.5ô¡æê¥îã­ãe|“÷RÚ*ÜíÆr•õ#©WÛeãcàé^°ûëâ6À]PS}#œJV«s?äÎR ¿R>UV‹¸ ò´ŠBÊ]:KzŸ¯|8éÌv“Rc@¸ûyúÉZ¹{1¢P?H*wóó†¶8ãĄ̃Ѽ¿nØö¿Ø4|“ÖhŸf°¶‚šÙ˜Ø«Ã ¿—9\ίD¨Âˆ»ŽJÜìÑöõ|CP¾¢Ä¿Ǽ¬ÑÞzúS»D³¹»à|-8îbèúÃ(”é ‡¹ä?E'c˜pÕÆ.R*TA*No΋.%ñ•dì"4Ç«Heíœ+\2aôϦÐëzÂ:Mh0j6ü¤{}$‡[@”Ÿd¹-ZÐìbEû¥#B0ÕuHd\_jL‰Ö46pjZo|k[p¯“•÷@K9ªÏfG¿ÆE¡C³Ÿà²r‰ze¨æO<”ö’þAð-Šö}{#\€9õËb‚¾ÖòA@¢½ÃÕÄY¡íömšÊ3A½yg®æ•gÎYRþH¼mÄ]¯!ÛRÑ@z>»J«/LOƲLUœÌdrù‹Ž—¬iǸÁ>›4õÐÏhôöØ\î”T‹|S#”î Ñú ½îD]k‘¶Ä6Ñ(~ø7ÙT¯‘„¶‡!¢‘çòWu°§%çµzæðiü´v[æ™ú¦XÇð;q«C·i‚’þ{žúáµàÃr&¨n6-óoµ|Í"Áª©ƒ*\@ÓÉf´Ë?jœÀ'úÒi:Äæä‘ã—ô¢Â­JÒœ<Jñ€Îù*òÁAš[ÆËA–á½Çý9 £LÖAšî\@¹çü¦… Mh´]>mâõA
+ŽÚZx7
+SîLü²¸ð€»-ˆuJ'¼p1^(Nv]Îß/Ú
+þzrÂb–e8m$ê6¡{"JžWÈNqq&½™¡°:Š0"™ß{5e´èc&X3>ÝŽí¶udÂÑP(ű¥‹s®霳`9è)ÞGã
+í/L%±%q&töÛáãR™¶é›lyCQ´ Y|ZÙj ÙϨÚVY-Nj,;Ü„WŒÉ$±
+ŠòøU˜?¶nêžä/ãåõ¯l«&¾üg›ˆ¥;òNÓ¦D-¦bI6ò)&ìœ ípÌ÷~_h^ËŸaeLå[ ®¯ø)×C8·Küäh ì¦^ ÑÁdB˜ç/4ǸÎòá_R¼§dqèà=N|jÑ<&…°êe–f÷ZŸ‚þã¾£É x+ =˜ØÔ….)Yˆˆ©]šÂ»÷Ò{}º&Ô\6û²JIÎý AlfUø,&¿¿Œ'IÁyZÐâžå€ {å‘YŠ»¾¼´u>ïk?Í‘L‰3&pÑÌ=P’Ô“4<¢²Æk£a½0’¡À…ì¶Â>ôEgÌ‘F°ÂÉS$e ¶E=–|¦PÃ0°SFAIÜj= 4%¯›†gíYóƒîeìeWŽÇøê1Ö5ÿëÚ?gÁøÕW».|ìE»"´ }ì'¤É œv³âümõÙ™ï’e ™VåÚÓ,€oä®Ù®fóÙ6r?för´¬_ÿxÇ<ÔWHÒFÏG ¼ä–Yùû V—jЭd ©HÄ‹â_gpMf¸ðE6H·PxÙ.··¸gúÚ 7êªRèœÁðPºsàÍzÙÿm²8Þš‡hOIt:U·h®Ãa‰)i‹9è.Õ®°bÏU¯i›ðUõ«~%ê"CI9]Sœƒ°©ÀÒõ7Ð= #fô+çÅyAƒé¾úú ¬éxòcf,ȳfdÃ"oÀqaG ×MkãÛéÅ6“+…cüˆøŽ°â;
+9`]ídjÙ¿ˆ,¡½Ê“ôOéwiȤº¿‘5ß
+Þ¢]I{ô”öb§#8‡ 
+ûúOU'²8²¼›+ÀeôŸæÞ i,@xj"t<0TÃ…ï0äm” Ô,fm%g®>{
+Õë±ÆáhÏÜ~Ÿ gÆ6šfVÛ‘Á~ ËU‘,Öº-¨<Ímíf‹ øñ„=–¯€½êuN @ÿÀQæ;|ܸg¿Cl@ó™ê@–B)‘/q>C•z ·à›¿’Xœ ‚ 5‘ ŒÂ¼˜›ôH!ë SÛ7²q#æRùŸòÚm„ñü@ álÀ ãó›óYr/c1ÂØyðî#¥%#“EX[‚–ªÓ™š†ß­jRO
+½m[aÁPsõ‡µŽ’ê¸NÌ*'y³zÞäÙ £]v]ÓGŠv6Ës„÷˜šŸAŠ:ïTʺ©þÚØ};¥zQ=Òy€c®Qù-©^F×#h‰Ëø@ ïˆÝÈ¿ÞU¥~X•ªü9ý†‡Y9¥{AžóÕÿªâxšÝg¼uà Fivš‰§1¸Ó ÿG‘jÑ=µÑ²ÔŽlëo:ñc Âß×cö¡^záL®ÙyÕdL]ËJÞ C±áPîïÆ,⬦3‰ÀáŸb3žÃ6 †¿àÜb> ìü«š¶òMYV}]$_Ró|ª1
+ìPÃëáîY’­”<È@5ž,_ð8,5§’¾í¼3|
+ ~ "‰öçôÛÕ—FùÙ²²T* Q+œuˆÈáŸeBÙY¥ë3Èm,{½W;ÑÂ%X%€1 êüLÌDqsºŒà;uUër/Ø÷ÜLh Ò½õ˜œ³ ˆ™ÎtrµYîÂG¢ÿ!<¥}(2ózoFXpbŸÑzÕ^Š'“iŸâ8ûLGxÞÞÒhE€³(öÄƽS¼JÅ¥ â~ ÁðÌGƒP­Á3!…S},6Á¤ûð&Yô”vQà‚Ü:jtÀ5!˜`b]{»×;*[¿cQY%Yzþü>4lISD|çN'Q€q_ÏþŒUòÁLµÎè@I%làŠ£ÚŽ¹Tu(X,¢ÈKß¾aÄO2ÔFàðÙÁdžüYaþž§d± ¨¢…Iþošg¯¿g î`p·N{kWš(¥û˜EY^=¥œ]DžQ,åÏšØnâµj|¤{<«2%ýý—\—&}@æJë³pˆãñ~=!ë²a8B˜K/Ey†#n¶
+tQ´’™ø°ÔìÝ‚¬y—<á Á–2íYJWOGÎâ¶@
+çÜwZ
+2èTßô &£êOlä|²(«tOLÖúTæ[yÙ‰¢M[AJD5«2»¤v{øàûÑÈG¬WÓ\ÊK+I“ܽ†:ªyjgïƒÏÑK>tœö¿‡YÀÄ ãÛõü*q wÆg ªøY°yjº3Õ`êÈ=O¸ºcü„ŽRÍSÑXíÙÚƒ
+w¢2K „ÕIøõbÅ#™Ui<MªµÐh¡ ØKøã¨)Œ«ÄžÖb’„]·­²‚GC¨P_Ú•º‰ñ ÎæàôiH6å³é ®íœf™tU•ŽŠöù…Vr$¡75­7§òKº3ë%µ…£ š¬Ï RÕmV¿)½§+ $¢. MetÔ )hÈ·g›êa9®]7®3L-ÃÔ߉ÑYœ’Á€‰kGòyœ
+%A»{+HxaÐãëY7ü$C¬M,|µ¢ïWÕN^ô ¸tðœ"b:ðg°’"Î74º²­·£†ð¤^mäõa©žÄ³|ý66ZG–<ý˜»a;x|[Žî»Õ繑‹ç?à/B\KL“ÿûñ
+-…8\F7Bäòf`¸cW#¹R„gc\öÕ€%ѹ×F÷½dÓ ‘†ŠÒ™œ¿ßðé›t±_€ÍEMÀ8¢Äa$ϬîdhUQsÓ+A›—éø¤¯Ý?ÏÚÖøìS·*Ú?ÌZWŽøƒå C?Â)m©ïOz~ÀÂïíú »e6è*Ç4×6”˯ވ¸¯ÿ~ªÍ ÷ŒtSÏ3Øä¯|l̺ϣþøôàÁçnæÛí© µëó…Îø<ˆÚ›ðÒ¥ún½gÜ™™
+%_5hiT[ÛÔþNR§©•šíåRœ¢0óJ k«¹˜IøøãË”«ÌZPÈ Õz€–ÅŒ]y$ß~2d}ŸF¶†'â\,`®¿–Noš€zÐX®…Œ,uM$[a»æG7¸’EÑ4
+”Œ”/#×ôÏ|‚SfßÂèÚbi´ÓK#°]ë¨!dá>%K)!|fôâúbqAÝÒ Oõ¤uXz<ö±Æ õ—óì‚lyùôœË
+¶7íâŒT5§:µ7‡–UK~é²³a,DG^À§‹¸}ÆÓ¹G˜9”/bãYgÆíázãSeñrµâo„@OúB gùüý–5œ¦Æ*?0Ô¾¤Êî>ГŸHÇî}"rÅÀWºßTÒ‚
+J9û à½Ã™°ËÌrOwc&ø
+`
+Û&5…³uü„·ÿo$¯Ïø[Gÿþ‡¥í¤` l™YÔî{Aál
+à‹"7d»¡éÔdàg¼ßú ÀYÖI<"Ø×^) D±l«sãÁ×ì¡,ßZ%c\_t©\\åáÅI3­l𷚊±óËY 4kM¼æh”LN­j.aĽŒÚ Œ™E¢} 8>êÙ§ŠÀN j¡`n¢T?©¢]‚‹EEéØ}Qêf•ü˜q-Ìj¶oœuövNœ×l„ê«Ó³ÜdXœ²¦ û@‚Äz1ÜöáörÐUs¢¡\[®ƒb[Btä·)ðVX³óð;%§®x©^³ìA›ˆz†z?£IÔŽäDh,bQ8ÉU2û÷åž¼›­ÉC ¼‰ Á{}˜ãʈ_ÌPŠÀ³ñƒÎŸ8¸n4Ÿ°±;£oíËú¶ç’™ÁeÂägŽWú§N½Þfâ•¢¶Êh&e½í­z퉿ƒù)¼-‹»AÅ\GGb í½áä÷ ]a#x¶Á'ÑþÆ9!Íl *¦ÄþNáñÓDiyV\<ƒf5\À$;+;ë³Ú!(#œž¡×Žb} )X£âbT¾ŠÌ–UƒÚú蔋A{<›÷Ì]&ké1i®ƒÞîºÊ$8÷͇M1MáŸmƒÒ&‹Å>*iYk±x·ò1uÝ0lK²ój˽qY´½½Z£¸"Çü¹SäF¸è×Èu˜ßm³cöçžSLÔ~Â\‹#Âg[?«²ž™aÜÅÌB¥ø}íwWIQUñõ¦ò°PUÂ=¼ùä95?‘îãÿg©qB“/˜èø¯†¹XQáK´~Ù‚™1˜ Ë´¾­í'œ¶ê¾~à ‘ßtµÏ_á×Ï’Z„«ò«#äÞ¶D#ØþÜ_™·žy‡>L'-³PJ > û±§l²•?»BùAjH®Á0&.Œ2U(Α âi¡n)¡6¦?_B×Ó Ýrr¤y$ Óçdfˆ5ìÒ¯m憜5]¿ÆAŸ[ 0&úᤞF¥Ù.ç^‰½yé » Dw¶ìÅzÈJÁ·9ù­I”s!L­ZC#€7‡¿ƒ³vm
+V(ü†V?õØ\t&UÕ¸yïŒ.&kûÀãW»Úä”ölêCñxcü]º“Íß ;éU<*²œK`2ò©h *“ºÆcSQ§©'½Â[÷ŽÄ¾@ø"º&Yû;ÐþÐÌjÕz<1(¦È¨©Ïx}z7n‚0]>íâédAaMŸÕÂKš9ód8Zà…UØ‘ÇØÇ`ŽY¬:ܶÞ½ˆ´Ï_áhmó¹e—åQ*Œ•nwkù²2 ýÔЃ¼B’ˆÕª¨ñã›#ås¶У¶:,cây‡ëÇ~¸1…"èÔLmU³?×LdgtE¾jHt îL¡…o¦Td&¦å~sJ±øÔ)‚w§õs7v Á€iîÆz˜z]o‰¨„†¿ß9ßpµÙð-´$u]?$"->¿‚µæbæ©fOùA{ŒÊ f5ã´œÕåû¯HÒíµ•ûµŒRtZFB>+Óˆ˜Õnò0ÖVtùkVdTÈ•33òa¹Г mH.ÿ3€ë/Qa_¿0ˆklgÎ{Â¥´\õîÆ­‚GãT'|k4Fúì)!è÷Ÿ±d£AG꣢Ú=Î?#‡Œ;¿Ð;ëšRÅônÆà8Ìé!ç02c=½ï™èœ@ŒñÆ?kDVºá>“- ù˜¡ø©9ßba›µ€ØÎ|SžÆ™¡ QÍ«æóeWüãYwÇÌ“‘ƒp¡R!ö™Eé‘ÑKÖ*‡™•½Œ¹ÿÒNŠ‘[1EýÍ*•Î‘îiòÁˆê#¤$vÌ_æ¼ik¬·Å
+-…µs:9=—}Dü§ŒlÎJÌÝSˆRêŽüûŠW
+qUÆ?ñúiŽòQxtþÝ¢´àé+˜Àiûb’iP)ÌûÁ×È9QdÒ{p™…„™žfäw#‚GO/4¨8ÑY«ë90µ·RŶ´!NÚÆçüeþ»ž¶…R™­X
+|°üZw<Îb8@ŒÕèH¢
+ÄwÚ0—±ªç©†ÉÞ&×?¤T{s=ñUÑPi|Êû 1tHËûkªÉË¿T¢*ñ˜&°ü¹¾ÄF¶2ž+ú§@3z…5¼”¤ƒì3ô*6Kåªv'þ¢Ãz­')ù“€†ÁáÄ8¦·q>à¶P‰ð{÷$Y"GˆËsw¡(V@ŠÙ¹:@ ¦.&’Ô†“쟃å SŒ¿Ôï ù-v$$߈NfTÒGQZÌ%~c­]»¬däÐ<ôÎ6òÞ!ˆ”å%LÖBÔEV ×%Çp#†(ÖÐÝ}ïg
+Müt$žŒ#3¥„ñ, 9÷38`ŽŒÈÿäÅO«þ‰†¢6r*ä@)yKõKVè4Ù]zû®)ÒŽi2Ó„äô›Á™™Áɼ² ö©éßx3k;X q.aØuê©f(ª2 c>¦}í•F‘˜I:$u$fB8Q,ãWG¨.DÐG¼û<࿤Ž—´’)½¾
+DRCr4·+éÕÜèÍøWñ†Xê¼bu<gò4Ò3`äð Îû¹USÇ=Ð& †@šMV¨õ7GaWõ ‘}}ñ=£8êà@›Ôït¡ZY+¼/mæ°
+Uäƒ=¯Qs(ÇiêŸÞª l¬ŽsV5÷F*¶BýûèÛ9
+­‰0%E‰¯Ìv§¾y²£béºWÔ—å̘,$zßÄgQÑÖ'جr’*2…’ˆ<ã‘ïU-€Œ@ÿ0ë}Aª7R §©°) Â@¬§y8~d…Í)0ÿZuxüÖ/ÅpÒNï<î­ù
+­O¤[BnQc?ÿ`žˆØk¥•â¾
+
+)³”ò‰¼âl¢KhN?÷ª'r‹n0ÝTÐ:É6æ‚OÝLâh5dX’p+UŒÜÂý|7_ÉñMõ»¥OköÊÑ­ñZcƒäÐtûÐ…›…±ÞE^VÜ!
+Ý/
+¸Œn4žŠ›¬kãøÃgÒu½ã%%Oäú/^3GQË]R{ø¢® 4Þ›‚ÍìÁ§ÿIñATÕL¿º†Ù»µY»1J©`–æ_¨—®ÎêûŠè;–ƒ8<ȹGŸÌñî7dÆvÞj¥ÐDO‡ˆ ÎdîO1z S]ÂZ–‘ âAwvÂ[-ö(hA{¦Qjo½2äR¦öD{¦ŠQ)…‡“èN¿7§‘<H‰Ó²7ùfÞ®iÔ‚‘x.þIt/&<  pï ‹1ç —hc‰•¬²\aèN˜O³á¡Ü/.—ÖÀÉ8Q¸pm“Úíóšj½› =@³€XAXÇo¨DðPð;p&g·ˆðßàx´J{ú¡bí…Ê¿
+âmÖåI°œÁNJû“.þ´'/ÏgF7‚dj@ÅK^
+e TOw¼>üÀm
+´ôÚ#2u_Hv)æÄ….Èwd/T-íàäâþFoHŸ¬X¬„\"U}^§GÙ³XêÏ4ÎùMEëpÅè´`1ëvïتÜòi önEoÖx½8•X›N”m‡A=XéÕ8}òÓL|*Gˆ)
+í;ù†ÿåþ¦#=5²FTuDõE‹opó€äNašvìFp`_³‹uÏzBRúéÿ˜üdxÙ|ÙîlˆD.¼í«ê6¶5CL'gmzÐmpœ “Ð2osÈ,C›NÜsgìì‡oH4W*ŒpR’ kø¼—?õ.–xjÂ*àZ“OÉ»½QìqöG>†.ø… ίPI¤±€0y%/'OmUtR>&yI$Di©uK¤
+wíÏ ›~)¤Î'Žq ż;W.†kÏÖ·hVÉ´Ù‰GJTWiÕJI>äúQJÒ!. £iAðÅ…û˜Ï{öõj„Ñ`u$»gk®êŸ–ž'úâ`Tpb-éì…V"<+½å½{á{-ô¾Ÿ_§§bßWÃKúá,k>Ïp^ ®8¨ç'amc#µQBá⃲‚(8•†èäÄ~¤ÂQôñùA"˜&q(°¡6 „ÈV5·#ˆ9·G†1ÆÂàQz&%®2߉mhSÔ‘V©bi»í?mb‚?ŸÖ‚ªÔXsë"Ç–}»ãŽ‘ÙPÄ°+eìÖ\ÁöÏh{âF>øµ ™6›ãn|ɃŸæ{af;jõ‰×¢ö6ÉÏ^ ™öˆ½U|)Ég`Oª›¢êÈï·:嘼v?®Õjõ„»œÅB)Ô±ÒÅo{º––.)êèý×`óÄ»ëÊÍ ˜`¶KúæC“¡çKGC~ ˜
+Í ê?(ß ÚÒ”ü>Ÿ?ªu¢¾>y`CD­Ï:µý,Œ|?|ÜÅçÕ9ƒ²9‰­‰ }p™’¾\Áóê‹Ûø5œ6b A0“Hud@ù¤Ý¿–Œz1òæÑHöx'M˜.·4O8ã)EQ‡Z.A`΃ïÄߣ—Ûê/7òxÒ[¥%°ÿYõ*ï|/ùЋ/ÆUýÒ•rb{ „ÚÆîÑ1¨¸.r­ЗyH14N Òç&‹ŠºóíÔÆ}YÞ8F„vò®Zò8yA8ω½w+FB¦ñøR _\õBµX ˜cÉ7 åJWN´­jù× Ždï§Hvš‹!³óz' Kbw9Ç}dÎÍɳ·V
+×z ɃsÒ>a>• d…7Fä•ÐõÆÒˆì„ /¹JšËäûóùTDLD°Y# Lþ7Õ¶`mÌcxgvì8A¡ñ§$$ž×8/™¤×õ5éùè“­wÖät\‡ ž%.ÖHÙ â/›ì.,ïzŒÒð©Ë+Ö;mÈÊUp˜›ôH@löW>O]ìÕùØDnƼ^á[ŒH-µÎßö¯…vAFojü51d÷(ÝûˆûE#zeŒ4 š­ãúóR
+€
+\Œå‡“pþ´fˆ¦*µ5$x-Ûñ”öDádô#ÖgôDö>~G¤
+ýf­F“§-ʪœÈëÕÂèqˆ…WÈ€÷.á·s=‹fx~2ÏþxÀS<ŸbA[FqYBëÂí—Ÿ¨öþËËä¤6ïvq{74Ϙê¬?t±º~|mHTÒÁ\àUh1N”éœ\Þ»ãÃ7ËžGyÇâhópŠå»­Êýµ™‘¡ÂÊ/Ÿjk²½ä¤²2Äÿ.þ ¬VtÙ;¥NÚyE,ÝÆ‘=ŒÙå!Ó»<oõ kœÉ­jNu ïçø5ÏÅ#³³¶ª·«Ô
+»ù„â´ ×3F0Á>ÄJ‚ŠÅ°#D¡nID¼—2††ˆnŒÌó`ë8“¿0”ºû T ¼ï •¹œÕ þÜþ—³Šz\/•X>û-:‹ùŸÊ~e*˜ƒ·€¨¡ì¦,mÚÊ—Õòœ³
+iKýk”½œ›ƒ4f¬+xfÍ}'€’ÂÓìúÊàáÚè-RM>e·Ú¼;lëºM\›$
+C rº¨dõŸ…’¡‹ß-D…-µ²U®é×Æ5È”ØÖœçÛ–l‡Œ™´ãÁi±‹&… pÕ‘sÆYaH»Sc‹Ño­x(~ üžŽñöpín=³òê"N;¤©›pÎŽ/ÿ­¶i‚çS†ë'ꇋþ–géy6^;öî &ìvIµ`ö®ô
+‘ þíâNp¬Içÿ$ZmβØb¦ f[Ô?ú͜㽈z¯mFØÀS3¢D,šõœ—d,u”‡Í†¾ ›YEÕ]õj¿¿ñúyUË(`œ`¼™9OœœƒÝÖŽ¹#þs@äßjpÇâÞÒ.Kh¹žµÜ¾Ïµ‹TÒz_î¯ò€¬D HNSDå)†Ýü« …'ƒ¨éĹb^'ôé‚F­óU÷º 8õg]¨—#»Îȳ4ÐUV ÞëØ‚f:œº#‹J™rø%{ºÎiË4<Ód*½Ú4¯[JßÓ5“”qivú'+ÕTÁSÁ¾ÖÖÓ#Ì‹-øB‹bÔ¿ª”ˆb¡TQ\íÆ
+œÝ
+VÿQs
+apþã¿pEh% jøm;F\ šÝ¡hrxM†}ðXý‘±Q×bß!ñö¼ÔØ3º1;ÆÓvš»¯5RÁʯ¶à¸/€‹Ù }çèÛ¾Ù~ü¸c=(+F¤žÌöéÄÍÔyý¸Y?î#T>Fäî¤enÈ7]VÅÀ™yAþ°¶û°SÉõäT<‘þrïü§èë†p³H|¦è§z½¶•tˆþƈüî$¿µq9cR4ÂÖ¤]·£ác<1XÑ¢ °·¤6òyMx\Ô‘a81U6®öæÂf666á©+'¼p§>\'Á
+¥(º»uÉ#5 …ÜI˜Î. @Å刞O§;"0¾·¹I’ ôäÕgbT =JrÞ¢ÔÌÉâ9ˆÃ”ðÃ{'ÓŤësp›Ÿö½V™ JÔ¤†dJÍ
+šu£Í3¦”ºÍq4@×/òG‘³R}÷¢¤=6ésO%d"½[•Þ„| íÏIªÚFìÊYÔgÒ úb8w„Ô¯ú±ÊØïKÉ|”Šì^m¢.ݦÖîŠï÷ÈáÚm*ÌQê´ ˜‘Hk`ˆµiÂ#zs{÷‹ó¦€O µ·KlH
+E~‘ò|b'µŽG¬g߈÷í-#óÔª¾ZVcº,/TÚ¨Oãÿ «C’Ï„%¸kÜÐ öÃUô ÍuÞYô
+ia'^×ïQË´ÄzÁÚ`Œë˜Á—¾ö8JÑBöãHÀ‚§Hêý+¨v¦a×ùè\ºžx$øf¨¶—˜l8.¥„œ´‹‰dœ;o
+\ÇÃBìG+ÙîÇ^r\Å⛺;\` è=­~C6ŠøjhÓEÝT¾Y6íO~þLJã%GÂÁïuƒ ó> GÍeš[Ìa<îÎÇ&¦ïZËVÏ©XÖk]UŒ‘àæIknÆ’_®Q!¥Ïf¥ð¸7Ò~ˆ<Bÿêºø]¡úŠAALHÛEv£Uƒ¡Ð[ÎÒƒ?ya0``¢&ú]ÅÞ_u$®¾Õ8?à›rí¨¢ÌÙÐe¬0éc@f®ÂÎÊ—朑ãGhŽêùBøã thŒÃLˆI X“›Å›>cºÞx̽7Y‚~¬FL9–ºƒ½¥”lÍSMlc”a†NxǬK·Åµ÷§ôq´?é“á1&Þ¶óéR4Ö÷½Wÿ›Òü±#1€¨œ«çLÕ
+/ëúMû´¯'&À¨(`põÓÄUjlQr;J^k¯áøM ËÙ¹n0”sféC0¿yÙT}ÐAÝB$1”[¨XÄlÔTî­ýfÆ©]w‚Zv·”¥’¨ÏÕ"Ü,ÉKû›Сk=BÝÖ”,šG ¢]—ciÅ~'Ã
+kܦMõÐg¢2BF105ù%Í’ t䨰{'Rm†-fï.9,i&pDéâ„Æ;d: Tº¨3¾ÆðÒI&q˜u–d3¹ûÝp
+°¿ñGëÉ>‚}ÔTêŒwo+…¨É°)u¸vÃ7é>êнž†¶h˜™Q|f –¤šž×$ÌD¤ÃÙRïù`+Ê£¬âi êf÷˜á¦ Áÿ/Ãó¹VýoÌê²tö…Ù
+õ\¸ä{`óæsÕ%{·<Ý(§éeI¦Œ¾^ïÎ:yÛ{¨#2êè¿Ù8®r×Éwð¨}LÁ þÞ„HWñ» p¢áb*üI „Ou>­x¦ø|ë ÝS£‚xNÓU î~…Â"Âjâª"»ÒEæ£o ÁUÇ1í0ÖÔAªAAöæJh›½‚ˆµöèåi)Z.^ò3…¾9ý'¡YŸo6ÈA‹ºN'c1ß'«´ÿGœÔ×ÚÑ~^E2pT¥òàd˜µ¹6ýÔ¨@%ƒÚ)rð0Ég}áŒLŠjÐîBq„FûLE¼ç{xkI~®k‘îÈ‹M…n(@në2Q¦bô‰ÁUJƒ¤>8 Ò eNÞ6¯QãÞËú””x'YâZzý…˜&Xu+ÔetT‘HòÇqLFF pw;çÝ
+-УÂÃOïD:7ó÷Èû÷!ÇTDBÐvKwq”ý:gÑ2,øýšN þ+9õüN¶£„ï-c´±ÊÊìØgTYð<éZ:Ú6§_½«} BÚºK 0§…mj„Vn£‚ ¤"黬ǚ´yzR—ß°°(ó>œ ²sP;íýäíÑçÁjS¼bÔ¶Ñ"*ït2Žü° JÐöÉûèÃ`iRñå¹ÔwpÛˆëø¾Âª_ªÑù €öŸù¹pÕ
+E{N‘™ôƒSì'”Ã#pxðÜÈNg¹õ" `õÌ+ánÚ ¸5úžWæü-6[Á¶·UýÿŸ­Kâ•´a¡"O±³Þª˜V…º×ªà«G¬
+÷AýÂQø´Pîšý¹h`äŽ^ «¿ry{¬ž…bQ»}=°æÑÉú‹—rˆÕ>tD©èa¨HúügDŒC{ãc”
+ÕÚàfö¼“pñVÅ2„QL®î½ý:4%L8¨
+¶¿©TÛvzNj €xAµþ?…4VÖ¬O™àx’
+Å çÆ`†ç+ÄE7;»¹š‚7i“W„ï{³q»K°.ÙÉé|ø‹—>Ë+›þú·‘¬\ ¬…šºkß`ŸåÖâ·IÀ]`¬%ç¯^¦¥¦nEtBYYäßûE/†(BâØ~)¸UPÏOÿþw»Çd¿Gm±>†ø‡¼P¯G|¨o1³rÈE]][Gé©ß1J!ÛPˆF*¯>ñ±–ð#«2KdùÀÚÅyP° ÜaÉÈquÏ(«Eê}Îa„Š´¬b=RXÔ¬Ul<² ï-¤,O÷T…÷wJ“šóMeÐðYŠ‡¥vHî¦,K¾€WÇsu'— 6WŸ]Òp0UQ8®*”
+/“;Ÿ9y°cßnªéUÊEµ¼m˜ÂßBt |e&ÿÄñžLXO'´î<éMôáM'–ü
+/j¥ºB§¿Ül D±!ô °FFaXó÷ù «–+…„“K^,M_Iò|ƒßNJ2÷%µ§wá¡R¢ÃaÕ÷”Œoƒž5Ï ¤Ä¬QkTwRä}ÏÒp'ÃäðE´àÔ¡>I¤“KHâÑZðÞKå– Gð<¡Ð¦oÏOÉe|ë4)Ø)­·û°wÀ*D–"tüœ³c¥è¯Í[H;074iˆ/;IÌйQ»Xvq.æ®×b‹tQ¼¸0$lÔ]Iþ&1ˆñàÁUäYƒáCª×OãˆÕGuð 
+$ ¿Ó$¥ pO¥@ý7ÜÁ[ðük¦sNÆ…^pÆ‹8c½¡Ð/cQÿWë¥pVÃâRƒö‰P‚D¹šö W ¾à¾SßÚ»@æà»Û5…;žÈ^´ªì•4'-7Ý¡äº$NŒ±—ËŽ?ú>ÎŽšØP{üþ0æÂy4j™×Û·z¦aÍ–îy`MXP¬©‘ eiù\ ¤ÃéØ,óX#cS)i8ZÄÌ7PÌ›uxT€@Ìwïý3‚L~Gbu¢ƒýð¨Õ·ÓÇ¡]B2»¹½Âj»Í5dr& ¦™=žÑs±Ä„dåB¡UK¡Ô«òË~ÝâÓzu
+]Ò-îlÞŒzmñó“n]I3´ÀüÚ²M…芩ýÎ¥%†Ós[L*Pë”Æñÿ-žÅGÁ'y~4“ºÒèÎä}Òª^½’BT/å \ðZ›G%fO»ÄC !ÿ&MÊ&“×ã|)ÛÚ‡ŽÚÒq XãnØÑÜJ ŒåG-:;tʼ¯ |gè1ùƒCWÈ­ßnP}p¾º
+nXqkýšžÆn ®Aršh©ìèœñS^äþùÃñƒidl“»_8NÆMdÔYäg§)Cûš58å6¶9+P¾;Îqͨp3F ýÚŽœ£#~´T—²u»#
+O…æ#4sãYM3B´{°¢i_ ƒ§®˜L^ã†c­PPªêÊš9Ö@bðÇî\åäÚ´ë§ëüÔ£nƒŸDžãQÊ„Lh¹• ýùêô˜í  r|ZVz–ó÷¾Î‡-ÄÔñ²Pþ’-7™©QLuˆ¼‚©!9MýN­/€K<X”ÃɘñK-w lµ_:Î ž†»ÿè¨fk;‰É
+ÜŸ­)C¹457®0ºÒH?nNƒApPÉz”éf*òÝ^X ¦à-­ÄvSUMÆ¢‘·vÖNhµ€ã¼IÒbuBX¬_Is‚ÝÁX¦k .Û/PzeñüNß»0OgŒŸp}§&"˜Ì2¹œ¢Tw×J£ûÓú(¿QüÍIA"ð CƒYH„~¿kï¾xTì‘·jýAA+¥Èù®ÿÌ‚j2/£jÏTþ*ß ö ʽ‡Ir°Ù¤^£{xc¿tZÏ5~Á2äÛÁÑöØ„‰I‰Íà™¼ÞOgÔ¾gXOáÕ³÷Áë ‹¦@…Çï¨Ý€òÝ¿xé¢ï/!<‰·ÇØU|¬”³ÕZ€w@ÒÔy$Ÿ÷Ô¡$)}8šgÜ–{‚¡—&¬Ùî—üêö÷–õÉ)¯Ö]z’à9Yˆ—hwCL‘>Ã"íüÅsD÷ð©–›dä³4£D;ÙPÏ m—ã)a§Í£ùök³4«ÂwÃÃ4{óuŸ kï„ì-™ÒÕU -£õôàÀÿË?øËÓ%‘‘8÷DŽˆ1èW¾‘(FÄ¡_3ý顧¨ZZû'ufäÞàþ²?²²)Aùxè‘è?}³]fgáÿëÝé[xQ#·ÿ¢]§2ÿ s(žjGÊñ‚ü ḩË* äHløÝzË%©«WœÅd] Naæî`HES– ÉæO¨“½½Ú¡% +7îᑉ3¢,eKtöNXÜæœRG½Ëù(PÒôy=²qA9bчüÃѯI
+kΆ+È—´Í°[›ðëþL,ƒ±ðc»ìèNX/Þ€ ›ä: Å
+–< 8©)ð-w0µWë°h㺠QÙÉ3 Ã=)ˆöé!ò>q¦óüº»E;‚­ìœÜ”ÐvMª7©T‘—“ u@k9#ʲXJ¨©¢³A¡
+ÿO±ãq?ðƘTÙp£x™‹·ä>Z>åÑD‚|äëztºw-yá×éÇJÙz«2¤•:ú Xîö§ý?`o¥ÙXÉ'æ‡6ê§õÀ5Ï–üVœÎ’Š(e)}6uÊ?Sü™ò3 à+ªÓ7W—k{öý¥0`Å1VÞ)ŸáÆÑE\ÂÑ̈Ç.¼c ‘™ôzV …$g)QW¢]Ãå‚ÚÝš÷¸.‹êwáI òž¼#€m¹Vu-ö—I1Küºó&´Ýﲬ¨1­?‰(¶;)û‘E©7R7 õÈ?Š*«Ôcä&ƒŸÌâ4<±œÑ &Çw\Ìó\¯«…ÓýáçÀd'Á8–ÃÖ¤çSJPh ™Ês¦Áo…‰]ûqè9Ïic&¡þ†ÃÄVD¹¸Q
+±at½²‡½ò®½í‰ ÞÇ€ŒMs¼¢ÆîÐm«
+ùž|œÂH¡$oÌW» õùôE]½ö÷|E3î LÉÇ-?7÷˜j¿Œ&§ùÛØsaÉ:Z•uÖPë`Ï1 Óe4Є¨:ÈDf@wSV5ÉÝeš
+&ÚÊ°t·]^ÏÌÃ||úwÒVýÆ®?ˆ9»Öðf—ô@•:§íj#Vþqµ”mÛ
+àþK´Ræº÷KàQÐE…ø—/ÚÃd‰ÑÇz&ý‡öë øÜjxÀ·wCl%Ðûè/R«½*öÁï¨t–ÚÛrÌíÏ]ôû6 g\֮Ě
+ì*‰¸qÅ´å’í‘CXÐœÿ!K62&÷™õ;#"Uj@ÈÌ3Èú8tëfe¼š_\P7÷`®ß€?R0MH>r?ôˆžV4KÉ•ÔÙ"úÐNÂj=dVÖ W2pé&Å5Ì® ‹ï
+x3ØkðñWž²?)cÜì¼ÍF°¥¾>íÇ>
+@Á #31¬X×ûá/Z( áW¾Éž‡"Ycùj#uu‰Û²hÀ§‰&4 Pµsÿu%>¯+9Â+P8;IàæÖÞ–ˆ—‹P:ü8дû ÉgËg#Du÷þ•#V(êp¥5!€1¨ÖªeN.zì嶯Éb»lýò¾ØlÈ2)¿Ëþ–Sðù‚H·PpøÚðð·Å€M“{ vv¼°Wû2=åç·g»ÕÔã5
+Þ co5_‘~  ØÑKYèÉFÛ#¼˜ÆU2Ák\án
+ýÞ5^}’÷‰D´
+ `Qnµ“q//"·«˜H›öy…ÒOzôšˆðøÞl…ÕОF Pñ——…r&*z8g"[c8¡¶íª‰f"Y!·ßrŠ©*ÄéÈqV5š?He ±®ð×1^°Ï2ê¸;èñÞÊÖãÒ×Î×ì^Ÿ/ðÑd:?[ÎRÚŸ†’0îO„xc|vLKŠM ; :8}{ð8qKàÄ€Â
+ÊE ”díUƒZpºµ¡p¢VÈIÇ`:ŽÅ)
+-–Vê¸{{ãAÕ6hÚâ%F3,“bo.+V9M
+}:àè•® Þ’1Üãu>”8¥XÑ)„œ©©À$ýo\¥'j9#åd(%¦'OÝ{YÏÕ|µ-4UêPæ1øz¥~ùÎñ[*>UåLª¦/íåÖЗÄe¹.Ï™ª½ †? ¿¯Ú櫾ÄÞw3÷²·@Ì·ìöy<f ˆ§]C”4¼ø¤G+Tƒ»µ*–ý²i$©ZQºòg\ûlp7mj£xOÛF²öÓk;L-©mfhKT< òéî—›oVíåÊ8È®û
+þI7Âþix+´‘°ÅèAB{ÕùE–Wßû½[ï7ëºÔ ‡Ê-ë?·³^B uO[ô(
+Œhè Ö”Eî»BÖßÍ´·â
+% ÛÕ¨d+Û>†>äz8—Üi‰/8ŸÒðGò”¿×Wµ©Õ±mM¬ª¯´ŒÊ ´VËÃ=B
+‘œ§®íZ®Å|ìœG-ãW‘GLŲ3o¹êPˆ´ïç£cÉäÉ'ª9 0ÎÌCŸîö¦çAÅ72MF篵瑚„¨”Žhð)E„r´êµ(2·ÅÚ±LÜ0I0 ½çd°•/#ëÍn”øÓ…-æújëñEš=Œï_Œ”ÔÍ;YJXËœ•Îbª8,yêÉFbr¥!ÀðΰW­6À}÷ØØò¥Ü¸¿lª6µ!;âOä•­2?BñÄX/(³*² f5@XŸèü„e ºvñEí&
+Û,Hrü/Á:5$ÁGß¡ù¶’zîòåJ:øÊ%x ˆ¨sïY–t>†¿‘‚–˜x¯-ã*Uò4Z4ýç!à°a¡å¿¿|,1¡°Yžk·pt—•Îœõ‚^eMžÝÙ c¥Ðè§-Ú“Êu
+š»ßþ 6ÉÁXã‘áþ ÍêMù>Ì/Ð9ÎshvøI½íZ»É2é¶>ËŠˆù_&~0œÛ|‹Rºmûȃ­l'_Q:û™   ±ºÝ[v‡âûhAèE5c½ÀIìÆLÑ*ÒmíåÎ!½ÿ"³¥m’€;ßôe@}ÔTùú‘È=ξ Ã&°Êp6T¿¿˜ÖI !1üâ„ûG»éçŒ!L;6¨§³¥‚E^Nœw‡M‹Åݽ RrDQd’çxϹ‰c
+%µPÿjŸÓ½!û©_ù´²IÊÖÌ3*Š¤[¡ ê59Ôì¼F·lFÇs“¢¹*À¦q>o³³sÕ†…\i;éÒ%òìuóÍÿkhtœ!T¬ÒËN· õLVq¬x3ݸÚÞحĹ¯¢(ŠÁ¯—«‘-s›ƒÉâ³x÷ÎàdÐM ºo(ºn
+2Mí̸S8¯öõœRÉqñÍ®ÀŸ6~XNÖŸ37nŸGݘTÓçU@0Å¿èE(¿fº9:Šðpðº¿RµÅ¥þ{Þ±¾‰mœn¸K( Á‹%áátæTb“‘Nóó³7<˜†¼N»”t]Î|­ô+™²¡ÓM¶£¶%ýn“†oA¡ó°0¼¬e'Åq–gEî
+Χ·ÃôØ› ½dcUzýŽ½[_‘VŽÜòÝFS(ìâ/öéÚ.
+BÎ-×Ý”2—püýRR¥U“„]«ê'{°1™?ŠWô¥1Ïîј lÖP“k‚ ÇÆìÝ„ëp.œ¯\’Ö™VØA6­G+‡=ã~t_wÒ¥Ÿ =ßà2p¬ yÔG¡„Oo§4ú0axH]‘6ûry¯˜×äI6‡’«ÁfÝy ó-
+eÒûI;”Zì§ÔA©_ÚˆPî%R`ªoŽŒ\¸sîVù†àQvEšs³›»lW
+fh¯Ÿ˜ ‹¨KÙ5¢7r 1=)-ËÙªÏ
+%‚N
+fQjœMØÚÁ€Î.Å[füšëZ6
+^ÛÿAä×BÕäüùäQKG\Huh¶ÖŽŽPœ¥\A4é6vàï(fŒØw„-!ƒoå.HÞÔ¸óNëÕ7á¼Äu- â‘e"‘„¼Ú÷>°ÓÚÅm×<—Z#LGaË{rèN ìܽðT{¶þ Dƒ]?c:1à™ Œ íˆà[“ªnŸnŠ¼S”çç¥Ì`ýn X.ºÛ¶üC`R‰”ŒåW&7þtq¡çÌy•÷'}kŒc~Ëo¥~eµX×ú1¤kÓ¥qBÍÕXªK<¸ÇÅéëþòúÌÄJ*!¦§„G¢/ †+d­ÉLÒ¹*g·³ýã„Fxn±\
+¦nâaâ›#n4µ»[º¶:oWúS–ö«§•'6™öѾê+|Uë¡mÊz¿\¹6ï
+¦¬x´ò÷÷`¾„A“
+-gåØPWC`io`ÀXýyÔRµÔÛ£ŸÂóìð.çtwV´NêÇ…QÞÝ•œ´Ÿãc
+RNN¢ žRÊÞ<¢:o8 O¾öíÅñkÿÏ®/Ô¹±ýG8áMp`Ž,ÎPD¡ìÕùîŠÇé×ÀZEïÌ€-€ôyõ/‰W5Øù ÊjÎ+¸Æ)Ñe‘‰Ì¯±Fˆ«WqæŠWÎiæt¦˜h#úD/ ³‰¢Ë"*ª{©PÇ“ºÛöƒòÀºÐ¹ƒ10ÒÙgë'@Á`µñj)Û2ãôÖèÒ«ßÎø< ‰ˆð¡ Hf|?¦«rCç›ÚwAYÇ[Y1*ƒ/ó¾4^¯Èñ²*]£)>À†vú­ë,Ö‡‰i°OÛ
+wÉý¼û™^)±…;"£6¡ÉîÞz®kgpýDh¶Ã¨HD`6«UG(1·|H•Î×T•>i”Xå†âl9AC IYXÂFV.¹1˜Ê$¥7h—,ú@÷V^O·A JO8ý,ïoT/ËNu_¦5ªŽûˆ{»ŒŽâÚÞÌœ%1ˆš•ñ^V¦Ç$ŽdÜf¹V> NipjuªÇý瘝B£bŸÍ'þ3·ÂE¬•”‘Àí[*læ «Q1G€]B0bE]}fXs²þNJö_y*O Áh+´5ê6‰×<ò@OËq(Y‰Çr ²2{{”Õä?£ªÛì“-h¢Ä¿@ýùC
+Nƒp}‡&fæÉiTèÞÎãtßs{±y¼„.'ËIQWzÓ[¹·¹lh<DJ¢Ïm¸=–Òdpž¼ Lo¥Ì™‘c>å×m
+)ÏÀ« f)Ñ£­<ì)F-zæ($<Y)y6áaõHoÏ cߥ¡Þ²g•Ó Æ'?J=ûþÊtÆN)㜮éëd# ×I¬ž\JöYŸß±Ý”e°yóÄVèšpq|k;ðÕUýßGéjŸÁÖ ~+z…!Jî÷
+Œf0ÜÝ¥žÁ’.ퟴp’¯[¨eÂ4
+¯z®(œ+±D +1oI>ɱ˜ Ü/©ÑBßp¡áËiþPäxŸ‹š÷§¤'à­³ëPÓ›ÖÙ®€` ¡°GaÃ!Ä®ÊSG²˜ DÞþ>!ü`WÇ`F`´„ãV×Ð¥š…ÿD“Äd‹/nÚ’«$¼=*žL}ʳã_€¦‹*1eíB[#g4èCbš_4_,ïz¶–í¥¢VÀ癵òõ=ù-™åœêØ¿”êÊ’
+XüŽ6Q–&åòÑßl)b}uÁ[Φ8"-«I½.{ð&oOå(ñüW¼7X©¾×ªüum~¨„Á§Yóž¨?÷ï7ÍÇÃz›ÂàrÖ#ùó÷¦§ý©ÏìpÝ-Õ÷ 30µûâùê™)Ûu‘ _òg`dx3 ?5¦œ•ÙØ~ùÜûIôÞ…©—qÕÂÕÅ:a7Ÿ¸DØèeÎœW§  ÿìšy
+êxÈ ‡í¤e*Íüáɶ µ»nκ…§K)Õ ÝáZí9UMæ=d^®Ã”e;LFÙg9þm×ÄÖ¿™å}¥
+¬L eßVϺ«CÁ/â{)sœp6~ªé
+§(S™úÎÃÎDn—Dä×Ëä©<²}<Ýù¿jÒâ+wà»0J‹kôðèýº¨+îS›$šÚ'_ÉçgÌP4ÌðókUìú%Ga±¿ó‰CSÁMÎÊQ†”¤X¼F¦B*DüÜ >¹Q¬ÏvH¿¸·ð“;ºD½³~4ÓÀW9KGwtß-fçe:¹+¨KÙ±;”6m]ð¡÷gaUï=|¼‘è¬ìœµa´ídͦ¨3%–„!C¸…-¢¬b—9Ónl‰¢¹c¨dä4ãꤠÿlRÕ›[¹4 ; (‚LðÓðùÌ$TJb¢Ôb‘ƒ£—MÏ¿jKÁ2ôC`§¶ÌŒ¶¸ÖâÅë¾ñ@ÜÌLJÌ 'úçÕÄ/ \}@–IP6Ìì-¨¯>QZ9€¹Å«læ>&ðÛåɃӲ"°:G&T\ݘçbh<uú¯/€”ôÕØܘ ×^{õÏI]QCy`d„iVn„¯J˜î˜SÈM›ÒÔÛ»<åËø°µ¶“»pÒ2$R¬ÕÉë-…€T=,qæÂ-‘C—.4S¡Õ
+ƒ¨œó¦Ã ]2uµR•ø¢ŠJZ‘V$`^wÅ<–u»¼¨¾6ŒûÄme™<Ävk–a¦W¯é:_l;5¬ÏNÐã\5 …#h9!ÝvTTžÆ$héÂg#,¢DÁ½‡]i
+ºÅ¤A9û´ S•å?í¹n„ ^C•3R/«÷Ä\— +îßZèÀ±ùQd1‰(S5Ê=ø0wÒ\¨r2}8,óý ”U-‰éív4È@bë£ Ç÷3QºNp hµÑÂ!뽄©[%z\WÖö4Ã$ MÀ+r[TKé;9ßÔóCË"ÊjËA=ž_˜ÉSc7Ë—<Š™P«6ŸÈ{Ýí/Þ“t+Šx³,Gð‚R$Va¯":‘Ì$¬b²EJ‰ë/ŠÈðžzKðSµ×PÖ›ÉöØv„¸G£(Eî"“d}1„ÓF`}¾çò±‰fXzrüÔX*ŽVàkrÊF´p&t¬¥›ÃXÖñ椼ŠJñ–ûªû³€®J\뇾œSbϯ˜à(ìPS ²üƧO‹ÄÄý
+l¶
+[|¼§…*З¢L7玉‰ÒgÉ¡y
+×½a~&_3¨{oÝðp¡"úý—,ùüµZÛ•~¶$!Þ—Ïrêµ›Ú*ÉõBíF¥„êºó×÷Ɉd‡n \l!ß[
+`Ûl5FïèA0@í„»
+ˆ@ÙÚ(…ð² RH]ç*óøÂÆ1í³|xà–b.jÔø)Gø“‘!`[nwDDªçÞ´[0z+îzSZ+Ïê¹RÉ5uÞbˆatÆlÃÉõ!s-_x»»i¼0K&|#K×E—–«êtz¤òÙEƒOÄ:T ê­ãv®û‚Ûôì~º± |êi!ÞüC$€ö!ï&¯DIGm¾fý$í¨T¦åuáèÛ2M¨fàŠßHÛ€#˜x<‰Uüº,»˜ÝÖ¨?F£ köº9ÅÈDéM4.a·¶þeù6orGGx7ÏrÔų64*8j|(•ˆZG¯>ÜOdãÐQD•”GÅS‘ÌtKþZs¼Pù]Éó9Ž¬/¨,$Þè,‚â8éºÕŠÜMòzAe½¨–íÚäðŽÀ{¯Nõô¢)âGn¯Ì·¶³Æ›1xi1ÂGGèâ#l\ÙK¨îöƒf]´Fä ­ GtãÆä£n(Îtc`2 Ï[p†•/™H÷ضʓ@¢h[&!Võsdÿþ‚"°¥O³üfþ é‚ÓÌìóŒåÑU?b¦€r
+,oÖ*g¤_þ%ñœGú¿ù¹i`Â-P2Ý”µ‡#­­¾¾aOIK^廈ͼaÜ8^²Áf+Ïý‹3‹§ÿäj“ì]DhåýÅéer[ÉË%v7÷ÄÐ'Ü:ŒL³9żê=äüšTkŸøhºFƒU†VMšsÜ¡×v¿I˜=ÿä;¿‡Ó_ðŸ¸ÚF†*òQ¼××{J+ÄÂ8?p@~ZÒ/±µ—u…ÿ;0*|0jâáaäÊÒ*]Y“¤³øs›Z­?…¨ÏäDîŽ;_x1”eœs< ¤ÌÓ‘–֜һXŸ†+ZÀÓ^î*—ñ–cÿi57MÇO]Ðglì »{vqÕsȺh \hz×7‡ÚÎü`×Å–=Ž²ÖòTáü22æ¤F@Ÿð2f…|4VÑ¥Ú‰ÙtH2’<á˜×K/­z§òWÑ|L^øØÓR_Tu#¢Öå„ Ÿò0±íáñªCB‡Þ¾šôõ¯ ¨W Ë‹.‡ÉçT^b_O
+”ê@X™÷DÀ¯‘©R|±_÷qÔt5•(í¼W鈦5‚ÑݳÖ:—wKÝN- NDóª«^&q>qÁ£Öp ÊB9ž[+ý%y:Ï40_þT蘭Þ*šCuõ’š4Ö¸0ÒúÔ{ÖJföÂ[³z‡±Øà¢|‡p×S8öíÖ{ÍqvÔ 1 Õ4‡&‰#?úÓFMºÖë¡Y¾§ÃÕ¡Âõ‹ÊlèýÎ"ØE÷ට¬yè™ëNÐ~Á§-AÝb˜ Kžµk'hölR/«]÷ÿN-RrÌ6$ŽºrÍSšø•…îM'?ý:Oü«õp7IR›€_åUöm†ÓXr“‹äùSj9ðQhCÖ¢›HœË~‡Cèݪð‚­7•.È2´piÁþŸ87¿Öˆ ñô^ˆ…"=XêÄìíõy;Y
+üp¾¸ÿXiBqÑ ñ­Ö¢Ï\?8Œ[ÊÙÒòßØ9[–åcôüÔ·ýW þãÍUKŒÿÔuÄaóK´®fÐÁ&û\ŠW
+]§°]/%ƒ[*Iç
+"BŸâA 7P
+BKrc¡·¿–8q2ÚŽi­»`ðX)9çö‡Ü†•+HÙ‚F:ðòL%w5ÓýœTN–“ˆY4EökAf‹eÕk ;E) x3F#ýóDa_z§¡»œ¸ÊŽ0 ò–ÑÌæ3½ßŸÛZ"«þZ_C‚«Ø`ùò>ßÀ5°òß<•
+5òi>Š&¬¤/›BLÌl— ];øx–%+÷?"kûÚ-t¥ÁŠ„ðÑÂjêàŒ:÷dg"
+l$–¼„ê]‘FCqA¤fW£ÈPšç¡™¢zÀwKfcºÔvc5‹ uå$™¶fQI:e¶;À´·9‡0Q¥r: R„±‚Â[l3í±”®±è•ž@\ e©$: çhT®§µ?êÄÚ tõ¹¿tƒ¾ôä0ÿÜ,ëzÞ(€çƒ5ÚrF ¯Y„¥‚ô@áTÝ%Сß% lxƒAnÐÞã^X`NÃüov÷Îë”gEº{zÛv;ê=]¼]g8µ·kŒ-¡åƒ§ùlÜ6HJã5Ûx·6Ãpõåå>:§øL5©~{šq½sp[ 6ê‹kZ¨=Dr`(–`Ó´G‡£8M7hÏèíLÐ)1ù‰:û™¶** ©PChÉnèÌÉÄWþo\KRµêý
+®…?#ÊìfÃÐyè¼{;<MSõÝI4†âþ™Gzµ $
+@°ÛRÃ.¾(q‰{'9Š0:Õ¥0
+Ìþžs×]aì‰lQ7Q^'<–=>µ‹KR‘+‚n4IÈ¢6åšþP*ô¤±2bª-$u2Mü”L4Ù`ÝÖr×aY:ê¡2,Øå5“ü„!v‘ÀP±©„'C©¸í/2Æ_‚}‚¿_øpV@mP;H=[€Ûcq5ɳH[9H“̾גRÁ ٘ȸ<ôúu~²Ü(˜¯V Òè³ p÷WQ¶€|ÿ/°Â ónâ70îƒå²šèÀnºì8P—wμÖB~*¡“X z½›UºôDºéµ ì4£ÏikÔ€iÐ)Û®àá,¼¦36„l2°ÕX:+ÊrX\V
+
+l¡8ËË⭤ŷM`+Ê.QñÀ 4ÊT±qφB›
+|B…ÅÎOÖ¬Ãp5ÒyÕê{¿»^·³µÄ¡éE¥ `„ >—û¡gÅÀö˘4;¿¯éŒoŸûö‰´[Áè!Ȳ8p6GI§ja¾áy½Ü¦Ò·
+ôªñžBîºv9„Îó=ýr)9çUÍü,aÅ[EҥΥ¹1™rí5"׉ƒ÷ÔO½{©•Bª¸HB}I_ ¹ô{^*Ï  þ†÷8÷5‹þÒV£Q¥1È­ºq§}α׉֩îz¯jMúæ-ü^ c)$ÿ81
+¸Ô‘ÑCxÖÈ|lJqdD¿Í„¹@û¡›„—Ìkøsmœ‚±¥,îÑA©ª®ä=zIûV¸I«O´ö¢…PMÑ€ Âcˆ™ZƒÂ»ÊÌ[à ‰]SÊ
+뛂Énòè(QyÇ4¨dˆ¹—uÝ´m”±&ªÜ5²[¶èŸ6ïõÞMWÙäø‰ë0^¨•Kf…€càÙΨxæLiiÿ`.T®›yI:]hÎYŸx*±³7¾Šn`¢$ŸêÖ&"Š©œo3ýüȼ£_UŽ6
+¹9WÍŽ ø¢Õ\¶»À®i´{ÑêëÌ›&m\+ñ®_.ÊÁãÃ?©/Ê.X^?jÜ÷ñzŽpzÒ†mnkçn¯¶ª½ûr¸Ø_¡|HסˆÐÉÃäÔ¥}ÌŠr4Çj¤ð}çvzÇ|'$:ÇFPʳœCÆtÓ•»°­4ÈÎanlÓ^ïXˆ Ðn;?Í&(›‰™})§ÜÙÑ(ðWó½î)92œò©Ê|Ô-#­ö7r&§ú×ÆÆEקˆWõç`ˆÑÜ1¡Õ±’¡·lØÙ’¸t¸¸B5¡“愤ê{üÏDÚ Ç§ÌΓ­´3˜ûZ yàz³ED<¤t~gôñYÐËûâ>×ngÙn”h…ÃK.t1þ&‡Ã‚óžBqy—¢ßâè7Øq•\U¡XÄø“£6x†oj¼ˆaÂ…¥ DuùCžˆP»«?•2šþ“‡ÑÖk/X“‘º€·ó’È NÉÄ÷³ø1Ë9’RÐãuú)
+î%"ÊË}¬[L7øàäN»×©6ÿé« þ©JÆŒEoU>µÕh¡úÌ;½¬×îpg•W90®Ð¿L þ Âj[y¡¢ÍP`‡ Ý0üBó0nñ|âŽ1ª,kåíiƒ0€¬u': SN—Ú|Ed<­Nõ>óŸÏJÓË'änVö‡SÔVÓM¬
+“y‹
+`Å߯*uïî‘tùH
+“EóÃÓß #¼$b­ òj ÈÒ¤Òh¸ë‘Š¡ÈÄ?€½3 cY$_Hx.¼PÆûZQN¾¦æ[jÿÍ6¨¥*å¿éN-tß„mÅ(žaV÷ØEHím
+·wX7k…Ͻ–£hFÓ»“á‰Ö‚<£óP7Ï$ܳ "¼çKO]À)1ø—0¼T$¯. p*)»y| L]¯6kdfǪíÝðc€çr
+›Ñm!}e-«£é™ji™tÒ`'èÚ¢ÛÚ›l¤‰H±d0õRZ8
+x)‹õgȨʪ’YTõ_g !IÚš ¦Vw{Õh¦p«Ï(§‰8&p¶ =Z§üùj6A¼­0ËåÓí™Ùd6õˆÞK~Ž%“»gALø´±
+C):4FFØqîCX¦.‹TþA=í5ì‰Âfóø¶œ&Šn&y\AÙwÞàyJ|·þE·W úß²ª‚AèAnÛQÏñû±´*4ƒ ôû­³¼/l—¬šf
+¬„:a° õ¤©¶Ei•[ü³¥ZC“7/£\Ü@älÉᔫº=ÈáÁËvH‚iî’*¶®mÂØGoÿöû8/¹ì]•V¶_ÓðBš¦ÓÓµXô”ˆÞà¨Ümgá¨Cp&ÜS“öߣt"ãC¼èL ]Ù'GÄ×:/B.väKÔz4Òy±´ŠêÉHlé+¶Hi·ÄÁ\ßkU%±ºéˆÊeìmôùXÑzŠ1G_„þê¼ÊÐ`ÆâÎ÷KàôâV!’.Î_Ä¢ßÒX¾ö‚¾@ÜQ’R–­ ¼éGš>ÀÅ;ÁfÉ Mi¦!$m#-˜C®o yOŽ³öèñà‚þnåRJ[N§9+²áàÕìlž²lsêÿ‰VãWœg;þÄCÚظ×Ô 73ò‚©œ±Y^É <sÒÄù*§’:ïx“{OĽ¡‚-Çà QþUº”àê°}c®,²>’1ÍJɺžÂ³¶ÛT—¾£Ü°ÿº5­®=8Q®aÎë¾×pU7ÓᡘŸÒ“D%ëêø ¢FûY㥜ãÌRe†•¦5„ ÷VŽUa RóŸºÒdu6*wÄF#ñ]2…ωŒT´=ÇŒ#yÊ›'R:‡-t4u§c¶h°/-áüSô¼/O°C=D63à8qÕ–Y át( ôœ©ÛfK/™0º#_ËÌ1Ý`Éå$‹ò)†H‡ô·8¢ˆuB´¢ƒóáñvÌõàxòNBe§âúB †“I·¸»Þû£I™>e•‡ÎÊM®§‘íÔBÅñ©$Ke¶›nfúá:ÜG*‚;ý¥ä®Ò`ÝE–Í’+Ô4¼ Omjo¯6Xš­@‹ruÉÞ( ȺcŒ“zã7±²À·VMÖ¡§[¹æoªÏ ëvB|]gÁîxq ‘Ãß’æã†ô
+MXÈ%ŽW~VWƒ|·Úr‹ãžd«cB­] ûÅÎýXä˜j-T‰`.ÍN
+-e]zÔØíƒB˜à u!*ãþOÝís£½4w@QU‹
+D¹ó™>ËcVø/“¹ì=ê^ÔŠœg}¾ždÞÇõ ¼©òÇŸtD,ßiÜUåÆ_Þ;ù"/ÓhšÛºû}TûˆO ‚gŠhnÆ‹Þ™/—eߎä²á"ò6÷¢äß2l.°@„ï`€aŸì.ö«Êóå&ööÌáwÙ‘ý‹bW:¨Dqا€I¤$Ž M•^)B¹ŽMrC¯' Q“Ø®)U}OÌ„{Ni’; ›íUQĆ‘°“XÊ´+‡†—SqVÞÔ>ÓÖÕqÌmб MSbIæó±ÍUíqñR3‰.Å€‡èvúÔdƒ'Wbj°¬Hýá‹<š‘Hó'‹;'Ë´R˜&Ê>½¶ÕU ²Z ‹Ïß·þ¥r቉A#%ŒOrôØY°é0O¦R!ëYÄ5pë°å4K»ÈeÝÄÓ{ªÒîÏ+CµL0`Û—Ùeî€jrîÜvÿ¨yåbkêuÜCÎCŽŒª˜s«8˜(›4ÿîT!ë1°ö{GØæÇó‚“^jiBRÄ“
+­ÓÃ"¤®\ ÃcÕ ;AÏÃJ쬟;–S€A¸êÞŽ÷ %wèVGž i¬VgU°5 0ÛÚÓ‚6TÜ—”Œ›¬m¾"RDúRb±Åô_]7ú>dܘb~o“‚w•'Øý »Ò†öÙQÆ+¨}Š›çIþ4£mU6|Äk–1M+³^ ‚F—j“ªb¦=ô˜ïBSŸenB*ðX`¡ðÔé!eIÂ2ÑA`ºV æ¾ÐI$o[z”¢Únð‚Ãz”MÞÉŒ¸8Ä©šë¶ÛÙž*Ôص¡¹àó¼A ÁñSI)VAˆô˜
+ì­ïÖ IïXo¢œ²‚Ÿž<,7êvl葼 Ù¬ùúTyÔµ"û³<€V°ð°žÍž#à9ÿlT–ëú®.B˜ïÅ
+ÀˆÑØ1qk_dn|žš1hß,{îÔ»Ë%G9<Iq£Ƙí?­x«mùKáÆ€[«Lãbw$æ%KØ`$Ge Á¦Ÿá¤ÜŠQ¾¿E}šÄ!¨l˜E’ÈI±»¦ßg@yùÿ¾¶£­ÿ~¡%ÃDV×7OŠÈ¥}ZŠVƒÕ›:éÕ~»
+54OÙ’º.ÉÓâú&y„X3 °'ž<¢ bÛN :L1ÄtèX^/KÕ¯´ŽÁ;¬£vB1r;‚7
+ Ãºòi¶È%÷»tš:ꧺLa3q9Y¸ÚÄC\:³üíëüÐ}!0rʈ¦^ƒÖ5""Š zœà€ƒÍóè"—ÖE/ðh*j‡.bX,¿.ûѶ·ý¶Ýœz±oÁ½(°½ —íwD0ºßÔxOUˆ³Æ®B¼…ãËZ*+M7O߃ÆÚÁ1§…²v$B®8L§Lõ•“éÙý
+C’†ÓùeƼA}ˆ¡†Wê@ØáuàÃü/_Ä;5ìÑ5+áï*Ù2Ç®ö{Eó6Ò^ªÜŸœ)úí o·O=¾¬Z`½H”¨Üû çä‚ЖKoA=¼S7dvpR)»äh,±h¶É±ÉEFÔ~S¼™QÅýúj©sm
+›)%En¼få“bÍ©ÌXñT+°oì!«lý £ÐÓôsͤÐé¯äÇðÝlº¼gìÿ«ÊÞI9ïQp Jwpó× ¾)M°¾ð…|=òî’a
+ÌáÕßËË@ª€6;ý
+.± "^ÑÙÉ (bä 0­Q ^øß¡ž oc_ò/X´S­³}óº©  \Íe™D9.d¬á•h%{„·[sÛÍÌT/ PòžòL|‚À®Ú }øÕõ]’0åö/‰™ YGt?gˆZ ì."÷{4_(s˜ˆR
+QÝI'{?çX¿ úl[?›V ’‘¼,áô®°€Ö[ÓÉ)5Gc‹Æ ¨½zT×E­›Ëd²šì¯N>©ŠH ùšƒ²nÿ—Gs×I}yhHn•óë-¿û}Ê^pRÌYþFÁÙ‚1(3Q|¯æ©•)"Q ï€×Eƒ#Æx­Šp}M
+„MìfÆ rž<üÔEœÊö$‚Óüš
+wŒ,f+¶G×|´:V}ê~'T °ëÃv zZ÷Hg9½yý´c¹ïðþ’2î%JÑEQ[ƒSàS`é]Ê®"`¯Mv"¢dÄÁXÒ]ã¤ðd5É_£ƒxÒÚò]‰†‘E+ Ó'§JÑž³…·:(qßIq`7DÉñonÏ[#Ö òJ¨6Ç)Û`^»$;½õ³í¸C5àiJxöà]ò«òL€(_W,²Zdy°j.è¨&oxõ1‹é³b8s<^ ÔÞx´:yt0ç>ê<E4ùð%g×06t曲TÛ åÆfþÙ•@`ÂòƒÇõÿ%GÁS—媎ktY)óå ⊬ cIÙô#¢>,ùçU“ûùŶÑÄæ«[ÕAŸ8«Ïs>¥êIMfMÊóùÇÔOéÅšµÆÔÇXä,Ó}QɯºQnßÄ9ûÔVjÒX¡´ ‹2$•A·‹—n|ÊéÖ‡•œÅQÓéØ*N[
+J÷3˜ÆµŽÓ0œ°ÞŠ¯Á=¢Òßß®[oÂÿµQEñ­E[ù8H#$*„fü€¾pGÎôÝ"XùÁ4æÏp»Z%Žgù̽sΧõ—i©
+ðr±žB¥UfÁ×:Ö‘-ÐPNÝg•9x9˜)”˜ãѱªÆºÒ·‡‡ÙlpRÁQÍ7áç^e¡2-Ì|aŒ 뺃
+˜ÌóôpJN?oøû·d¶Ù«)©7h™&;‡îð¦îÔ\&„¯¥ÌNóV¼Y G€î]þÿ€•¨Š¸¾ìß¹y2È%}ÀÒ¿—q;ÎEHEÁ—¤Ðvª“ßÜ¿<_ãªZÊÙ¾òúo8ûÐd%¬¢dD®ÇÛ Jalè6’ðíÑù'Äs^eí8nR¶ž5½0] )
+ô†$f \W$®¤:¢Æµ¨¦mj§B“pùAR*=²‚È1´•_Ô—“Å×gØD&üÖ¦S¡ÍÆ•Œ"ÉTL;®ŽŒóøÊ»C³°EMQ–lR«Ö®ÜÀL&]öÀG¨åÚ¯Ò>¢&£ G ³c/:ô¨¨)°rÁ¢$½3, çt­Ôlö®ßïž÷Íu>˜Úê©€÷>ÞMšm¬?Q5‘ÀŠê‡
+UÈfä!¼ñ}·"Žôu¢ÔÍŽÿa4ãÐĶYzîzdiŸJŽÕ›Æ'CR@[°wË5 Ñiˆâøù~·Ž£©‘²ièXEJ0¯´–@±”•D»SN€ôp×ò?™Âktå<^]—!o€Mñýµ×Ú²°#”'åÔa_¸ªKV™iŸ’ún§‹'Ì$t‡Ý–šõäŠøÚJz%Ši­?"1®ž×Çl‹A'É"9Lì…ˆæk+³
+¶½Â•;ïZÍCaÄáù®jmvÒÙÏ#SäÎåÕÔÉo·ÊGgSØ[{ò!£«Ë Ýœ½¾ƒ¥ï¡$=æ”4ÅíC96q®/G«Ž§†Iå¹YYàAÜ—ÐJÜó„ 5kx´'–*˜=œeÎΙib„¤ìý[:¯ŒRÑ»¸ó]§¤¨‹'ÒG"λŠ6BiÀO ¯]æ¾ú3+Ä9Êf1M)·˜áåô³¿ÔJžp§_Ñ»²ÐŽ&L¨ÈÝ|xáS‡<“˜ü®ö§ñù㇦8œ©‰§C*Wó<kþêÃÇ‚óW‚®KÑk¸®…Ø` eÔ«¦ÔJ´dúú' á1iaŽ.ÅÿŽkns9ÉÌßG'xÙ¤”{ñȉÒ*9ê;]ÙŠ±"á]ëy#Î0\›­{½QÖc†@N¡V+[?šoïLtãFýPÆp±¬ò˜ÌÌbb|‹ÚÍ+•d͈;¬ùº7BþXZ•PeÐÚÞªªLvñ&•ö5¹P16½1”Jm>$PWøu
+†½q¬ºúü.pVÜ‘ìbmˆ5wÔ¢@ví|âðÓ„,ï¾f¡!Ü9öŠ‰±<¡ºãÁ«Óç̲‹^¹cý¡´mìÖ{[Å‘òw%VîúÇeD2í¯0áˆÂ¨³û­Þò49.U«ì÷4Íb9mà®ç£TÎÞwMyu;g\ w!v3ÝJ{ÿƒÞ¤SV±úÉä¤q쥽m‚ ŽÉúƒ¦E]õ7 ~ÝÛŽPX2:±ßÈ'?êÏÌhÏRY=!FæH°È
+æ„å-b³E•‰I½B‡2í£K-üüü¾¸³U^Eð§Õ¸šã¹Ä¯þ_']5Z˜#B¸ÙϦÕéØnˆoŸæPb  éEè|BÁ&9’$-šñk]V6XcÖêÄЄ
+(Z½Àÿs~P`¡Ão>rÍt”Ô™ŸumŽJëTÄ“\í=>UŸ`OëBÐN¾ÙkÉ$P’ùšh«2鋪L2-¨Ê«õ”wr/'QzÝ#{ZdZËw
+ÞþHu雥i “>­ ®_?QáÐË°ÿ"¾ õr¼¶  ~q¡³äE ÞV•·Œ¬]ó7¢{Kk¬y1óAÏÛÌù›ïY¡yÙèo 7Z9;ª©0L©z“w%›Cn×^ŸNZÊêÞŒDJ–ëM­ï—åµäY&Åh%\4ßÄ¥ýOk á¡€’ÎO3ˆM^uˆV"Ž
+¹ï²bŸLªét}ò2B@¡KŠt!²1Ê´<LÙÒ:S"ê€12
+¾öS<¨ïüE‚¸¯"š”ÑÅä?«FKü¯ÐÆiYRU·¢œäFÐ=]7Ú9÷R¢ÆÆ:Ó߈¹zTÒoãï$#Õˆ Q­ ­ü´a›kå÷¤ØÑÇý^˜2¿Ì®SÈ@àAJ‡ßlA§‹¿ZÃ+_Ä †|«½@Uusjž}B|Ãß/ &£c-'ò$[î|È'Áƒ¢Õž I©Ÿï|Æ{Þ‹ÛÒF6$å[‹X#¡hë¬&”F…³•b°‚r¬gXª÷tJ¥Ta…<öÆB>m-IG0Á;íRÂ4tú˜Ô×Z?4¹æ‹•Þ1"S°¹¸AEµ™‰Ÿw¼><…;wle
+0¹€€æ ÂÏvPîÄl~á9ÕíHþ$8ˆëñΠ¤­x†þCN`0;·ªíS©-èUŒ’ 2Ø(Óo
+š¹è”¶Cauñ
+£!"I[º \çô²®‡­‹,íýÂX}G@Q Ç÷åÕû ¿$ë´ûÓµrªåÞád]ç¿ÀkÚ’ — ñüYó’Ø&õ¶c—-54<wê-cKÎ(ZŽz<½ÜÞV¥øÍ„†O¤S·nú9KÙvƒþRKÍÿOÜC„cWt5ûD™Šzɯkœ¨º6¦‡ˆÄLÀ¢„šxì½""jÒÐ>-q ‹b(œ1=üóÙ;§äŽ~!‡ÉÚµ‰»AŒÌœäý¹…§¾¼x1ýE7§ð
+$àAÔ¢Hÿ¯§»‡œoÇorh= ­“·+Ø ¹øë2÷Ê^-L0‹U­«+Ä¢<Pf¿.°©U3e–MõDQm++w–ÓŽÂjÉá>öÚé Ê Ð12 ³ì+ ìvJî$[mN¾îCf=ì=¿ƒh· stõ½æ@KgÒV_EöV…”h‘T`‚"÷ ¾5°±*øßBŽWÒdÎ`ã^Ž[!Þ£~ÿÑ÷F¶Jäp†w³¨Ø¢$Ätô¸˜ècÕõŸ×ˆ<a™„%ƒÿÐ4–¯qÅe_4à}Ào}ÜZO·ƒÐÚf+…8~ÿsŸaBÓrð:eÖY7iÀß÷B\o;èÌh…Oó U²ïß¡§“öm´¥Ÿ®V.XKÒvcf|ÃDº{8sè™±¶ì‡5 ÊE麰¾½â~­]Zÿ1öÚï‚fxj&s5®¬ØÏ%õ<º&Öæ騺ĹXÉ{X3·oÅ0…>x°9Ç?[Ï?‰Û“(’pcÜ9ïlhýÝxí}à‚ÍUbјa°®¼n¨‘ßôÿ_#|Ò¢Âm€3ÝÏyqé!Îæ´+*ߟ9DÎ'ÊЋøúÜ2=ìEIß/žJ'«#¤Z(!ŒZÔ—!}êØdÓW§L¬ž‡7Žß¤øø•¯o‡ø*U¸ÇjÔƒG€™BÓ›ím€Uaj ­ž-š/¼.Kr×l…sô;›,ƒ IPA
+•‰sîUýœç%Â\åwåØ+Ó´˜_Î
+ä,ÝžîÂÂ8U»%v GoįÃÈ›ÿÀ¶Û yxƹ'^)Tãšã®Ð—äFÞòÂmf{þTûƒ3ØußRƒ2ÌÖ©A‹€ngݬpj”=z¨%õšŽï-‡úº¿„Ùˆ‡}‡œÌk‰l‰î ›fn–°óV|Í]úϳ¿›k±Y˜°(·O”´ÅÊ$»gÙ‚äFHÐ yjªN)ÜryLÎÎ
+ûÛRô•l3ÿ$\'…1r@Oü)„ŽQ‰veä,æƒE:_oÛ`7ê5(ž%lpD3w<Ê^9™"…zÁäŬPú7V4ÇÊ…€—6Žo)•#:O]æ¤Éó/ñ7`ºúŸ™k8ýH3ë¯vNWŒò‡xÉ­˜ï<Ï!þ´—X„ó:°ñúŒŒ«Wl}^Äå³[Hv·2›lhhq;?›Ã=E}6nñ3Ô›ÎrHçµ÷çÏÜ,2Ò^/{ªdg8Aè'¨KÁcJiqÕw(À?>߬qô„üQVõø£QîÒó(/ z CåÄõ¨]ã¢ñªÓøZŸpßϲEaÿxÿµh'ÑA#çQä©
+=Ä”XgÔ{›±Z°®î@üMÐ_Èþ9åMsçpò3¤§¿ì{.³èm½WÔ >oÙÃ
+'ʉ'ׄ`
+ ×Mo'÷…-H%¯ºLˆé–*Uª¡ÕÍï/ÛÙÞ8@†½\ ¥SÕÙìõ‚Ý6fþ[ûŠÇ'Fxg8B,ü4ž‹èû_0K Ní¶Ÿ:L/œŸ
+øR±.¯6hV:x”«‰Ø9Ë‘Epb_ÄÖlºìLçiˆ‘b0)¹°R©íAhÉwŽèrYèK¹w 0r‘C4Á.vú‰JiKÑ_ÑËN=‘§ã¯•t¼ˆnIUJà¡û­H R˜6 ^~ë±eó(j³(  êfšfêÅ€P?E`ÒÞ<ñBÑ°+Š$[º¿¹b;àLøbz:Ãm$éªHQyã|r$åFÏA‚&b‘ª›Œ:®#ÅR¯FË»D¬½§ $;¼è`o>œ¾lwBOÃ'ØÿÞ ,Ÿ²…IJ2»@3ÖÌy¥‡ì¦É‰°ŒÊÿ• wµ%/ЯD#ÐäóÉczÈj°•tMÝ°Ó—­·ÖŒ² ùDf ÉƒI¤2®^ÿÀ¨ÆšfúŒ)¹‹`“TO\L;:¤kÕØ°m™f(âx`?”*(søñQ¾óõ&ª‰/ú;¦ñòyô´ÞL‹A\çlrW[ oc·'L¡ ‡µÌ:P½ÏÓ•CpßZ•ᾆÂíG€)5äýÕÁVЕEŠ×£–ÙžaÉMÞ.MÆÙûÑ«Õˆùûg’ÂkÏ{¹O 9Ç4åŽAŽÜ„É9²sÙš%Få’®înÊë"Ẽâ*’‘y;Å´ÆwŒ’[119À숸í²]ƒ’ÌO«á…:o0pµ’¥ºVIçR›˜à¦bü6›—¿ŒÄÙó÷»/Ž¥8§[\é¶"@°Mxž™zD #’Ò”¢+ã“-Ç»8 Y´zйè/ÕyåÅ/²Ì
+ˆ<ñ‚ˆ6G­¨
+?rŽ„˜EËPÔörxóºâQÉ1IɪÌQµèÉ°a }l°…½(åk.8(¤eÉÀrâÄɳÄDºO¹ÍL®M™±ýðg2>M|ïÀD¤Â{1!>ód{u"¦ ÄSå±hZW2ð€»@#&wÖýÛë¹›RíØ7m¦XAjÿwÌB:’ô¿´ÔʽÐ[»TpÜ–Éöª8d©‚/LÀPÑìzÉûbK%`†w”§3
+YyÚ(ó·åcÎïf3Å­¯é_>’¶:©hsÏ ØÁe‘v;ûÁ( ¾¯ Áïµ»oÕü<ÑG„Û¡
+&ò²Áx*¨Ë˜œwâ‹a
+ñ…ü•Ç‹;Ã#C¤ÿmýøÛ¡Þ®éhíØTÀàÅ>nBõ1”9ºÆÈÑw2x\­õóÞ
+qøÇØ=ðBU<ô~àÛôË0YPçz9¥x`!G¤Ì°àSŽÆ P•oÔ周arrξ €<Q‹ý©¨”"Øð4IÅ=co­u,30͉>ÎHt[Êö«Ýe1òöº
+)WX1N$‚Ò*DïÿÃGW
+Þ+vA -RÙ'ð4Ç8ƒV…`“dR+ ¸Ù¶U:k‘ÓCˆnXžµÅ!å’a7u+¿3Ó‡4™Û&.h¤ÅúÃú³8P®©îÏl.
+2þÅ
+4v±aßç)±›ûϤir| Ÿ€Æo¾+²Ûs;\£k½¨ü9Ë[sÚ€Ý
+>¡÷í£¥ÂS.ˆQ ìè!;ƒ
+ÅÁÔ×ຠýs)¤7ðƤ÷ ’9êÍL%šäáQÿ
+:|sAÅâcõËÔ«a’£ _hj« ±k7[ÂïŸÙÝò]8
+Wvä@ÿrîÃðŒMŸš9E4ø!ýã[J4iô\ϸ:©ïtP”@ËúOY«’ÌJ|ZË£*]DÍùWbÀUp;gfD¬¿ªí{Ý>ZJƒ‡²¢J$ÓÂ+}e´V×p·iåÂaµ
+av'•C5ZNÒ[¿¶#š <âÖhŠ¯#´NoDɵm¼Þ¿—É«í n`ªòžjFs|ÇÕsÙà×'×é|+’³—uWH'YP ± ¡³ÓTË÷ÞH`G²Êi‡¡fñ¤‰ëQ€2Ü”Ät&9…·uÒe/xNº†Ëò”%¹ÊHë°7xW½™Z‘.*øæpUO¡êÈúôqFÙ¬+P ¤„ñÆÊ{0Ïý˜xÆ-ÈÊ ¾y-¢Ã ‡ i:SëÜý<vOøÇÂ~8~# 6+lhå6÷Óæ¼8x; ·T%Ìä î¡üÚ™Þ¬j{èþ’ ±Ý¶ÍçË‹<Ζ£´Jq’Áf'y¿2^s'«,½O1Bsá¼7ÁÊ«tã>÷"™BØXÛµW§@¨rg'2­¤KZ3ôhα&
+y\nAR}òc‡ËÛÂ=àÅ6
+Ÿ`ï€å‰þT®·Ê?=è#ß2ɸ8þ¯¢tŒvúÇ“«/‹ÀæqïÍ÷¬SfÏž;'iFãÈ•¤iDj@'ˆ­z/,íâ$xìU EäZ‹Ê6 ÷ƒwf)«LÈr8Y9mKîBX9ãóIbÃA)9oÓ4 ö+»šÉ*J}ŒÀø“äSâŒdÿ¦›Œ ÷Ãä™ÇﯚWÿiEµ¥¤á1YΑ¢ÃÐaÒV¹û&GÂ
+×
+*
+Cy{(›•º‚Â:â5ÒL-¸}PUÉ“ â‚lê·‘G²AÛ}JôÙxõŠµ&(9ËtDãìbª|™î¶žÝ=ÞJbr§Übb.ùuñ’ΤâÊ›Ýî‡0ê÷Þ7´6Ç÷•'…kº ƒñ›Ž„‚CÇïÓ¡Òè’ôÐÍtK縢¶_»QwVÛ¦€”Lžhr 7 -£ñš³|Ÿ`f5ŸüŽøç¤ñ»²ë
+÷Hê÷ô•DÈTþ¦zt=PWþdrÛ3"›šÿÑQè pŽ:ƒyŠj¾{í$â¼ZîÏé»~bÞ}ÑC 'ˆ@¤:Ljoc8.‰Žëf0[fW‹„Û8I5ÕH·«8Íå_åصw1 ™YÕý)±PtÖ†ñÀÈf³®­Ÿ‡ôÑ‘+·_½™èU$)^wöè¯4ï/³ák™¨¸1P¶4Ïye ®Á­ù]™ÕbßS{š c3'ŸéœœœC©r²ÓI÷JrìÈ[Ì—R
+TrðÐœà)MŸ“[ijµIŽ»æœðµHFLKäm
+Ìò~%&v' iÑþ«îY$êƒhÕø0L?GèaºPœáe>=6ß!9sÚ<%Òýë$T_s»gÑm»ñä¤`›ï§B#@5—_@Íeðž Bâî>i;!vöÍ9¦³¦Éz÷ƒÄl”¡”(Aç9\,ï\[%Ò
+í6‘•?Q{Ã2Dbb17aøð9%úðkiÀŒƒxÂÆÓ(»f¹;Ú6nU8Ò‹¼a1_§¹©°_# œåÍlô1¦(m¸Ù8Ü!•¶ÈCþo5y_Ÿð”ð0“½×UÞÇ_)¶1$gê5utQ×;T}¹GÄÕ" !§­Ð”ÇHgµ”ößéè±[á{.}¸S:¥BáIU­´¾}íþ€w–À¨¿TV“ïá? yÐDÄü¡{Þû`Ò×[6’ K×ÊÒj”éÀ9m1„m}é';_3LÈð…=y„õËëð0!t6fÒå;K¢„mZZëbèûÍ<Š‘ bª -|Äô#qÖÃIÀ¶5ó À\‰t͉ëb÷äé²,s`¡\ánXv@è6f—4ðÓE´
+È$ ÷Jü·±`.‚—Ý©ÝiV;
+Ä9¤x7Í« ãÂ[’臶Þkf†iEÎÊ
+«³'|\ Å=}b–S!=‚,±ÇŒ¶Ó#ú€ÝÒ¥Ý “ýÏóU²Å§êlLVx£%!`™IŒ‹…K`•Ãkߤ%_}Ä ^'òí4‰ÿü=ûYö«<ÂY`t`ŒYå¹'œ¯ñÃQi{ÝcßÒÖºc2¯ ê…5’çÕŒ0m5jC™å'G8.’ǹœ`U¢Ä˜b'S+á–­xƒOØëv•=‰  ÜÄLTæÛá¨Ö>`Ô5¡3ÎßÊq»ÅdînìLp¸¤sí à¶j¢ÜË1© [Ýèn ¼ãs,ø"/4¸„íΟÁ$g™¥lÊÕ’Ü­’«¯’uú"Õ‰§V„àÔ)“àfƒŒÍ«ª«ér<ÕÙ—¨Å
+J®Ñ5ô96ß|Wò ¾˜±ž$ýùø$I‹Vv¿uãzCl«®ñBË·$^læšN‡£ðòæÜNÌ)|æWò§ï*÷Pb#å«Sóë;éÂE2ÌŒãç_þá:Fí¢áî·àåñþóMoäÒó)Æ_
+OÒcŒxê:†GŒV;‘:T9jj"„mï΂æ|gÍÜ¿fûž  Fó†1Ö*#—ÃäØÌڕ˵©r¨7Âë×Þ×ó7jÅõ¥8rí¢y ‚5ì›–gd¿ï_µlôIo8
++LóøK6̸ìÞüò_Jé‚h¾°ŒGk#ÉÓ°](ÒdÒ×`HGj#ǯÖådÔÈ¡Þ6’‡}D$Ò©÷p“duá=®§ì<ˆÇ†ÙtÂ<"o…—ø«Üc›œ)bX¹à7ª~JëíA\¯b8ÖÄ’.£Z$["ë\ z["nôJ$›ðTÇ* ø¡œ…++'ô ÝBÅG#Ÿ¾‚ĶŒZdõž‡E!Ô4½ÏÒþ cH"åÞ7èx –Wkns‘Õä¿,‰šXxXå8žX.îįFË`gö…ÝÊ2®í}Äxή.…{È[†h-´2•Ñö¤Û¤ûϸ)¢É8òÓUk.RÏÈ€öBãj ­3èýíÖ’ÿ\y½`îUÑí Ü;+óMâCžTóHÜÝwLSÒǹiÙËœ÷ ø^ZÕ¹Ûìéãºïðµ£I3pÊ™ÍnDʶElŽîJ‹¹ÓÄh‚1ÃV^f3œlí®½ÀBÕoó/ɇÑóí 9s8×ä”z#Ô]ùž‡¯Óþ^ŠX¾|åzÚõþš)+ÅâKãø3 OÉÎ>$WðèÇtû‡=›½„Sý§‡]5Š—1˜£Üj€ÏW€Ã^»M®r¼ÝêÑ#y@Ü ;6{nœÚ‡íÄö“п%dà®sAPQ‚dª‰§"û›¤ª »¶u›Íßsµ:vÚ *¾¥$0Þý‘ØQAp®t„TiÑ&]“û‚ÄI%pC?l9~p•”þ©€JÃ(”Ó­ó_©™ì»Ïm®:
+g í}B-b ÿcá=z ósþ![mwi„1Dõ¸¡é-RNo‚ß~šÆá KG`8)ëfëryzé?ݱiUÁ•!N- ói°zkçË‚jÏYÞa›·Èìè+©ZjJ,‡Ö`ò†Ôáuïù²>H Oó?ŽÌ.g’úÊ .ý\<˜iÂvjíϘÆsFñÂé6<’
+ªÝ¨ì| ÓX‚'6Ä k€ ŽTä{ï?ÿŸc=™Z‡ÞöDx«Õ§ÉËé|4÷‚ìþ¼%ÀKûe½N¾
+àF+h6ï^GÂóæÙô¹ÿVSsãcmÀÏ­
+ör6¾œÍ¾;5aˆn”²™£«YS ß?óâwtn"ÿ âŽož™þà‹0¥EâkØK©ÞÒÔA0V„cèÅ…™©³¡ˆ.ï_¶û„o« ¥¹F£^M÷ïÌø\~D-2Ò¸·ˆî Ûô×Ä[)B‹Kpü ­¿ç+žs>4€w¿ ÛOçO[É°0ìX½ðF³fÝcNŒ»AfŒqçDi5бcK}WB±.4#ÓŸ®0>\„‚ÍP“Ê2>òñ·€Œ\}vØЊo7^|œïÄ
+(U°v  † ñ”‹Lz©do!Z)³b*4ðU`jÓÓÕ…óºô‹Më"»èIÌ––u‡/¾lÌm‰3 Ü%»¢¬Ew_‚`d d5¯nvò¨äy£³ŒIÆÑòRy\$˜Ç-§k¯ðäv† vN'õØÎ'‰™ÃY>¹­ƒŽ½ÝB‰)3J¾Š­ÂOŠÔ$¬ºwÇW’ø9ƒë?+Žx„ zaA:
+ Idä¹Ö ¿Œ”ŸýˆD/ôóÊY
+ª3‰¡ÿR1‚ x­v?Úi…˘’í”Lت¡apœñKŽ·€W©ÃtáÄË ‡|+6//•'7­j¢:LìcpÕ‘Á•†Èäû¸Ç‰39ÒÛpß™gUmø®faµlÅîr˜«$ŠÎ€a»Ë«‹ãhÊ«‹+*sè#*)V`vÔ)bhjþªÌ,ÕrýsK™Ø“ëøÖxÞ˜ºÆ·ö÷,IS`R€T’ý~]ž± ¦+Aý
+GÛ˱lT+ÄßÆø ½
+qÇH+mÊ(¯ ^µ,âWǯÜú4Ìß-¢\±â>Å„4ó]¼ ¦¯Vµ,útaÀ×ÐÏ~¾,} €ãÂû¸äaÌq¾önþ5"ª“Ÿ¤lù‰±Tùcc®b·+û&c´Åô¡cY?é|Õ“ö)©b¨ì©"›ž©ÓCt\ :òãÍ„wsS¾&w¯ùÉ!vÎ캹—ÕžíÈËêõMóþßZ€(t˜¼-ƒ£ø}*A=öý’ýc¥‡ÊaáœÓÓMÃé¬Ý•í¾OÈ­ |Ù³´™ ìSYãlEÉÿdänZeYµ™ìQ‘a9o1š
+lB¥š´ž6L¡²Ø£Wô:7¬£† ¨˜Ý&'¤Ñ´p¹ï˜&FV/cfòô[T´Z½A_™•>ÈôßÓ :ò?^Cܼ@ºùÇîy½Wä»b·x¹
+Ìô/Jnô}½Z’œ÷*\µ·…Òi~–Ái™¥¶ r$¾–ø`?!î.ªDÑ̈ŸÑqÛÜ7l¥}ÐIEK'0Ê&e§þ¢â9T7‹š…,oV<ÃæÛ0 ®lrgþ±Û;9fuÉ@ó™0”k*
+»-ü¦¡Â“|ŽçwüePÁu"(‹7™½•9u¡ËT_x0
+ëJ䜥áí{?:ë%ÚKhÑtàúý½µò ]­¤†ÓÝé/n½$¹@ü¢A±äL»lž°³wRôØ;3ÊÆë3œHŠx1,BŸ0Ÿô¥ÒìHþ›[”"!pF
+ÄLÀzdá|Ù±§Ûâˆ2›2àqo
+—ö~/Nc›îà1ßí]èóAY¯MÖûLÏ"@S˜•úà¬xh¨L–þQ!B_,nź!iVe6LzÇ%2ÞZ‹C"ípòX…Å.þäŒyMsÐ ÄšWÇÕDâšãKCÙ41~ãÕ@,(°ÃC§ÿ4Ü®æûòù÷Eí?¥7@}Mó¦yÅñϯ©6 Ð1š2ƒexUBŠfÑûÙ{Û/áé6½3‹É}e0—â’ZPý¤á>ʧECƒ†¨øA^‡!6";|Òi*Bo-¶RعÐs._( êì«¢ÿi¼ùºyþê>BÔbÞæÓ‡°¯3ŽüҬ腎rZMkÙàF}¬Q¶ a# @ëß~#¥6íõ2¹€Ì ·Ÿµ|hýŽ ¿h5¾ýC0BÝmQ—•ÿ¤F%´©·qQ±bÿ¹8IøÆE¥háŽUs6Y ¶:ÜÖsUütØÄCG#Bħ¢Z&ãõqÿ*R¬Þ[çX‚@SŸ„s(S<è}0¸ÚÚ’!Q[‘ ]#+‡ä&= ]Ÿs’øž÷æÙ ™v!ôÄ4Ö¡? ðß¿YìRSái/ðÐÕk=)t¿‚Ú·:‡M`trs' ÔᇬêÁ(±†FhË°wKW·Â¢¡·gÓX%óÓëvÊESÒ)PKa‹çCJnXáaävôNÓ6åFû?JÔû4FÔ‘ 6ˆÈÐø´*s»ÊýPœ_(·š¾e®_ÌoÏ€´Mm›7}P,½ëõc»òJÒF¾_CŠ\IPÓ#¸ü¬Y iÏ<Ì(ž¥ÖFŠ+Cx ë
+Ú@$ë$Q{/Sç¶p©!ˆÎ,Jÿö×…cðu º{8ÜœrbÂIZ:?X2ÜeXf~…oB~PWJ%9¬pÀOˆvWhj):ù«ñÍ›%ѾD45zRnÇWà3l)"QXo¸ªyeíw— µ/QlF$]õ¬¼ØbUžˆÔ™ÒØ+ýËCëh]µ»‚+ß^ˆýèÁÕ-  ™ Ê;`¡ Év+uä¦çÿȘÏUêbšwåÙܲ/k-K× B([ðZc’ø;8¹æáY{û¬æËp3ë
+AË‹,¿’_>‹¨Ä°þ/Bûé¢|«¥r¸Þ—™ÀnnJ\å·u¢
+G8g¬{¯&˜µÜ¥RªKáx2ŠÜì72Z7%Ÿ±s£™ß ’M·uÕh¯ªWÿB˽箬Ç<PÃ%åt‘¹K¾£¢ÁƒŒÀÓôÙ0·nÉämìŸE¹tå±)?¶@Š?~0Š’çT„ ¶ …`V`u&¾kÀÌœ§×UvþÑ;JÛ{ •¹EÝ”u_ïb·¿yôe‘«^Uàë^‹°Þ ®.0Ö+†'=n‚ü‚×UŒ™Ç'{(úæc…ŒöJü0—#+ƒ¨9¾Ñót-©ÔÝGe"Sõ8fR ¸Œ|m†gbãM4ù§èM¬À5ÚÜ6¦½«{ób·Í¨3‚Ë3žUÏü­í
+ø¹Ða)¥»:m7_”Í =cä x7ëf‡˜½ÏdbÎ…rupÍ$[÷ce4^¨ñ¸i–¾s/bµüzP) "é ó(„/2<Éž¨RriÊ,‹/!Ó']Éð»I*þ/£ÍÚO±&\;§Rt×É™ Nö/×*‡x ìGwXxä$©s7þéy¼óïfÿeç6jM’@yk£Hî"«‚tçyÃÅS´;¼t¾'í–8oµxé¾Y‚õU¾ cóª€`]#Ž€h,Þµ\u‚^›PThñ#9úîéR>˜ó G¸½ýÎDµ|ßu›…‹óãyßû¬ìÑ<*š_c Ø-ùpŠ W0"*!ýº&H–yNb)F¬ŒÀZè+Ȥ€uOZOs‰SíMÍ‘ªÐñŒ!ËÚ)ïs•ñ þm½z¤€‰å9¢sFQÚÓÖD;-V4ì&šÞ›Akq$Ûèë05ç¡í^„Pc©øøJ#Ý`׬CÙâ%GOFPúÞnÇAx[JilìWŽ”ö`\;¶^\ef*Q ÷éÝDµC<ýj‹Ä–þ£ÇÃK¤¬ˆ»äIJÀJu s–HçöúâÑ.*|dIÛe…k<3?¨8lXŸ£~Ô¦Éø¿¥F‹*£gÉœYäHôosÐÃ;„~òc3*‡Q6›ãVœGbµma“²þõÿÞFíõÐñÉôL¨œˆÈ_bl„q›='‚TfãÿÙ/SM‹÷•ŸÏ×ל¼ŸRÏEâ;2¯©+ÞXþšÒGzñ4Ø[äÈ=WD}Hˆ}PUÉ“ â‚l—§šRB‚€xÇKç´\RÍ„{…Õâ9Ë%8²’Ö ÌgæXȬ|À„IWD¼DõŸâ3nµõ@æ]Y“Ú…Ò·J´©qéà+Ñ& ú)ƒá—(üÊ¡N6Ž ¼æ­sú£)WÒÞéS;Bú®“±+`3åþMA|žt»_¼kK«èAròòîM¿›ZîöÀùÒtp÷Y{êœf7û×å}Š K0à> Aâÿn¤À¼'ÒhO„W šr­˜¹ªu )ž…ŠCEšg„$·}e»;–Çw)¾Ì"TÚC?ÛԻTqŒ4vsΉõúWO‰‘b„ø˜\˜Nnðœ€bìKPš³ÉR¹vÖ·j0§YÁzìyÅÿ%Ç8JÛ1+1ñ‚ ›:;™„é_Gû „¡'ahžðjºz¥7¦|ãÈ_ÛÖÿoÐ&™Ú½Úñ« íʃ¶”Ÿ«sÆ
+|ÓœÓÐ+îÌÞ÷ˆYE½ZM˜;cÊ°€§’ø£gሺuï½¾Ò›¿–c¤0çios[0¦<qݘšr 1x±Ø‹(9Õáu, öÀµÖåP¤GÞﺻÝyGÿo_müÿI¦‹¥‹Ê‚ëeõË,r.¡¿
+œÿ dt¾×¤µÚŠ~«ùÍp£åËh®Öü£íÔ‘x Wâk±xw_¶èê.(§õV5ㆵ[˜¡\A8•7ÈGb°³~?
+CÜWTYE3ÒWÔ6—¨£­Ì+‚ž0X®yD×)y±+5\†‰@±FÛØbt‰@‡>Ÿ+œ3„Ó>#()EÇ~ÐÆw`I´Â&lŠÂ¬©¢ -{z«/g8SMÏE@)•@¬
+-\²êf|ha
+¥'膄ÝРчO­oÓÞE¦§ýšD$CdÇô) YŸI'Ì&äc² EË
+Œ‡}ñÖÑ¡¿zgžTË5ßjø vˆ%6yñ²6õö”ì…¸;°±ø⡪yrOj ñX;"Ú?šqý»Flô¾ªÁÀÖ0¡È<Œõà>DA®é,-ïC6•tŠ\̲z”«‡•J”TÀÀ!y¤Î¿R¢nŽ”¾çonš.|
+ŸA[äl"eèÏ Y´qPÝ 1b!û¤ÿ'ãäzàŒaQ_«6­N?˜K$–^H£¿áïµ)ÙKo£¼Ã-&ÈïÜE_7nþi‚x‘8TZGPÝC ¬¾î°ó¢ƒ?„Ï«Ýkc)>3ˆùÏ ™†¹!`]I7I%›P®RZ˜NÓãi?N–¤xÛÄ×£y«ø°Z7ý±ãØ›ÄÔ >sV=œC”¿e}¥@Ke(+¾à.YN](*íco^gb#ÐX¤†ÙÞíA‰½jQ/‰˜2­wÈcê/WØÂÀ‹SËî·«,5 1w¹$éÊÀðÁ6t@C`ꇭMÜL5 ʻ金 Çã <º)þÿä@rE•:ÜÂ/Õ€ÌHe“š=ð”sð¸E³ñLÀæÿ×ç[ÁEÒ{bËJQ…Ñ×δ?™#—Á`³Uwyõ"wý¬@¾7N€©Ïh›ÏgPzV['mô«@½2¼¦u²|oGÔA
+<å­¸§ëJ¦ùQDSÀ-­Ó€a1Ý‘îÜÓ%a|×^Ÿ/<8âêt1fæª.ô¢T£‚9‰ü¹Œ“M{yo¦Q|ÆìpØ K| ?]ÿ¸Ÿ]Läu½Íp1Oè|–UÝZŠ G2|§ê‚´E„?¦s˜‹ ©OSæLû0\hJ¡A…ó"çê22x”# ôš-ªøªÂ ÚöUÒçús`Ÿte»å¸ã_ Øøl#ž{$Í€V¿Gú $1Ñâ“MØ"%?ͪ–ƒÓ9íÅ~Á©¤5«ˆÃCR_”9ÔU×»LxÈ–çHPµðæÝèÃ74NYĵե¼·ê5«ÝH*Ì–¸øá›Pè™êEjjúD˜ü Vsï`«îð[fvè†4ò[›5Üwé¬7yxŠJ|\Q)½ìJ.Õ±.ו)KzClU¬±’®žü•hÿ“q5†„¸¬Î{Ǻr aŸ/Èe+¡¿eeŽ:¹ôÒîù|£ä´>¶Èבf"õrŠÁËk|‹XžÍʼn—LtCÐS~S™C
+QÏc®ä׿ñŸæW${0[™®qͱÛÚ†Ó×_€´8; ìi›­ëi £åQœÎuüÑ3¹î7hv ÷ݯ¦–HE²®E²ËƒùE·~«
+þÐ)•kA¡îx×û,§ë¬n @ƒhÈÖóШpUzIÁ‹gb4²Ù³
+9o=ÍDS‚DÅu!Æ“RªWûÂn¼[X‡¢û`«=¾ ú¤‚¿BR{˜
+Óe•TAc–H夋êÄØx–,%¶g›ÌF×
+\Ï…vTNj.›±o–—m¦»“' w£ S?èÊ2VñÓX5â‹‘2¦ŸëÍÉ x¡wŸ…pé"9Gƒ|KÍO©îåè#4˜Pb»r´=T‘á|¸
+·þ@Z'ÜÝ
+ÛTÃÔtRóçc8Ø#¤Wã #¬o.7»Kß’ eQ/L‹
+£NÆí“ Ü{q0¸ÑÍ}?3O®~[ #aSª2ÃÜá¼zèÕClZj‰+÷;íS=]שX¹#­ Ö#9™øÀ:á‡9i`sñÎ1?äĺ&O;Sš•Ü€€ÚÑ™ü‰¾÷xnC¶ÄÛA™}ÕÏ÷ °]xzïÓ
+ˆ9ΕKp‡LwZ”¥žcü£Öø°)´0xS>#q/4C%Mî².ˆ…X»QÒz»$9"4ógÕG#½×°ù ÔH~‹‘W;¥’V¬šÍ¤(d‰wÕ6©h{Ug™r^Å™©Þ~éò/*?Û{k y—‘ƒ¾Zleã?hɇµM…«˜ªÑnÙŒ¤Üaߥ7ÕFdR; ´ ´4¾°ÜÈø‚/ÏU@¸â6jÓÛØcã#æìô»» »Û¹ÇXø€±›‹u¦X®Ëˆ&Šþq
+8øoþ––Ê‹w8È=¶DRæë2&v9«¬ùŸÃVR쳨_ˆi7ƒ…¼×‡×ܾÆ–ùúO<5Fƒå;æÆ%›’lƒT{Ã(߸}ŸU
+ÞúÂßânÍÕýÇÔèødnÀ*›è´Šþö{dpNÆY!RúEמe„}™x2¼IóÎb=w{­° ý³—­¦:‰÷Î ¢ ƒtê«F<™~O-{d¶áêãBá[.Í~‰®XñÞ°7÷@î‡eP=¡¦i¹jæ¸RÊùlzW–}ÀIÊtÑV*Õ^Nìû[ ­`¨í&÷8ɈԹöV2¿íjðåNÑuÕÿ_Ç—k_­•;+¬aUUù(<Ò' çU­rþΗêºÅrÃ)±öE"ÐÁe©ÀÙÞU2ÁîhýƒszOuiˆ»XtõÄÏ3OŠzWËh3d‹æ€ô³©‘ nn襉:.ß"¤òd­½ÉróÆ:%fÊNω¿Q1ÖG÷ë yñ‡¯ÙÍ_F_ßT›­™”ÿ%¤Ë4··{„Qñ+ä="ºæ¸ˆ“drgnXù˜å÷»ãìzá?»v&ÃÙp/ñ· BÜÄÒ‰„T¼òȧòCÑck¡Šjà|›ôÃR;¬öé‚J3$Ë,ªXª«»œ$‚Yëd~@]Â’ÚSOá^iï)Ûòܾ·¥žxÕñð‘ê€|õt‘¬}„ÕÞ~ ÐE;'-â/ÔÐè¥x^7㙪 J@|z=:Ö²0ÌI³Ê¹¾ v\<ñKžS=¡Ü3¿´tDÓì=SÀH°¥ÞÉ6Š
+8v|Áp sÑòÑöØp©Û‹V+U«£ ªp+{GkÉ–•À¼ø7h?C=UÅŠo|ÕŽ/uô ‹„H‡ >káÐ @XôÓžB%εWÝÙeIƒzƒn=/¹uüåÀÊkZ+%­ÃF®Ë©K%¡ä1}ªo›¨"z9S$,ÇA%ÀmdÀ²jy˜6m-üL%
+nÓ
+P<|½—e¹«1«)ƒÌÂÊ“¬ hñrù ÊÙøÍKwÔÌ Empì˜ú~»0„°’‘ûz¤¬Ë5€ ñèPfΨCÿÔ‰B4gz¿ZþžzIEç#˜e&·±BXö#Á6á6:0ë’Ãó\zF'3‰í t$™ƒuÀ/©P"–8¼JéÀC Jëq![[öÉXMˆ$#à&ŒT:€Å6­M§·¡F[¶Œ¯º'•E˜û‘Ït—jä:ƒ2Ñ“)Z¬×©óëÓÏD“²4qÒFƒ£Æ'sI,ûI:Aw ‰Å0a $ªËªjk,öŸÙ8©ù×M¿qÒ¿Š·… ú0UÙ¡b£\Üô]SeŒÈjåè';G|J¡Ùæýäæ ïµÖgšÉ[ø1–L‹ýÍ —Ü°Œ
+ô~Í®à
+ç |ëΆ¶¥ÙWb“Ñàøo¹¾ dGgúpfë…VŽëjÙÄ+OïJTbÀû«<sÀÚò¬ÛB®®"CØ»uâ¿{bz™ç°²g†@\RJ©…ÏZ¡Š`• HüQÄ`y÷Fò*#´5v56õc2L¡ù“|Ö[õÍøÚßF¯)ŠWC7oy·NÿÜÕ*¦Ó6"ì~h‘òóÉV7žiuF»¢õÕæ#À(aÊhhì¯$açZ_D½ ¿’gÿš¯"bUüÇRò¡mÕÏ@âžáé EÖ wëÕš[lÀä:¢dBa“ÂnC`ÚÑ›Щü¾ÀÀh­bë]žJ¯Ëš|ì?e¯U
+LħW·d[ªÙ€;ký ê^,Uÿhö9§Õ|0Y¬_±V#å$ñ‘|8È!E·AKw7¹ºÇÚ£·èb+5¶Êy±ß?د¬ÜÇ2Ú0o6è§hÒ1P£`ç_z—}Ñœnu¤Ä#¶ÊÀ¯>ŒŠN†5¯¨­W]RZÎ^AM(Gz®ñÄëV9–)}–¤é£»ýGXæF ÃëÔá¥] Ï.Þ»â¯ÐùtoúŸV¡T‰Ñ ™H1A Ë1Øo6+ÎP$†w™#,y,ÎRHú2󽺬ØV˜u¾†±Ã²½)N*ð,®¤…+BòDŒ¹ñ[ž¼W ŒÝmPÓ³ƒ«ÝpµQ9[f£I¼êlplRK½ké‚Øc™%\ågIî¶[hÆ^[x ôÁTn™Žv’Kº€t¥šw¨óùÎ)ÞL`Ç'Ä’2L¿ûœ°í@l„i>X¨Z…±?bQÄ|$šÕÎrµä;°\X?È+¸–0‡JÜ<tR]öÐmxD|Û)þ#@Öÿ«BíP2@ÚUÁmfV+¸ˆˆç§dc§Ø=¥^³Í§&œåYœV2~ß[Ó¦!¿ý(¶æ}»Nÿµ9ˆfùÝ/¿â&Ñ.2ª9f÷~ î,D ÑwÜVÜËXãƒì»Ÿ¦D_Ú­÷gLž³PŽïœ.¼›¯A"(<Ò±ùÕð
+¸ -îõ Û8æ&”ž:-¬|Yâ@L.]y!EÁß3=‹õ5aKMµV`ϸ;!ÄE‡Ò™ƒ êÏ–$2±žãyCð{Ýg…ºÃ¦Ü< Æø~p¾è@†2.x†X@Ö23»"‚5Lµ%ãÎ °ùoY4»¬–ñ“‘b7MÎ;9tÐ\<‹_eŃŒYØ…œ)“YÕó}Š¡ˆµ‹™ 4Ï}>ŸÍw“_ér{*’ÞÊ€¼•Â»M›™˜ñ•ÉÍ9TÛ¼Ò"dxÅÑÔˆzýªŠèª^$|y̬ÁѪLbe^v×pØúi{õΣLO/7Ÿ[côÀ³žÌ½¯¸ÍV+V¬ú'à”pV% U'ü¦á¥|dòÖßÌrC£-4ëワ¤Í‡ëñQƒÖåŧ
+iÜ
+=7.À;Ìô>¾úÃwÐa{÷x#º¦¬‰™»¿‚JðÚÏR2 3d÷„2\ 0¸ÌQ
+$ë^3°h]ñ´ÚÏ> Ú’ aZö“·¦:Å ‰…M 3(ÞL–¬TÞd¡Ï%¶úƒIé f?I£l(è/%Ròï2Až'Ò´‘ìºÂ^*÷Š“t&¾¥ž1P¥b¦–)þ«Ò „ë©8ZR2I1{,¡“¥·„3Æ4ŽZX
+"‹¢Žá¼M†í¥ÒÓ±ç^ÓMÓdï:W@¯ ·ÐDEÜ\ Àÿâp]²Ð‹/ðl7ÌÖ,_`OØí:RÌtgæaa–YŒ˜?@ôvÚšè2‡i
+³„HªÝƧ͆§ÇÆz_Œ&ëø6 ²!@yµNv“
+^ìy \Ýü¯íP´™vŸ^&UþÁ‚ëAèaDÞ+³ðñOX,ÔZqúˆsóÜʵ ì“2bÛ«ä+¿Æªëίêª×Ik±É¢žOåûl>Š íx+ßç‡&g@qJPwCú7uHhfObM¾I,5Œ>÷!ÌíÇ°L"]ˆÑ–÷Üq«RE¼Ôï=LxP'åpA#5'M< žucÄï¤7° 5‡ £ -¶™j…HEŽ…5æÇ̪º© ŽƒŽ¤¡ŽÂk£s–ù ™›£XÀD^IÖ<*À?ÚA«1ÏpÂÍÙ­Òÿ<Úà`GÀÅI€¹„lËÔÑ/V¤¤Á£TD#âÚ„%Úð¥ŸKVoõÔ\¼íà²BJúËèûégø0ËãËDb¢xcfMç€4†Üôº®iûu¢›ß ê,RÕÁ[ßÌG`äÝöÁVLúŠ!÷ZjW:3¢Ví0T3³`û~ô)t0çú›³ø%€",ha²d¤Û“ÛVcñ»ã˜Vg¬p]‡˜{²ãQ§Wªòôá…¢°;6—Ú!Õo™¬u¨kÀÍ©Å’£}3[Ê;rG0žÐÎÁÑt>Âj×O·ùù*š²jMÿÚªWÑB„u[)WMrÜÎâû/øÁÏt^Zì§>]eŒz®)6†äÿ£2ht½)—šù"b{eÁ]×oÀTz·nÏÈo¸€ÖNzÜRjPtô2äêü—ˆ LçpbÏüš?—RyÞ.ãýìójé|/ºèsÚžoÓ^^u¤fjó:§ÿÿ­ ó­ýÿp
+ŸÛsò(u}8i@òYµ—D3ª•¯n>LžÄb±shÍB'R^pKÚEÜŒž æ3òÞÇE,ëI>*'´¢²ˆª!®4ƒ'êK^í&Á{KÙ1ã:ðQyn‡Ç­têˆû^üMó‹L¡øEõ~{O‰Ð3n…Àz`>Kïri0u%·ûÃÃkcÆÞ=,ÏxŒ­ûáã}LRÖZ¿ÆO«núÄ[Á{£MJ– qhO¶¦bøÊAV'Oé­˜‹¯ˆ.þ瘬<5\bJ=Á¥NAÄ!¬Ué6^ÔÑM^Îä$ûÕWœf*wúËŽhžK”Ge;ÿ®Í;: Š&T_qÒê°å è=Š‚Γì=¨Úïy¨A}4™V–ŸŒZ(*¯êq¥P±‚ïpÛÇŒ‰¬Þz¢64“Vx#!å=¨í©}«žg/Eê m¨B‘˜^Ê nuºÒüõõ.y8ÁJ¢™EN»  çþ
+m³:G¤
+ƒ&-Φ‘^ge íöÄäþ*~ù7û¯a¦@Âml`¥U,÷¸ö_ÙvT( è o§õ@’S0`¾¬ˆÛköî5ïI5õhÍ8xgi‡>z1êŠ[Pt¤cºt¢kíK0t²úfÌÕl˜•—õß;ßrl>F¹ôu­ˆÊÄMùŸð]‰Ìoâ oà H¬¤ÏRDø$:tQ¹MÆ .#O °e ÷’þµ»d‹è/®Þû ÀäÉ †
+n,4ô àkP×7!²Å˜`7ÓâSfs/ö*©7¼n–óD3/‹ ¾Þó0–Úì‚ü‘å'Eò´‚Ò¯øÖ¬É-î Ý©6–†¸ÔÛÇÑÄÈÈ.á· dþ•“Åý˜à[½•üž5e¥|cc¦ŠËòLqŽhR¶øŠfFZ@‚¯²Kz;ºržÊÓÿ5ÃÀUžÊ}!Ĉáå ™ËÈ·×ÖêSh,$<;™Åßã-Do08b’ŒxRon
+×ïVìŽ{»CœƒI©ë‘câb<ÊÛûPvâ¹nÌï!®+"*kóUÎ$Õw
+Sù©ä†$+G–™e‰$¸ã’Xãàù‚TH7ÿK"DË!$õ¸©÷ßäCi”»ˆq??BÔrˆÝO5ûÑ…<(»ç µ‰PÑu‡š‹9AþH´Àrv^~cµ±|w•möÛQØæŽÏÜj̸~×í¬”µa€¬Ó‰€î׸ªÓìvc
+™‰¾üpYš•Ê¦ù÷óæ¸%¨áÖ¿F¼öF¿×2ÙØžìWŽFC0¬JükWë' îbO&’J=cUq‰ßO/“Jã^øYÃD=رq'fg.G6y8íÄDB_áÆø¾®ë;k/|Ä+]Û"ªÝÝT¦¾ƒwñîÒ/4}s‚Զ͹çÝ7)‚ukg gRžyÝÕ¬%{¶BŠ˜Çc&2û5töÙCЊ³ˆ±áüJVØ›Ðײ´Ñ=ð_ˆÏëݪ_”ÿ–óµP^øX®xßiž0µŽ³
+o‹QŸÀ’{ÖÜùÖNF8¤‰Àd'Em à½7+/`Ñãzü*芮¹%öt%fd§ðÝÕÿ‚E±­zŽìָݡAz=-uú%ëûiH¥à‰_è ÖŽ ºU1ÌAn”
+J#™ŠB1† ÷©i üôG§ …U vÔ!µ@ÜÙ€dHú ýÙ*AbŽšV÷™Eð|
+Ó)ÞÝŠëëÌ×FÇ·î€c€®3
+x†ÓÐæ‚œ\W0Û#LhÁƒ¸ ÁG˜<ßË~›H,ÁV9ûÿ¸çxd~ä:/PÂʉ)/¼ã åŸIònâKª~ª^¹ Óÿfü‹0n5—¶Ÿæ
+”ˆfFY~ÍŒ¾ xÇ>§ïÃnúŽäŒ`okÄÑá ñ]HôÏ¢c<?7ËZ°,)ؘúgøÕB¹=Œ|¥¾ÂÍÛæ4YØBÂÛ¢î>IiËæ)g'úžœ¤7•™‡¶§ a¼O
+SM’ùœ·†£ÕYWåf"غ ¹Óòø¹è´ (ä$3×.|1wG…Û„Õœ¶
+Ëmà~,H˜+BS'Wt† TOPòû‚ððÔÛ¾qróãÅØÒößO²R4Š€ÓqLZµŠä`÷¢qZ'¯,̃K¶G¶¶èâÓâµk@é'¾3J‡tKñý pâ4û%ìﮞJÜðe ½‘7üvƒ°ðJ!ðFçCÙñÿ¦
+Cf¾îö­ÚVs_º®ô+$¹PUò?å'*ö€á/óÎTÖÛ÷“
+îÿM:NüÉW/kñ#K@svE¾Kïý⑵×Mžc˜—¦‡ôƒ¤ÉT„åiùšj‡Š§Ø÷b` JV0ŒKR¯i™ ;F¶Ìž
+Î`ö‘á aÊŒ¶8©’›Ô;Ö¥&¡@Ò¹åïkô­„—ÿ£*…l‡ïªöŸÆöpjQËãÿu<Ig¬­{GÙ4C”‚ÜÀ’†/+Œáá1[a„’$K]+Ø»jiìxn5u#IŽÚè-ºŒNû©¨ÝÆæ¨$Ÿ%h?“YQ‚ìº/ÓwpØ>”€£Ù]×j‹¢í¡ø²ˆ ËâÏêÖou•T)gËŒ‡ba};ô‡çFLq¡°S@@H½i —’.útÛžÒÐ
+Q®n0ó1^ÒG¸”x»lw¯K*aÈàKeÅooy˜_ÄȤ5_fäʨÚÿ‚غ˜
+ÒÜ;Ç#MÆ®+üo¬ 2QÐeM…f«„Ç«^í­—‘³MÅ©‡â8Ÿ)ØQŠœãü‡ö˜7\àµí>›†{¸ª»ÇS¡Xÿ9ã“ Öš™_˜’Vº‘ú‚„K“V©*…Ij¶®ó´²kV!‡C,­§eËG‘/ãS9Àdh:U5 ˜À¶ž§tÁlZ©¤rHÁÇD}‰TðŠr‰«=b;È÷³~ÀGðÇOœ¡ÞœjU‘-ÚÃyËLì—ö kUñ ×8PQî×0¹YæŸ"o°
+ }ñf*·Y=æäu§TìC1·›´ _ƒðG0*ݺLd<²2\å,ýj]øßÛX…Ûƒ¨©zbÑ ÷K‹”ß;+9íü`¯1ã$CÕJýž8ůj®ž%U75FH}]¶aïtÛ1ç/…½xú¤Ó,ôÀÜ#$sâÀ8Q/É´ a7…æø«È|rÃU¬¥jÆx¼ÏZG†ââ.$
+Ã.ñ·u./èa~í9ß?¢é°9aG!p¨ÊVì)I nø1¤"+¥ôÿƒdI\ð±>[U—y¾à¡ê,²ÄèôïßY‡¥yP©òqEtPåXŠŽ^Å€jÃÉñzë ô}ßYp…5¨ ˜ê9
+99¾ßÄ­œY JðSº[ Ó—Òáz"Náoc€±UÇ»ù–KP܉¾*ë+Õ1Të1O]´}èZï›2u›:Šƒ¤
+¹gCÛqYz•â_T€4\ÎÙEjëÙÚ '£ W½é6fewM·vþÖ„‡Fž?2ÍÿNØÂU
+T}—uÀ$«ûتjÑw±£Ñõ¢z[éÓ ´?/q$•F.‰¼fäºéSÇ„$ž\m¶„é¢zKF5.¸45úhs¡}ÌðÞ
+ò–‹Üº²&Îü ’¯9y¸A ,D2;¥ã¿Ü¥.jêY?V—ïÆIÜ…q(1Z–Ä­¨tI lÏqü•NÂþÌâ†, ÍgK¶© ?°uaé1Ñ€£·ðZ¤%ÑÁ­Ë
+‡Ãz…wPµMšˆ=/•‹Q‹º*›P‡6HP=¡ŒÄY¿½[îuPs9Üa«Z{,¬D7ì)P úO æ”ôö$ÕÎÉ4%…uöïNl¤F¤YÞ}_,ŒãÖ ØéD¿_”ÿìoÓÝñØ%ÌZñ5Õ{´°ˆÙÀpk+nŠÍ×àh™ú™ÞÝW>¹½«£LÙg¥J1›c}FÀ<”Šà@ñœ¹i¿³Ï#MMµTºQöŸX”ˆSÓßdÜR¦oÊRð¾csËÔOÑ+ß'F˜¡!fÜyš"wÑŠ¬=]la<AéWÚ'\zF?ët¼hÚQFB[²¾2ÛÔÑ(I0þ„«W:…¹fˆÙo–ž:ë^ûõÒ˜'ÐÑý^67³½ÖÚF$A†@(Ÿ.vÙçㆀ~dìÓp*‰íÃì$‹âeFÊGâvËT6+ë%2…†1ªËaÜsI«5/¿õ˜RSqH—JÑ߬
+„4
+ÐѦjÖž†‘!0eûœþÓ觃¾ß°”ËÀ׊Käd¯ö«Ødê)Ù™aèõ.‚¥Â?lÜý$+ƒé}3âš#ÖdƒÕ5ôf—æù0¥ˆ©ÚºN
+±ŒõÄ6£ùE0]9<d(+5Ë4Öø¢
+é S§ l”Z@×ÂfÑAœ¡·BžRþ§xSŠMÖ4 ªÒrMæjfe²Èó—õÁš2ho†¥º—ã%¶5&“ÀÒ@¿qÎ/áÁå)öê-õ™–á:WY¤mNâ¢Ó"W$Ý Ø´o+ëÏÄþ÷Øätz"*›ï•í_R•+‹±Ý+Tý>5“S)iq;Ofi±¿þ®´5öo÷qüq3Ò£Šº®šUUAhÏB5v.»’Ók’ýgEO}Û”1Þþ¸¤ÓDõ£~ÓÄ0¦!ÞÄw€8*M¸zЩëY¯žúàÍKŠ^mGÔô;¨»=i|²?8±_‹ºÿðEÙ #:p“¥š„T,ìCÃÛooÀrsƒ‡›l-¸ò²ùRåý:\ïmØðnz¬ÃêÐoÀ ´•PÂ×
+Âîj¤SÍÿÊPªš?ÉÞà~xägsæ‘Øsqô†ýMï“ w($›¢·Ð>œPùÜá Ž=Ö.¢¨WT›„äÌ$%é÷=„ൊÿF}tx½l¯þJzm¹`nÏYÖcÉ·[—ÇÇc°õ ¹=!‘¾µ TuùzLuIo9ïïr9«9rfeº7‘ð3ã½L~}Z¯öóÄ-iÑÑêø£¶â㉯¨rzC¢›Ó£xɪ¾~vÕçÇ€¶ëó8»uo$¹ÆÆD†$å6­EÓµÕ–ó*ýÛEÇγ‡cGw@nRé5ý†ÈÀZ*Ççú8ŒGç©©¦ÑÛŒngÞŽg|,Lß{Õ7,Ÿ¢e‚ìùÍ[“1NoF‡†-/ß6»z:ˆÍVU>îÖ·”`x}W;-¡ñ„Ôë~ƒl.ÐÌ&ÑaÄ=âu‚¯8D—r¶Øòü9®äëZ†©dg†w%pƒ=4—~¸ø­-]RŠ´ÒÆn Ê7xB±6mÅÎÜ‚Ö9 ð9¼tjÁPXw숰ãwÒõÒ°+T\k=¡€›ýÿk×>¶ãËÝ;ò¬>ÍOk2 s¶1cÜ0>sv7¹ŽòU`G{ ¾:¥dKЯ&x¾Ì‰[N€q‰r«'¯þñåå°•…^¬‡BøU–ç"¿Ìð.ÖðL¸C ‡Xg‹JýN±|«=,ˆÞô9 ô°pï{À…–9.°)"DÐgØ‹¾ú¼` ,ð˜õÒêLà·ÆQx$¬ïû™ß\
+ÆFç™ÕÖ”ë][Ï©yŠ¸Ú×E$=‚Qi±çr
+–ÐÓzâ®T2 Ì½+9
+6HÿÝìJÖtÑtÏ$žTž@öä—«K@«†B³lN
+Cqú’'î‡OM+q/p‚ãÙù:ºO€Äjrô¾»!.µYnuS9I‘nûÔÔÕºC 6Ÿâaô§LDWÌY8Œ"‡Sm ñŸNS\mÔ?ú$Ó¯ÄbÂA—ro­ ±ë˜
+þ²yþ·z‡ñ¤1Éͬڥ
+AC²jp£³íÚ~í%‘;×®í´0Ygg¦2;aõKF,Ÿ^Oº»9ÚU­ïõÔ“ýàhEµ=û aµ\MJ3(ý"RA÷mš~Ä7ÚlÙJy¸TÎ<¥H/ÖK–ô²!â>ÿaÿ5'do•uáI M‹š±Ϧx–+‰^8”¦Ø]Ï®B0d…£Çæ+¨¶ôŽWò)7ܹ˜:—£‡PLâÿ}œo„t[X.|ÐJL ”5>¤Ë¥ejIÊ@7bQý¤ï>µ¤‚h¿ LG/éŽ2Úó6¹ž1áðÛ—ýÀжC&àüVe¸Jœ'×±£ú7òùÑîr y{×\:$<ÿ&$MbÇ®ÁžNÝ4ÿÔ@uËD#®=&ôÑ•h “Ä{œ(_©Nê‰Àê¼-xút ÜM)ö°É¤Y–ô2±ݱ=écǬPœpò†uø¿bÜãé*øÒÜÀwû
+²®ÖÛµÍ27g’ÓdŽf¬î‚NÅdWr‡Ñmt™N-_i¹ôÕÚÉ{"ƒ;½:>`¶‰jpÑCêsöÛ–AµÀ|ÕJ§£Wð³ôºà~øq×4ÝúˆÚ¯ˆ8ß0>ì{—mžv
+"ÈÞþº;J¬†‡¿“ék+¥ Ô³üÿ’íÎ@}–ÜÉöiØhh>ÉÌ%4™!«2‡G0”y7öå¾^ó=¼°NÞþ0©dñÐ’é­ãÉѼͿµÝn3»8œ¹bÏ«‡GŠw‚ÎdÈ&Ïþï,ò|ízwv¾a?ŸSÜäz>¬X±Ó x +éT!ﵡR¾*ˆi}gJîैI^‰“Ëh*Û芗=43j>’ä¼£<n¿—ÇY m¼/F2I¬h—è¦Iói{dQE=Æ
+Ž#9nȼz¡Î"à†
+ÔEC$Ë£na§pœôÿ¡«2Æع#B›’n,]ì—öņ邇ܤíšÑjqÓÊk÷¯5kª½‰œõ6 Ý+œö«º Íiá¦îZ³ó½r¹—Œd¬‘áUõì^<²†D×z%MÙ‰þ.Z6­=‡s-fH)h[%zx}[N)>k(Þ{暣±0BŒ}¹`ØaݸZ€sóJ„IÚzzµ
+ù]C© ¸»N‚¯
+˜¨^øUM«í0KsÒã
+Œ³Òq§*wèuëÿ[´ã«™²g¸ÀÓi%r¬ç_O:Ó0n% Bnq¿G¿jï¤Øo  «@ÿ÷\UIŠ÷é7¼qV¬R²Ìº‘œœÞÊ31IÌȃ=*O~ÊgÚ‰•Œ‘?ó_&‹".œì,½„H¹Na4…sa¾Ýì ?$×Ið UÓ;un ’Å!ç0óÁ®&ӃȢ̺âñè‘“Uj~ã´’Îgãx7[R0u9 ýö`t†VÁÌÍû=…9ŽbðU@NáR0©ŒwF©@¹,+È[4»Y¨ èLWtÛKÉž"—FØCŸ½o/w\%=›óf …uþfRÛ>è÷\7“™Ù‹9ñ•‡>²<ßÉNñ?<!+—º Q©eÐ|žU?ÕçÖ\©8>:Õ$ɪáHáîÔ&++¶\¸úr‰V¹êIù5h¡×<ùcL"4¥ æiyì"u²é2í (Qsºý8ÛǨïhJ\WÿÖU^QOnÎÍ0¡aYüiƒ}6…ÐPŽgµdÐ +,'?ø!š² FyS=Jµ®€v(d<ÈX|Ûí˜m
+÷ȵu gISÔÝQŠžÞ² ÚÕ§é»S.
+”æÓÓ=Ad.ç–Š3+zq¯îœKH¦Êh›{äN$%?Ø—6Ÿ¾„‘ïï<c¢l‹©À ¥Wx«[koµ)m=£†~ž°Æê$
+_+(©ŒÏá]ÐÛl‹S*z—ª9{gÎìûÙâè!gËì:Y¶*ˆ.<ôõÉFKҤ˞Ù8eJ ­²cÚ+/µ)7S&[„뇀b¯¾Ü*÷?÷ŽÀÊKã‰ì¤ñ™xebiø
+‡FÚ–/¬33-@+sÛò ÉN~¹õ¿“+áF¬*ÚT+x|Û.˜£ÓMM؇ô#…›‚È‹‘ŸÐJç£B?ÆÎTŒC{á›.‡‚ûXb6bÔúÖk=;¾("]gMí<ªËÎéa€°¿ÑNsʯ4-+˜ Þ-v¬+ð ƒá(w|c-:Àqb²? Ç]Í {5^ÿúžðh’žÙp™9+—<XlKzhj°ŸÆñºm·6–‹{X&ŠÙ<Ü“žä8¿†‚ŸËËÈk* V€'ABŸò_vs‚¡g½®©<Aª§5ò™\´OÈÒÍÖbÀúôF^_ã­ž[l„Wƒx¡”hy-
+}µÝ÷gAkp÷Ö¶ ÕK¿Ó¨x•àØk±LYíuöÉS§þ7 ŠŸT—)n¸®<=eÑ~ñF\Ž6DzpŠ@Ù*À6É›½ŸH”qè~8o²öÆTNă)o[Áb;Q$íqÞ€µPNrÜc¶7Lmj@ÆöÇÑ#Ý9RŠS¦±²ËuA5$ºˆÛ›ŒwV$³âKpše_ê™Ýó*¤{ Õ+§±7Ã==:“ô’Ùœ³¸M\ú\°zf.g÷­ÄåyzK‰¥qk\>ÁÚ¸ÚS3þ9•Fd”ˆv°;7ûœ…ní”Æ ÀÅzæ¹ztÖ1€~Xó“4-ÆEäÓ€›Û¥óyÍHSšß ý7Lϲ×f?Üéö´„>98vøÅP_¿ [-¿W·m7> j±XDâØÔåkD¥~Ø¢½ ‰@÷Q/ú¼°ãCNüBìÜ>™¯áìÒâj‘L“‹„¶£Ú´7g·Cêgj÷µâ¢\je{—ãÍŸlŠ4|¬ªöÓj•‹]Œî®8ܧ·5ôd¼ª§?«Î\®`ªà•P2O©[¡ÿê.Þ_È34›{ u]hø¶Ãê1±]‰î4‡øV#\ÒT…îóÅr­²#8”aø,ÝêaÍú-òÁP¢®ÏÜØU„ æ¨c?Z†å6Ljd€–°íÁ6)‘r>rödÈmá«OàÂÉ…\¬S’tšf‡èësáe=^]v
+ÁkpAÈ0?¤’Ž08¢¨E‚nC’Èé¨U‚Ãêé å¸î«‰y@cJĶÑÃWiéÁšG“,(6—Ò”¨~“íHï·Ú…šëF2{ϱìÅ5©p*N´û+5lâj9pøEž!¾(gÆ«Í põ€ &H5‘)¨;.’âX5/0ª\”îôÅýÂÆgdŽ…%2‘ö7ðCµ%¦J×öc`<F[o, OHiÓ‘ÿˆpFr§ nñóÖÊp{„ðÜ>J¿_= Àó¢ÖrÅžôïr±ö¯
+üh™à9ú!ÚÓ”=Ò”üµ•¦T؆b¡@ôÚå@‚(ÛÂmøˆ Ÿ„SŒ`]´…‹•C°è--‘Õy͆éú·bKUdÄ/äsˆxµªU]÷bv¸-šFp«l ÆÒZ ùÿž4FèÏåC ûIé”Ý6¸¼M˜3 ­°ûl«Þ®
+±¶å¨­¤‡?»rÜB«
+¾VÕH´óigÑH|U1ÄY=ü·VðÑ Ý›)IðaÈ
+Õ¢c<Øž`…º$¡´8³¸õ,à­~{DÞf×ÀT r˜"¶Þšæ„”þ)è¢xÇ„O‘\t¢O˜ úT\c|@hhB¾‹†Ùµ*1¢Ø;ÝàŒ÷K‚6S%É’ƒ„|pK`Û†zòý×L ˆ•vqн笜!É/¬>ÈVÂHWß+—¹à<5;·uÊtDÂåÄšµÉÖ䲎®'ÞH%“å N&ÿ}Pì 3à õêa£0;eE¿ÏŒGQŠüw;„«- <b!ÊXâ+ ôh&–«Fæš/N›™[ s¾p—ô†7%Þ”-ƒ!ˆ©h…ƒ»ç-ºÆôÈpÕ9I¦+Ɖu:”a¯ÓW¦Ýmd%Mòiiÿ¤™ŽÅ¤ÙÂO„’õ¥0‹5¹«ßŽÀ ©°r<åæ»É1ϵ#u×rXX?FÊšà»Aéñë3`²/©ßw"È-Ój€×ìiÇÎÒ㌎(&g‡ödâ1lK* A¾çxý|w”ð+ù­qÿú¥,Z'rzþ¼æ(O;!/AáÌPý=—ÂãÑe EÄ×Ë«Ë‹l°€¹+è‡ME í€òïrØ÷UfÉ[ èM½Õ‚™i•ûb{ÜV½&”Ù½”%SͤиÑjÉÏˤR‰JTI@Èä PÊù:ÓR )m…FÎGP»Áœ´j¸àeàì0)ÂPvÑLÀ~V?¶
+¿Ï?3þÔ¡EÅgþòÉŽä@騎²ÂÖÖʤo¬š„_EŠðꯆÙV^g~™ú0ù` C<bàìêª |€° 3U[‚Ö¼ ™õMVÆß·„íÀ¾¥SÉý°^ázËT\@¹z,õèƒ*ÇvžM±õ4ÏYàÞ8–X é2ÆO >{«öC¯´ëžƒezHï9øõ§©Î‘[á_i³™Ö ÝvE\À€TC%özs¶ÏÀ¦ßÊÛîãÄãòK æ ¶ô¬j}tv
+W]{§í¨áÀÒˆ÷"ÃŽìWLá<Λ•œµ[âîÔß!ò®§q¤ÈÝLtd®ØUg¢R¡¨*Œ=p†…ݦ¾xûÈ»À§‹ÈUV—">ŒÖ½^v’,³+šhZL;lÚœ)ot¹!${ÛôQ½uZ¶LabÆwahë¾¼̺dZËY‡Ä‰û’‰3T#hÿ¼œb>©¦â·ÔR4Ãfng9£ãúŸ¡«ï.¥bx‰ÆÍ;ò-ë°KOóV£Ò£ë1+*ïJ<=#ì
+ôS~¼^ÚÒ/Ø´1œÌ <$5ç|JÏvp 1R8:Z‡:"ѧ±]‹ Çc(ÃAëQf÷j¸š¦¯ÌiWÔg(k2i‘ÓC¨Îx$ÇËCcM”Ë-mù¥‡ÕnˆD #ûu»CSË÷îiAßÀ’T1N‘@kxh™¿™bÈ3X¹SŠ/´W"uTõr4䆧 T*
+‡ƒ4à¤É
+ŠZ@JÙy˜þh7ì’5rP“lÜüãé¿c”„5Èz#³BƒK8mâÄÊlŠUì$©ç€‰7jpI˜¨ÍqZ=Yª30 ?k蹘›'mR,F¼ÅU\;ø®ÈBÚ3“°¯Nø™—êyŸ¤jð{«j
+»“äw@æÑ0Ä'h‚>lÁ“ƒ)Aó2XÉË@Å]+ݨý0ÿþ8£…IP¤;?å/ªN°)±x8/çýé³Â$w(‹Ì¤ö4Œ‘¿ÆÙá™üSo 0à±LÃœ9,ãYˆp`¡<ö{³€øKU$WL5;~ &ÂѼÚÓØ9K¤s¿Ò¢êG}inkf(sŠ«Bg–ñQ¸Š’ E¾ãÂÞ˜š©w.¯ƒÎ<Ssåæ_«…áÊÁ¼ã
+‚raÛ÷âéˆJσz7/{î;ÅNçÌ.ÊÁd=ô5 ‘?` …Èš‹5ãøÞ,E?üLá]ðFž aW)Hö Ïè½5£š
+žŒ Û,”›æÝ`m•]÷À÷™òmc‘u~¾õÿØma¢TA=„‡‹Áöüq´&·¡eîCàù“¦59°`U—DíÄáœâR]$-óÝY¤E}1 ÓwGAún¨+!È›d‘äû8 ç²C®Í!åcŸ§öìd?êëܧZf)SÛ†‚»yàYÓ¹äúÐn"`$N:ÒŸz;-Öµ"˘6z\ótãŒM ]ß:H3_'šqscViZ°¾j44qN?‘ë0ïÝ
+%šøh8ƘÍØSÉX²Rà„T3G#Ø_Ü)×ÛOÐÄB^h«˜†j:Á5"Þ3‰l¬®D£1ÒÂ4©¢v›fFÍ›©ï‡¿†¯ê
+±~¸\ÚÐR¨…g, wQàc
+Õ‚S›1I¸€^ 2è\÷»Ã[±G¶×Á‡I0A#µY(Åw± «÷¾Î;ÏÜ[žÌCV9ÚÌ¥_v9õ÷,Â3“ ysGßpÕ½~|îQÁlV€œvÙ¨3ä#š—3|F’oõÕ%,”BÒá¬ÿÀ—ÁŒ¥8áÇ”&aÛÔŠ‘'Zhcgà ÛfPÌHÜŒTPØ×£Ù°´|Ýe’=×!Ò€\¤£aÛ$›¨‰¬Ë”€¯Mª3ÈÒlq†!dÓÅÏ9 ?ÃNXøx=z‰¨ºæQÀHAm*¨Šf¾qÒ
+lýñ¯°GüŽX?1g¸htœ\6ÒOÑ¿>‘õsñ¸õØý÷JÆWˆúYXÆqtùsz\ ÊîŒ%†ÙöªŒ+7e¤`¼i%#"j²*“ÿœëö§Àg‚·OJÚRŸñïG
+ø¹÷)º’s¦Þf8Oco¼n´Ñæ‘ë…Žb“(Ήr¶7WMÁѼ©zémç¹]S`–2^`÷ ¢Ï¯Áœê¯”õß䦓_¸
+˜#J†m¯—&»+ÄN²Ä^³Jt.Ã_7‘´§ÈgÞD‰À[]
+3¾ øƒöËö I
+ RñZ24Û¤HÔµ£ºŠ­ËP rÕ3C8AÚ—ßWÌC&Æ¢ÑÏñ;l–óœúÔ} DZz ÙB7B?çè¬]mwíÜná ðdJÛçÅ
+«6z#lû¤Ò“Ì?-ÀÖn" FÀ1'0Í+ì`z<®ÇÔý€tH l,·ø”wb˜çP“̃ªg+’y¾Lˆç­wEÍsHetsY@cöK¾rAT(©æËB_C& LlãÁ‹†§¿œH'Ê‘óNاùÔ¿mAŠ$6ŸiËUç’Ú!ýÔÎ1ô/°ƒ¾Ü—Ò4ÅIù"¾Ã‡áÒY¨³áÞÄ:_îñ£ò]¡é›Õ½Oú©ÓD(NwS?*wÁ“×+äàæÒíÜu¹qPáЦ„‡ð,é÷œÉ­
+Êr€ß3¬0 éçX-倷ðýŒf‚ Yo⧳µèO^dé8|ÑaúÜ´d– “7¸Ýž¡·¡÷zÃñrôÍ[3›~†AÊóA÷ÉŽ"h|õÖÔùÆUgDo:EõÙÍ_Òj‘©òtfäiØ]oÂ_–"wú1tÈ,ª÷ô rPeƒç=ó.|ohd}D$Éõú V·Fµã¾mL£À|‰Êã–ø<MìuØÎùTi°ÛE TV:]æÕZékNoÇ^¨u£b\„,ó@å£ÏÔ˜™ˆJ/Z)Æӹƪ¹-Š-H·Á׈ZQâL,oé(u
+‚VÛL;»C1‰èˆ[Ì1xìõFZĽô–:z*NO¶oÌx;!r¥ÿF!ˆš˜ûöž ™d']À0{Y•ãÐ èxoºÝ2øé&œÙç?v@.˜¶.)¿QVgöŠ\êQÁ›Û䣯}I‘éIõ5*Ù*®ùŒSü~¸Àî®E.èrªP+­/k[µt¥ïCôÇÃR&Sþ[¦dk¦ 'ÝùYY0'Hi^íbÚÉr6:ÏåÚv~¶¨þ(hwn²a øRÚ“Ç%WÀJ¤h¹}üš×Pë/]ïÒ?´ç¬!A_˜ÿŠ®hÉ/÷±­îH×â-˜
+Ÿo8ùeipñ9ùÝßšØå{ü·„ÿoÂÅãàŠXüBÝ6ŠÁ’ù•×q–[¿ÃÔ>[ÁpÂaõrÖz|0Uoo19†p¯ë±vðXð'¡ÂïSà é Ö;[nﺸPH^ò`ЈßǼh¬¨_KŸ²ÈâUϘöåhk»Z!RíÿQÉV½é î0ÂkDÝT7Áñï ]G%ÈšqãV3»®ºLÊßò T•bsS EøOÞŶ/ˆ³|
+³ãûRá—TeÌb8µ…c•­œ’£ïâùmþs¬ìï¨ÍZ¿!Äçø¥Ùp'†…£dP*@Ô^
+Ë!t¸¨ôŸ-!Ê@ 9Èä$Wäô`EF¾å…érQÅè1F¬‹ÝFãY~†s?Så„‹‹Ã·¹3pwà:š¯*RnA^¤êj †}ÃlwW¶™îüÇxµë8òðÔÉ)€»¤‰¹a9mÅö3š,°ý1v>¸LamIàD‹_9h1…šSŒ4ψõÖÉÔź,.Ç@'Ñ[N…÷Ú{dñ˜k†žŠï
+ÆÇgœ:!mÝÙP˜_á[(÷wü›[F—ïd„SÅE <;Â"ûåx[Xƒ@ÙÐ;ÎU¾L&Ý.Þ‡U¤^¾æFâV9Ÿæ\FrÿdX(ˆ*d–Hÿ
+ GªoN%Õ´sÏT:!õè
+o¢æ^tN)Ÿì¢†‰¹ ­ùC§hŸ~^´ÿ×æQáÐÿèaœú:Öi¡0cúm`ÇHêœF%ßø?
+xÖ~+SLßi©².íM<ådßÎì¾ L’Ó3yàPÉup¿ò·'•b– ¼Ô€ò½OQ ÂÝßtNs…2Šå&"ãÞ\?+eÂ>Ll{AµñƒmÌ-\ÝZ­Àrƒe]œÝöSàýë,ÞZ%H¿ûílì,
+P+fñµ—tßKBã…÷ßÜ ±¾û\ ;^~’œfö§uRŒ­Úú~þtĈ:$.&ÐQ²}±œÁý
+IÜ!C?q²ˆ´¡AX÷Iàü•i^¿–Âo¤›ú˜m`$O.cø Ð,€Ø¯¾ÊçÞ@è ‹T Ý×úþ
+&n½ˆÔb”ò†Äoù29â: ûTF2€
+݃g¾[ÇÓ“×ØŒAOuÿYÁ|UNÁ>•°|?&Uø}J ™ô
+M´ ®„&{0ªÞÎ`¶öYøcêZX˪Ɋ-Ê~=ÇÝ+þ l¥šÛ+Kåå`YÐÞõé#}©ðà‚Š—’ÊÝ
+Ri}¸ÙÈ–AMOmÇ5Õz¦q8á6¨î§ZÓÑ@Z*zäc®ê¸ï­%ìl*4“ìpˉÛúßÊæì„R¯²ÚõðØÍqWp—J*ø5Ï÷Ÿšî+ÜY@ò… ½`µ‰<6¦“:w ›Èõ˜üT׫\›
+äÖ]Ì÷ù31ѪB'’Wÿÿ "‹jGn‘½µ`ïçíû·¬jla5jöj¥ÿ0y«ã¼uHŠCþ”“þŽWfËÁî)Ž–‚Âæ
+æù…ÐϦÏÖãÖ¬/ÍB±ü¿ôÇ]•Gú/˜òôÊJ*g<Ì«Aœ[Q"¨T~U?™ÿ!à ï¨w¬Hô2²MfP5+ ò1oÊÓ\HtŸ’ÝQ*–­Jdà¹EÕÒô=ÂãÞ× E7\ס‚@aã
+´í`
+47öµj¶otk£—jo¯VA˜drêLqøÉQÔ«ô¤ž@˜ˆÂy—Ì3Žƒk‘£«ªxžáo5ËÕÆee¢}ËK‰Ýi¦yžã*¢?ï‘›óÝ 'Æb¹]{Å3#ù‡#ÍË®Öçj˜ÂàÅGÏnÒ£Ãnlxò,ÃÔåǬd`ºu¶ªÑjS½éfð3²íÃîû(ñââ;U¬gÏJ´ô€:þª»¾b<2AÅ1Å;ÙûPmm—•ð‘º¢T5CI;£$
+›µ8 7à|­ÈLóL˨ˆu±"û„5ÎSÚÒ¦3,dÔ‘8æ)š‰i”4ÛRä5.(B_†ò´­5Ùôì¯ÙV7P*WX+1Y‘jF„Ï@8×»‡ØDhõ† VµÇÕ•‘¶¸9óC‘°‡:Éפ”¯=ÀšS”ÔŽ§?‡ôVùªIÚ]÷€=qjPëìŒæßÓÝî5°d­¦™C%%’%^•3Þ¢« Ofí›oGz>ÕyÂ@ŸwÙ=SiMŠ ý>¹áS„ý€KŠðæ2¶ÁŸ¤¿–Áˆkoã
+mDE·vÝ­aɾ6gâL‰ŒÍT½^†3©‡ë ¥øÔìÄ°3Æu¸¿¥¢ä°0,²Ž;À?sƒN®‹Ï¼Š%àÅó&Œ­²?û)x»V"Ùzè’Ù~ÕžF*°®ü¯`Ò
+^QhTÌ;–Q¶Èàä8Þ{Úãô8Ý s-6õº&PCÉCªMèÔëx4¸¿3´°ÀøxÕ £îj·eH߉d³™¡#†iHU£7ñ~°±.ýÏÝøn·a‰¡Ýu}ægdÔÍ& iìè›R(×؃ýW> %T²Q¾[ÁQn¯‡¬ÜBÃhvIC%ÆÇPãMÄ€€»mýб
+ ç’âvD'Uq§ºÖÖÒˆ_ßlbp?Ÿøö„ËVW‹TŸ±¶AÐ ·-—÷;4ó&|;çÔô«-bÐß„ò =+Ú¢¢>Õ=5õ?Ô¯›æ¢îÒçÝ ¬†C*ñÞ¡¦Ã;i¿©9;Ù8no²Ì2daêX¢ÇÍD2Òí†ØØCw>â–ªýÑ4B~¼LáDfAøþä(> ÂF–ÇUh“†Ù2¬ŽÎÍ
+Ö#`ï°sÍFñ9ôS#~tœw‚ìÛÔgüÎÓ ôúlS‰‘ µ?Eµ×ä{ ô3²a –­Ù¶ïoˆ¯ãc/­Ÿý¡pkáˆT&Öa%·©ð'Óöz´‚€ƒû¬q=ï³Ï¢ÅÓ÷]:¾š·…‡o"»û“xb! gNÍŒ„ôuQR^ÛØpjNc“kÄ/@9Ç 9¦êï{çë¾²3weµ÷ìóô}¯t$œ“Ü›/©9¢ÆkcÝà=æä§ÞäÏóéÚìO%Ñd÷¢À>?'¯äŠxzpž-·ÌšÁ°âhÿÀ|üÔÈí>yöMõeÒNáG›Ï³#ò$‚Ô£Û ý„žê¡Dîò¼›Á‚n*ˆµ«ÂgC8³NnåáÛ>¶'*õÏGÑœ’¢EÇÕ=7¥Û‘ofG9'gRüÒTY9’ö<UªQðhA\8ºv;GÈÏ„<Û²
+,]þÕ·É8Љ?W̃rG¢5n½[åô£P™ °wˆœêXá4
+å›-YÑn{VÕÞXÛHXdÆ«„
+"Á›ÜÓŠ{öM1B£æ–/~^VÄ3·k­™v,æB‰“uOsSñAg"Êp»
+Ͳ®‘’}RâCàlýÒˆ¿4û áŽoªÇ‡KHŸd‡®¤ëŸ·€Ú9‡]ØO4|ëdðœ”,Ó-jpCÒœ„Û¯<9M,âìi5qšãÈËF§b€$X=’™1ý¶|b®Ž>rÂÞÀ~Nó„)q“ªJJNò#šÍÈñªî¦GÎsƒž%Ó•žÈ®'©@*†l6`A§¿Âc{?Œâ¿y[biIòRõþAµÔ*O6µÌNcY*A drç.•Ì»…-¹iq¸ëÅór’ 16ð ¶:ˆõL”Óß`’¼æ²~Ëá©6q™ïHŒæ·•Á²Õë¤Ö=ÑWÒÊ1tlÂìjøœ!Á¿ä•!-‘©«¹t_Àiñu—3p>«:<23ÓµUœXâGBéè=çç‚|\³îâÅVs¶
+= Ö—¬<(NÆúݯ_FŽ5ÂÒÁ‰¢Ñ–Æ"ÃÚØQQ£pèŸå¼`¸M™°fMÞ-3
+>èåÁTyDZ±/[…Ëë0TMïá7RïõÖɳšîŠŸGo~˜í:L²Ñá¿}.¯gYzIbY‚¯¢Ï”ùA‘έ¢T¿š °úôy UBBô¡˜“Ïÿ7Ê6"×°Ò.üá«17=£Â jzßšiÏâk©¸*Š«"ÔÅYHÝ+8_
+üŸ`^l¶S"˜oã˜:ÙŽq±¥ÓN¼ÑêŸê<ÖÕ!vÂgõ»TæèFgú1}ZÆ?¯ …½7qbm
+[i´‚ÓÀQ,¡Ž(Íúm]²FËGø²FÃÐ9Ãÿr‘:`­œ£y\Ì5Õ s£mò—8Fæ]‡†ëêü‹’ŽãùýÖ›,SÏø0a#v³I"½[Öæ]N(åà9vä²Q›Füßý7‰•ú‚PûÙ† Žim' ºd‹Fq53S4
+ü±©¦‚½.Ôý' êE¹]·|» `æŸùé¤Ýð<4-»UÒÉ!ñ³iZçÎjDSÀšùjˆTvãî•/'…æõS̽"¦ ñ”¶¿1-oEx™eS»¼Æüê£$F 1µAatÝ 2³9pÚîy*Ø3êÐL¿AÖ}SÝL\ë
+Í,6ºÿ‰HP#¶¿×‹ô†€è¾c¿Nþì+4lÏ
+ð“®â£õjò*IÑT‡|S;JÆ0a¹p®ÓJ}V© uü+þÚ*º¤®ø ÔZ]î/˜þúTæ%8ö7ª]mf†ÈÿSÒPVj²]{ƒ’_"Œ‡@l*ýhDaÂòT'áf×CÜÃ'T®±î¯^ ×‘=¢ŠôwêgSk î›¿ÒÑ3ÏF`»ÊIÜã‹Š§nÑïs¹J—ƒQ…JZ{7mòý»èÀ–,ê&K½
+endstream
+endobj
+
+%QDF: ignore_newline
+22 0 obj
+146576
+endobj
+
+xref
+0 23
+0000000000 65535 f
+0000000025 00000 n
+0000000097 00000 n
+0000000221 00000 n
+0000003486 00000 n
+0000003507 00000 n
+0000003589 00000 n
+0000003741 00000 n
+0000003793 00000 n
+0000004252 00000 n
+0000004272 00000 n
+0000004336 00000 n
+0000004534 00000 n
+0000004570 00000 n
+0000004884 00000 n
+0000004904 00000 n
+0000006922 00000 n
+0000006965 00000 n
+0000007208 00000 n
+0000009576 00000 n
+0000009598 00000 n
+0000009682 00000 n
+0000156384 00000 n
+trailer <<
+ /Info 2 0 R
+ /Root 1 0 R
+ /Size 23
+ /ID [<d1db92ffc47f1749a08e8a3b57190061><31415926535897932384626433832795>]
+>>
+startxref
+156408
+%%EOF
diff --git a/examples/qtest/mod-info/files/3.qdf b/examples/qtest/mod-info/files/3.qdf
new file mode 100644
index 00000000..ff82f567
--- /dev/null
+++ b/examples/qtest/mod-info/files/3.qdf
Binary files differ
diff --git a/examples/qtest/mod-info/files/4.qdf b/examples/qtest/mod-info/files/4.qdf
new file mode 100644
index 00000000..992314c7
--- /dev/null
+++ b/examples/qtest/mod-info/files/4.qdf
Binary files differ
diff --git a/examples/qtest/mod-info/files/empty-info.pdf b/examples/qtest/mod-info/files/empty-info.pdf
new file mode 100644
index 00000000..37bef288
--- /dev/null
+++ b/examples/qtest/mod-info/files/empty-info.pdf
Binary files differ
diff --git a/examples/qtest/mod-info/files/no-info.pdf b/examples/qtest/mod-info/files/no-info.pdf
new file mode 100644
index 00000000..05180443
--- /dev/null
+++ b/examples/qtest/mod-info/files/no-info.pdf
Binary files differ
diff --git a/examples/qtest/mod-info/files/source1.pdf b/examples/qtest/mod-info/files/source1.pdf
new file mode 100644
index 00000000..86cc3477
--- /dev/null
+++ b/examples/qtest/mod-info/files/source1.pdf
Binary files differ
diff --git a/examples/qtest/mod-info/files/source2.pdf b/examples/qtest/mod-info/files/source2.pdf
new file mode 100644
index 00000000..1a814e91
--- /dev/null
+++ b/examples/qtest/mod-info/files/source2.pdf
Binary files differ
diff --git a/examples/qtest/mod-info/usage.out b/examples/qtest/mod-info/usage.out
new file mode 100644
index 00000000..5eeba82e
--- /dev/null
+++ b/examples/qtest/mod-info/usage.out
@@ -0,0 +1,5 @@
+Usage: pdf-mod-info -in in_file [-out out_file] [-key key [-val val]?]+
+Modifies/Adds/Removes PDF /Info entries in the in_file
+and stores the result in out_file
+Special mode: pdf-mod-info --dump file
+dumps all /Info entries to stdout
diff --git a/examples/qtest/npages.test b/examples/qtest/npages.test
new file mode 100644
index 00000000..cd81e6b8
--- /dev/null
+++ b/examples/qtest/npages.test
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("npages");
+
+require TestDriver;
+
+my $td = new TestDriver('pdf-npages');
+
+$td->runtest("normal",
+ {$td->COMMAND => "pdf-npages minimal.pdf"},
+ {$td->STRING => "1\n", $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("error",
+ {$td->COMMAND => "pdf-npages bad"},
+ {$td->STRING => "pdf-npages: bad: offset 0: not a PDF file\n",
+ $td->EXIT_STATUS => 2},
+ $td->NORMALIZE_NEWLINES);
+
+$td->report(2);
diff --git a/examples/qtest/npages/bad b/examples/qtest/npages/bad
new file mode 100644
index 00000000..9daeafb9
--- /dev/null
+++ b/examples/qtest/npages/bad
@@ -0,0 +1 @@
+test
diff --git a/examples/qtest/npages/minimal.pdf b/examples/qtest/npages/minimal.pdf
new file mode 100644
index 00000000..a7e01f91
--- /dev/null
+++ b/examples/qtest/npages/minimal.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/include/qpdf/Buffer.hh b/include/qpdf/Buffer.hh
new file mode 100644
index 00000000..703dee3e
--- /dev/null
+++ b/include/qpdf/Buffer.hh
@@ -0,0 +1,32 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __BUFFER_HH__
+#define __BUFFER_HH__
+
+class Buffer
+{
+ public:
+ Buffer();
+ Buffer(unsigned long size);
+ Buffer(Buffer const&);
+ Buffer& operator=(Buffer const&);
+ ~Buffer();
+ unsigned long getSize() const;
+ unsigned char const* getBuffer() const;
+ unsigned char* getBuffer();
+
+ private:
+ void init(unsigned long size);
+ void copy(Buffer const&);
+ void destroy();
+
+ unsigned long size;
+ unsigned char* buf;
+};
+
+#endif // __BUFFER_HH__
diff --git a/include/qpdf/Pipeline.hh b/include/qpdf/Pipeline.hh
new file mode 100644
index 00000000..acbc2d98
--- /dev/null
+++ b/include/qpdf/Pipeline.hh
@@ -0,0 +1,73 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+// Generalized Pipeline interface. By convention, subclasses of
+// Pipeline are called Pl_Something.
+//
+// When an instance of Pipeline is created with a pointer to a next
+// pipeline, that pipeline writes its data to the next one when it
+// finishes with it. In order to make possible a usage style in which
+// a pipeline may be passed to a function which may stick other
+// pipelines in front of it, the allocator of a pipeline is
+// responsible for its destruction. In other words, one pipeline
+// object does not attempt to manage the memory of its successor.
+//
+// The client is required to call finish() before destroying a
+// Pipeline in order to avoid loss of data. A Pipeline class should
+// not throw an exception in the destructor if this hasn't been done
+// though since doing so causes too mcuh trouble when deleting
+// pipelines during error conditions.
+//
+// Some pipelines are resuable (i.e., you can call write() after
+// calling finish() and can call finish() multiple times) while others
+// are not. It is up to the caller to use a pipeline according to its
+// own restrictions.
+
+#ifndef __PIPELINE_HH__
+#define __PIPELINE_HH__
+
+#include <qpdf/QEXC.hh>
+
+class Pipeline
+{
+ public:
+ class Exception: public QEXC::General
+ {
+ public:
+ Exception(std::string const& message) :
+ QEXC::General(message)
+ {
+ }
+
+ virtual ~Exception() throw()
+ {
+ }
+ };
+
+ Pipeline(char const* identifier, Pipeline* next);
+
+ virtual ~Pipeline();
+
+ // Subclasses should implement write and finish to do their jobs
+ // and then, if they are not end-of-line pipelines, call
+ // getNext()->write or getNext()->finish.
+ virtual void write(unsigned char* data, int len) = 0;
+ virtual void finish() = 0;
+
+ protected:
+ Pipeline* getNext(bool allow_null = false);
+ std::string identifier;
+
+ private:
+ // Do not implement copy or assign
+ Pipeline(Pipeline const&);
+ Pipeline& operator=(Pipeline const&);
+
+ Pipeline* next;
+};
+
+#endif // __PIPELINE_HH__
diff --git a/include/qpdf/Pl_Buffer.hh b/include/qpdf/Pl_Buffer.hh
new file mode 100644
index 00000000..e78b5a17
--- /dev/null
+++ b/include/qpdf/Pl_Buffer.hh
@@ -0,0 +1,46 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __PL_BUFFER_HH__
+#define __PL_BUFFER_HH__
+
+// This pipeline accumulates the data passed to it into a memory
+// buffer. Each subsequent use of this buffer appends to the data
+// accumulated so far. getBuffer() may be called only after calling
+// finish() and before calling any subsequent write(). At that point,
+// a dynamically allocated Buffer object is returned and the internal
+// buffer is reset. The caller is responseible for deleting the
+// returned Buffer.
+//
+// For this pipeline, "next" may be null. If a next pointer is
+// provided, this pipeline will also pass the data through to it.
+
+#include <qpdf/Pipeline.hh>
+#include <qpdf/PointerHolder.hh>
+#include <qpdf/Buffer.hh>
+#include <list>
+
+class Pl_Buffer: public Pipeline
+{
+ public:
+ Pl_Buffer(char const* identifier, Pipeline* next = 0);
+ virtual ~Pl_Buffer();
+ virtual void write(unsigned char*, int);
+ virtual void finish();
+
+ // Each call to getBuffer() resets this object -- see notes above.
+ // The caller is responsible for deleting the returned Buffer
+ // object.
+ Buffer* getBuffer();
+
+ private:
+ bool ready;
+ std::list<PointerHolder<Buffer> > data;
+ size_t total_size;
+};
+
+#endif // __PL_BUFFER_HH__
diff --git a/include/qpdf/Pl_Count.hh b/include/qpdf/Pl_Count.hh
new file mode 100644
index 00000000..287b8297
--- /dev/null
+++ b/include/qpdf/Pl_Count.hh
@@ -0,0 +1,34 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __PL_COUNT_HH__
+#define __PL_COUNT_HH__
+
+// This pipeline is reusable; i.e., it is safe to call write() after
+// calling finish().
+
+#include <qpdf/Pipeline.hh>
+
+class Pl_Count: public Pipeline
+{
+ public:
+ Pl_Count(char const* identifier, Pipeline* next);
+ virtual ~Pl_Count();
+ virtual void write(unsigned char*, int);
+ virtual void finish();
+ // Returns the number of bytes written
+ int getCount() const;
+ // Returns the last character written, or '\0' if no characters
+ // have been written (in which case getCount() returns 0)
+ unsigned char getLastChar() const;
+
+ private:
+ int count;
+ unsigned char last_char;
+};
+
+#endif // __PL_COUNT_HH__
diff --git a/include/qpdf/Pl_Discard.hh b/include/qpdf/Pl_Discard.hh
new file mode 100644
index 00000000..cd0865a8
--- /dev/null
+++ b/include/qpdf/Pl_Discard.hh
@@ -0,0 +1,28 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __PL_DISCARD_HH__
+#define __PL_DISCARD_HH__
+
+// This pipeline discards its output. It is an end-of-line pipeline
+// (with no next).
+
+// This pipeline is reusable; i.e., it is safe to call write() after
+// calling finish().
+
+#include <qpdf/Pipeline.hh>
+
+class Pl_Discard: public Pipeline
+{
+ public:
+ Pl_Discard();
+ virtual ~Pl_Discard();
+ virtual void write(unsigned char*, int);
+ virtual void finish();
+};
+
+#endif // __PL_DISCARD_HH__
diff --git a/include/qpdf/Pl_Flate.hh b/include/qpdf/Pl_Flate.hh
new file mode 100644
index 00000000..16058d37
--- /dev/null
+++ b/include/qpdf/Pl_Flate.hh
@@ -0,0 +1,53 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __PL_FLATE_HH__
+#define __PL_FLATE_HH__
+
+#include <qpdf/Pipeline.hh>
+
+#include <zlib.h>
+
+class Pl_Flate: public Pipeline
+{
+ public:
+ class Exception: public Pipeline::Exception
+ {
+ public:
+ Exception(std::string const& message) :
+ Pipeline::Exception(message)
+ {
+ }
+
+ virtual ~Exception() throw ()
+ {
+ }
+ };
+
+ static int const def_bufsize = 65536;
+
+ enum action_e { a_inflate, a_deflate };
+
+ Pl_Flate(char const* identifier, Pipeline* next,
+ action_e action, int out_bufsize = def_bufsize);
+ virtual ~Pl_Flate();
+
+ virtual void write(unsigned char* data, int len);
+ virtual void finish();
+
+ private:
+ void handleData(unsigned char* data, int len, int flush);
+ void checkError(char const* prefix, int error_code);
+
+ unsigned char* outbuf;
+ int out_bufsize;
+ action_e action;
+ bool initialized;
+ z_stream zstream;
+};
+
+#endif // __PL_FLATE_HH__
diff --git a/include/qpdf/Pl_StdioFile.hh b/include/qpdf/Pl_StdioFile.hh
new file mode 100644
index 00000000..d74ded3a
--- /dev/null
+++ b/include/qpdf/Pl_StdioFile.hh
@@ -0,0 +1,49 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+// End-of-line pipeline that simply writes its data to a stdio FILE* object.
+
+#ifndef __PL_STDIOFILE_HH__
+#define __PL_STDIOFILE_HH__
+
+#include <qpdf/Pipeline.hh>
+
+#include <stdio.h>
+
+//
+// This pipeline is reusable.
+//
+
+class Pl_StdioFile: public Pipeline
+{
+ public:
+ class Exception: public Pipeline::Exception
+ {
+ public:
+ Exception(std::string const& message) :
+ Pipeline::Exception(message)
+ {
+ }
+
+ virtual ~Exception() throw ()
+ {
+ }
+ };
+
+ // f is externally maintained; this class just writes to and
+ // flushes it. It does not close it.
+ Pl_StdioFile(char const* identifier, FILE* f);
+ virtual ~Pl_StdioFile();
+
+ virtual void write(unsigned char* buf, int len);
+ virtual void finish();
+
+ private:
+ FILE* file;
+};
+
+#endif // __PL_STDIOFILE_HH__
diff --git a/include/qpdf/PointerHolder.hh b/include/qpdf/PointerHolder.hh
new file mode 100644
index 00000000..b4e9bb64
--- /dev/null
+++ b/include/qpdf/PointerHolder.hh
@@ -0,0 +1,170 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __POINTERHOLDER_HH__
+#define __POINTERHOLDER_HH__
+
+#include <iostream>
+
+// This class is basically boost::shared_pointer but predates that by
+// several years.
+
+// This class expects to be initialized with a dynamically allocated
+// object pointer. It keeps a reference count and deletes this once
+// the reference count goes to zero. PointerHolder objects are
+// explicitly safe for use in STL containers.
+
+// It is very important that a client who pulls the pointer out of
+// this holder does not let the holder go out of scope until it is
+// finished with the pointer. It is also important that exactly one
+// instance of this object ever gets initialized with a given pointer.
+// Otherwise, the pointer will be deleted twice, and before that, some
+// objects will be left with a pointer to a deleted object. In other
+// words, the only legitimate way for two PointerHolder objects to
+// contain the same pointer is for one to be a copy of the other.
+// Copy and assignment semantics are well-defined and essentially
+// allow you to use PointerHolder as a means to get pass-by-reference
+// semantics in a pass-by-value environment without having to worry
+// about memory management details.
+
+// Comparison (== and <) are defined and operate on the internally
+// stored pointers, not on the data. This makes it possible to store
+// PointerHolder objects in sorted lists or to find them in STL
+// containers just as one would be able to store pointers. Comparing
+// the underlying pointers provides a well-defined, if not
+// particularly meaningful, ordering.
+
+template <class T>
+class PointerHolder
+{
+ private:
+ class Data
+ {
+ public:
+ Data(T* pointer, bool tracing) :
+ pointer(pointer),
+ tracing(tracing),
+ refcount(0)
+ {
+ static int next_id = 0;
+ this->unique_id = ++next_id;
+ }
+ ~Data()
+ {
+ if (this->tracing)
+ {
+ std::cerr << "PointerHolder deleting pointer "
+ << (void*)pointer
+ << std::endl;
+ }
+ delete this->pointer;
+ if (this->tracing)
+ {
+ std::cerr << "PointerHolder done deleting pointer "
+ << (void*)pointer
+ << std::endl;
+ }
+ }
+ T* pointer;
+ bool tracing;
+ int refcount;
+ int unique_id;
+ private:
+ Data(Data const&);
+ Data& operator=(Data const&);
+ };
+
+ public:
+ PointerHolder(T* pointer = 0, bool tracing = false)
+ {
+ this->init(new Data(pointer, tracing));
+ }
+ PointerHolder(PointerHolder const& rhs)
+ {
+ this->copy(rhs);
+ }
+ PointerHolder& operator=(PointerHolder const& rhs)
+ {
+ if (this != &rhs)
+ {
+ this->destroy();
+ this->copy(rhs);
+ }
+ return *this;
+ }
+ ~PointerHolder()
+ {
+ this->destroy();
+ }
+ bool operator==(PointerHolder const& rhs) const
+ {
+ return this->data->pointer == rhs.data->pointer;
+ }
+ bool operator<(PointerHolder const& rhs) const
+ {
+ return this->data->pointer < rhs.data->pointer;
+ }
+
+ // NOTE: The pointer returned by getPointer turns into a pumpkin
+ // when the last PointerHolder that contains it disappears.
+ T* getPointer()
+ {
+ return this->data->pointer;
+ }
+ T const* getPointer() const
+ {
+ return this->data->pointer;
+ }
+ int getRefcount() const
+ {
+ return this->data->refcount;
+ }
+
+ private:
+ void init(Data* data)
+ {
+ this->data = data;
+ {
+ ++this->data->refcount;
+ if (this->data->tracing)
+ {
+ std::cerr << "PointerHolder " << this->data->unique_id
+ << " refcount increased to " << this->data->refcount
+ << std::endl;
+ }
+ }
+ }
+ void copy(PointerHolder const& rhs)
+ {
+ this->init(rhs.data);
+ }
+ void destroy()
+ {
+ bool gone = false;
+ {
+ if (--this->data->refcount == 0)
+ {
+ gone = true;
+ }
+ if (this->data->tracing)
+ {
+ std::cerr << "PointerHolder " << this->data->unique_id
+ << " refcount decreased to "
+ << this->data->refcount
+ << std::endl;
+ }
+ }
+ if (gone)
+ {
+ delete this->data;
+ }
+ }
+
+ Data* data;
+};
+
+#endif // __POINTERHOLDER_HH__
diff --git a/include/qpdf/QEXC.hh b/include/qpdf/QEXC.hh
new file mode 100644
index 00000000..b94edf7a
--- /dev/null
+++ b/include/qpdf/QEXC.hh
@@ -0,0 +1,119 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QEXC_HH__
+#define __QEXC_HH__
+
+#include <string>
+#include <exception>
+#include <errno.h>
+
+namespace QEXC
+{
+ // This namespace contains all exception classes used by the
+ // library.
+
+ // The class hierarchy is as follows:
+
+ // std::exception
+ // |
+ // +-> QEXC::Base
+ // |
+ // +-> QEXC::General
+ // |
+ // +-> QEXC::Internal
+
+ // QEXC::General is the base class of all standard user-defined
+ // exceptions and "expected" error conditions raised by QClass.
+ // Applications or libraries using QClass are encouraged to derive
+ // their own exceptions from these classes if they wish. It is
+ // entirely reasonable for code to catch QEXC::General or specific
+ // subclasses of it as part of normal error handling.
+
+ // QEXC::Internal is reserved for internal errors. These should
+ // be used only for situations that indicate a likely bug in the
+ // software itself. This may include improper use of a library
+ // function. Operator errors should not be able to cause Internal
+ // errors. (There may be some exceptions to this such as users
+ // invoking programs that were intended only to be invoked by
+ // other programs.) QEXC::Internal should generally not be
+ // trapped except in terminate handlers or top-level exception
+ // handlers which will want to translate them into error messages
+ // and cause the program to exit. Such top-level handlers may
+ // want to catch std::exception instead.
+
+ // All subclasses of QEXC::Base implement a const unparse() method
+ // which returns a std::string const&. They also override
+ // std::exception::what() to return a char* with the same value.
+ // unparse() should be implemented in such a way that a program
+ // catching QEXC::Base or std::exception can use the text returned
+ // by unparse() (or what()) without any exception-specific
+ // adornment. (The program may prefix the program name or other
+ // general information.) Note that std::exception::what() is a
+ // const method that returns a const char*. For this reason, it
+ // is essential that unparse() return a const reference to a
+ // string so that what() can be implemented by calling unparse().
+ // This means that the string that unparse() returns a reference
+ // to must not be allocated on the stack in the call to unparse().
+ // The recommended way to do this is for derived exception classes
+ // to store their string descriptions by calling the protected
+ // setMessage() method and then to not override unparse().
+
+ class Base: public std::exception
+ {
+ // This is the common base class for all exceptions in qclass.
+ // Application/library code should not generally catch this
+ // directly. See above for caveats.
+ public:
+ Base();
+ Base(std::string const& message);
+ virtual ~Base() throw() {}
+ virtual std::string const& unparse() const;
+ virtual const char* what() const throw();
+
+ protected:
+ void setMessage(std::string const& message);
+
+ private:
+ std::string message;
+ };
+
+ class General: public Base
+ {
+ // This is the base class for normal user/library-defined
+ // error conditions.
+ public:
+ General();
+ General(std::string const& message);
+ virtual ~General() throw() {};
+ };
+
+ // Note that Internal is not derived from General. Internal
+ // errors are too severe. We don't want internal errors
+ // accidentally trapped as part of QEXC::General. If you are
+ // going to deal with internal errors, you have to do so
+ // explicitly.
+ class Internal: public Base
+ {
+ public:
+ Internal(std::string const& message);
+ virtual ~Internal() throw() {};
+ };
+
+ class System: public General
+ {
+ public:
+ System(std::string const& prefix, int sys_errno);
+ virtual ~System() throw() {};
+ int getErrno() const;
+
+ private:
+ int sys_errno;
+ };
+};
+
+#endif // __QEXC_HH__
diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh
new file mode 100644
index 00000000..d311b3c8
--- /dev/null
+++ b/include/qpdf/QPDF.hh
@@ -0,0 +1,750 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QPDF_HH__
+#define __QPDF_HH__
+
+#include <stdio.h>
+#include <string>
+#include <map>
+#include <list>
+
+#include <qpdf/QPDFXRefEntry.hh>
+#include <qpdf/QPDFObjectHandle.hh>
+#include <qpdf/QPDFTokenizer.hh>
+#include <qpdf/Buffer.hh>
+
+class QPDF_Stream;
+class BitStream;
+class BitWriter;
+class QPDFExc;
+
+class QPDF
+{
+ public:
+ QPDF();
+ ~QPDF();
+
+ // Associate a file with a QPDF object and do initial parsing of
+ // the file. PDF objects are not read until they are needed. A
+ // QPDF object may be associated with only on file in its
+ // lifetime. This method must be called before any methods that
+ // potentially ask for information about the PDF file are called.
+ // Prior to calling this, the only methods that are allowed are
+ // those that set parameters.
+ void processFile(char const* filename, char const* password = "");
+
+ // Parameter settings
+
+ // If true, ignore any cross-reference streams in a hybrid file
+ // (one that contains both cross-reference streams and
+ // cross-reference tables). This can be useful for testing to
+ // ensure that a hybrid file would work with an older reader.
+ void setIgnoreXRefStreams(bool);
+
+ // By default, any warnings are issued to stderr as they are
+ // encountered. If this is called with a true value, reporitng of
+ // warnings is suppressed. You may still retrieve warnings by
+ // calling getWarnings.
+ void setSuppressWarnings(bool);
+
+ // By default, QPDF will try to recover if it finds certain types
+ // of errors in PDF files. If turned off, it will throw an
+ // exception on the first such problem it finds without attempting
+ // recovery.
+ void setAttemptRecovery(bool);
+
+ // Other public methods
+
+ // Return the list of warnings that have been issued so far and
+ // clear the list. This method may be called even if processFile
+ // throws an exception. Note that if setSuppressWarnings was not
+ // called or was called with a false value, any warnings retrieved
+ // here will have already been issued to stderr.
+ std::vector<std::string> getWarnings();
+
+ std::string getFilename() const;
+ std::string getPDFVersion() const;
+ QPDFObjectHandle getTrailer();
+ QPDFObjectHandle getRoot();
+
+ // Install this object handle as an indirect object and return an
+ // indirect reference to it.
+ QPDFObjectHandle makeIndirectObject(QPDFObjectHandle);
+
+ // Retrieve an object by object ID and generation. Returns an
+ // indirect reference to it.
+ QPDFObjectHandle getObjectByID(int objid, int generation);
+
+ // Encryption support
+
+ struct EncryptionData
+ {
+ // This class holds data read from the encryption dictionary.
+ EncryptionData(int V, int R, int Length_bytes, long P,
+ std::string const& O, std::string const& U,
+ std::string const& id1) :
+ V(V),
+ R(R),
+ Length_bytes(Length_bytes),
+ P(P),
+ O(O),
+ U(U),
+ id1(id1)
+ {
+ }
+
+ int V;
+ int R;
+ int Length_bytes;
+ long P;
+ std::string O;
+ std::string U;
+ std::string id1;
+ };
+
+ static void trim_user_password(std::string& user_password);
+ static std::string compute_data_key(
+ std::string const& encryption_key, int objid, int generation);
+ static std::string compute_encryption_key(
+ std::string const& password, EncryptionData const& data);
+
+ static void compute_encryption_O_U(
+ char const* user_password, char const* owner_password,
+ int V, int R, int key_len, unsigned long P,
+ std::string const& id1,
+ std::string& O, std::string& U);
+ std::string const& getUserPassword() const;
+
+ // Linearization support
+
+ // Returns true iff the file starts with a linearization parameter
+ // dictionary. Does no additional validation.
+ bool isLinearized();
+
+ // Performs various sanity checks on a linearized file. Return
+ // true if no errors or warnings. Otherwise, return false and
+ // output errors and warnings to stdout.
+ bool checkLinearization();
+
+ // Calls checkLinearization() and, if possible, prints normalized
+ // contents of some of the hints tables to stdout. Normalization
+ // includes adding min values to delta values and adjusting
+ // offsets based on the location and size of the primary hint
+ // stream.
+ void showLinearizationData();
+
+ // Shows the contents of the cross-reference table
+ void showXRefTable();
+
+ // Optimization support -- see doc/optimization. Implemented in
+ // QPDF_optimization.cc
+
+ // The object_stream_data map maps from a "compressed" object to
+ // the object stream that contains it. This enables optimize to
+ // populate the object <-> user maps with only uncompressed
+ // objects. If allow_changes is false, an exception will be
+ // thrown if any changes are made during the optimization process.
+ // This is available so that the test suite can make sure that a
+ // linearized file is already optimized. When called in this way,
+ // optimize() still populates the object <-> user maps
+ void optimize(std::map<int, int> const& object_stream_data,
+ bool allow_changes = true);
+
+ // Replace all references to indirect objects that are "scalars"
+ // (i.e., things that don't have children: not arrays, streams, or
+ // dictionaries) with direct objects.
+ void flattenScalarReferences();
+
+ // For QPDFWriter:
+
+ // Remove /ID, /Encrypt, and /Prev keys from the trailer
+ // dictionary since these are regenerated during write.
+ void trimTrailerForWrite();
+
+ // Get lists of all objects in order according to the part of a
+ // linearized file that they belong to.
+ void getLinearizedParts(
+ std::map<int, int> const& object_stream_data,
+ std::vector<QPDFObjectHandle>& part4,
+ std::vector<QPDFObjectHandle>& part6,
+ std::vector<QPDFObjectHandle>& part7,
+ std::vector<QPDFObjectHandle>& part8,
+ std::vector<QPDFObjectHandle>& part9);
+
+ void generateHintStream(std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber,
+ PointerHolder<Buffer>& hint_stream,
+ int& S, int& O);
+
+ // Map object to object stream that contains it
+ void getObjectStreamData(std::map<int, int>&);
+ // Get a list of objects that would be permitted in an object
+ // stream
+ std::vector<int> getCompressibleObjects();
+
+ // Convenience routines for common functions. See also
+ // QPDFObjectHandle.hh for additional convenience routines.
+
+ // Traverse page tree return all /Page objects.
+ std::vector<QPDFObjectHandle> const& getAllPages();
+
+ // Resolver class is restricted to QPDFObjectHandle so that only
+ // it can resolve indirect references.
+ class Resolver
+ {
+ friend class QPDFObjectHandle;
+ private:
+ static PointerHolder<QPDFObject> resolve(
+ QPDF* qpdf, int objid, int generation)
+ {
+ return qpdf->resolve(objid, generation);
+ }
+ };
+ friend class Resolver;
+
+ // Pipe class is restricted to QPDF_Stream
+ class Pipe
+ {
+ friend class QPDF_Stream;
+ private:
+ static void pipeStreamData(QPDF* qpdf, int objid, int generation,
+ off_t offset, size_t length,
+ QPDFObjectHandle dict,
+ Pipeline* pipeline)
+ {
+ qpdf->pipeStreamData(
+ objid, generation, offset, length, dict, pipeline);
+ }
+ };
+ friend class Pipe;
+
+ private:
+ class InputSource
+ {
+ public:
+ InputSource() :
+ last_offset(0)
+ {
+ }
+ virtual ~InputSource()
+ {
+ }
+
+ void setLastOffset(off_t);
+ off_t getLastOffset() const;
+ std::string readLine();
+
+ virtual std::string const& getName() const = 0;
+ virtual off_t tell() = 0;
+ virtual void seek(off_t offset, int whence) = 0;
+ virtual void rewind() = 0;
+ virtual size_t read(char* buffer, int length) = 0;
+ virtual void unreadCh(char ch) = 0;
+
+ protected:
+ off_t last_offset;
+ };
+
+ class FileInputSource: public InputSource
+ {
+ public:
+ FileInputSource();
+ void setFilename(char const* filename);
+ virtual ~FileInputSource();
+ virtual std::string const& getName() const;
+ virtual off_t tell();
+ virtual void seek(off_t offset, int whence);
+ virtual void rewind();
+ virtual size_t read(char* buffer, int length);
+ virtual void unreadCh(char ch);
+
+ private:
+ FileInputSource(FileInputSource const&);
+ FileInputSource& operator=(FileInputSource const&);
+
+ void destroy();
+
+ std::string filename;
+ FILE* file;
+ };
+
+ class BufferInputSource: public InputSource
+ {
+ public:
+ BufferInputSource(std::string const& description, Buffer* buf);
+ virtual ~BufferInputSource();
+ virtual std::string const& getName() const;
+ virtual off_t tell();
+ virtual void seek(off_t offset, int whence);
+ virtual void rewind();
+ virtual size_t read(char* buffer, int length);
+ virtual void unreadCh(char ch);
+
+ private:
+ std::string description;
+ Buffer* buf;
+ off_t cur_offset;
+ };
+
+ class ObjGen
+ {
+ public:
+ ObjGen();
+ ObjGen(int obj, int gen);
+ bool operator<(ObjGen const&) const;
+
+ int obj;
+ int gen;
+ };
+
+ class ObjCache
+ {
+ public:
+ ObjCache() :
+ end_before_space(0),
+ end_after_space(0)
+ {
+ }
+ ObjCache(PointerHolder<QPDFObject> object,
+ off_t end_before_space,
+ off_t end_after_space) :
+ object(object),
+ end_before_space(end_before_space),
+ end_after_space(end_after_space)
+ {
+ }
+
+ PointerHolder<QPDFObject> object;
+ off_t end_before_space;
+ off_t end_after_space;
+ };
+
+ void parse();
+ void warn(QPDFExc const& e);
+ void setTrailer(QPDFObjectHandle obj);
+ void read_xref(off_t offset);
+ void reconstruct_xref(QPDFExc& e);
+ int read_xrefTable(off_t offset);
+ int read_xrefStream(off_t offset);
+ int processXRefStream(off_t offset, QPDFObjectHandle& xref_stream);
+ void insertXrefEntry(int obj, int f0, int f1, int f2);
+ QPDFObjectHandle readObject(
+ InputSource*, int objid, int generation,
+ bool in_object_stream);
+ QPDFObjectHandle readObjectInternal(
+ InputSource* input, int objid, int generation,
+ bool in_object_stream,
+ bool in_array, bool in_dictionary);
+ int recoverStreamLength(
+ InputSource* input, int objid, int generation, off_t stream_offset);
+ QPDFTokenizer::Token readToken(InputSource*);
+
+ QPDFObjectHandle readObjectAtOffset(
+ off_t offset,
+ int exp_objid, int exp_generation,
+ int& act_objid, int& act_generation);
+ PointerHolder<QPDFObject> resolve(int objid, int generation);
+ void resolveObjectsInStream(int obj_stream_number);
+
+ // Calls finish() on the pipeline when done but does not delete it
+ void pipeStreamData(int objid, int generation,
+ off_t offset, size_t length,
+ QPDFObjectHandle dict,
+ Pipeline* pipeline);
+ void getAllPagesInternal(QPDFObjectHandle cur_pages,
+ std::vector<QPDFObjectHandle>& result);
+
+ // methods to support encryption -- implemented in QPDF_encryption.cc
+ void initializeEncryption();
+ std::string getKeyForObject(int objid, int generation);
+ void decryptString(std::string&, int objid, int generation);
+ void decryptStream(Pipeline*& pipeline, int objid, int generation,
+ std::vector<PointerHolder<Pipeline> >& heap);
+
+ // Linearization Hint table structures.
+ // Naming conventions:
+
+ // HSomething is the Something Hint Table or table header
+ // HSomethingEntry is an entry in the Something table
+
+ // delta_something + min_something = something
+ // nbits_something = number of bits required for something
+
+ // something_offset is the pre-adjusted offset in the file. If >=
+ // H0_offset, H0_length must be added to get an actual file
+ // offset.
+
+ // PDF 1.4: Table F.4
+ struct HPageOffsetEntry
+ {
+ HPageOffsetEntry() :
+ delta_nobjects(0),
+ delta_page_length(0),
+ nshared_objects(0),
+ delta_content_offset(0),
+ delta_content_length(0)
+ {
+ }
+
+ int delta_nobjects; // 1
+ int delta_page_length; // 2
+ int nshared_objects; // 3
+ // vectors' sizes = nshared_objects
+ std::vector<int> shared_identifiers; // 4
+ std::vector<int> shared_numerators; // 5
+ int delta_content_offset; // 6
+ int delta_content_length; // 7
+ };
+
+ // PDF 1.4: Table F.3
+ struct HPageOffset
+ {
+ HPageOffset() :
+ min_nobjects(0),
+ first_page_offset(0),
+ nbits_delta_nobjects(0),
+ min_page_length(0),
+ nbits_delta_page_length(0),
+ min_content_offset(0),
+ nbits_delta_content_offset(0),
+ min_content_length(0),
+ nbits_delta_content_length(0),
+ nbits_nshared_objects(0),
+ nbits_shared_identifier(0),
+ nbits_shared_numerator(0),
+ shared_denominator(0)
+ {
+ }
+
+ int min_nobjects; // 1
+ int first_page_offset; // 2
+ int nbits_delta_nobjects; // 3
+ int min_page_length; // 4
+ int nbits_delta_page_length; // 5
+ int min_content_offset; // 6
+ int nbits_delta_content_offset; // 7
+ int min_content_length; // 8
+ int nbits_delta_content_length; // 9
+ int nbits_nshared_objects; // 10
+ int nbits_shared_identifier; // 11
+ int nbits_shared_numerator; // 12
+ int shared_denominator; // 13
+ // vector size is npages
+ std::vector<HPageOffsetEntry> entries;
+ };
+
+ // PDF 1.4: Table F.6
+ struct HSharedObjectEntry
+ {
+ HSharedObjectEntry() :
+ delta_group_length(0),
+ signature_present(0),
+ nobjects_minus_one(0)
+ {
+ }
+
+ // Item 3 is a 128-bit signature (unsupported by Acrobat)
+ int delta_group_length; // 1
+ int signature_present; // 2 -- always 0
+ int nobjects_minus_one; // 4 -- always 0
+ };
+
+ // PDF 1.4: Table F.5
+ struct HSharedObject
+ {
+ HSharedObject() :
+ first_shared_obj(0),
+ first_shared_offset(0),
+ nshared_first_page(0),
+ nshared_total(0),
+ nbits_nobjects(0),
+ min_group_length(0),
+ nbits_delta_group_length(0)
+ {
+ }
+
+ int first_shared_obj; // 1
+ int first_shared_offset; // 2
+ int nshared_first_page; // 3
+ int nshared_total; // 4
+ int nbits_nobjects; // 5
+ int min_group_length; // 6
+ int nbits_delta_group_length; // 7
+ // vector size is nshared_total
+ std::vector<HSharedObjectEntry> entries;
+ };
+
+ // PDF 1.4: Table F.9
+ struct HGeneric
+ {
+ HGeneric() :
+ first_object(0),
+ first_object_offset(0),
+ nobjects(0),
+ group_length(0)
+ {
+ }
+
+ int first_object; // 1
+ int first_object_offset; // 2
+ int nobjects; // 3
+ int group_length; // 4
+ };
+
+ // Other linearization data structures
+
+ // Initialized from Linearization Parameter dictionary
+ struct LinParameters
+ {
+ LinParameters() :
+ file_size(0),
+ first_page_object(0),
+ first_page_end(0),
+ npages(0),
+ xref_zero_offset(0),
+ first_page(0),
+ H_offset(0),
+ H_length(0)
+ {
+ }
+
+ int file_size; // /L
+ int first_page_object; // /O
+ int first_page_end; // /E
+ int npages; // /N
+ int xref_zero_offset; // /T
+ int first_page; // /P
+ int H_offset; // offset of primary hint stream
+ int H_length; // length of primary hint stream
+ };
+
+ // Computed hint table value data structures. These tables
+ // contain the computed values on which the hint table values are
+ // based. They exclude things like number of bits and store
+ // actual values instead of mins and deltas. File offsets are
+ // also absolute rather than being offset by the size of the
+ // primary hint table. We populate the hint table structures from
+ // these during writing and compare the hint table values with
+ // these during validation. We ignore some values for various
+ // reasons described in the code. Those values are omitted from
+ // these structures. Note also that object numbers are object
+ // numbers from the input file, not the output file.
+
+ // Naming convention: CHSomething is analogous to HSomething
+ // above. "CH" is computed hint.
+
+ struct CHPageOffsetEntry
+ {
+ CHPageOffsetEntry() :
+ nobjects(0),
+ nshared_objects(0)
+ {
+ }
+
+ int nobjects;
+ int nshared_objects;
+ // vectors' sizes = nshared_objects
+ std::vector<int> shared_identifiers;
+ };
+
+ struct CHPageOffset
+ {
+ // vector size is npages
+ std::vector<CHPageOffsetEntry> entries;
+ };
+
+ struct CHSharedObjectEntry
+ {
+ CHSharedObjectEntry(int object) :
+ object(object)
+ {
+ }
+
+ int object;
+ };
+
+ // PDF 1.4: Table F.5
+ struct CHSharedObject
+ {
+ CHSharedObject() :
+ first_shared_obj(0),
+ nshared_first_page(0),
+ nshared_total(0)
+ {
+ }
+
+ int first_shared_obj;
+ int nshared_first_page;
+ int nshared_total;
+ // vector size is nshared_total
+ std::vector<CHSharedObjectEntry> entries;
+ };
+
+ // No need for CHGeneric -- HGeneric is fine as is.
+
+
+ // Data structures to support optimization -- implemented in
+ // QPDF_optimization.cc
+
+ class ObjUser
+ {
+ public:
+ enum user_e
+ {
+ ou_bad,
+ ou_page,
+ ou_thumb,
+ ou_trailer_key,
+ ou_root_key,
+ ou_root
+ };
+
+ // type is set to ou_bad
+ ObjUser();
+
+ // type must be ou_root
+ ObjUser(user_e type);
+
+ // type must be one of ou_page or ou_thumb
+ ObjUser(user_e type, int pageno);
+
+ // type must be one of ou_trailer_key or ou_root_key
+ ObjUser(user_e type, std::string const& key);
+
+ bool operator<(ObjUser const&) const;
+
+ user_e ou_type;
+ int pageno; // if ou_page;
+ std::string key; // if ou_trailer_key or ou_root_key
+ };
+
+ // methods to support linearization checking -- implemented in
+ // QPDF_linearization.cc
+ void readLinearizationData();
+ bool checkLinearizationInternal();
+ void dumpLinearizationDataInternal();
+ QPDFObjectHandle readHintStream(Pipeline&, off_t offset, size_t length);
+ void readHPageOffset(BitStream);
+ void readHSharedObject(BitStream);
+ void readHGeneric(BitStream, HGeneric&);
+ int maxEnd(ObjUser const& ou);
+ int getLinearizationOffset(ObjGen const&);
+ QPDFObjectHandle getUncompressedObject(
+ QPDFObjectHandle&, std::map<int, int> const& object_stream_data);
+ int lengthNextN(int first_object, int n,
+ std::list<std::string>& errors);
+ void checkHPageOffset(std::list<std::string>& errors,
+ std::list<std::string>& warnings,
+ std::vector<QPDFObjectHandle> const& pages,
+ std::map<int, int>& idx_to_obj);
+ void checkHSharedObject(std::list<std::string>& warnings,
+ std::list<std::string>& errors,
+ std::vector<QPDFObjectHandle> const& pages,
+ std::map<int, int>& idx_to_obj);
+ void checkHOutlines(std::list<std::string>& warnings);
+ void dumpHPageOffset();
+ void dumpHSharedObject();
+ void dumpHGeneric(HGeneric&);
+ int adjusted_offset(int offset);
+ QPDFObjectHandle objGenToIndirect(ObjGen const&);
+ void calculateLinearizationData(
+ std::map<int, int> const& object_stream_data);
+ void pushOutlinesToPart(
+ std::vector<QPDFObjectHandle>& part,
+ std::set<ObjGen>& lc_outlines,
+ std::map<int, int> const& object_stream_data);
+ int outputLengthNextN(
+ int in_object, int n,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber);
+ void calculateHPageOffset(
+ std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber);
+ void calculateHSharedObject(
+ std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber);
+ void calculateHOutline(
+ std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber);
+ void writeHPageOffset(BitWriter&);
+ void writeHSharedObject(BitWriter&);
+ void writeHGeneric(BitWriter&, HGeneric&);
+
+
+ // Methods to support optimization
+
+ void optimizePagesTree(
+ QPDFObjectHandle,
+ std::map<std::string, std::vector<QPDFObjectHandle> >&,
+ int& pageno, bool allow_changes);
+ void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh);
+ void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
+ std::set<ObjGen>& visited, bool top);
+ void filterCompressedObjects(std::map<int, int> const& object_stream_data);
+
+
+ QPDFTokenizer tokenizer;
+ FileInputSource file;
+ bool encrypted;
+ bool encryption_initialized;
+ bool ignore_xref_streams;
+ bool suppress_warnings;
+ bool attempt_recovery;
+ std::string provided_password;
+ std::string user_password;
+ std::string encryption_key;
+ std::string cached_object_encryption_key;
+ int cached_key_objid;
+ int cached_key_generation;
+ std::string pdf_version;
+ std::map<ObjGen, QPDFXRefEntry> xref_table;
+ std::set<int> deleted_objects;
+ std::map<ObjGen, ObjCache> obj_cache;
+ QPDFObjectHandle trailer;
+ std::vector<QPDFObjectHandle> all_pages;
+ std::vector<std::string> warnings;
+
+ // Linearization data
+ int first_xref_item_offset; // actual value from file
+ bool uncompressed_after_compressed;
+
+ // Linearization parameter dictionary and hint table data: may be
+ // read from file or computed prior to writing a linearized file
+ QPDFObjectHandle lindict;
+ LinParameters linp;
+ HPageOffset page_offset_hints;
+ HSharedObject shared_object_hints;
+ HGeneric outline_hints;
+
+ // Computed linearization data: used to populate above tables
+ // during writing and to compare with them during validation. c_
+ // means computed.
+ LinParameters c_linp;
+ CHPageOffset c_page_offset_data;
+ CHSharedObject c_shared_object_data;
+ HGeneric c_outline_data;
+
+ // Object ordering data for linearized files: initialized by
+ // calculateLinearizationData(). Part numbers refer to the PDF
+ // 1.4 specification.
+ std::vector<QPDFObjectHandle> part4;
+ std::vector<QPDFObjectHandle> part6;
+ std::vector<QPDFObjectHandle> part7;
+ std::vector<QPDFObjectHandle> part8;
+ std::vector<QPDFObjectHandle> part9;
+
+ // Optimization data
+ std::map<ObjUser, std::set<ObjGen> > obj_user_to_objects;
+ std::map<ObjGen, std::set<ObjUser> > object_to_obj_users;
+};
+
+#endif // __QPDF_HH__
diff --git a/include/qpdf/QPDFExc.hh b/include/qpdf/QPDFExc.hh
new file mode 100644
index 00000000..d3efb3b9
--- /dev/null
+++ b/include/qpdf/QPDFExc.hh
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QPDFEXC_HH__
+#define __QPDFEXC_HH__
+
+#include <qpdf/QEXC.hh>
+
+class QPDFExc: public QEXC::General
+{
+ public:
+ QPDFExc(std::string const& message);
+ QPDFExc(std::string const& filename, int offset,
+ std::string const& message);
+ virtual ~QPDFExc() throw ();
+};
+
+#endif // __QPDFEXC_HH__
diff --git a/include/qpdf/QPDFObject.hh b/include/qpdf/QPDFObject.hh
new file mode 100644
index 00000000..1597e20e
--- /dev/null
+++ b/include/qpdf/QPDFObject.hh
@@ -0,0 +1,20 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QPDFOBJECT_HH__
+#define __QPDFOBJECT_HH__
+
+#include <string>
+
+class QPDFObject
+{
+ public:
+ virtual ~QPDFObject() {}
+ virtual std::string unparse() = 0;
+};
+
+#endif // __QPDFOBJECT_HH__
diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh
new file mode 100644
index 00000000..e38eb116
--- /dev/null
+++ b/include/qpdf/QPDFObjectHandle.hh
@@ -0,0 +1,221 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QPDFOBJECTHANDLE_HH__
+#define __QPDFOBJECTHANDLE_HH__
+
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+
+#include <qpdf/PointerHolder.hh>
+#include <qpdf/Buffer.hh>
+
+#include <qpdf/QPDFObject.hh>
+
+class Pipeline;
+class QPDF;
+
+class QPDFObjectHandle
+{
+ public:
+ QPDFObjectHandle();
+ bool isInitialized() const;
+
+ // Exactly one of these will return true for any object.
+ bool isBool();
+ bool isNull();
+ bool isInteger();
+ bool isReal();
+ bool isName();
+ bool isString();
+ bool isArray();
+ bool isDictionary();
+ bool isStream();
+
+ // This returns true in addition to the query for the specific
+ // type for indirect objects.
+ bool isIndirect();
+
+ // True for everything except array, dictionary, and stream
+ bool isScalar();
+
+ // Public factory methods
+
+ static QPDFObjectHandle newNull();
+ static QPDFObjectHandle newBool(bool value);
+ static QPDFObjectHandle newInteger(int value);
+ static QPDFObjectHandle newReal(std::string const& value);
+ static QPDFObjectHandle newName(std::string const& name);
+ static QPDFObjectHandle newString(std::string const& str);
+ static QPDFObjectHandle newArray(
+ std::vector<QPDFObjectHandle> const& items);
+ static QPDFObjectHandle newDictionary(
+ std::map<std::string, QPDFObjectHandle> const& items);
+
+ // Accessor methods. If an accessor method that is valid for only
+ // a particular object type is called on an object of the wrong
+ // type, an exception is thrown.
+
+ // Methods for bool objects
+ bool getBoolValue();
+
+ // Methods for integer objects
+ int getIntValue();
+
+ // Methods for real objects
+ std::string getRealValue();
+
+ // Methods that work for both integer and real objects
+ bool isNumber();
+ double getNumericValue();
+
+ // Methods for name objects
+ std::string getName();
+
+ // Methods for string objects
+ std::string getStringValue();
+ std::string getUTF8Value();
+
+ // Methods for array objects
+ int getArrayNItems();
+ QPDFObjectHandle getArrayItem(int n);
+
+ // Methods for dictionary objects
+ bool hasKey(std::string const&);
+ QPDFObjectHandle getKey(std::string const&);
+ std::set<std::string> getKeys();
+
+ // Mutator methods. Use with caution.
+
+ // Recursively copy this object, making it direct. Throws an
+ // exception if a loop is detected or any sub-object is a stream.
+ void makeDirect();
+
+ // Mutator methods for array objects
+ void setArrayItem(int, QPDFObjectHandle const&);
+
+ // Mutator methods for dictionary objects
+
+ // Replace value of key, adding it if it does not exist
+ void replaceKey(std::string const& key, QPDFObjectHandle const&);
+ // Remove key, doing nothing if key does not exist
+ void removeKey(std::string const& key);
+
+ // Methods for stream objects
+ QPDFObjectHandle getDict();
+
+ // Returns filtered (uncompressed) stream data. Throws an
+ // exception if the stream is filtered and we can't decode it.
+ PointerHolder<Buffer> getStreamData();
+
+ // Write stream data through the given pipeline. A null pipeline
+ // value may be used if all you want to do is determine whether a
+ // stream is filterable. If filter is false, write raw stream
+ // data and return false. If filter is true, then attempt to
+ // apply all the decoding filters to the stream data. If we are
+ // successful, return true. Otherwise, return false and write raw
+ // data. If filtering is requested and successfully performed,
+ // then the normalize and compress flags are used to determine
+ // whether stream data should be normalized and compressed. In
+ // all cases, if this function returns false, raw data has been
+ // written. If it returns true, then any requested filtering has
+ // been performed. Note that if the original stream data has no
+ // filters applied to it, the return value will be equal to the
+ // value of the filter parameter. Callers may use the return
+ // value of this function to determine whether or not the /Filter
+ // and /DecodeParms keys in the stream dictionary should be
+ // replaced if writing a new stream object.
+ bool pipeStreamData(Pipeline*, bool filter,
+ bool normalize, bool compress);
+
+ // return 0 for direct objects
+ int getObjectID() const;
+ int getGeneration() const;
+
+ std::string unparse();
+ std::string unparseResolved();
+
+ // Convenience routines for commonly performed functions
+
+ // Throws an exception if this is not a Page object. Returns an
+ // empty map if there are no images or no resources. This
+ // function does not presently support inherited resources. See
+ // comment in the source for details. Return value is a map from
+ // XObject name to the image object, which is always a stream.
+ std::map<std::string, QPDFObjectHandle> getPageImages();
+
+ // Throws an exception if this is not a Page object. Returns a
+ // vector of stream objects representing the content streams for
+ // the given page. This routine allows the caller to not care
+ // whether there are one or more than one content streams for a
+ // page.
+ std::vector<QPDFObjectHandle> getPageContents();
+
+ // Initializers for objects. This Factory class gives the QPDF
+ // class specific permission to call factory methods without
+ // making it a friend of the whole QPDFObjectHandle class.
+ class Factory
+ {
+ friend class QPDF;
+ private:
+ static QPDFObjectHandle newIndirect(QPDF* qpdf,
+ int objid, int generation)
+ {
+ return QPDFObjectHandle::newIndirect(qpdf, objid, generation);
+ }
+ // object must be dictionary object
+ static QPDFObjectHandle newStream(
+ QPDF* qpdf, int objid, int generation,
+ QPDFObjectHandle stream_dict, off_t offset, int length)
+ {
+ return QPDFObjectHandle::newStream(
+ qpdf, objid, generation, stream_dict, offset, length);
+ }
+ };
+ friend class Factory;
+
+ // Accessor for raw underlying object -- only QPDF is allowed to
+ // call this.
+ class ObjAccessor
+ {
+ friend class QPDF;
+ private:
+ static PointerHolder<QPDFObject> getObject(QPDFObjectHandle& o)
+ {
+ o.dereference();
+ return o.obj;
+ }
+ };
+ friend class ObjAccessor;
+
+ private:
+ QPDFObjectHandle(QPDF*, int objid, int generation);
+ QPDFObjectHandle(QPDFObject*);
+
+ // Private object factory methods
+ static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation);
+ static QPDFObjectHandle newStream(
+ QPDF* qpdf, int objid, int generation,
+ QPDFObjectHandle stream_dict, off_t offset, int length);
+
+ void assertInitialized() const;
+ void assertType(char const* type_name, bool istype);
+ void assertPageObject();
+ void dereference();
+ void makeDirectInternal(std::set<int>& visited);
+
+ bool initialized;
+
+ QPDF* qpdf; // 0 for direct object
+ int objid; // 0 for direct object
+ int generation;
+ PointerHolder<QPDFObject> obj;
+};
+
+#endif // __QPDFOBJECTHANDLE_HH__
diff --git a/include/qpdf/QPDFTokenizer.hh b/include/qpdf/QPDFTokenizer.hh
new file mode 100644
index 00000000..e921bfc5
--- /dev/null
+++ b/include/qpdf/QPDFTokenizer.hh
@@ -0,0 +1,141 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QPDFTOKENIZER_HH__
+#define __QPDFTOKENIZER_HH__
+
+#include <string>
+#include <stdio.h>
+
+class QPDFTokenizer
+{
+ public:
+ enum token_type_e
+ {
+ tt_bad,
+ tt_array_close,
+ tt_array_open,
+ tt_brace_close,
+ tt_brace_open,
+ tt_dict_close,
+ tt_dict_open,
+ tt_integer,
+ tt_name,
+ tt_real,
+ tt_string,
+ tt_null,
+ tt_bool,
+ tt_word,
+ };
+
+ class Token
+ {
+ public:
+ Token() : type(tt_bad) {}
+
+ Token(token_type_e type, std::string const& value) :
+ type(type),
+ value(value)
+ {
+ }
+
+ Token(token_type_e type, std::string const& value,
+ std::string raw_value, std::string error_message) :
+ type(type),
+ value(value),
+ raw_value(raw_value),
+ error_message(error_message)
+ {
+ }
+ token_type_e getType() const
+ {
+ return this->type;
+ }
+ std::string const& getValue() const
+ {
+ return this->value;
+ }
+ std::string const& getRawValue() const
+ {
+ return this->raw_value;
+ }
+ std::string const& getErrorMessage() const
+ {
+ return this->error_message;
+ }
+ bool operator==(Token const& rhs)
+ {
+ // Ignore fields other than type and value
+ return ((this->type != tt_bad) &&
+ (this->type == rhs.type) &&
+ (this->value == rhs.value));
+ }
+
+ private:
+ token_type_e type;
+ std::string value;
+ std::string raw_value;
+ std::string error_message;
+ };
+
+ QPDFTokenizer();
+
+ // PDF files with version < 1.2 allowed the pound character
+ // anywhere in a name. Starting with version 1.2, the pound
+ // character was allowed only when followed by two hexadecimal
+ // digits. This method should be called when parsing a PDF file
+ // whose version is older than 1.2.
+ void allowPoundAnywhereInName();
+
+ // Mode of operation:
+
+ // Keep presenting characters and calling getToken() until
+ // getToken() returns true. When it does, be sure to check
+ // unread_ch and to unread ch if it is true.
+
+ // It these are called when a token is available, an exception
+ // will be thrown.
+ void presentCharacter(char ch);
+ void presentEOF();
+
+ // If a token is available, return true and initialize token with
+ // the token, unread_char with whether or not we have to unread
+ // the last character, and if unread_char, ch with the character
+ // to unread.
+ bool getToken(Token& token, bool& unread_char, char& ch);
+
+ // This function returns true of the current character is between
+ // tokens (i.e., white space that is not part of a string) or is
+ // part of a comment. A tokenizing filter can call this to
+ // determine whether to output the character.
+ bool betweenTokens();
+
+ private:
+ void reset();
+
+ // Lexer state
+ enum { st_top, st_in_comment, st_in_string, st_lt, st_gt,
+ st_literal, st_in_hexstring, st_token_ready } state;
+
+ bool pound_special_in_name;
+
+ // Current token accumulation
+ token_type_e type;
+ std::string val;
+ std::string raw_val;
+ std::string error_message;
+ bool unread_char;
+ char char_to_unread;
+
+ // State for strings
+ int string_depth;
+ bool string_ignoring_newline;
+ char bs_num_register[4];
+ bool last_char_was_bs;
+};
+
+#endif // __QPDFTOKENIZER_HH__
diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh
new file mode 100644
index 00000000..f332a227
--- /dev/null
+++ b/include/qpdf/QPDFWriter.hh
@@ -0,0 +1,243 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+// This class implements a simple writer for saving QPDF objects to
+// new PDF files. See comments through the header file for additional
+// details.
+
+#ifndef __QPDFWRITER_HH__
+#define __QPDFWRITER_HH__
+
+#include <stdio.h>
+#include <string>
+#include <list>
+#include <vector>
+#include <set>
+#include <map>
+
+#include <qpdf/QPDFXRefEntry.hh>
+
+#include <qpdf/PointerHolder.hh>
+#include <qpdf/Pipeline.hh>
+#include <qpdf/Buffer.hh>
+
+class QPDF;
+class QPDFObjectHandle;
+class Pl_Count;
+
+class QPDFWriter
+{
+ public:
+ // Passing null as filename means write to stdout
+ QPDFWriter(QPDF& pdf, char const* filename);
+ ~QPDFWriter();
+
+ // Set the value of object stream mode. In disable mode, we never
+ // generate any object streams. In preserve mode, we preserve
+ // object stream structure from the original file. In generate
+ // mode, we generate our own object streams. In all cases, we
+ // generate a conventional cross-reference table if there are no
+ // object streams and a cross-reference stream if there are object
+ // streams. The default is o_preserve.
+ enum object_stream_e { o_disable, o_preserve, o_generate };
+ void setObjectStreamMode(object_stream_e);
+
+ // Set value of stream data mode. In uncompress mode, we attempt
+ // to uncompress any stream that we can. In preserve mode, we
+ // preserve any filtering applied to streams. In compress mode,
+ // if we can apply all filters and the stream is not already
+ // optimally compressed, recompress the stream.
+ enum stream_data_e { s_uncompress, s_preserve, s_compress };
+ void setStreamDataMode(stream_data_e);
+
+ // Set value of content stream normalization. The default is
+ // "false". If true, we attempt to normalize newlines inside of
+ // content streams. Some constructs such as inline images may
+ // thwart our efforts. There may be some cases where this can
+ // damage the content stream. This flag should be used only for
+ // debugging and experimenting with PDF content streams. Never
+ // use it for production files.
+ void setContentNormalization(bool);
+
+ // Set QDF mode. QDF mode causes special "pretty printing" of
+ // PDF objects, adds comments for easier perusing of files.
+ // Resulting PDF files can be edited in a text editor and then run
+ // through fix-qdf to update cross reference tables and stream
+ // lengths.
+ void setQDFMode(bool);
+
+ // Cause a static /ID value to be generated. Use only in test
+ // suites.
+ void setStaticID(bool);
+
+ // Preserve encryption. The default is true unless prefilering,
+ // content normalization, or qdf mode has been selected in which
+ // case encryption is never preserved. Encryption is also not
+ // preserved if we explicitly set encryption parameters.
+ void setPreserveEncryption(bool);
+
+ // Set up for encrypted output. Disables stream prefiltering and
+ // content normalization. Note that setting R2 encryption
+ // parameters sets the PDF version to at least 1.3, and setting R3
+ // encryption parameters pushes the PDF version number to at least
+ // 1.4.
+ void setR2EncryptionParameters(
+ char const* user_password, char const* owner_password,
+ bool allow_print, bool allow_modify,
+ bool allow_extract, bool allow_annotate);
+ enum r3_print_e
+ {
+ r3p_full, // allow all printing
+ r3p_low, // allow only low-resolution printing
+ r3p_none // allow no printing
+ };
+ enum r3_modify_e
+ {
+ r3m_all, // allow all modification
+ r3m_annotate, // allow comment authoring and form operations
+ r3m_form, // allow form field fill-in or signing
+ r3m_assembly, // allow only document assembly
+ r3m_none // allow no modification
+ };
+ void setR3EncryptionParameters(
+ char const* user_password, char const* owner_password,
+ bool allow_accessibility, bool allow_extract,
+ r3_print_e print, r3_modify_e modify);
+
+ // Create linearized output. Disables qdf mode, content
+ // normalization, and stream prefiltering.
+ void setLinearization(bool);
+
+ void write();
+
+ private:
+ // flags used by unparseObject
+ static int const f_stream = 1 << 0;
+ static int const f_filtered = 1 << 1;
+ static int const f_in_ostream = 1 << 2;
+
+ enum trailer_e { t_normal, t_lin_first, t_lin_second };
+
+ int bytesNeeded(unsigned long n);
+ void writeBinary(unsigned long val, unsigned int bytes);
+ void writeString(std::string const& str);
+ void writeBuffer(PointerHolder<Buffer>&);
+ void writeStringQDF(std::string const& str);
+ void writeStringNoQDF(std::string const& str);
+ void assignCompressedObjectNumbers(int objid);
+ void enqueueObject(QPDFObjectHandle object);
+ void writeObjectStreamOffsets(std::vector<int>& offsets, int first_obj);
+ void writeObjectStream(QPDFObjectHandle object);
+ void writeObject(QPDFObjectHandle object, int object_stream_index = -1);
+ void writeTrailer(trailer_e which, int size,
+ bool xref_stream, int prev = 0);
+ void unparseObject(QPDFObjectHandle object, int level,
+ unsigned int flags);
+ void unparseObject(QPDFObjectHandle object, int level,
+ unsigned int flags,
+ // for stream dictionaries
+ int stream_length, bool compress);
+ void unparseChild(QPDFObjectHandle child, int level, int flags);
+ void initializeSpecialStreams();
+ void preserveObjectStreams();
+ void generateObjectStreams();
+ void generateID();
+ void setEncryptionParameters(
+ char const* user_password, char const* owner_password,
+ int V, int R, int key_len, std::set<int>& bits_to_clear);
+ void setEncryptionParametersInternal(
+ int V, int R, int key_len, long P,
+ std::string const& O, std::string const& U,
+ std::string const& id1, std::string const& user_password);
+ void copyEncryptionParameters();
+ void setDataKey(int objid);
+ int openObject(int objid = 0);
+ void closeObject(int objid);
+ void writeStandard();
+ void writeLinearized();
+ void enqueuePart(std::vector<QPDFObjectHandle>& part);
+ void writeEncryptionDictionary();
+ void writeHeader();
+ void writeHintStream(int hint_id);
+ int writeXRefTable(trailer_e which, int first, int last, int size);
+ int writeXRefTable(trailer_e which, int first, int last, int size,
+ // for linearization
+ int prev,
+ bool suppress_offsets,
+ int hint_id,
+ int hint_offset,
+ int hint_length);
+ int writeXRefStream(int objid, int max_id, int max_offset,
+ trailer_e which, int first, int last, int size);
+ int writeXRefStream(int objid, int max_id, int max_offset,
+ trailer_e which, int first, int last, int size,
+ // for linearization
+ int prev,
+ int hint_id,
+ int hint_offset,
+ int hint_length);
+
+ // When filtering subsections, push additional pipelines to the
+ // stack. When ready to switch, activate the pipeline stack.
+ // Pipelines passed to pushPipeline are deleted when
+ // clearPipelineStack is called.
+ Pipeline* pushPipeline(Pipeline*);
+ void activatePipelineStack();
+
+ // Calls finish on the current pipeline and pops the pipeline
+ // stack until the top of stack is a previous active top of stack,
+ // and restores the pipeline to that point. Deletes any piplines
+ // that it pops. If the bp argument is non-null and any of the
+ // stack items are of type Pl_Buffer, the buffer is retrieved.
+ void popPipelineStack(PointerHolder<Buffer>* bp = 0);
+
+ void pushEncryptionFilter();
+ void pushDiscardFilter();
+
+ QPDF& pdf;
+ char const* filename;
+ FILE* file;
+ bool close_file;
+ bool normalize_content_set;
+ bool normalize_content;
+ bool stream_data_mode_set;
+ stream_data_e stream_data_mode;
+ bool qdf_mode;
+ bool static_id;
+ bool direct_stream_lengths;
+ bool encrypted;
+ bool preserve_encryption;
+ bool linearized;
+ object_stream_e object_stream_mode;
+ std::string encryption_key;
+ std::map<std::string, std::string> encryption_dictionary;
+
+ std::string id1; // for /ID key of
+ std::string id2; // trailer dictionary
+ std::string min_pdf_version;
+ int encryption_dict_objid;
+ std::string cur_data_key;
+ std::list<PointerHolder<Pipeline> > to_delete;
+ Pl_Count* pipeline;
+ std::list<QPDFObjectHandle> object_queue;
+ std::map<int, int> obj_renumber;
+ std::map<int, QPDFXRefEntry> xref;
+ std::map<int, size_t> lengths;
+ int next_objid;
+ int cur_stream_length_id;
+ int cur_stream_length;
+ bool added_newline;
+ int max_ostream_index;
+ std::set<int> normalized_streams;
+ std::map<int, int> page_object_to_seq;
+ std::map<int, int> contents_to_page_seq;
+ std::map<int, int> object_to_object_stream;
+ std::map<int, std::set<int> > object_stream_to_objects;
+ std::list<Pipeline*> pipeline_stack;
+};
+
+#endif // __QPDFWRITER_HH__
diff --git a/include/qpdf/QPDFXRefEntry.hh b/include/qpdf/QPDFXRefEntry.hh
new file mode 100644
index 00000000..4b1db9a2
--- /dev/null
+++ b/include/qpdf/QPDFXRefEntry.hh
@@ -0,0 +1,34 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QPDFXREFENTRY_HH__
+#define __QPDFXREFENTRY_HH__
+
+class QPDFXRefEntry
+{
+ public:
+ // Type constants are from the PDF spec section
+ // "Cross-Reference Streams":
+ // 0 = free entry; not used
+ // 1 = "uncompressed"; field 1 = offset
+ // 2 = "compressed"; field 1 = object stream number, field 2 = index
+
+ QPDFXRefEntry();
+ QPDFXRefEntry(int type, int field1, int field2);
+
+ int getType() const;
+ int getOffset() const; // only for type 1
+ int getObjStreamNumber() const; // only for type 2
+ int getObjStreamIndex() const; // only for type 2
+
+ private:
+ int type;
+ int field1;
+ int field2;
+};
+
+#endif // __QPDFXREFENTRY_HH__
diff --git a/include/qpdf/QTC.hh b/include/qpdf/QTC.hh
new file mode 100644
index 00000000..3d9597d4
--- /dev/null
+++ b/include/qpdf/QTC.hh
@@ -0,0 +1,16 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QTC_HH__
+#define __QTC_HH__
+
+namespace QTC
+{
+ void TC(char const* const scope, char const* const ccase, int n = 0);
+};
+
+#endif // __QTC_HH__
diff --git a/include/qpdf/QUtil.hh b/include/qpdf/QUtil.hh
new file mode 100644
index 00000000..f2b67d92
--- /dev/null
+++ b/include/qpdf/QUtil.hh
@@ -0,0 +1,45 @@
+// Copyright (c) 2005-2008 Jay Berkenbilt
+//
+// This file is part of qpdf. This software may be distributed under
+// the terms of version 2 of the Artistic License which may be found
+// in the source distribution. It is provided "as is" without express
+// or implied warranty.
+
+#ifndef __QUTIL_HH__
+#define __QUTIL_HH__
+
+#include <string>
+#include <list>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include <qpdf/QEXC.hh>
+
+namespace QUtil
+{
+ // This is a collection of useful utility functions that don't
+ // really go anywhere else.
+ std::string int_to_string(int, int length = 0);
+ std::string double_to_string(double, int decimal_places = 0);
+
+ // If status is -1, convert the current value of errno to a
+ // QEXC::System exception. Otherwise, return status.
+ int os_wrapper(std::string const& description, int status)
+ throw (QEXC::System);
+
+ FILE* fopen_wrapper(std::string const&, FILE*)
+ throw (QEXC::System);
+
+ char* copy_string(std::string const&);
+
+ // Get the value of an environment variable in a portable fashion.
+ // Returns true iff the variable is defined. If `value' is
+ // non-null, initializes it with the value of the variable.
+ bool get_env(std::string const& var, std::string* value = 0);
+
+ // Return a string containing the byte representation of the UTF-8
+ // encoding for the unicode value passed in.
+ std::string toUTF8(unsigned long uval);
+};
+
+#endif // __QUTIL_HH__
diff --git a/install-sh b/install-sh
new file mode 100755
index 00000000..a5897de6
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/libqpdf/BitStream.cc b/libqpdf/BitStream.cc
new file mode 100644
index 00000000..c6fda4e6
--- /dev/null
+++ b/libqpdf/BitStream.cc
@@ -0,0 +1,45 @@
+
+
+#include <qpdf/BitStream.hh>
+
+// See comments in bits.cc
+#define BITS_READ 1
+#include "bits.icc"
+
+BitStream::BitStream(unsigned char const* p, int nbytes) :
+ start(p),
+ nbytes(nbytes)
+{
+ reset();
+}
+
+void
+BitStream::reset()
+{
+ p = start;
+ bit_offset = 7;
+ bits_available = 8 * nbytes;
+}
+
+unsigned long
+BitStream::getBits(int nbits)
+{
+ return read_bits(this->p, this->bit_offset,
+ this->bits_available, nbits);
+}
+
+void
+BitStream::skipToNextByte()
+{
+ if (bit_offset != 7)
+ {
+ unsigned int bits_to_skip = bit_offset + 1;
+ if (bits_available < bits_to_skip)
+ {
+ throw QEXC::Internal("overflow skipping to next byte in bitstream");
+ }
+ bit_offset = 7;
+ ++p;
+ bits_available -= bits_to_skip;
+ }
+}
diff --git a/libqpdf/BitWriter.cc b/libqpdf/BitWriter.cc
new file mode 100644
index 00000000..f682aac5
--- /dev/null
+++ b/libqpdf/BitWriter.cc
@@ -0,0 +1,30 @@
+
+
+#include <qpdf/BitWriter.hh>
+
+// See comments in bits.cc
+#define BITS_WRITE 1
+#include "bits.icc"
+
+BitWriter::BitWriter(Pipeline* pl) :
+ pl(pl),
+ ch(0),
+ bit_offset(7)
+{
+}
+
+void
+BitWriter::writeBits(unsigned long val, int bits)
+{
+ write_bits(this->ch, this->bit_offset, val, bits, this->pl);
+}
+
+void
+BitWriter::flush()
+{
+ if (bit_offset < 7)
+ {
+ int bits_to_write = bit_offset + 1;
+ write_bits(this->ch, this->bit_offset, 0, bits_to_write, this->pl);
+ }
+}
diff --git a/libqpdf/Buffer.cc b/libqpdf/Buffer.cc
new file mode 100644
index 00000000..3dde1f90
--- /dev/null
+++ b/libqpdf/Buffer.cc
@@ -0,0 +1,79 @@
+
+#include <qpdf/Buffer.hh>
+
+#include <string.h>
+
+Buffer::Buffer()
+{
+ init(0);
+}
+
+Buffer::Buffer(unsigned long size)
+{
+ init(size);
+}
+
+Buffer::Buffer(Buffer const& rhs)
+{
+ init(0);
+ copy(rhs);
+}
+
+Buffer&
+Buffer::operator=(Buffer const& rhs)
+{
+ copy(rhs);
+ return *this;
+}
+
+Buffer::~Buffer()
+{
+ destroy();
+}
+
+void
+Buffer::init(unsigned long size)
+{
+ this->size = size;
+ this->buf = (size ? new unsigned char[size] : 0);
+}
+
+void
+Buffer::copy(Buffer const& rhs)
+{
+ if (this != &rhs)
+ {
+ this->destroy();
+ this->init(rhs.size);
+ if (this->size)
+ {
+ memcpy(this->buf, rhs.buf, this->size);
+ }
+ }
+}
+
+void
+Buffer::destroy()
+{
+ delete [] this->buf;
+ this->size = 0;
+ this->buf = 0;
+}
+
+unsigned long
+Buffer::getSize() const
+{
+ return this->size;
+}
+
+unsigned char const*
+Buffer::getBuffer() const
+{
+ return this->buf;
+}
+
+unsigned char*
+Buffer::getBuffer()
+{
+ return this->buf;
+}
diff --git a/libqpdf/MD5.cc b/libqpdf/MD5.cc
new file mode 100644
index 00000000..ecdd8a33
--- /dev/null
+++ b/libqpdf/MD5.cc
@@ -0,0 +1,441 @@
+// This file implements a class for computation of MD5 checksums.
+// It is derived from the reference algorithm for MD5 as given in
+// RFC 1321. The original copyright notice is as follows:
+//
+/////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD5 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+//
+/////////////////////////////////////////////////////////////////////////
+
+#include <qpdf/MD5.hh>
+
+#include <stdio.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+int const S11 = 7;
+int const S12 = 12;
+int const S13 = 17;
+int const S14 = 22;
+int const S21 = 5;
+int const S22 = 9;
+int const S23 = 14;
+int const S24 = 20;
+int const S31 = 4;
+int const S32 = 11;
+int const S33 = 16;
+int const S34 = 23;
+int const S41 = 6;
+int const S42 = 10;
+int const S43 = 15;
+int const S44 = 21;
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+// F, G, H and I are basic MD5 functions.
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+// ROTATE_LEFT rotates x left n bits.
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+// Rotation is separate from addition to prevent recomputation.
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+// MD5 initialization. Begins an MD5 operation, writing a new context.
+void MD5::init()
+{
+ count[0] = count[1] = 0;
+ // Load magic initialization constants.
+ state[0] = 0x67452301;
+ state[1] = 0xefcdab89;
+ state[2] = 0x98badcfe;
+ state[3] = 0x10325476;
+
+ finalized = false;
+ memset(digest_val, 0, sizeof(digest_val));
+}
+
+// MD5 block update operation. Continues an MD5 message-digest
+// operation, processing another message block, and updating the
+// context.
+
+void MD5::update(unsigned char *input,
+ unsigned int inputLen)
+{
+ unsigned int i, index, partLen;
+
+ // Compute number of bytes mod 64
+ index = (unsigned int)((count[0] >> 3) & 0x3F);
+
+ // Update number of bits
+ if ((count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ count[1]++;
+ count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ // Transform as many times as possible.
+
+ if (inputLen >= partLen) {
+ memcpy
+ ((POINTER)&buffer[index], (POINTER)input, partLen);
+ transform(state, buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ transform(state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ // Buffer remaining input
+ memcpy
+ ((POINTER)&buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+// MD5 finalization. Ends an MD5 message-digest operation, writing the
+// the message digest and zeroizing the context.
+void MD5::final()
+{
+ if (finalized)
+ {
+ return;
+ }
+
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ // Save number of bits
+ encode(bits, count, 8);
+
+ // Pad out to 56 mod 64.
+
+ index = (unsigned int)((count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ update(PADDING, padLen);
+
+ // Append length (before padding)
+ update(bits, 8);
+ // Store state in digest_val
+ encode(digest_val, state, 16);
+
+ // Zeroize sensitive information.
+ memset(state, 0, sizeof(state));
+ memset(count, 0, sizeof(count));
+ memset(buffer, 0, sizeof(buffer));
+
+ finalized = true;
+}
+
+// MD5 basic transformation. Transforms state based on block.
+void MD5::transform(UINT4 state[4], unsigned char block[64])
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ decode(x, block, 64);
+
+ // Round 1
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); // 1
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); // 2
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); // 3
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); // 4
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); // 5
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); // 6
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); // 7
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); // 8
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); // 9
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); // 10
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); // 11
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); // 12
+ FF (a, b, c, d, x[12], S11, 0x6b901122); // 13
+ FF (d, a, b, c, x[13], S12, 0xfd987193); // 14
+ FF (c, d, a, b, x[14], S13, 0xa679438e); // 15
+ FF (b, c, d, a, x[15], S14, 0x49b40821); // 16
+
+ // Round 2
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); // 17
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); // 18
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); // 19
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); // 20
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); // 21
+ GG (d, a, b, c, x[10], S22, 0x2441453); // 22
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); // 23
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); // 24
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); // 25
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); // 26
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); // 27
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); // 28
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); // 29
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); // 30
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); // 31
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32
+
+ // Round 3
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); // 33
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); // 34
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); // 35
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); // 36
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); // 37
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); // 38
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); // 39
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); // 40
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); // 41
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); // 42
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); // 43
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); // 44
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); // 45
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); // 46
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); // 47
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); // 48
+
+ // Round 4
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); // 49
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); // 50
+ II (c, d, a, b, x[14], S43, 0xab9423a7); // 51
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); // 52
+ II (a, b, c, d, x[12], S41, 0x655b59c3); // 53
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); // 54
+ II (c, d, a, b, x[10], S43, 0xffeff47d); // 55
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); // 56
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); // 57
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); // 59
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); // 60
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); // 61
+ II (d, a, b, c, x[11], S42, 0xbd3af235); // 62
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); // 63
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); // 64
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ // Zeroize sensitive information.
+
+ memset ((POINTER)x, 0, sizeof (x));
+}
+
+// Encodes input (UINT4) into output (unsigned char). Assumes len is a
+// multiple of 4.
+void MD5::encode(unsigned char *output, UINT4 *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+// Decodes input (unsigned char) into output (UINT4). Assumes len is a
+// multiple of 4.
+void MD5::decode(UINT4 *output, unsigned char *input, unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+// Public functions
+
+MD5::MD5()
+{
+ init();
+}
+
+void MD5::reset()
+{
+ init();
+}
+
+void MD5::encodeString(char const* str)
+{
+ unsigned int len = strlen(str);
+
+ update((unsigned char *)str, len);
+ final();
+}
+
+void MD5::appendString(char const* input_string)
+{
+ update((unsigned char *)input_string, strlen(input_string));
+}
+
+void MD5::encodeDataIncrementally(char const* data, int len)
+{
+ update((unsigned char *)data, len);
+}
+
+void MD5::encodeFile(char const *filename, int up_to_size)
+ throw (QEXC::System)
+{
+ FILE *file;
+ unsigned char buffer[1024];
+
+ if ((file = fopen (filename, "rb")) == NULL)
+ {
+ throw QEXC::System(std::string("MD5: can't open ") + filename, errno);
+ }
+
+ int len;
+ int so_far = 0;
+ int to_try = 1024;
+ do
+ {
+ if ((up_to_size >= 0) && ((so_far + to_try) > up_to_size))
+ {
+ to_try = up_to_size - so_far;
+ }
+ len = fread(buffer, 1, to_try, file);
+ if (len > 0)
+ {
+ update(buffer, len);
+ so_far += len;
+ if ((up_to_size >= 0) && (so_far >= up_to_size))
+ {
+ break;
+ }
+ }
+ } while (len > 0);
+ if (ferror(file))
+ {
+ // Assume, perhaps incorrectly, that errno was set by the
+ // underlying call to read....
+ (void) fclose(file);
+ throw QEXC::System(std::string("MD5: read error on ") + filename, errno);
+ }
+ (void) fclose(file);
+
+ final();
+}
+
+void MD5::digest(Digest result)
+{
+ final();
+ memcpy(result, digest_val, sizeof(digest_val));
+}
+
+void MD5::print()
+{
+ final();
+
+ unsigned int i;
+ for (i = 0; i < 16; ++i)
+ {
+ printf("%02x", digest_val[i]);
+ }
+ printf("\n");
+}
+
+std::string MD5::unparse()
+{
+ final();
+
+ char result[33];
+ char* p = result;
+ unsigned int i;
+ for (i = 0; i < 16; ++i)
+ {
+ sprintf(p, "%02x", digest_val[i]);
+ p += 2;
+ }
+ return result;
+}
+
+std::string
+MD5::getDataChecksum(char const* buf, int len)
+{
+ MD5 m;
+ m.encodeDataIncrementally(buf, len);
+ return m.unparse();
+}
+
+std::string
+MD5::getFileChecksum(char const* filename, int up_to_size)
+{
+ MD5 m;
+ m.encodeFile(filename, up_to_size);
+ return m.unparse();
+}
+
+bool
+MD5::checkDataChecksum(char const* const checksum,
+ char const* buf, int len)
+{
+ std::string actual_checksum = getDataChecksum(buf, len);
+ return (checksum == actual_checksum);
+}
+
+bool
+MD5::checkFileChecksum(char const* const checksum,
+ char const* filename, int up_to_size)
+{
+ bool result = false;
+ try
+ {
+ std::string actual_checksum = getFileChecksum(filename, up_to_size);
+ result = (checksum == actual_checksum);
+ }
+ catch (QEXC::System)
+ {
+ // Ignore -- return false
+ }
+ return result;
+}
diff --git a/libqpdf/Makefile b/libqpdf/Makefile
new file mode 100644
index 00000000..90899055
--- /dev/null
+++ b/libqpdf/Makefile
@@ -0,0 +1 @@
+include ../make/proxy.mk
diff --git a/libqpdf/PCRE.cc b/libqpdf/PCRE.cc
new file mode 100644
index 00000000..afa6e954
--- /dev/null
+++ b/libqpdf/PCRE.cc
@@ -0,0 +1,365 @@
+
+
+#include <qpdf/PCRE.hh>
+#include <qpdf/QUtil.hh>
+
+#include <iostream>
+
+PCRE::Exception::Exception(std::string const& message)
+{
+ this->setMessage("PCRE error: " + message);
+}
+
+PCRE::NoBackref::NoBackref() :
+ Exception("no match")
+{
+}
+
+PCRE::Match::Match(int nbackrefs, char const* subject)
+{
+ this->init(-1, nbackrefs, subject);
+}
+
+PCRE::Match::~Match()
+{
+ this->destroy();
+}
+
+PCRE::Match::Match(Match const& rhs)
+{
+ this->copy(rhs);
+}
+
+PCRE::Match&
+PCRE::Match::operator=(Match const& rhs)
+{
+ if (this != &rhs)
+ {
+ this->destroy();
+ this->copy(rhs);
+ }
+ return *this;
+}
+
+void
+PCRE::Match::init(int nmatches, int nbackrefs, char const* subject)
+{
+ this->nmatches = nmatches;
+ this->nbackrefs = nbackrefs;
+ this->subject = subject;
+ this->ovecsize = 3 * (1 + nbackrefs);
+ this->ovector = 0;
+ if (this->ovecsize)
+ {
+ this->ovector = new int[this->ovecsize];
+ }
+}
+
+void
+PCRE::Match::copy(Match const& rhs)
+{
+ this->init(rhs.nmatches, rhs.nbackrefs, rhs.subject);
+ int i;
+ for (i = 0; i < this->ovecsize; ++i)
+ {
+ this->ovector[i] = rhs.ovector[i];
+ }
+}
+
+void
+PCRE::Match::destroy()
+{
+ delete [] this->ovector;
+}
+
+PCRE::Match::operator bool()
+{
+ return (this->nmatches >= 0);
+}
+
+
+std::string
+PCRE::Match::getMatch(int n, int flags)
+ throw(QEXC::General, Exception)
+{
+ // This method used to be implemented in terms of
+ // pcre_get_substring, but that function gives you an empty string
+ // for an unmatched backreference that is in range.
+
+ int offset;
+ int length;
+ try
+ {
+ getOffsetLength(n, offset, length);
+ }
+ catch (NoBackref&)
+ {
+ if (flags & gm_no_substring_returns_empty)
+ {
+ return "";
+ }
+ else
+ {
+ throw;
+ }
+ }
+
+ return std::string(this->subject).substr(offset, length);
+}
+
+void
+PCRE::Match::getOffsetLength(int n, int& offset, int& length) throw(Exception)
+{
+ if ((this->nmatches < 0) ||
+ (n > this->nmatches - 1) ||
+ (this->ovector[n * 2] == -1))
+ {
+ throw NoBackref();
+ }
+ offset = this->ovector[n * 2];
+ length = this->ovector[n * 2 + 1] - offset;
+}
+
+
+int
+PCRE::Match::getOffset(int n) throw(Exception)
+{
+ int offset;
+ int length;
+ this->getOffsetLength(n, offset, length);
+ return offset;
+}
+
+
+int
+PCRE::Match::getLength(int n) throw(Exception)
+{
+ int offset;
+ int length;
+ this->getOffsetLength(n, offset, length);
+ return length;
+}
+
+
+int
+PCRE::Match::nMatches() const
+{
+ return this->nmatches;
+}
+
+PCRE::PCRE(char const* pattern, int options) throw (Exception)
+{
+ char const *errptr;
+ int erroffset;
+ this->code = pcre_compile(pattern, options, &errptr, &erroffset, 0);
+ if (this->code)
+ {
+ this->nbackrefs = pcre_info(this->code, 0, 0);
+ }
+ else
+ {
+ std::string message = (std::string("compilation of ") + pattern +
+ " failed at offset " +
+ QUtil::int_to_string(erroffset) + ": " +
+ errptr);
+ throw Exception(message);
+ }
+}
+
+PCRE::~PCRE()
+{
+ pcre_free(this->code);
+}
+
+PCRE::Match
+PCRE::match(char const* subject, int options, int startoffset, int size)
+ throw (QEXC::General, Exception)
+{
+ if (size == -1)
+ {
+ size = strlen(subject);
+ }
+
+ Match result(this->nbackrefs, subject);
+ int status = pcre_exec(this->code, 0, subject, size,
+ startoffset, options,
+ result.ovector, result.ovecsize);
+ if (status >= 0)
+ {
+ result.nmatches = status;
+ }
+ else
+ {
+ std::string message;
+
+ switch (status)
+ {
+ case PCRE_ERROR_NOMATCH:
+ break;
+
+ case PCRE_ERROR_BADOPTION:
+ message = "bad option passed to PCRE::match()";
+ throw Exception(message);
+ break;
+
+ case PCRE_ERROR_NOMEMORY:
+ message = "insufficient memory";
+ throw Exception(message);
+ break;
+
+ case PCRE_ERROR_NULL:
+ case PCRE_ERROR_BADMAGIC:
+ case PCRE_ERROR_UNKNOWN_NODE:
+ default:
+ message = "pcre_exec returned " + QUtil::int_to_string(status);
+ throw QEXC::Internal(message);
+ }
+ }
+
+ return result;
+}
+
+void
+PCRE::test(int n)
+{
+ try
+ {
+ if (n == 1)
+ {
+ static char const* utf8 = "abπdefq";
+ PCRE u1("^([[:alpha:]]+)");
+ PCRE u2("^([\\p{L}]+)", PCRE_UTF8);
+ PCRE::Match m1 = u1.match(utf8);
+ if (m1)
+ {
+ std::cout << "no utf8: " << m1.getMatch(1) << std::endl;
+ }
+ PCRE::Match m2 = u2.match(utf8);
+ if (m2)
+ {
+ std::cout << "utf8: " << m2.getMatch(1) << std::endl;
+ }
+ return;
+ }
+
+ try
+ {
+ PCRE pcre1("a**");
+ }
+ catch (Exception& e)
+ {
+ std::cout << e.unparse() << std::endl;
+ }
+
+ PCRE pcre2("^([^\\s:]*)\\s*:\\s*(.*?)\\s*$");
+ PCRE::Match m2 = pcre2.match("key: value one two three ");
+ if (m2)
+ {
+ std::cout << m2.nMatches() << std::endl;
+ std::cout << m2.getMatch(0) << std::endl;
+ std::cout << m2.getOffset(0) << std::endl;
+ std::cout << m2.getLength(0) << std::endl;
+ std::cout << m2.getMatch(1) << std::endl;
+ std::cout << m2.getOffset(1) << std::endl;
+ std::cout << m2.getLength(1) << std::endl;
+ std::cout << m2.getMatch(2) << std::endl;
+ std::cout << m2.getOffset(2) << std::endl;
+ std::cout << m2.getLength(2) << std::endl;
+ try
+ {
+ std::cout << m2.getMatch(3) << std::endl;
+ }
+ catch (Exception& e)
+ {
+ std::cout << e.unparse() << std::endl;
+ }
+ try
+ {
+ std::cout << m2.getOffset(3) << std::endl;
+ }
+ catch (Exception& e)
+ {
+ std::cout << e.unparse() << std::endl;
+ }
+ }
+ PCRE pcre3("^(a+)(b+)?$");
+ PCRE::Match m3 = pcre3.match("aaa");
+ try
+ {
+ if (m3)
+ {
+ std::cout << m3.nMatches() << std::endl;
+ std::cout << m3.getMatch(0) << std::endl;
+ std::cout << m3.getMatch(1) << std::endl;
+ std::cout << "-"
+ << m3.getMatch(
+ 2, Match::gm_no_substring_returns_empty)
+ << "-" << std::endl;
+ std::cout << "hello" << std::endl;
+ std::cout << m3.getMatch(2) << std::endl;
+ std::cout << "can't see this" << std::endl;
+ }
+ }
+ catch (Exception& e)
+ {
+ std::cout << e.unparse() << std::endl;
+ }
+
+ // backref: 1 2 3 4 5
+ PCRE pcre4("^((?:(a(b)?)(?:,(c))?)|(c))?$");
+ static char const* candidates[] = {
+ "qqqcqqq", // no match
+ "ab,c", // backrefs: 0, 1, 2, 3, 4
+ "ab", // backrefs: 0, 1, 2, 3
+ "a", // backrefs: 0, 1, 2
+ "a,c", // backrefs: 0, 1, 2, 4
+ "c", // backrefs: 0, 1, 5
+ "", // backrefs: 0
+ 0
+ };
+ for (char const** p = candidates; *p; ++p)
+ {
+ PCRE::Match m(pcre4.match(*p));
+ if (m)
+ {
+ int nmatches = m.nMatches();
+ for (int i = 0; i < nmatches; ++i)
+ {
+ std::cout << *p << ": " << i << ": ";
+ try
+ {
+ std::string match = m.getMatch(i);
+ std::cout << match;
+ }
+ catch (NoBackref&)
+ {
+ std::cout << "no backref (getMatch)";
+ }
+ std::cout << std::endl;
+
+ std::cout << *p << ": " << i << ": ";
+ try
+ {
+ int offset;
+ int length;
+ m.getOffsetLength(i, offset, length);
+ std::cout << offset << ", " << length;
+ }
+ catch (NoBackref&)
+ {
+ std::cout << "no backref (getOffsetLength)";
+ }
+ std:: cout << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << *p << ": no match" << std::endl;
+ }
+ }
+ }
+ catch (QEXC::General& e)
+ {
+ std::cout << "unexpected exception: " << e.unparse() << std::endl;
+ }
+}
diff --git a/libqpdf/Pipeline.cc b/libqpdf/Pipeline.cc
new file mode 100644
index 00000000..17c0c8b2
--- /dev/null
+++ b/libqpdf/Pipeline.cc
@@ -0,0 +1,25 @@
+
+
+#include <qpdf/Pipeline.hh>
+
+Pipeline::Pipeline(char const* identifier, Pipeline* next) :
+ identifier(identifier),
+ next(next)
+{
+}
+
+Pipeline::~Pipeline()
+{
+}
+
+Pipeline*
+Pipeline::getNext(bool allow_null)
+{
+ if ((next == 0) && (! allow_null))
+ {
+ throw Exception(
+ this->identifier +
+ ": Pipeline::getNext() called on pipeline with no next");
+ }
+ return this->next;
+}
diff --git a/libqpdf/Pl_ASCII85Decoder.cc b/libqpdf/Pl_ASCII85Decoder.cc
new file mode 100644
index 00000000..4ecdaf41
--- /dev/null
+++ b/libqpdf/Pl_ASCII85Decoder.cc
@@ -0,0 +1,131 @@
+#include <qpdf/Pl_ASCII85Decoder.hh>
+#include <qpdf/QEXC.hh>
+#include <qpdf/QTC.hh>
+#include <string.h>
+
+Pl_ASCII85Decoder::Pl_ASCII85Decoder(char const* identifier, Pipeline* next) :
+ Pipeline(identifier, next),
+ pos(0),
+ eod(0)
+{
+ memset(this->inbuf, 117, 5);
+}
+
+Pl_ASCII85Decoder::~Pl_ASCII85Decoder()
+{
+}
+
+void
+Pl_ASCII85Decoder::write(unsigned char* buf, int len)
+{
+ if (eod > 1)
+ {
+ return;
+ }
+ for (int i = 0; i < len; ++i)
+ {
+ if (eod > 1)
+ {
+ break;
+ }
+ else if (eod == 1)
+ {
+ if (buf[i] == '>')
+ {
+ flush();
+ eod = 2;
+ }
+ else
+ {
+ throw QEXC::General(
+ "broken end-of-data sequence in base 85 data");
+ }
+ }
+ else
+ {
+ switch (buf[i])
+ {
+ case ' ':
+ case '\f':
+ case '\v':
+ case '\t':
+ case '\r':
+ case '\n':
+ QTC::TC("libtests", "Pl_ASCII85Decoder ignore space");
+ // ignore whitespace
+ break;
+
+ case '~':
+ eod = 1;
+ break;
+
+ case 'z':
+ if (pos != 0)
+ {
+ throw QEXC::General(
+ "unexpected z during base 85 decode");
+ }
+ else
+ {
+ QTC::TC("libtests", "Pl_ASCII85Decoder read z");
+ getNext()->write((unsigned char*)"\000\000\000\000", 4);
+ }
+ break;
+
+ default:
+ if ((buf[i] < 33) || (buf[i] > 117))
+ {
+ throw QEXC::General
+ ("character out of range during base 85 decode");
+ }
+ else
+ {
+ this->inbuf[this->pos++] = buf[i];
+ if (pos == 5)
+ {
+ flush();
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+void
+Pl_ASCII85Decoder::flush()
+{
+ if (this->pos == 0)
+ {
+ QTC::TC("libtests", "Pl_ASCII85Decoder no-op flush");
+ return;
+ }
+ unsigned long lval = 0;
+ for (int i = 0; i < 5; ++i)
+ {
+ lval *= 85;
+ lval += (this->inbuf[i] - 33);
+ }
+
+ unsigned char outbuf[4];
+ memset(outbuf, 0, 4);
+ for (int i = 3; i >= 0; --i)
+ {
+ outbuf[i] = lval & 0xff;
+ lval >>= 8;
+ }
+
+ QTC::TC("libtests", "Pl_ASCII85Decoder partial flush",
+ (this->pos == 5) ? 0 : 1);
+ getNext()->write(outbuf, this->pos - 1);
+
+ this->pos = 0;
+ memset(this->inbuf, 117, 5);
+}
+
+void
+Pl_ASCII85Decoder::finish()
+{
+ flush();
+ getNext()->finish();
+}
diff --git a/libqpdf/Pl_ASCIIHexDecoder.cc b/libqpdf/Pl_ASCIIHexDecoder.cc
new file mode 100644
index 00000000..d1b4ef1c
--- /dev/null
+++ b/libqpdf/Pl_ASCIIHexDecoder.cc
@@ -0,0 +1,108 @@
+#include <qpdf/Pl_ASCIIHexDecoder.hh>
+#include <qpdf/QEXC.hh>
+#include <qpdf/QTC.hh>
+#include <string.h>
+#include <ctype.h>
+
+Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
+ Pipeline(identifier, next),
+ pos(0),
+ eod(false)
+{
+ strcpy(this->inbuf, "00");
+}
+
+Pl_ASCIIHexDecoder::~Pl_ASCIIHexDecoder()
+{
+}
+
+void
+Pl_ASCIIHexDecoder::write(unsigned char* buf, int len)
+{
+ if (this->eod)
+ {
+ return;
+ }
+ for (int i = 0; i < len; ++i)
+ {
+ char ch = toupper(buf[i]);
+ switch (ch)
+ {
+ case ' ':
+ case '\f':
+ case '\v':
+ case '\t':
+ case '\r':
+ case '\n':
+ QTC::TC("libtests", "Pl_ASCIIHexDecoder ignore space");
+ // ignore whitespace
+ break;
+
+ case '>':
+ this->eod = true;
+ flush();
+ break;
+
+ default:
+ if (((ch >= '0') && (ch <= '9')) ||
+ ((ch >= 'A') && (ch <= 'F')))
+ {
+ this->inbuf[this->pos++] = ch;
+ if (this->pos == 2)
+ {
+ flush();
+ }
+ }
+ else
+ {
+ char t[2];
+ t[0] = ch;
+ t[1] = 0;
+ throw QEXC::General(
+ std::string("character out of range during base Hex decode: ") + t);
+ }
+ break;
+ }
+ if (this->eod)
+ {
+ break;
+ }
+ }
+}
+
+void
+Pl_ASCIIHexDecoder::flush()
+{
+ if (this->pos == 0)
+ {
+ QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
+ return;
+ }
+ int b[2];
+ for (int i = 0; i < 2; ++i)
+ {
+ if (this->inbuf[i] >= 'A')
+ {
+ b[i] = this->inbuf[i] - 'A' + 10;
+ }
+ else
+ {
+ b[i] = this->inbuf[i] - '0';
+ }
+ }
+ unsigned char ch = (unsigned char)((b[0] << 4) + b[1]);
+
+ QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush",
+ (this->pos == 2) ? 0 : 1);
+ getNext()->write(&ch, 1);
+
+ this->pos = 0;
+ strcpy(this->inbuf, "00");
+}
+
+void
+Pl_ASCIIHexDecoder::finish()
+{
+ flush();
+ getNext()->finish();
+}
diff --git a/libqpdf/Pl_Buffer.cc b/libqpdf/Pl_Buffer.cc
new file mode 100644
index 00000000..185cf636
--- /dev/null
+++ b/libqpdf/Pl_Buffer.cc
@@ -0,0 +1,67 @@
+
+#include <qpdf/Pl_Buffer.hh>
+#include <qpdf/QEXC.hh>
+#include <assert.h>
+
+Pl_Buffer::Pl_Buffer(char const* identifier, Pipeline* next) :
+ Pipeline(identifier, next),
+ ready(false),
+ total_size(0)
+{
+}
+
+Pl_Buffer::~Pl_Buffer()
+{
+}
+
+void
+Pl_Buffer::write(unsigned char* buf, int len)
+{
+ Buffer* b = new Buffer(len);
+ memcpy(b->getBuffer(), buf, len);
+ this->data.push_back(b);
+ this->ready = false;
+ this->total_size += len;
+
+ if (getNext(true))
+ {
+ getNext()->write(buf, len);
+ }
+}
+
+void
+Pl_Buffer::finish()
+{
+ this->ready = true;
+ if (getNext(true))
+ {
+ getNext()->finish();
+ }
+}
+
+Buffer*
+Pl_Buffer::getBuffer()
+{
+ if (! this->ready)
+ {
+ throw QEXC::Internal("Pl_Buffer::getBuffer() called when not ready");
+ }
+
+ Buffer* b = new Buffer(this->total_size);
+ unsigned char* p = b->getBuffer();
+ while (! this->data.empty())
+ {
+ PointerHolder<Buffer> bph = this->data.front();
+ this->data.pop_front();
+ Buffer* bp = bph.getPointer();
+ size_t bytes = bp->getSize();
+ memcpy(p, bp->getBuffer(), bytes);
+ p += bytes;
+ this->total_size -= bytes;
+ }
+
+ assert(this->total_size == 0);
+ this->ready = false;
+
+ return b;
+}
diff --git a/libqpdf/Pl_Count.cc b/libqpdf/Pl_Count.cc
new file mode 100644
index 00000000..8a361ad5
--- /dev/null
+++ b/libqpdf/Pl_Count.cc
@@ -0,0 +1,42 @@
+
+#include <qpdf/Pl_Count.hh>
+
+Pl_Count::Pl_Count(char const* identifier, Pipeline* next) :
+ Pipeline(identifier, next),
+ count(0),
+ last_char('\0')
+{
+}
+
+Pl_Count::~Pl_Count()
+{
+}
+
+void
+Pl_Count::write(unsigned char* buf, int len)
+{
+ if (len)
+ {
+ this->count += len;
+ getNext()->write(buf, len);
+ this->last_char = buf[len - 1];
+ }
+}
+
+void
+Pl_Count::finish()
+{
+ getNext()->finish();
+}
+
+int
+Pl_Count::getCount() const
+{
+ return this->count;
+}
+
+unsigned char
+Pl_Count::getLastChar() const
+{
+ return this->last_char;
+}
diff --git a/libqpdf/Pl_Discard.cc b/libqpdf/Pl_Discard.cc
new file mode 100644
index 00000000..1632ea23
--- /dev/null
+++ b/libqpdf/Pl_Discard.cc
@@ -0,0 +1,23 @@
+
+#include <qpdf/Pl_Discard.hh>
+
+// Exercised in md5 test suite
+
+Pl_Discard::Pl_Discard() :
+ Pipeline("discard", 0)
+{
+}
+
+Pl_Discard::~Pl_Discard()
+{
+}
+
+void
+Pl_Discard::write(unsigned char* buf, int len)
+{
+}
+
+void
+Pl_Discard::finish()
+{
+}
diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc
new file mode 100644
index 00000000..ba60c472
--- /dev/null
+++ b/libqpdf/Pl_Flate.cc
@@ -0,0 +1,198 @@
+
+#include <qpdf/Pl_Flate.hh>
+
+#include <qpdf/QUtil.hh>
+
+Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next,
+ action_e action, int out_bufsize) :
+ Pipeline(identifier, next),
+ out_bufsize(out_bufsize),
+ action(action),
+ initialized(false)
+{
+ this->outbuf = new unsigned char[out_bufsize];
+
+ zstream.zalloc = (alloc_func)0;
+ zstream.zfree = (free_func)0;
+ zstream.opaque = (voidpf)0;
+ zstream.next_in = 0;
+ zstream.avail_in = 0;
+ zstream.next_out = this->outbuf;
+ zstream.avail_out = out_bufsize;
+}
+
+Pl_Flate::~Pl_Flate()
+{
+ if (this->outbuf)
+ {
+ delete [] this->outbuf;
+ this->outbuf = 0;
+ }
+}
+
+void
+Pl_Flate::write(unsigned char* data, int len)
+{
+ if (this->outbuf == 0)
+ {
+ throw Exception(
+ this->identifier +
+ ": Pl_Flate: write() called after finish() called");
+ }
+ handleData(data, len, Z_NO_FLUSH);
+}
+
+void
+Pl_Flate::handleData(unsigned char* data, int len, int flush)
+{
+ this->zstream.next_in = data;
+ this->zstream.avail_in = len;
+
+ if (! this->initialized)
+ {
+ int err = Z_OK;
+ if (this->action == a_deflate)
+ {
+ err = deflateInit(&this->zstream, Z_DEFAULT_COMPRESSION);
+ }
+ else
+ {
+ err = inflateInit(&this->zstream);
+ }
+ checkError("Init", err);
+ this->initialized = true;
+ }
+
+ int err = Z_OK;
+
+ bool done = false;
+ while (! done)
+ {
+ if (action == a_deflate)
+ {
+ err = deflate(&this->zstream, flush);
+ }
+ else
+ {
+ err = inflate(&this->zstream, flush);
+ }
+ switch (err)
+ {
+ case Z_BUF_ERROR:
+ // Probably shouldn't be able to happen, but possible as a
+ // boundary condition: if the last call to inflate exactly
+ // filled the output buffer, it's possible that the next
+ // call to inflate could have nothing to do.
+ done = true;
+ break;
+
+ case Z_STREAM_END:
+ done = true;
+ // fall through
+
+ case Z_OK:
+ {
+ if ((this->zstream.avail_in == 0) &&
+ (this->zstream.avail_out > 0))
+ {
+ // There is nothing left to read, and there was
+ // sufficient buffer space to write everything we
+ // needed, so we're done for now.
+ done = true;
+ }
+ uLong ready = (this->out_bufsize - this->zstream.avail_out);
+ if (ready > 0)
+ {
+ this->getNext()->write(this->outbuf, ready);
+ this->zstream.next_out = this->outbuf;
+ this->zstream.avail_out = this->out_bufsize;
+ }
+ }
+ break;
+
+ default:
+ this->checkError("data", err);
+ break;
+ }
+ }
+}
+
+void
+Pl_Flate::finish()
+{
+ if (this->outbuf)
+ {
+ if (this->initialized)
+ {
+ unsigned char buf[1];
+ buf[0] = '\0';
+ handleData(buf, 0, Z_FINISH);
+ int err = Z_OK;
+ if (action == a_deflate)
+ {
+ err = deflateEnd(&this->zstream);
+ }
+ else
+ {
+ err = inflateEnd(&this->zstream);
+ }
+ checkError("End", err);
+ }
+
+ delete [] this->outbuf;
+ this->outbuf = 0;
+ }
+ this->getNext()->finish();
+}
+
+void
+Pl_Flate::checkError(char const* prefix, int error_code)
+{
+ if (error_code != Z_OK)
+ {
+ char const* action_str = (action == a_deflate ? "deflate" : "inflate");
+ std::string msg =
+ this->identifier + ": " + action_str + ": " + prefix + ": ";
+
+ if (this->zstream.msg)
+ {
+ msg += this->zstream.msg;
+ }
+ else
+ {
+ switch (error_code)
+ {
+ case Z_ERRNO:
+ msg += "zlib system error";
+ break;
+
+ case Z_STREAM_ERROR:
+ msg += "zlib stream error";
+ break;
+
+ case Z_DATA_ERROR:
+ msg += "zlib data error";
+ break;
+
+ case Z_MEM_ERROR:
+ msg += "zlib memory error";
+ break;
+
+ case Z_BUF_ERROR:
+ msg += "zlib buffer error";
+ break;
+
+ case Z_VERSION_ERROR:
+ msg += "zlib version error";
+ break;
+
+ default:
+ msg += std::string("zlib unknown error (") +
+ QUtil::int_to_string(error_code) + ")";
+ break;
+ }
+ }
+
+ throw Exception(msg);
+ }
+}
diff --git a/libqpdf/Pl_LZWDecoder.cc b/libqpdf/Pl_LZWDecoder.cc
new file mode 100644
index 00000000..e85531e9
--- /dev/null
+++ b/libqpdf/Pl_LZWDecoder.cc
@@ -0,0 +1,229 @@
+#include <qpdf/Pl_LZWDecoder.hh>
+
+#include <qpdf/QEXC.hh>
+#include <qpdf/QTC.hh>
+#include <string.h>
+#include <assert.h>
+
+Pl_LZWDecoder::Pl_LZWDecoder(char const* identifier, Pipeline* next,
+ bool early_code_change) :
+ Pipeline(identifier, next),
+ code_size(9),
+ next(0),
+ byte_pos(0),
+ bit_pos(0),
+ bits_available(0),
+ code_change_delta(early_code_change ? 1 : 0),
+ eod(false),
+ last_code(256)
+{
+ memset(buf, 0, 3);
+}
+
+
+Pl_LZWDecoder::~Pl_LZWDecoder()
+{
+}
+
+void
+Pl_LZWDecoder::write(unsigned char* bytes, int len)
+{
+ for (int i = 0; i < len; ++i)
+ {
+ this->buf[next++] = bytes[i];
+ if (this->next == 3)
+ {
+ this->next = 0;
+ }
+ this->bits_available += 8;
+ if (this->bits_available >= this->code_size)
+ {
+ sendNextCode();
+ }
+ }
+}
+
+void
+Pl_LZWDecoder::finish()
+{
+ getNext()->finish();
+}
+
+void
+Pl_LZWDecoder::sendNextCode()
+{
+ int high = this->byte_pos;
+ int med = (this->byte_pos + 1) % 3;
+ int low = (this->byte_pos + 2) % 3;
+
+ int bits_from_high = 8 - this->bit_pos;
+ int bits_from_med = this->code_size - bits_from_high;
+ int bits_from_low = 0;
+ if (bits_from_med > 8)
+ {
+ bits_from_low = bits_from_med - 8;
+ bits_from_med = 8;
+ }
+ int high_mask = (1 << bits_from_high) - 1;
+ int med_mask = 0xff - ((1 << (8 - bits_from_med)) - 1);
+ int low_mask = 0xff - ((1 << (8 - bits_from_low)) - 1);
+ int code = 0;
+ code += (this->buf[high] & high_mask) << bits_from_med;
+ code += ((this->buf[med] & med_mask) >> (8 - bits_from_med));
+ if (bits_from_low)
+ {
+ code <<= bits_from_low;
+ code += ((this->buf[low] & low_mask) >> (8 - bits_from_low));
+ this->byte_pos = low;
+ this->bit_pos = bits_from_low;
+ }
+ else
+ {
+ this->byte_pos = med;
+ this->bit_pos = bits_from_med;
+ }
+ if (this->bit_pos == 8)
+ {
+ this->bit_pos = 0;
+ ++this->byte_pos;
+ this->byte_pos %= 3;
+ }
+ this->bits_available -= this->code_size;
+
+ handleCode(code);
+}
+
+unsigned char
+Pl_LZWDecoder::getFirstChar(int code)
+{
+ unsigned char result = '\0';
+ if (code < 256)
+ {
+ result = (unsigned char) code;
+ }
+ else
+ {
+ assert(code > 257);
+ unsigned int idx = code - 258;
+ assert(idx < table.size());
+ Buffer& b = table[idx];
+ result = b.getBuffer()[0];
+ }
+ return result;
+}
+
+void
+Pl_LZWDecoder::addToTable(unsigned char next)
+{
+ unsigned int last_size = 0;
+ unsigned char const* last_data = 0;
+ unsigned char tmp[1];
+
+ if (this->last_code < 256)
+ {
+ tmp[0] = this->last_code;
+ last_data = tmp;
+ last_size = 1;
+ }
+ else
+ {
+ assert(this->last_code > 257);
+ unsigned int idx = this->last_code - 258;
+ assert(idx < table.size());
+ Buffer& b = table[idx];
+ last_data = b.getBuffer();
+ last_size = b.getSize();
+ }
+
+ Buffer entry(1 + last_size);
+ unsigned char* new_data = entry.getBuffer();
+ memcpy(new_data, last_data, last_size);
+ new_data[last_size] = next;
+ this->table.push_back(entry);
+}
+
+void
+Pl_LZWDecoder::handleCode(int code)
+{
+ if (this->eod)
+ {
+ return;
+ }
+
+ if (code == 256)
+ {
+ if (! this->table.empty())
+ {
+ QTC::TC("libtests", "Pl_LZWDecoder intermediate reset");
+ }
+ this->table.clear();
+ this->code_size = 9;
+ }
+ else if (code == 257)
+ {
+ this->eod = true;
+ }
+ else
+ {
+ if (this->last_code != 256)
+ {
+ // Add to the table from last time. New table entry would
+ // be what we read last plus the first character of what
+ // we're reading now.
+ unsigned char next = '\0';
+ unsigned int table_size = table.size();
+ if (code < 256)
+ {
+ // just read < 256; last time's next was code
+ next = code;
+ }
+ else if (code > 257)
+ {
+ unsigned int idx = code - 258;
+ if (idx > table_size)
+ {
+ throw QEXC::General("LZWDecoder: bad code received");
+ }
+ else if (idx == table_size)
+ {
+ // The encoder would have just created this entry,
+ // so the first character of this entry would have
+ // been the same as the first character of the
+ // last entry.
+ QTC::TC("libtests", "Pl_LZWDecoder last was table size");
+ next = getFirstChar(this->last_code);
+ }
+ else
+ {
+ next = getFirstChar(code);
+ }
+ }
+ unsigned int last_idx = 258 + table_size;
+ if (last_idx == 4095)
+ {
+ throw QEXC::General("LZWDecoder: table full");
+ }
+ addToTable(next);
+ unsigned int change_idx = last_idx + code_change_delta;
+ if ((change_idx == 511) ||
+ (change_idx == 1023) ||
+ (change_idx == 2047))
+ {
+ ++this->code_size;
+ }
+ }
+
+ if (code < 256)
+ {
+ unsigned char ch = (unsigned char) code;
+ getNext()->write(&ch, 1);
+ }
+ else
+ {
+ Buffer& b = table[code - 258];
+ getNext()->write(b.getBuffer(), b.getSize());
+ }
+ }
+
+ this->last_code = code;
+}
diff --git a/libqpdf/Pl_MD5.cc b/libqpdf/Pl_MD5.cc
new file mode 100644
index 00000000..0a2711b8
--- /dev/null
+++ b/libqpdf/Pl_MD5.cc
@@ -0,0 +1,43 @@
+
+#include <qpdf/Pl_MD5.hh>
+
+#include <qpdf/QEXC.hh>
+
+Pl_MD5::Pl_MD5(char const* identifier, Pipeline* next) :
+ Pipeline(identifier, next),
+ in_progress(false)
+{
+}
+
+Pl_MD5::~Pl_MD5()
+{
+}
+
+void
+Pl_MD5::write(unsigned char* buf, int len)
+{
+ if (! this->in_progress)
+ {
+ this->md5.reset();
+ this->in_progress = true;
+ }
+ this->md5.encodeDataIncrementally((char*) buf, len);
+ this->getNext()->write(buf, len);
+}
+
+void
+Pl_MD5::finish()
+{
+ this->getNext()->finish();
+ this->in_progress = false;
+}
+
+std::string
+Pl_MD5::getHexDigest()
+{
+ if (this->in_progress)
+ {
+ throw QEXC::General("digest requested for in-progress MD5 Pipeline");
+ }
+ return this->md5.unparse();
+}
diff --git a/libqpdf/Pl_PNGFilter.cc b/libqpdf/Pl_PNGFilter.cc
new file mode 100644
index 00000000..28b87c5e
--- /dev/null
+++ b/libqpdf/Pl_PNGFilter.cc
@@ -0,0 +1,146 @@
+
+#include <qpdf/Pl_PNGFilter.hh>
+#include <string.h>
+
+Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
+ action_e action, unsigned int columns,
+ unsigned int bytes_per_pixel) :
+ Pipeline(identifier, next),
+ action(action),
+ columns(columns),
+ cur_row(0),
+ prev_row(0),
+ buf1(0),
+ buf2(0),
+ pos(0)
+{
+ this->buf1 = new unsigned char[columns + 1];
+ this->buf2 = new unsigned char[columns + 1];
+ this->cur_row = buf1;
+
+ // number of bytes per incoming row
+ this->incoming = (action == a_encode ? columns : columns + 1);
+}
+
+Pl_PNGFilter::~Pl_PNGFilter()
+{
+ delete [] buf1;
+ delete [] buf2;
+}
+
+void
+Pl_PNGFilter::write(unsigned char* data, int len)
+{
+ int left = this->incoming - this->pos;
+ unsigned int offset = 0;
+ while (len >= left)
+ {
+ // finish off current row
+ memcpy(this->cur_row + this->pos, data + offset, left);
+ offset += left;
+ len -= left;
+
+ processRow();
+
+ // Swap rows
+ unsigned char* t = this->prev_row;
+ this->prev_row = this->cur_row;
+ this->cur_row = t ? t : this->buf2;
+ memset(this->cur_row, 0, this->columns + 1);
+ left = this->incoming;
+ this->pos = 0;
+ }
+ if (len)
+ {
+ memcpy(this->cur_row + this->pos, data + offset, len);
+ }
+ this->pos += len;
+}
+
+void
+Pl_PNGFilter::processRow()
+{
+ if (this->action == a_encode)
+ {
+ encodeRow();
+ }
+ else
+ {
+ decodeRow();
+ }
+}
+
+void
+Pl_PNGFilter::decodeRow()
+{
+ int filter = (int) this->cur_row[0];
+ if (this->prev_row)
+ {
+ switch (filter)
+ {
+ case 0: // none
+ break;
+
+ case 1: // sub
+ throw Exception("sub filter not implemented");
+ break;
+
+ case 2: // up
+ for (unsigned int i = 1; i <= this->columns; ++i)
+ {
+ this->cur_row[i] += this->prev_row[i];
+ }
+ break;
+
+ case 3: // average
+ throw Exception("average filter not implemented");
+ break;
+
+ case 4: // Paeth
+ throw Exception("Paeth filter not implemented");
+ break;
+
+ default:
+ // ignore
+ break;
+ }
+ }
+
+ getNext()->write(this->cur_row + 1, this->columns);
+}
+
+void
+Pl_PNGFilter::encodeRow()
+{
+ // For now, hard-code to using UP filter.
+ unsigned char ch = 2;
+ getNext()->write(&ch, 1);
+ if (this->prev_row)
+ {
+ for (unsigned int i = 0; i < this->columns; ++i)
+ {
+ ch = this->cur_row[i] - this->prev_row[i];
+ getNext()->write(&ch, 1);
+ }
+ }
+ else
+ {
+ getNext()->write(this->cur_row, this->columns);
+ }
+}
+
+void
+Pl_PNGFilter::finish()
+{
+ if (this->pos)
+ {
+ // write partial row
+ processRow();
+ }
+ this->prev_row = 0;
+ this->cur_row = buf1;
+ this->pos = 0;
+ memset(this->cur_row, 0, this->columns + 1);
+
+ getNext()->finish();
+}
diff --git a/libqpdf/Pl_QPDFTokenizer.cc b/libqpdf/Pl_QPDFTokenizer.cc
new file mode 100644
index 00000000..63f0caaf
--- /dev/null
+++ b/libqpdf/Pl_QPDFTokenizer.cc
@@ -0,0 +1,179 @@
+
+#include <qpdf/Pl_QPDFTokenizer.hh>
+#include <qpdf/QPDF_String.hh>
+#include <qpdf/QPDF_Name.hh>
+
+Pl_QPDFTokenizer::Pl_QPDFTokenizer(char const* identifier, Pipeline* next) :
+ Pipeline(identifier, next),
+ newline_after_next_token(false),
+ just_wrote_nl(false),
+ last_char_was_cr(false),
+ unread_char(false),
+ char_to_unread('\0'),
+ pass_through(false)
+{
+}
+
+Pl_QPDFTokenizer::~Pl_QPDFTokenizer()
+{
+}
+
+void
+Pl_QPDFTokenizer::writeNext(char const* buf, int len)
+{
+ if (len)
+ {
+ unsigned char* t = new unsigned char[len];
+ memcpy(t, buf, len);
+ getNext()->write(t, len);
+ delete [] t;
+ this->just_wrote_nl = (buf[len-1] == '\n');
+ }
+}
+
+void
+Pl_QPDFTokenizer::writeToken(QPDFTokenizer::Token& token)
+{
+ std::string value = token.getRawValue();
+
+ switch (token.getType())
+ {
+ case QPDFTokenizer::tt_string:
+ value = QPDF_String(token.getValue()).unparse();
+ break;
+
+ case QPDFTokenizer::tt_name:
+ value = QPDF_Name(token.getValue()).unparse();
+ break;
+
+ default:
+ break;
+ }
+ writeNext(value.c_str(), value.length());
+}
+
+void
+Pl_QPDFTokenizer::processChar(char ch)
+{
+ if (this->pass_through)
+ {
+ // We're not noramlizing anymore -- just write this without
+ // looking at it.
+ writeNext(&ch, 1);
+ return;
+ }
+
+ tokenizer.presentCharacter(ch);
+ QPDFTokenizer::Token token;
+ if (tokenizer.getToken(token, this->unread_char, this->char_to_unread))
+ {
+ writeToken(token);
+ if (this->newline_after_next_token)
+ {
+ writeNext("\n", 1);
+ this->newline_after_next_token = false;
+ }
+ if ((token.getType() == QPDFTokenizer::tt_word) &&
+ (token.getValue() == "BI"))
+ {
+ // Uh oh.... we're not sophisticated enough to handle
+ // inline images safely. We'd have to to set up all the
+ // filters and pipe the iamge data through it until the
+ // filtered output was the right size for an image of the
+ // specified dimensions. Then we'd either have to write
+ // out raw image data or continue to write filtered data,
+ // resuming normalization when we get to the end.
+ // Insetad, for now, we'll just turn off noramlization for
+ // the remainder of this stream.
+ this->pass_through = true;
+ if (this->unread_char)
+ {
+ writeNext(&this->char_to_unread, 1);
+ this->unread_char = false;
+ }
+ }
+ }
+ else
+ {
+ bool suppress = false;
+ if ((ch == '\n') && (this->last_char_was_cr))
+ {
+ // Always ignore \n following \r
+ suppress = true;
+ }
+
+ if ((this->last_char_was_cr = (ch == '\r')))
+ {
+ ch = '\n';
+ }
+
+ if (this->tokenizer.betweenTokens())
+ {
+ if (! suppress)
+ {
+ writeNext(&ch, 1);
+ }
+ }
+ else
+ {
+ if (ch == '\n')
+ {
+ this->newline_after_next_token = true;
+ }
+ }
+ }
+}
+
+
+void
+Pl_QPDFTokenizer::checkUnread()
+{
+ if (this->unread_char)
+ {
+ processChar(this->char_to_unread);
+ if (this->unread_char)
+ {
+ throw QEXC::Internal("unread_char still true after processing "
+ "unread character");
+ }
+ }
+}
+
+void
+Pl_QPDFTokenizer::write(unsigned char* buf, int len)
+{
+ checkUnread();
+ for (int i = 0; i < len; ++i)
+ {
+ processChar(buf[i]);
+ checkUnread();
+ }
+}
+
+void
+Pl_QPDFTokenizer::finish()
+{
+ this->tokenizer.presentEOF();
+ if (! this->pass_through)
+ {
+ QPDFTokenizer::Token token;
+ if (tokenizer.getToken(token, this->unread_char, this->char_to_unread))
+ {
+ writeToken(token);
+ if (unread_char)
+ {
+ if (this->char_to_unread == '\r')
+ {
+ this->char_to_unread = '\n';
+ }
+ writeNext(&this->char_to_unread, 1);
+ }
+ }
+ }
+ if (! this->just_wrote_nl)
+ {
+ writeNext("\n", 1);
+ }
+
+ getNext()->finish();
+}
diff --git a/libqpdf/Pl_RC4.cc b/libqpdf/Pl_RC4.cc
new file mode 100644
index 00000000..74e53c8b
--- /dev/null
+++ b/libqpdf/Pl_RC4.cc
@@ -0,0 +1,57 @@
+
+#include <qpdf/Pl_RC4.hh>
+
+#include <qpdf/QUtil.hh>
+
+Pl_RC4::Pl_RC4(char const* identifier, Pipeline* next,
+ unsigned char const* key_data, int key_len,
+ int out_bufsize) :
+ Pipeline(identifier, next),
+ out_bufsize(out_bufsize),
+ rc4(key_data, key_len)
+{
+ this->outbuf = new unsigned char[out_bufsize];
+}
+
+Pl_RC4::~Pl_RC4()
+{
+ if (this->outbuf)
+ {
+ delete [] this->outbuf;
+ this->outbuf = 0;
+ }
+}
+
+void
+Pl_RC4::write(unsigned char* data, int len)
+{
+ if (this->outbuf == 0)
+ {
+ throw Exception(
+ this->identifier +
+ ": Pl_RC4: write() called after finish() called");
+ }
+
+ int bytes_left = len;
+ unsigned char* p = data;
+
+ while (bytes_left > 0)
+ {
+ int bytes = (bytes_left < this->out_bufsize ? bytes_left : out_bufsize);
+ bytes_left -= bytes;
+ rc4.process(p, bytes, outbuf);
+ p += bytes;
+ getNext()->write(outbuf, bytes);
+ }
+}
+
+void
+Pl_RC4::finish()
+{
+ if (this->outbuf)
+ {
+ delete [] this->outbuf;
+ this->outbuf = 0;
+ }
+ this->getNext()->finish();
+}
diff --git a/libqpdf/Pl_StdioFile.cc b/libqpdf/Pl_StdioFile.cc
new file mode 100644
index 00000000..c0f42afd
--- /dev/null
+++ b/libqpdf/Pl_StdioFile.cc
@@ -0,0 +1,48 @@
+
+#include <qpdf/Pl_StdioFile.hh>
+
+#include <errno.h>
+
+Pl_StdioFile::Pl_StdioFile(char const* identifier, FILE* f) :
+ Pipeline(identifier, 0),
+ file(f)
+{
+}
+
+Pl_StdioFile::~Pl_StdioFile()
+{
+}
+
+void
+Pl_StdioFile::write(unsigned char* buf, int len)
+{
+ size_t so_far = 0;
+ while (len > 0)
+ {
+ so_far = fwrite(buf, 1, len, this->file);
+ if (so_far == 0)
+ {
+ throw QEXC::System(this->identifier + ": Pl_StdioFile::write",
+ errno);
+ }
+ else
+ {
+ buf += so_far;
+ len -= so_far;
+ }
+ }
+}
+
+void
+Pl_StdioFile::finish()
+{
+ if (fileno(this->file) != -1)
+ {
+ fflush(this->file);
+ }
+ else
+ {
+ throw QEXC::Internal(this->identifier +
+ ": Pl_StdioFile::finish: stream already closed");
+ }
+}
diff --git a/libqpdf/QEXC.cc b/libqpdf/QEXC.cc
new file mode 100644
index 00000000..c65afbb6
--- /dev/null
+++ b/libqpdf/QEXC.cc
@@ -0,0 +1,67 @@
+
+#include <qpdf/QEXC.hh>
+#include <string.h>
+#include <errno.h>
+
+QEXC::Base::Base()
+{
+ // nothing needed
+}
+
+QEXC::Base::Base(std::string const& message) :
+ message(message)
+{
+ // nothing needed
+}
+
+std::string const&
+QEXC::Base::unparse() const
+{
+ return this->message;
+}
+
+void
+QEXC::Base::setMessage(std::string const& message)
+{
+ this->message = message;
+}
+
+const char*
+QEXC::Base::what() const throw()
+{
+ // Since unparse() returns a const string reference, its
+ // implementors must arrange to have it return a reference to a
+ // string that is not going to disappear. It is therefore safe
+ // for us to return it's c_str() pointer.
+ return this->unparse().c_str();
+}
+
+QEXC::General::General()
+{
+ // nothing needed
+}
+
+QEXC::General::General(std::string const& message) :
+ Base(message)
+{
+ // nothing needed
+}
+
+QEXC::System::System(std::string const& prefix, int sys_errno)
+{
+ // Note: using sys_errno in case errno is a macro.
+ this->sys_errno = sys_errno;
+ this->setMessage(prefix + ": " + strerror(sys_errno));
+}
+
+int
+QEXC::System::getErrno() const
+{
+ return this->sys_errno;
+}
+
+QEXC::Internal::Internal(std::string const& message) :
+ Base("INTERNAL ERROR: " + message)
+{
+ // nothing needed
+}
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc
new file mode 100644
index 00000000..6f51fa2c
--- /dev/null
+++ b/libqpdf/QPDF.cc
@@ -0,0 +1,1851 @@
+
+#include <qpdf/QPDF.hh>
+
+#include <vector>
+#include <map>
+#include <string.h>
+#include <memory.h>
+
+#include <qpdf/QTC.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/PCRE.hh>
+#include <qpdf/Pipeline.hh>
+
+#include <qpdf/QPDFExc.hh>
+#include <qpdf/QPDF_Null.hh>
+#include <qpdf/QPDF_Dictionary.hh>
+
+void
+QPDF::InputSource::setLastOffset(off_t offset)
+{
+ this->last_offset = offset;
+}
+
+off_t
+QPDF::InputSource::getLastOffset() const
+{
+ return this->last_offset;
+}
+
+std::string
+QPDF::InputSource::readLine()
+{
+ // Read a line terminated by one or more \r or \n characters
+ // without caring what the exact terminator is. Consume the
+ // trailing newline characters but don't return them.
+
+ off_t offset = this->tell();
+ std::string buf;
+ enum { st_before_nl, st_at_nl } state = st_before_nl;
+ char ch;
+ while (1)
+ {
+ size_t len = this->read(&ch, 1);
+ if (len == 0)
+ {
+ break;
+ }
+
+ if (state == st_before_nl)
+ {
+ if ((ch == '\012') || (ch == '\015'))
+ {
+ state = st_at_nl;
+ }
+ else
+ {
+ buf += ch;
+ }
+ }
+ else if (state == st_at_nl)
+ {
+ if ((ch == '\012') || (ch == '\015'))
+ {
+ // do nothing
+ }
+ else
+ {
+ // unread this character
+ this->unreadCh(ch);
+ break;
+ }
+ }
+ }
+ // Override last offset to be where we started this line rather
+ // than before the last character read
+ this->last_offset = offset;
+ return buf;
+}
+
+QPDF::FileInputSource::FileInputSource() :
+ file(0)
+{
+}
+
+void
+QPDF::FileInputSource::setFilename(char const* filename)
+{
+ destroy();
+ this->filename = filename;
+ this->file = QUtil::fopen_wrapper(std::string("open ") + this->filename,
+ fopen(this->filename.c_str(), "rb"));
+}
+
+QPDF::FileInputSource::~FileInputSource()
+{
+ destroy();
+}
+
+void
+QPDF::FileInputSource::destroy()
+{
+ if (this->file)
+ {
+ fclose(this->file);
+ this->file = 0;
+ }
+}
+
+std::string const&
+QPDF::FileInputSource::getName() const
+{
+ return this->filename;
+}
+
+off_t
+QPDF::FileInputSource::tell()
+{
+ return ftell(this->file);
+}
+
+void
+QPDF::FileInputSource::seek(off_t offset, int whence)
+{
+ QUtil::os_wrapper(std::string("seek to ") + this->filename + ", offset " +
+ QUtil::int_to_string(offset) + " (" +
+ QUtil::int_to_string(whence) + ")",
+ fseek(this->file, offset, whence));
+}
+
+void
+QPDF::FileInputSource::rewind()
+{
+ ::rewind(this->file);
+}
+
+size_t
+QPDF::FileInputSource::read(char* buffer, int length)
+{
+ this->last_offset = ftell(this->file);
+ size_t len = fread(buffer, 1, length, this->file);
+ if ((len == 0) && ferror(this->file))
+ {
+ throw QPDFExc(this->filename, this->last_offset,
+ std::string("read ") +
+ QUtil::int_to_string(length) + " bytes");
+ }
+ return len;
+}
+
+void
+QPDF::FileInputSource::unreadCh(char ch)
+{
+ QUtil::os_wrapper(this->filename + ": unread character",
+ ungetc((unsigned char)ch, this->file));
+}
+
+QPDF::BufferInputSource::BufferInputSource(std::string const& description,
+ Buffer* buf) :
+ description(description),
+ buf(buf),
+ cur_offset(0)
+{
+}
+
+QPDF::BufferInputSource::~BufferInputSource()
+{
+}
+
+std::string const&
+QPDF::BufferInputSource::getName() const
+{
+ return this->description;
+}
+
+off_t
+QPDF::BufferInputSource::tell()
+{
+ return this->cur_offset;
+}
+
+void
+QPDF::BufferInputSource::seek(off_t offset, int whence)
+{
+ switch (whence)
+ {
+ case SEEK_SET:
+ this->cur_offset = offset;
+ break;
+
+ case SEEK_END:
+ this->cur_offset = this->buf->getSize() - offset;
+ break;
+
+ case SEEK_CUR:
+ this->cur_offset += offset;
+ break;
+
+ default:
+ throw QEXC::Internal("invalid argument to BufferInputSource::seek");
+ break;
+ }
+}
+
+void
+QPDF::BufferInputSource::rewind()
+{
+ this->cur_offset = 0;
+}
+
+size_t
+QPDF::BufferInputSource::read(char* buffer, int length)
+{
+ off_t end_pos = this->buf->getSize();
+ if (this->cur_offset >= end_pos)
+ {
+ this->last_offset = end_pos;
+ return 0;
+ }
+
+ this->last_offset = this->cur_offset;
+ size_t len = std::min((int)(end_pos - this->cur_offset), length);
+ memcpy(buffer, buf->getBuffer() + this->cur_offset, len);
+ this->cur_offset += len;
+ return len;
+}
+
+void
+QPDF::BufferInputSource::unreadCh(char ch)
+{
+ if (this->cur_offset > 0)
+ {
+ --this->cur_offset;
+ }
+}
+
+QPDF::ObjGen::ObjGen(int o = 0, int g = 0) :
+ obj(o),
+ gen(g)
+{
+}
+
+bool
+QPDF::ObjGen::ObjGen::operator<(ObjGen const& rhs) const
+{
+ return ((this->obj < rhs.obj) ||
+ ((this->obj == rhs.obj) && (this->gen < rhs.gen)));
+}
+
+QPDF::QPDF() :
+ encrypted(false),
+ encryption_initialized(false),
+ ignore_xref_streams(false),
+ suppress_warnings(false),
+ attempt_recovery(true),
+ cached_key_objid(0),
+ cached_key_generation(0),
+ first_xref_item_offset(0),
+ uncompressed_after_compressed(false)
+{
+}
+
+QPDF::~QPDF()
+{
+}
+
+void
+QPDF::processFile(char const* filename, char const* password)
+{
+ this->file.setFilename(filename);
+ this->provided_password = password;
+ parse();
+}
+
+void
+QPDF::setIgnoreXRefStreams(bool val)
+{
+ this->ignore_xref_streams = val;
+}
+
+void
+QPDF::setSuppressWarnings(bool val)
+{
+ this->suppress_warnings = val;
+}
+
+void
+QPDF::setAttemptRecovery(bool val)
+{
+ this->attempt_recovery = val;
+}
+
+std::vector<std::string>
+QPDF::getWarnings()
+{
+ std::vector<std::string> result = this->warnings;
+ this->warnings.clear();
+ return result;
+}
+
+void
+QPDF::parse()
+{
+ static PCRE header_re("^%PDF-(1.\\d+)\\b");
+ static PCRE eof_re("(?s:startxref\\s+(\\d+)\\s+%%EOF\\b)");
+
+ std::string line = this->file.readLine();
+ PCRE::Match m1 = header_re.match(line.c_str());
+ if (m1)
+ {
+ this->pdf_version = m1.getMatch(1);
+ if (atof(this->pdf_version.c_str()) < 1.2)
+ {
+ this->tokenizer.allowPoundAnywhereInName();
+ }
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF not a pdf file");
+ throw QPDFExc(this->file.getName(), 0, "not a PDF file");
+ }
+
+ // PDF spec says %%EOF must be found within the last 1024 bytes of
+ // the file. We add an extra 30 characters to leave room for the
+ // startxref stuff.
+ static int const tbuf_size = 1054;
+ this->file.seek(0, SEEK_END);
+ if (this->file.tell() > tbuf_size)
+ {
+ this->file.seek(-tbuf_size, SEEK_END);
+ }
+ else
+ {
+ this->file.rewind();
+ }
+ char* buf = new char[tbuf_size + 1];
+ // Put buf in a PointerHolder to guarantee deletion of buf. This
+ // calls delete rather than delete [], but it's okay since buf is
+ // an array of fundamental types.
+ PointerHolder<char> b(buf);
+ memset(buf, '\0', tbuf_size + 1);
+ this->file.read(buf, tbuf_size);
+
+ // Since buf may contain null characters, we can't do a regexp
+ // search on buf directly. Find the last occurrence within buf
+ // where the regexp matches.
+ char* p = buf;
+ char const* candidate = "";
+ while ((p = (char*)memchr(p, 's', tbuf_size - (p - buf))) != 0)
+ {
+ if (eof_re.match(p))
+ {
+ candidate = p;
+ }
+ ++p;
+ }
+
+ try
+ {
+ PCRE::Match m2 = eof_re.match(candidate);
+ if (! m2)
+ {
+ QTC::TC("qpdf", "QPDF can't find startxref");
+ throw QPDFExc(this->file.getName() + ": can't find startxref");
+ }
+ off_t xref_offset = atoi(m2.getMatch(1).c_str());
+ read_xref(xref_offset);
+ }
+ catch (QPDFExc& e)
+ {
+ if (this->attempt_recovery)
+ {
+ reconstruct_xref(e);
+ QTC::TC("qpdf", "QPDF reconstructed xref table");
+ }
+ else
+ {
+ throw e;
+ }
+ }
+
+ initializeEncryption();
+}
+
+void
+QPDF::warn(QPDFExc const& e)
+{
+ this->warnings.push_back(e.unparse());
+ if (! this->suppress_warnings)
+ {
+ std::cerr << "WARNING: " << this->warnings.back() << std::endl;
+ }
+}
+
+void
+QPDF::setTrailer(QPDFObjectHandle obj)
+{
+ if (this->trailer.isInitialized())
+ {
+ return;
+ }
+ this->trailer = obj;
+}
+
+void
+QPDF::reconstruct_xref(QPDFExc& e)
+{
+ static PCRE obj_re("^(\\d+) (\\d+) obj\\b");
+ static PCRE endobj_re("^endobj\\b");
+ static PCRE trailer_re("^trailer\\b");
+
+ warn(QPDFExc(this->file.getName(), 0, "file is damaged"));
+ warn(e);
+ warn(QPDFExc("Attempting to reconstruct cross-reference table"));
+
+ this->file.seek(0, SEEK_END);
+ off_t eof = this->file.tell();
+ this->file.seek(0, SEEK_SET);
+ bool in_obj = false;
+ while (this->file.tell() < eof)
+ {
+ std::string line = this->file.readLine();
+ if (in_obj)
+ {
+ if (endobj_re.match(line.c_str()))
+ {
+ in_obj = false;
+ }
+ }
+ else
+ {
+ PCRE::Match m = obj_re.match(line.c_str());
+ if (m)
+ {
+ in_obj = true;
+ int obj = atoi(m.getMatch(1).c_str());
+ int gen = atoi(m.getMatch(2).c_str());
+ int offset = this->file.getLastOffset();
+ insertXrefEntry(obj, 1, offset, gen);
+ }
+ else if ((! this->trailer.isInitialized()) &&
+ trailer_re.match(line.c_str()))
+ {
+ // read "trailer"
+ this->file.seek(this->file.getLastOffset(), SEEK_SET);
+ readToken(&this->file);
+ QPDFObjectHandle t = readObject(&this->file, 0, 0, false);
+ if (! t.isDictionary())
+ {
+ // Oh well. It was worth a try.
+ }
+ else
+ {
+ setTrailer(t);
+ }
+ }
+ }
+ }
+
+ if (! this->trailer.isInitialized())
+ {
+ // We could check the last encountered object to see if it was
+ // an xref stream. If so, we could try to get the trailer
+ // from there. This may make it possible to recover files
+ // with bad startxref pointers even when they have object
+ // streams.
+
+ throw QPDFExc(this->file.getName() + ": unable to find trailer "
+ "dictionary while recovering damanged file");
+ }
+
+ // We could iterate through the objects looking for streams and
+ // try to find objects inside of them, but it's probably not worth
+ // the trouble. Acrobat can't recover files with any errors in an
+ // xref stream, and this would be a real long shot anyway. If we
+ // wanted to do anything that involved looking at stream contents,
+ // we'd also have to call initializeEncryption() here. It's safe
+ // to call it more than once.
+}
+
+void
+QPDF::read_xref(off_t xref_offset)
+{
+ std::map<int, int> free_table;
+ while (xref_offset)
+ {
+ this->file.seek(xref_offset, SEEK_SET);
+ std::string line = this->file.readLine();
+ if (line == "xref")
+ {
+ xref_offset = read_xrefTable(this->file.tell());
+ }
+ else
+ {
+ xref_offset = read_xrefStream(xref_offset);
+ }
+ }
+
+ int size = this->trailer.getKey("/Size").getIntValue();
+ int max_obj = (*(xref_table.rbegin())).first.obj;
+ if (! this->deleted_objects.empty())
+ {
+ max_obj = std::max(max_obj, *(this->deleted_objects.rbegin()));
+ }
+ if (size != max_obj + 1)
+ {
+ QTC::TC("qpdf", "QPDF xref size mismatch");
+ warn(QPDFExc(this->file.getName() +
+ std::string(": reported number of objects (") +
+ QUtil::int_to_string(size) +
+ ") inconsistent with actual number of objects (" +
+ QUtil::int_to_string(max_obj + 1) + ")"));
+ }
+
+ // We no longer need the deleted_objects table, so go ahead and
+ // clear it out to make sure we never depend on its being set.
+ this->deleted_objects.clear();
+}
+
+int
+QPDF::read_xrefTable(off_t xref_offset)
+{
+ static PCRE xref_first_re("^(\\d+)\\s+(\\d+)");
+ static PCRE xref_entry_re("(?s:(^\\d{10}) (\\d{5}) ([fn])[ \r\n]{2}$)");
+
+ std::vector<ObjGen> deleted_items;
+
+ this->file.seek(xref_offset, SEEK_SET);
+ bool done = false;
+ while (! done)
+ {
+ std::string line = this->file.readLine();
+ PCRE::Match m1 = xref_first_re.match(line.c_str());
+ if (! m1)
+ {
+ QTC::TC("qpdf", "QPDF invalid xref");
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "xref syntax invalid");
+ }
+ int obj = atoi(m1.getMatch(1).c_str());
+ int num = atoi(m1.getMatch(2).c_str());
+ static int const xref_entry_size = 20;
+ char xref_entry[xref_entry_size + 1];
+ for (int i = obj; i < obj + num; ++i)
+ {
+ if (i == 0)
+ {
+ // This is needed by checkLinearization()
+ this->first_xref_item_offset = this->file.tell();
+ }
+ memset(xref_entry, 0, sizeof(xref_entry));
+ this->file.read(xref_entry, xref_entry_size);
+ PCRE::Match m2 = xref_entry_re.match(xref_entry);
+ if (! m2)
+ {
+ QTC::TC("qpdf", "QPDF invalid xref entry");
+ throw QPDFExc(
+ this->file.getName(), this->file.getLastOffset(),
+ "invalid xref entry (obj=" +
+ QUtil::int_to_string(i) + ")");
+ }
+
+ int f1 = atoi(m2.getMatch(1).c_str());
+ int f2 = atoi(m2.getMatch(2).c_str());
+ char type = m2.getMatch(3)[0];
+ if (type == 'f')
+ {
+ // Save deleted items until after we've checked the
+ // XRefStm, if any.
+ deleted_items.push_back(ObjGen(i, f2));
+ }
+ else
+ {
+ insertXrefEntry(i, 1, f1, f2);
+ }
+ }
+ off_t pos = this->file.tell();
+ QPDFTokenizer::Token t = readToken(&this->file);
+ if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))
+ {
+ done = true;
+ }
+ else
+ {
+ this->file.seek(pos, SEEK_SET);
+ }
+ }
+
+ // Set offset to previous xref table if any
+ QPDFObjectHandle cur_trailer = readObject(&this->file, 0, 0, false);
+ if (! cur_trailer.isDictionary())
+ {
+ QTC::TC("qpdf", "QPDF missing trailer");
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "expected trailer dictionary");
+ }
+
+ if (! this->trailer.isInitialized())
+ {
+ setTrailer(cur_trailer);
+
+ if (! this->trailer.hasKey("/Size"))
+ {
+ QTC::TC("qpdf", "QPDF trailer lacks size");
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "trailer dictionary lacks /Size key");
+ }
+ if (! this->trailer.getKey("/Size").isInteger())
+ {
+ QTC::TC("qpdf", "QPDF trailer size not integer");
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "/Size key in trailer dictionary is not "
+ "an integer");
+ }
+ }
+
+ if (cur_trailer.hasKey("/XRefStm"))
+ {
+ if (this->ignore_xref_streams)
+ {
+ QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
+ }
+ else
+ {
+ if (cur_trailer.getKey("/XRefStm").isInteger())
+ {
+ // Read the xref stream but disregard any return value
+ // -- we'll use our trailer's /Prev key instead of the
+ // xref stream's.
+ (void) read_xrefStream(
+ cur_trailer.getKey("/XRefStm").getIntValue());
+ }
+ else
+ {
+ throw QPDFExc(this->file.getName(), xref_offset,
+ "invalid /XRefStm");
+ }
+ }
+ }
+
+ // Handle any deleted items now that we've read the /XRefStm.
+ for (std::vector<ObjGen>::iterator iter = deleted_items.begin();
+ iter != deleted_items.end(); ++iter)
+ {
+ ObjGen& og = *iter;
+ insertXrefEntry(og.obj, 0, 0, og.gen);
+ }
+
+ if (cur_trailer.hasKey("/Prev"))
+ {
+ if (! cur_trailer.getKey("/Prev").isInteger())
+ {
+ QTC::TC("qpdf", "QPDF trailer prev not integer");
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "/Prev key in trailer dictionary is not "
+ "an integer");
+ }
+ QTC::TC("qpdf", "QPDF prev key in trailer dictionary");
+ xref_offset = cur_trailer.getKey("/Prev").getIntValue();
+ }
+ else
+ {
+ xref_offset = 0;
+ }
+
+ return xref_offset;
+}
+
+int
+QPDF::read_xrefStream(off_t xref_offset)
+{
+ bool found = false;
+ if (! this->ignore_xref_streams)
+ {
+ int xobj;
+ int xgen;
+ QPDFObjectHandle xref_obj;
+ try
+ {
+ xref_obj = readObjectAtOffset(xref_offset, 0, 0, xobj, xgen);
+ }
+ catch (QPDFExc& e)
+ {
+ // ignore -- report error below
+ }
+ if (xref_obj.isInitialized() &&
+ xref_obj.isStream() &&
+ xref_obj.getDict().getKey("/Type").isName() &&
+ xref_obj.getDict().getKey("/Type").getName() == "/XRef")
+ {
+ QTC::TC("qpdf", "QPDF found xref stream");
+ found = true;
+ xref_offset = processXRefStream(xref_offset, xref_obj);
+ }
+ }
+
+ if (! found)
+ {
+ QTC::TC("qpdf", "QPDF can't find xref");
+ throw QPDFExc(this->file.getName(), xref_offset, "xref not found");
+ }
+
+ return xref_offset;
+}
+
+int
+QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle& xref_obj)
+{
+ QPDFObjectHandle dict = xref_obj.getDict();
+ QPDFObjectHandle W_obj = dict.getKey("/W");
+ QPDFObjectHandle Index_obj = dict.getKey("/Index");
+ if (! (W_obj.isArray() &&
+ (W_obj.getArrayNItems() >= 3) &&
+ W_obj.getArrayItem(0).isInteger() &&
+ W_obj.getArrayItem(1).isInteger() &&
+ W_obj.getArrayItem(2).isInteger() &&
+ dict.getKey("/Size").isInteger() &&
+ (Index_obj.isArray() || Index_obj.isNull())))
+ {
+ throw QPDFExc(this->file.getName(), xref_offset,
+ "Cross-reference stream does not have"
+ " proper /W and /Index keys");
+ }
+ std::vector<int> indx;
+ if (Index_obj.isArray())
+ {
+ int n_index = Index_obj.getArrayNItems();
+ if ((n_index % 2) || (n_index < 2))
+ {
+ throw QPDFExc(this->file.getName(), xref_offset,
+ "Cross-reference stream's /Index has an"
+ " invalid number of values");
+ }
+ for (int i = 0; i < n_index; ++i)
+ {
+ if (Index_obj.getArrayItem(i).isInteger())
+ {
+ indx.push_back(Index_obj.getArrayItem(i).getIntValue());
+ }
+ else
+ {
+ throw QPDFExc(this->file.getName(), xref_offset,
+ "Cross-reference stream's /Index's item " +
+ QUtil::int_to_string(i) +
+ " is not an integer");
+ }
+ }
+ QTC::TC("qpdf", "QPDF xref /Index is array",
+ n_index == 2 ? 0 : 1);
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF xref /Index is null");
+ int size = dict.getKey("/Size").getIntValue();
+ indx.push_back(0);
+ indx.push_back(size);
+ }
+
+ int num_entries = 0;
+ for (unsigned int i = 1; i < indx.size(); i += 2)
+ {
+ num_entries += indx[i];
+ }
+
+ int W[3];
+ int entry_size = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ W[i] = W_obj.getArrayItem(i).getIntValue();
+ entry_size += W[i];
+ }
+
+ int expected_size = entry_size * num_entries;
+
+ PointerHolder<Buffer> bp = xref_obj.getStreamData();
+ int actual_size = bp.getPointer()->getSize();
+
+ if (expected_size != actual_size)
+ {
+ throw QPDFExc(this->file.getName(), xref_offset,
+ "Cross-reference stream data has the wrong size;"
+ " expected = " + QUtil::int_to_string(expected_size) +
+ "; actual = " + QUtil::int_to_string(actual_size));
+ }
+
+ int cur_chunk = 0;
+ int chunk_count = 0;
+
+ bool saw_first_compressed_object = false;
+
+ unsigned char const* data = bp.getPointer()->getBuffer();
+ for (int i = 0; i < num_entries; ++i)
+ {
+ // Read this entry
+ unsigned char const* entry = data + (entry_size * i);
+ int fields[3];
+ unsigned char const* p = entry;
+ for (int j = 0; j < 3; ++j)
+ {
+ fields[j] = 0;
+ if ((j == 0) && (W[0] == 0))
+ {
+ QTC::TC("qpdf", "QPDF default for xref stream field 0");
+ fields[0] = 1;
+ }
+ for (int k = 0; k < W[j]; ++k)
+ {
+ fields[j] <<= 8;
+ fields[j] += (int)(*p++);
+ }
+ }
+
+ // Get the object and generation number. The object number is
+ // based on /Index. The generation number is 0 unless this is
+ // an uncompressed object record, in which case the generation
+ // number appears as the third field.
+ int obj = indx[cur_chunk] + chunk_count;
+ ++chunk_count;
+ if (chunk_count >= indx[cur_chunk + 1])
+ {
+ cur_chunk += 2;
+ chunk_count = 0;
+ }
+
+ if (saw_first_compressed_object)
+ {
+ if (fields[0] != 2)
+ {
+ this->uncompressed_after_compressed = true;
+ }
+ }
+ else if (fields[0] == 2)
+ {
+ saw_first_compressed_object = true;
+ }
+ if (obj == 0)
+ {
+ // This is needed by checkLinearization()
+ this->first_xref_item_offset = xref_offset;
+ }
+ insertXrefEntry(obj, fields[0], fields[1], fields[2]);
+ }
+
+ if (! this->trailer.isInitialized())
+ {
+ setTrailer(dict);
+ }
+
+ if (dict.hasKey("/Prev"))
+ {
+ if (! dict.getKey("/Prev").isInteger())
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "/Prev key in xref stream dictionary is not "
+ "an integer");
+ }
+ QTC::TC("qpdf", "QPDF prev key in xref stream dictionary");
+ xref_offset = dict.getKey("/Prev").getIntValue();
+ }
+ else
+ {
+ xref_offset = 0;
+ }
+
+ return xref_offset;
+}
+
+void
+QPDF::insertXrefEntry(int obj, int f0, int f1, int f2)
+{
+ // Populate the xref table in such a way that the first reference
+ // to an object that we see, which is the one in the latest xref
+ // table in which it appears, is the one that gets stored.
+
+ // If there is already an entry for this object and generation in
+ // the table, it means that a later xref table has registered this
+ // object. Disregard this one.
+ { // private scope
+ int gen = (f0 == 2 ? 0 : f2);
+ ObjGen og(obj, gen);
+ if (this->xref_table.count(og))
+ {
+ QTC::TC("qpdf", "QPDF xref reused object");
+ return;
+ }
+ if (this->deleted_objects.count(obj))
+ {
+ QTC::TC("qpdf", "QPDF xref deleted object");
+ return;
+ }
+ }
+
+ switch (f0)
+ {
+ case 0:
+ this->deleted_objects.insert(obj);
+ break;
+
+ case 1:
+ // f2 is generation
+ QTC::TC("qpdf", "QPDF xref gen > 0", ((f2 > 0) ? 1 : 0));
+ this->xref_table[ObjGen(obj, f2)] = QPDFXRefEntry(f0, f1, f2);
+ break;
+
+ case 2:
+ this->xref_table[ObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2);
+ break;
+
+ default:
+ throw QPDFExc(this->file.getName(), 0,
+ "unknown xref stream entry type " +
+ QUtil::int_to_string(f0));
+ break;
+ }
+}
+
+void
+QPDF::showXRefTable()
+{
+ for (std::map<ObjGen, QPDFXRefEntry>::iterator iter =
+ this->xref_table.begin();
+ iter != this->xref_table.end(); ++iter)
+ {
+ ObjGen const& og = (*iter).first;
+ QPDFXRefEntry const& entry = (*iter).second;
+ std::cout << og.obj << "/" << og.gen << ": ";
+ switch (entry.getType())
+ {
+ case 1:
+ std::cout << "uncompressed; offset = " << entry.getOffset();
+ break;
+
+ case 2:
+ std::cout << "compressed; stream = " << entry.getObjStreamNumber()
+ << ", index = " << entry.getObjStreamIndex();
+ break;
+
+ default:
+ throw QEXC::Internal("unknown cross-reference table type while"
+ " showing xref_table");
+ break;
+ }
+ std::cout << std::endl;
+ }
+}
+
+QPDFObjectHandle
+QPDF::readObject(InputSource* input, int objid, int generation,
+ bool in_object_stream)
+{
+ off_t offset = input->tell();
+ QPDFObjectHandle object = readObjectInternal(
+ input, objid, generation, in_object_stream, false, false);
+ // Override last_offset so that it points to the beginning of the
+ // object we just read
+ input->setLastOffset(offset);
+ return object;
+}
+
+QPDFObjectHandle
+QPDF::readObjectInternal(InputSource* input,
+ int objid, int generation,
+ bool in_object_stream,
+ bool in_array, bool in_dictionary)
+{
+ if (in_dictionary && in_array)
+ {
+ // Although dictionaries and arrays arbitrarily nest, these
+ // variables indicate what is at the top of the stack right
+ // now, so they can, by definition, never both be true.
+ throw QEXC::Internal("readObjectInternal: in_dict && in_array");
+ }
+
+ QPDFObjectHandle object;
+
+ off_t offset = input->tell();
+ std::vector<QPDFObjectHandle> olist;
+ bool done = false;
+ while (! done)
+ {
+ object = QPDFObjectHandle();
+
+ QPDFTokenizer::Token token = readToken(input);
+
+ switch (token.getType())
+ {
+ case QPDFTokenizer::tt_brace_open:
+ case QPDFTokenizer::tt_brace_close:
+ // Don't know what to do with these for now
+ QTC::TC("qpdf", "QPDF bad brace");
+ throw QPDFExc(input->getName(), input->getLastOffset(),
+ "unexpected brace token");
+ break;
+
+ case QPDFTokenizer::tt_array_close:
+ if (in_array)
+ {
+ done = true;
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF bad array close");
+ throw QPDFExc(input->getName(), input->getLastOffset(),
+ "unexpected array close token");
+ }
+ break;
+
+ case QPDFTokenizer::tt_dict_close:
+ if (in_dictionary)
+ {
+ done = true;
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF bad dictionary close");
+ throw QPDFExc(input->getName(), input->getLastOffset(),
+ "unexpected dictionary close token");
+ }
+ break;
+
+ case QPDFTokenizer::tt_array_open:
+ object = readObjectInternal(
+ input, objid, generation, in_object_stream, true, false);
+ break;
+
+ case QPDFTokenizer::tt_dict_open:
+ object = readObjectInternal(
+ input, objid, generation, in_object_stream, false, true);
+ break;
+
+ case QPDFTokenizer::tt_bool:
+ object = QPDFObjectHandle::newBool(
+ (token.getValue() == "true"));
+ break;
+
+ case QPDFTokenizer::tt_null:
+ object = QPDFObjectHandle::newNull();
+ break;
+
+ case QPDFTokenizer::tt_integer:
+ object = QPDFObjectHandle::newInteger(
+ atoi(token.getValue().c_str()));
+ break;
+
+ case QPDFTokenizer::tt_real:
+ object = QPDFObjectHandle::newReal(token.getValue());
+ break;
+
+ case QPDFTokenizer::tt_name:
+ object = QPDFObjectHandle::newName(token.getValue());
+ break;
+
+ case QPDFTokenizer::tt_word:
+ {
+ std::string const& value = token.getValue();
+ if ((value == "R") && (in_array || in_dictionary) &&
+ (olist.size() >= 2) &&
+ (olist[olist.size() - 1].isInteger()) &&
+ (olist[olist.size() - 2].isInteger()))
+ {
+ // Try to resolve indirect objects
+ object = QPDFObjectHandle::Factory::newIndirect(
+ this,
+ olist[olist.size() - 2].getIntValue(),
+ olist[olist.size() - 1].getIntValue());
+ olist.pop_back();
+ olist.pop_back();
+ }
+ else
+ {
+ throw QPDFExc(input->getName(), input->getLastOffset(),
+ "unknown token while reading object (" +
+ value + ")");
+ }
+ }
+ break;
+
+ case QPDFTokenizer::tt_string:
+ {
+ std::string val = token.getValue();
+ if (this->encrypted && (! in_object_stream))
+ {
+ decryptString(val, objid, generation);
+ }
+ object = QPDFObjectHandle::newString(val);
+ }
+ break;
+
+ default:
+ throw QPDFExc(input->getName(), input->getLastOffset(),
+ "unknown token type while reading object");
+ break;
+ }
+
+ if (in_dictionary || in_array)
+ {
+ if (! done)
+ {
+ olist.push_back(object);
+ }
+ }
+ else if (! object.isInitialized())
+ {
+ throw QEXC::Internal(std::string("uninitialized object (token = ") +
+ QUtil::int_to_string(token.getType()) +
+ ", " + token.getValue() + ")");
+ }
+ else
+ {
+ done = true;
+ }
+ }
+
+ if (in_array)
+ {
+ object = QPDFObjectHandle::newArray(olist);
+ }
+ else if (in_dictionary)
+ {
+ // Convert list to map. Alternating elements are keys.
+ std::map<std::string, QPDFObjectHandle> dict;
+ if (olist.size() % 2)
+ {
+ QTC::TC("qpdf", "QPDF dictionary odd number of elements");
+ throw QPDFExc(
+ input->getName(), input->getLastOffset(),
+ "dictionary ending here has an odd number of elements");
+ }
+ for (unsigned int i = 0; i < olist.size(); i += 2)
+ {
+ QPDFObjectHandle key_obj = olist[i];
+ QPDFObjectHandle val = olist[i + 1];
+ if (! key_obj.isName())
+ {
+ throw QPDFExc(
+ input->getName(), offset,
+ std::string("dictionary key not name (") +
+ key_obj.unparse() + ")");
+ }
+ dict[key_obj.getName()] = val;
+ }
+ object = QPDFObjectHandle::newDictionary(dict);
+
+ if (! in_object_stream)
+ {
+ // check for stream
+ off_t cur_offset = input->tell();
+ if (readToken(input) ==
+ QPDFTokenizer::Token(QPDFTokenizer::tt_word, "stream"))
+ {
+ // Kill to next actual newline. Do not use readLine()
+ // here -- streams are a special case. The next
+ // single newline character marks the end of the
+ // stream token. It is incorrect to strip subsequent
+ // carriage returns or newlines as they may be part of
+ // the stream.
+ {
+ char ch;
+ do
+ {
+ if (input->read(&ch, 1) == 0)
+ {
+ // A premature EOF here will result in
+ // some other problem that will get
+ // reported at another time.
+ ch = '\n';
+ }
+ } while (ch != '\n');
+ }
+
+ // Must get offset before accessing any additional
+ // objects since resolving a previously unresolved
+ // indirect object will change file position.
+ off_t stream_offset = input->tell();
+ int length = 0;
+
+ try
+ {
+ if (dict.count("/Length") == 0)
+ {
+ QTC::TC("qpdf", "QPDF stream without length");
+ throw QPDFExc(input->getName(), offset,
+ "stream dictionary lacks /Length key");
+ }
+
+ QPDFObjectHandle length_obj = dict["/Length"];
+ if (! length_obj.isInteger())
+ {
+ QTC::TC("qpdf", "QPDF stream length not integer");
+ throw QPDFExc(input->getName(), offset,
+ "/Length key in stream dictionary is not "
+ "an integer");
+ }
+
+ length = length_obj.getIntValue();
+ input->seek(stream_offset + length, SEEK_SET);
+ if (! (readToken(input) ==
+ QPDFTokenizer::Token(
+ QPDFTokenizer::tt_word, "endstream")))
+ {
+ QTC::TC("qpdf", "QPDF missing endstream");
+ throw QPDFExc(input->getName(), input->getLastOffset(),
+ "expected endstream");
+ }
+ }
+ catch (QPDFExc& e)
+ {
+ if (this->attempt_recovery)
+ {
+ // may throw an exception
+ length = recoverStreamLength(
+ input, objid, generation, stream_offset);
+ }
+ else
+ {
+ throw e;
+ }
+ }
+ object = QPDFObjectHandle::Factory::newStream(
+ this, objid, generation, object, stream_offset, length);
+ }
+ else
+ {
+ input->seek(cur_offset, SEEK_SET);
+ }
+ }
+ }
+
+ return object;
+}
+
+int
+QPDF::recoverStreamLength(InputSource* input,
+ int objid, int generation, off_t stream_offset)
+{
+ static PCRE endobj_re("^endobj\\b");
+
+ // Try to reconstruct stream length by looking for
+ // endstream(\r\n?|\n)endobj
+ warn(QPDFExc(input->getName(), stream_offset,
+ "attempting to recover stream length"));
+
+ input->seek(0, SEEK_END);
+ off_t eof = input->tell();
+ input->seek(stream_offset, SEEK_SET);
+ std::string last_line;
+ off_t last_line_offset = 0;
+ int length = 0;
+ while (input->tell() < eof)
+ {
+ std::string line = input->readLine();
+ // Can't use regexp last_line since it might contain nulls
+ if (endobj_re.match(line.c_str()) &&
+ (last_line.length() >= 9) &&
+ (last_line.substr(last_line.length() - 9, 9) == "endstream"))
+ {
+ // Stream probably ends right before "endstream", which
+ // contains 9 characters.
+ length = last_line_offset + last_line.length() - 9 - stream_offset;
+ // Go back to where we would have been if we had just read
+ // the endstream.
+ input->seek(input->getLastOffset(), SEEK_SET);
+ break;
+ }
+ last_line = line;
+ last_line_offset = input->getLastOffset();
+ }
+
+ if (length)
+ {
+ int this_obj_offset = 0;
+ ObjGen this_obj(0, 0);
+
+ // Make sure this is inside this object
+ for (std::map<ObjGen, QPDFXRefEntry>::iterator iter =
+ this->xref_table.begin();
+ iter != this->xref_table.end(); ++iter)
+ {
+ ObjGen const& og = (*iter).first;
+ QPDFXRefEntry const& entry = (*iter).second;
+ if (entry.getType() == 1)
+ {
+ int obj_offset = entry.getOffset();
+ if ((obj_offset > stream_offset) &&
+ ((this_obj_offset == 0) ||
+ (this_obj_offset > obj_offset)))
+ {
+ this_obj_offset = obj_offset;
+ this_obj = og;
+ }
+ }
+ }
+ if (this_obj_offset &&
+ (this_obj.obj == objid) &&
+ (this_obj.gen == generation))
+ {
+ // Well, we found endstream\nendobj within the space
+ // allowed for this object, so we're probably in good
+ // shape.
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF found wrong endstream in recovery");
+ }
+ }
+
+ if (length == 0)
+ {
+ throw QPDFExc(input->getName(), stream_offset,
+ "unable to recover stream data");
+ }
+
+ QTC::TC("qpdf", "QPDF recovered stream length");
+ return length;
+}
+
+QPDFTokenizer::Token
+QPDF::readToken(InputSource* input)
+{
+ off_t offset = input->tell();
+ QPDFTokenizer::Token token;
+ bool unread_char;
+ char char_to_unread;
+ while (! this->tokenizer.getToken(token, unread_char, char_to_unread))
+ {
+ char ch;
+ if (input->read(&ch, 1) == 0)
+ {
+ throw QPDFExc(input->getName(), offset, "EOF while reading token");
+ }
+ else
+ {
+ if (isspace(ch) && (input->getLastOffset() == offset))
+ {
+ ++offset;
+ }
+ this->tokenizer.presentCharacter(ch);
+ }
+ }
+
+ if (unread_char)
+ {
+ input->unreadCh(char_to_unread);
+ }
+
+ if (token.getType() == QPDFTokenizer::tt_bad)
+ {
+ throw QPDFExc(input->getName(), offset, token.getErrorMessage());
+ }
+
+ input->setLastOffset(offset);
+
+ return token;
+}
+
+QPDFObjectHandle
+QPDF::readObjectAtOffset(off_t offset, int exp_objid, int exp_generation,
+ int& objid, int& generation)
+{
+ this->file.seek(offset, SEEK_SET);
+
+ QPDFTokenizer::Token tobjid = readToken(&this->file);
+ QPDFTokenizer::Token tgen = readToken(&this->file);
+ QPDFTokenizer::Token tobj = readToken(&this->file);
+
+ bool objidok = (tobjid.getType() == QPDFTokenizer::tt_integer);
+ int genok = (tgen.getType() == QPDFTokenizer::tt_integer);
+ int objok = (tobj == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "obj"));
+
+ QTC::TC("qpdf", "QPDF check objid", objidok ? 1 : 0);
+ QTC::TC("qpdf", "QPDF check generation", genok ? 1 : 0);
+ QTC::TC("qpdf", "QPDF check obj", objok ? 1 : 0);
+
+ try
+ {
+ if (! (objidok && genok && objok))
+ {
+ QTC::TC("qpdf", "QPDF expected n n obj");
+ throw QPDFExc(this->file.getName(), offset, "expected n n obj");
+ }
+ objid = atoi(tobjid.getValue().c_str());
+ generation = atoi(tgen.getValue().c_str());
+
+ if (exp_objid &&
+ (! ((objid == exp_objid) && (generation == exp_generation))))
+ {
+ QTC::TC("qpdf", "QPDF err wrong objid/generation");
+ throw QPDFExc(this->file.getName(), offset,
+ std::string("expected ") +
+ QUtil::int_to_string(exp_objid) + " " +
+ QUtil::int_to_string(exp_generation) + " obj");
+ }
+ }
+ catch (QPDFExc& e)
+ {
+ if (exp_objid && this->attempt_recovery)
+ {
+ // Try again after reconstructing xref table
+ reconstruct_xref(e);
+ ObjGen og(exp_objid, exp_generation);
+ if (this->xref_table.count(og) &&
+ (this->xref_table[og].getType() == 1))
+ {
+ off_t new_offset = this->xref_table[og].getOffset();
+ // Call readObjectAtOffset with 0 for exp_objid to
+ // avoid an infinite loop.
+ QPDFObjectHandle result =
+ readObjectAtOffset(new_offset, 0, 0, objid, generation);
+ QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset");
+ return result;
+ }
+ }
+ else
+ {
+ throw e;
+ }
+ }
+
+ QPDFObjectHandle oh = readObject(
+ &this->file, objid, generation, false);
+
+ if (! (readToken(&this->file) ==
+ QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj")))
+ {
+ QTC::TC("qpdf", "QPDF err expected endobj");
+ warn(QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "expected endobj"));
+ }
+
+ ObjGen og(objid, generation);
+ if (! this->obj_cache.count(og))
+ {
+ // Store the object in the cache here so it gets cached
+ // whether we first know the offset or whether we first know
+ // the object ID and generation (in which we case we would get
+ // here through resolve).
+
+ // Determine the end offset of this object before and after
+ // white space. We use these numbers to validate
+ // linearization hint tables. Offsets and lengths of objects
+ // may imply the end of an object to be anywhere between these
+ // values.
+ off_t end_before_space = this->file.tell();
+
+ // skip over spaces
+ while (true)
+ {
+ char ch;
+ if (this->file.read(&ch, 1))
+ {
+ if (! isspace(ch))
+ {
+ this->file.seek(-1, SEEK_CUR);
+ break;
+ }
+ }
+ else
+ {
+ throw QPDFExc(this->file.getName(), offset,
+ "EOF after endobj");
+ }
+ }
+ off_t end_after_space = this->file.tell();
+
+ this->obj_cache[og] =
+ ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh),
+ end_before_space, end_after_space);
+ }
+
+ return oh;
+}
+
+PointerHolder<QPDFObject>
+QPDF::resolve(int objid, int generation)
+{
+ // Check object cache before checking xref table. This allows us
+ // to insert things into the object cache that don't actually
+ // exist in the file.
+ ObjGen og(objid, generation);
+ if (! this->obj_cache.count(og))
+ {
+ if (! this->xref_table.count(og))
+ {
+ // PDF spec says unknown objects resolve to the null object.
+ return new QPDF_Null;
+ }
+
+ QPDFXRefEntry const& entry = this->xref_table[og];
+ switch (entry.getType())
+ {
+ case 1:
+ {
+ off_t offset = entry.getOffset();
+ // Object stored in cache by readObjectAtOffset
+ int aobjid;
+ int ageneration;
+ QPDFObjectHandle oh =
+ readObjectAtOffset(offset, objid, generation,
+ aobjid, ageneration);
+ }
+ break;
+
+ case 2:
+ resolveObjectsInStream(entry.getObjStreamNumber());
+ break;
+
+ default:
+ throw QPDFExc(this->file.getName(), 0,
+ "object " +
+ QUtil::int_to_string(objid) + "/" +
+ QUtil::int_to_string(generation) +
+ " has unexpected xref entry type");
+ }
+ }
+
+ return this->obj_cache[og].object;
+}
+
+void
+QPDF::resolveObjectsInStream(int obj_stream_number)
+{
+ // Force resolution of object stream
+ QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0);
+ if (! obj_stream.isStream())
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "supposed object stream " +
+ QUtil::int_to_string(obj_stream_number) +
+ " is not a stream");
+ }
+
+ // For linearization data in the object, use the data from the
+ // object stream for the objects in the stream.
+ ObjGen stream_og(obj_stream_number, 0);
+ off_t end_before_space = this->obj_cache[stream_og].end_before_space;
+ off_t end_after_space = this->obj_cache[stream_og].end_after_space;
+
+ QPDFObjectHandle dict = obj_stream.getDict();
+ if (! (dict.getKey("/Type").isName() &&
+ dict.getKey("/Type").getName() == "/ObjStm"))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "supposed object stream " +
+ QUtil::int_to_string(obj_stream_number) +
+ " has wrong type");
+ }
+
+ if (! (dict.getKey("/N").isInteger() &&
+ dict.getKey("/First").isInteger()))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "object stream " +
+ QUtil::int_to_string(obj_stream_number) +
+ " has incorrect keys");
+ }
+
+ int n = dict.getKey("/N").getIntValue();
+ int first = dict.getKey("/First").getIntValue();
+
+ std::map<int, int> offsets;
+
+ PointerHolder<Buffer> bp = obj_stream.getStreamData();
+ BufferInputSource input(
+ "object stream " + QUtil::int_to_string(obj_stream_number),
+ bp.getPointer());
+
+ for (int i = 0; i < n; ++i)
+ {
+ QPDFTokenizer::Token tnum = readToken(&input);
+ QPDFTokenizer::Token toffset = readToken(&input);
+ if (! ((tnum.getType() == QPDFTokenizer::tt_integer) &&
+ (toffset.getType() == QPDFTokenizer::tt_integer)))
+ {
+ throw QPDFExc(input.getName(), input.getLastOffset(),
+ "expected integer in object stream header");
+ }
+
+ int num = atoi(tnum.getValue().c_str());
+ int offset = atoi(toffset.getValue().c_str());
+ offsets[num] = offset + first;
+ }
+
+ for (std::map<int, int>::iterator iter = offsets.begin();
+ iter != offsets.end(); ++iter)
+ {
+ int obj = (*iter).first;
+ int offset = (*iter).second;
+ input.seek(offset, SEEK_SET);
+ QPDFObjectHandle oh = readObject(&input, obj, 0, true);
+
+ // Store in cache
+ ObjGen og(obj, 0);
+
+ this->obj_cache[og] =
+ ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh),
+ end_before_space, end_after_space);
+ }
+}
+
+QPDFObjectHandle
+QPDF::makeIndirectObject(QPDFObjectHandle oh)
+{
+ ObjGen o1 = (*(this->obj_cache.rbegin())).first;
+ ObjGen o2 = (*(this->xref_table.rbegin())).first;
+ QTC::TC("qpdf", "QPDF indirect last obj from xref",
+ (o2.obj > o1.obj) ? 1 : 0);
+ int max_objid = std::max(o1.obj, o2.obj);
+ ObjGen next(max_objid + 1, 0);
+ this->obj_cache[next] =
+ ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
+ return QPDFObjectHandle::Factory::newIndirect(this, next.obj, next.gen);
+}
+
+QPDFObjectHandle
+QPDF::getObjectByID(int objid, int generation)
+{
+ return QPDFObjectHandle::Factory::newIndirect(this, objid, generation);
+}
+
+void
+QPDF::trimTrailerForWrite()
+{
+ // Note that removing the encryption dictionary does not interfere
+ // with reading encrypted files. QPDF loads all the information
+ // it needs from the encryption dictionary at the beginning and
+ // never looks at it again.
+ this->trailer.removeKey("/ID");
+ this->trailer.removeKey("/Encrypt");
+ this->trailer.removeKey("/Prev");
+
+ // Remove all trailer keys that potentially come from a
+ // cross-reference stream
+ this->trailer.removeKey("/Index");
+ this->trailer.removeKey("/W");
+ this->trailer.removeKey("/Length");
+ this->trailer.removeKey("/Filter");
+ this->trailer.removeKey("/DecodeParms");
+ this->trailer.removeKey("/Type");
+ this->trailer.removeKey("/XRefStm");
+}
+
+std::string
+QPDF::getFilename() const
+{
+ return this->file.getName();
+}
+
+std::string
+QPDF::getPDFVersion() const
+{
+ return this->pdf_version;
+}
+
+QPDFObjectHandle
+QPDF::getTrailer()
+{
+ return this->trailer;
+}
+
+QPDFObjectHandle
+QPDF::getRoot()
+{
+ return this->trailer.getKey("/Root");
+}
+
+void
+QPDF::getObjectStreamData(std::map<int, int>& omap)
+{
+ for (std::map<ObjGen, QPDFXRefEntry>::iterator iter =
+ this->xref_table.begin();
+ iter != this->xref_table.end(); ++iter)
+ {
+ ObjGen const& og = (*iter).first;
+ QPDFXRefEntry const& entry = (*iter).second;
+ if (entry.getType() == 2)
+ {
+ omap[og.obj] = entry.getObjStreamNumber();
+ }
+ }
+}
+
+std::vector<int>
+QPDF::getCompressibleObjects()
+{
+ // Return a set of object numbers of objects that are allowed to
+ // be in object streams. We disregard generation numbers here
+ // since this is a helper function for QPDFWriter which is going
+ // to renumber objects anyway. This code will do weird things if
+ // we have two objects with the same object number and different
+ // generations, but so do virtually all PDF consumers,
+ // particularly since this is not a permitted condition.
+
+ // We walk through the objects by traversing the document from the
+ // root, including a traversal of the pages tree. This makes that
+ // objects that are on the same page are more likely to be in the
+ // same object stream, which is slightly more efficient,
+ // particularly with linearized files. This is better than
+ // iterating through the xref table since it avoids preserving
+ // orphaned items.
+
+ // Exclude encryption dictionary, if any
+ int encryption_dict_id = 0;
+ QPDFObjectHandle encryption_dict = trailer.getKey("/Encrypt");
+ if (encryption_dict.isIndirect())
+ {
+ encryption_dict_id = encryption_dict.getObjectID();
+ }
+
+ std::set<int> visited;
+ std::list<QPDFObjectHandle> queue;
+ queue.push_front(this->trailer);
+ std::vector<int> result;
+ while (! queue.empty())
+ {
+ QPDFObjectHandle obj = queue.front();
+ queue.pop_front();
+ if (obj.isIndirect())
+ {
+ int objid = obj.getObjectID();
+ if (visited.count(objid))
+ {
+ QTC::TC("qpdf", "QPDF loop detected traversing objects");
+ continue;
+ }
+ if (objid == encryption_dict_id)
+ {
+ QTC::TC("qpdf", "QPDF exclude encryption dictionary");
+ }
+ else if (! obj.isStream())
+ {
+ result.push_back(objid);
+ }
+ visited.insert(objid);
+ }
+ if (obj.isStream())
+ {
+ QPDFObjectHandle dict = obj.getDict();
+ std::set<std::string> keys = dict.getKeys();
+ for (std::set<std::string>::reverse_iterator iter = keys.rbegin();
+ iter != keys.rend(); ++iter)
+ {
+ std::string const& key = *iter;
+ QPDFObjectHandle value = dict.getKey(key);
+ if (key == "/Length")
+ {
+ // omit stream lengths
+ if (value.isIndirect())
+ {
+ QTC::TC("qpdf", "QPDF exclude indirect length");
+ }
+ }
+ else
+ {
+ queue.push_front(value);
+ }
+ }
+ }
+ else if (obj.isDictionary())
+ {
+ std::set<std::string> keys = obj.getKeys();
+ for (std::set<std::string>::reverse_iterator iter = keys.rbegin();
+ iter != keys.rend(); ++iter)
+ {
+ queue.push_front(obj.getKey(*iter));
+ }
+ }
+ else if (obj.isArray())
+ {
+ int n = obj.getArrayNItems();
+ for (int i = 1; i <= n; ++i)
+ {
+ queue.push_front(obj.getArrayItem(n - i));
+ }
+ }
+ }
+
+ return result;
+}
+
+void
+QPDF::pipeStreamData(int objid, int generation,
+ off_t offset, size_t length,
+ QPDFObjectHandle stream_dict,
+ Pipeline* pipeline)
+{
+ std::vector<PointerHolder<Pipeline> > to_delete;
+ if (this->encrypted)
+ {
+ bool xref_stream = false;
+ if (stream_dict.getKey("/Type").isName() &&
+ (stream_dict.getKey("/Type").getName() == "/XRef"))
+ {
+ QTC::TC("qpdf", "QPDF piping xref stream from encrypted file");
+ xref_stream = true;
+ }
+ if (! xref_stream)
+ {
+ decryptStream(pipeline, objid, generation, to_delete);
+ }
+ }
+
+ this->file.seek(offset, SEEK_SET);
+ char buf[10240];
+ while (length > 0)
+ {
+ size_t to_read = (sizeof(buf) < length ? sizeof(buf) : length);
+ size_t len = this->file.read(buf, to_read);
+ if (len == 0)
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "unexpected EOF reading stream data");
+ }
+ length -= len;
+ pipeline->write((unsigned char*)buf, len);
+ }
+ pipeline->finish();
+}
+
+std::vector<QPDFObjectHandle> const&
+QPDF::getAllPages()
+{
+ if (this->all_pages.empty())
+ {
+ getAllPagesInternal(
+ this->trailer.getKey("/Root").getKey("/Pages"), this->all_pages);
+ }
+ return this->all_pages;
+}
+
+void
+QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages,
+ std::vector<QPDFObjectHandle>& result)
+{
+ std::string type = cur_pages.getKey("/Type").getName();
+ if (type == "/Pages")
+ {
+ QPDFObjectHandle kids = cur_pages.getKey("/Kids");
+ int n = kids.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ getAllPagesInternal(kids.getArrayItem(i), result);
+ }
+ }
+ else if (type == "/Page")
+ {
+ result.push_back(cur_pages);
+ }
+ else
+ {
+ throw QPDFExc(this->file.getName() + ": invalid Type in page tree");
+ }
+}
diff --git a/libqpdf/QPDFExc.cc b/libqpdf/QPDFExc.cc
new file mode 100644
index 00000000..c7270677
--- /dev/null
+++ b/libqpdf/QPDFExc.cc
@@ -0,0 +1,20 @@
+
+#include <qpdf/QPDFExc.hh>
+
+#include <qpdf/QUtil.hh>
+
+QPDFExc::QPDFExc(std::string const& message) :
+ QEXC::General(message)
+{
+}
+
+QPDFExc::QPDFExc(std::string const& filename, int offset,
+ std::string const& message) :
+ QEXC::General(filename + ": offset " + QUtil::int_to_string(offset) +
+ ": " + message)
+{
+}
+
+QPDFExc::~QPDFExc() throw ()
+{
+}
diff --git a/libqpdf/QPDFObject.cc b/libqpdf/QPDFObject.cc
new file mode 100644
index 00000000..6c4963e2
--- /dev/null
+++ b/libqpdf/QPDFObject.cc
@@ -0,0 +1,2 @@
+
+#include <qpdf/QPDFObject.hh>
diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc
new file mode 100644
index 00000000..9fba7b43
--- /dev/null
+++ b/libqpdf/QPDFObjectHandle.cc
@@ -0,0 +1,637 @@
+
+#include <qpdf/QPDFObjectHandle.hh>
+
+#include <qpdf/QPDF.hh>
+#include <qpdf/QPDF_Bool.hh>
+#include <qpdf/QPDF_Null.hh>
+#include <qpdf/QPDF_Integer.hh>
+#include <qpdf/QPDF_Real.hh>
+#include <qpdf/QPDF_Name.hh>
+#include <qpdf/QPDF_String.hh>
+#include <qpdf/QPDF_Array.hh>
+#include <qpdf/QPDF_Dictionary.hh>
+#include <qpdf/QPDF_Stream.hh>
+
+#include <qpdf/QTC.hh>
+#include <qpdf/QEXC.hh>
+#include <qpdf/QUtil.hh>
+
+QPDFObjectHandle::QPDFObjectHandle() :
+ initialized(false),
+ objid(0),
+ generation(0)
+{
+}
+
+QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, int objid, int generation) :
+ initialized(true),
+ qpdf(qpdf),
+ objid(objid),
+ generation(generation)
+{
+}
+
+QPDFObjectHandle::QPDFObjectHandle(QPDFObject* data) :
+ initialized(true),
+ qpdf(0),
+ objid(0),
+ generation(0),
+ obj(data)
+{
+}
+
+bool
+QPDFObjectHandle::isInitialized() const
+{
+ return this->initialized;
+}
+
+template <class T>
+class QPDFObjectTypeAccessor
+{
+ public:
+ static bool check(QPDFObject* o)
+ {
+ return (o && dynamic_cast<T*>(o));
+ }
+};
+
+bool
+QPDFObjectHandle::isBool()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Bool>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isNull()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Null>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isInteger()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Integer>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isReal()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Real>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isNumber()
+{
+ return (isInteger() || isReal());
+}
+
+double
+QPDFObjectHandle::getNumericValue()
+{
+ double result = 0.0;
+ if (isInteger())
+ {
+ result = getIntValue();
+ }
+ else if (isReal())
+ {
+ result = atof(getRealValue().c_str());
+ }
+ else
+ {
+ throw QEXC::Internal("getNumericValue called for non-numeric object");
+ }
+ return result;
+}
+
+bool
+QPDFObjectHandle::isName()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Name>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isString()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_String>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isArray()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Array>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isDictionary()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Dictionary>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isStream()
+{
+ dereference();
+ return QPDFObjectTypeAccessor<QPDF_Stream>::check(obj.getPointer());
+}
+
+bool
+QPDFObjectHandle::isIndirect()
+{
+ assertInitialized();
+ return (this->objid != 0);
+}
+
+bool
+QPDFObjectHandle::isScalar()
+{
+ return (! (isArray() || isDictionary() || isStream()));
+}
+
+// Bool accessors
+
+bool
+QPDFObjectHandle::getBoolValue()
+{
+ assertType("Boolean", isBool());
+ return dynamic_cast<QPDF_Bool*>(obj.getPointer())->getVal();
+}
+
+// Integer accessors
+
+int
+QPDFObjectHandle::getIntValue()
+{
+ assertType("Integer", isInteger());
+ return dynamic_cast<QPDF_Integer*>(obj.getPointer())->getVal();
+}
+
+// Real accessors
+
+std::string
+QPDFObjectHandle::getRealValue()
+{
+ assertType("Real", isReal());
+ return dynamic_cast<QPDF_Real*>(obj.getPointer())->getVal();
+}
+
+// Name acessors
+
+std::string
+QPDFObjectHandle::getName()
+{
+ assertType("Name", isName());
+ return dynamic_cast<QPDF_Name*>(obj.getPointer())->getName();
+}
+
+// String accessors
+
+std::string
+QPDFObjectHandle::getStringValue()
+{
+ assertType("String", isString());
+ return dynamic_cast<QPDF_String*>(obj.getPointer())->getVal();
+}
+
+std::string
+QPDFObjectHandle::getUTF8Value()
+{
+ assertType("String", isString());
+ return dynamic_cast<QPDF_String*>(obj.getPointer())->getUTF8Val();
+}
+
+// Array acessors
+
+int
+QPDFObjectHandle::getArrayNItems()
+{
+ assertType("Array", isArray());
+ return dynamic_cast<QPDF_Array*>(obj.getPointer())->getNItems();
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::getArrayItem(int n)
+{
+ assertType("Array", isArray());
+ return dynamic_cast<QPDF_Array*>(obj.getPointer())->getItem(n);
+}
+
+// Array mutators
+
+void
+QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item)
+{
+ assertType("Array", isArray());
+ return dynamic_cast<QPDF_Array*>(obj.getPointer())->setItem(n, item);
+}
+
+// Dictionary accesors
+
+bool
+QPDFObjectHandle::hasKey(std::string const& key)
+{
+ assertType("Dictionary", isDictionary());
+ return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->hasKey(key);
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::getKey(std::string const& key)
+{
+ assertType("Dictionary", isDictionary());
+ return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->getKey(key);
+}
+
+std::set<std::string>
+QPDFObjectHandle::getKeys()
+{
+ assertType("Dictionary", isDictionary());
+ return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->getKeys();
+}
+
+// Dictionary mutators
+
+void
+QPDFObjectHandle::replaceKey(std::string const& key,
+ QPDFObjectHandle const& value)
+{
+ assertType("Dictionary", isDictionary());
+ return dynamic_cast<QPDF_Dictionary*>(
+ obj.getPointer())->replaceKey(key, value);
+}
+
+void
+QPDFObjectHandle::removeKey(std::string const& key)
+{
+ assertType("Dictionary", isDictionary());
+ return dynamic_cast<QPDF_Dictionary*>(obj.getPointer())->removeKey(key);
+}
+
+// Stream accessors
+QPDFObjectHandle
+QPDFObjectHandle::getDict()
+{
+ assertType("Stream", isStream());
+ return dynamic_cast<QPDF_Stream*>(obj.getPointer())->getDict();
+}
+
+PointerHolder<Buffer>
+QPDFObjectHandle::getStreamData()
+{
+ assertType("Stream", isStream());
+ return dynamic_cast<QPDF_Stream*>(obj.getPointer())->getStreamData();
+}
+
+bool
+QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter,
+ bool normalize, bool compress)
+{
+ assertType("Stream", isStream());
+ return dynamic_cast<QPDF_Stream*>(obj.getPointer())->pipeStreamData(
+ p, filter, normalize, compress);
+}
+
+int
+QPDFObjectHandle::getObjectID() const
+{
+ return this->objid;
+}
+
+int
+QPDFObjectHandle::getGeneration() const
+{
+ return this->generation;
+}
+
+std::map<std::string, QPDFObjectHandle>
+QPDFObjectHandle::getPageImages()
+{
+ assertPageObject();
+
+ // Note: this code doesn't handle inherited resources. If this
+ // page dictionary doesn't have a /Resources key or has one whose
+ // value is null or an empty dictionary, you are supposed to walk
+ // up the page tree until you find a /Resources dictionary. As of
+ // this writing, I don't have any test files that use inherited
+ // resources, and hand-generating one won't be a good test beacuse
+ // any mistakes in my understanding would be present in both the
+ // code and the test file.
+
+ // NOTE: If support of inherited resources (see above comment) is
+ // implemented, edit comment in QPDFObjectHandle.hh for this
+ // function.
+
+ std::map<std::string, QPDFObjectHandle> result;
+ if (this->hasKey("/Resources"))
+ {
+ QPDFObjectHandle resources = this->getKey("/Resources");
+ if (resources.hasKey("/XObject"))
+ {
+ QPDFObjectHandle xobject = resources.getKey("/XObject");
+ std::set<std::string> keys = xobject.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string key = (*iter);
+ QPDFObjectHandle value = xobject.getKey(key);
+ if (value.isStream())
+ {
+ QPDFObjectHandle dict = value.getDict();
+ if (dict.hasKey("/Subtype") &&
+ (dict.getKey("/Subtype").getName() == "/Image") &&
+ (! dict.hasKey("/ImageMask")))
+ {
+ result[key] = value;
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+std::vector<QPDFObjectHandle>
+QPDFObjectHandle::getPageContents()
+{
+ assertPageObject();
+
+ std::vector<QPDFObjectHandle> result;
+ QPDFObjectHandle contents = this->getKey("/Contents");
+ if (contents.isArray())
+ {
+ int n_items = contents.getArrayNItems();
+ for (int i = 0; i < n_items; ++i)
+ {
+ QPDFObjectHandle item = contents.getArrayItem(i);
+ if (item.isStream())
+ {
+ result.push_back(item);
+ }
+ else
+ {
+ throw QEXC::General("unknown item type while inspecting "
+ "element of /Contents array in page "
+ "dictionary");
+ }
+ }
+ }
+ else if (contents.isStream())
+ {
+ result.push_back(contents);
+ }
+ else
+ {
+ throw QEXC::General("unknown object type inspecting /Contents "
+ "key in page dictionary");
+ }
+
+ return result;
+}
+
+std::string
+QPDFObjectHandle::unparse()
+{
+ std::string result;
+ if (this->isIndirect())
+ {
+ result = QUtil::int_to_string(this->objid) + " " +
+ QUtil::int_to_string(this->generation) + " R";
+ }
+ else
+ {
+ result = unparseResolved();
+ }
+ return result;
+}
+
+std::string
+QPDFObjectHandle::unparseResolved()
+{
+ dereference();
+ return this->obj.getPointer()->unparse();
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation)
+{
+ return QPDFObjectHandle(qpdf, objid, generation);
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newBool(bool value)
+{
+ return QPDFObjectHandle(new QPDF_Bool(value));
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newNull()
+{
+ return QPDFObjectHandle(new QPDF_Null());
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newInteger(int value)
+{
+ return QPDFObjectHandle(new QPDF_Integer(value));
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newReal(std::string const& value)
+{
+ return QPDFObjectHandle(new QPDF_Real(value));
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newName(std::string const& name)
+{
+ return QPDFObjectHandle(new QPDF_Name(name));
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newString(std::string const& str)
+{
+ return QPDFObjectHandle(new QPDF_String(str));
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items)
+{
+ return QPDFObjectHandle(new QPDF_Array(items));
+}
+
+QPDFObjectHandle
+QPDFObjectHandle::newDictionary(
+ std::map<std::string, QPDFObjectHandle> const& items)
+{
+ return QPDFObjectHandle(new QPDF_Dictionary(items));
+}
+
+
+QPDFObjectHandle
+QPDFObjectHandle::newStream(QPDF* qpdf, int objid, int generation,
+ QPDFObjectHandle stream_dict,
+ off_t offset, int length)
+{
+ return QPDFObjectHandle(new QPDF_Stream(
+ qpdf, objid, generation,
+ stream_dict, offset, length));
+}
+
+void
+QPDFObjectHandle::makeDirectInternal(std::set<int>& visited)
+{
+ assertInitialized();
+
+ if (isStream())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle ERR clone stream");
+ throw QEXC::General("attempt to make a stream into a direct object");
+ }
+
+ int cur_objid = this->objid;
+ if (cur_objid != 0)
+ {
+ if (visited.count(cur_objid))
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle makeDirect loop");
+ throw QEXC::General("loop detected while converting object from "
+ "indirect to direct");
+ }
+ visited.insert(cur_objid);
+ }
+
+ dereference();
+ this->objid = 0;
+ this->generation = 0;
+
+ QPDFObject* new_obj = 0;
+
+ if (isBool())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone bool");
+ new_obj = new QPDF_Bool(getBoolValue());
+ }
+ else if (isNull())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone null");
+ new_obj = new QPDF_Null();
+ }
+ else if (isInteger())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone integer");
+ new_obj = new QPDF_Integer(getIntValue());
+ }
+ else if (isReal())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone real");
+ new_obj = new QPDF_Real(getRealValue());
+ }
+ else if (isName())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone name");
+ new_obj = new QPDF_Name(getName());
+ }
+ else if (isString())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone string");
+ new_obj = new QPDF_String(getStringValue());
+ }
+ else if (isArray())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone array");
+ std::vector<QPDFObjectHandle> items;
+ int n = getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ items.push_back(getArrayItem(i));
+ items.back().makeDirectInternal(visited);
+ }
+ new_obj = new QPDF_Array(items);
+ }
+ else if (isDictionary())
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle clone dictionary");
+ std::set<std::string> keys = getKeys();
+ std::map<std::string, QPDFObjectHandle> items;
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ items[*iter] = getKey(*iter);
+ items[*iter].makeDirectInternal(visited);
+ }
+ new_obj = new QPDF_Dictionary(items);
+ }
+ else
+ {
+ throw QEXC::Internal("QPDFObjectHandle::makeIndirect: "
+ "unknown object type");
+ }
+
+ this->obj = new_obj;
+
+ if (cur_objid)
+ {
+ visited.erase(cur_objid);
+ }
+}
+
+void
+QPDFObjectHandle::makeDirect()
+{
+ std::set<int> visited;
+ makeDirectInternal(visited);
+}
+
+void
+QPDFObjectHandle::assertInitialized() const
+{
+ if (! this->initialized)
+ {
+ throw QEXC::Internal("operation attempted on uninitialized "
+ "QPDFObjectHandle");
+ }
+}
+
+void
+QPDFObjectHandle::assertType(char const* type_name, bool istype)
+{
+ if (! istype)
+ {
+ throw QEXC::Internal(std::string("operation for ") + type_name +
+ " object attempted on object of wrong type");
+ }
+}
+
+void
+QPDFObjectHandle::assertPageObject()
+{
+ if (! (this->isDictionary() && this->hasKey("/Type") &&
+ (this->getKey("/Type").getName() == "/Page")))
+ {
+ throw QEXC::Internal("page operation called on non-Page object");
+ }
+}
+
+void
+QPDFObjectHandle::dereference()
+{
+ if (this->obj.getPointer() == 0)
+ {
+ this->obj = QPDF::Resolver::resolve(
+ this->qpdf, this->objid, this->generation);
+ if (this->obj.getPointer() == 0)
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle indirect to unknown");
+ this->obj = new QPDF_Null();
+ }
+ }
+}
diff --git a/libqpdf/QPDFTokenizer.cc b/libqpdf/QPDFTokenizer.cc
new file mode 100644
index 00000000..4eed6f16
--- /dev/null
+++ b/libqpdf/QPDFTokenizer.cc
@@ -0,0 +1,458 @@
+
+#include <qpdf/QPDFTokenizer.hh>
+
+// DO NOT USE ctype -- it is locale dependent for some things, and
+// it's not worth the risk of including it in case it may accidentally
+// be used.
+
+#include <qpdf/PCRE.hh>
+#include <qpdf/QEXC.hh>
+#include <qpdf/QTC.hh>
+
+// See note above about ctype.
+static bool is_hex_digit(char ch)
+{
+ return (strchr("0123456789abcdefABCDEF", ch) != 0);
+}
+
+QPDFTokenizer::QPDFTokenizer() :
+ pound_special_in_name(true)
+{
+ reset();
+}
+
+void
+QPDFTokenizer::allowPoundAnywhereInName()
+{
+ QTC::TC("qpdf", "QPDFTokenizer allow pound anywhere in name");
+ this->pound_special_in_name = false;
+}
+
+void
+QPDFTokenizer::reset()
+{
+ state = st_top;
+ type = tt_bad;
+ val = "";
+ raw_val = "";
+ error_message = "";
+ unread_char = false;
+ char_to_unread = '\0';
+ string_depth = 0;
+ string_ignoring_newline = false;
+ last_char_was_bs = false;
+}
+
+void
+QPDFTokenizer::presentCharacter(char ch)
+{
+ static PCRE num_re("^[\\+\\-]?(?:\\.\\d+|\\d+(?:\\.\\d+)?)$");
+
+ if (state == st_token_ready)
+ {
+ throw QEXC::Internal("QPDF tokenizer presented character "
+ "while token is waiting");
+ }
+
+ char orig_ch = ch;
+
+ // State machine is implemented such that some characters may be
+ // handled more than once. This happens whenever you have to use
+ // the character that caused a state change in the new state.
+
+ bool handled = true;
+ if (state == st_top)
+ {
+ // Note: we specifically do not use ctype here. It is
+ // locale-dependent.
+ if (strchr(" \t\n\v\f\r", ch))
+ {
+ // ignore
+ }
+ else if (ch == '%')
+ {
+ // Discard comments
+ state = st_in_comment;
+ }
+ else if (ch == '(')
+ {
+ string_depth = 1;
+ string_ignoring_newline = false;
+ memset(bs_num_register, '\0', sizeof(bs_num_register));
+ last_char_was_bs = false;
+ state = st_in_string;
+ }
+ else if (ch == '<')
+ {
+ state = st_lt;
+ }
+ else if (ch == '>')
+ {
+ state = st_gt;
+ }
+ else
+ {
+ val += ch;
+ if (ch == ')')
+ {
+ type = tt_bad;
+ QTC::TC("qpdf", "QPDF_Tokenizer bad )");
+ error_message = "unexpected )";
+ state = st_token_ready;
+ }
+ else if (ch == '[')
+ {
+ type = tt_array_open;
+ state = st_token_ready;
+ }
+ else if (ch == ']')
+ {
+ type = tt_array_close;
+ state = st_token_ready;
+ }
+ else if (ch == '{')
+ {
+ type = tt_brace_open;
+ state = st_token_ready;
+ }
+ else if (ch == '}')
+ {
+ type = tt_brace_close;
+ state = st_token_ready;
+ }
+ else
+ {
+ state = st_literal;
+ }
+ }
+ }
+ else if (state == st_in_comment)
+ {
+ if ((ch == '\r') || (ch == '\n'))
+ {
+ state = st_top;
+ }
+ }
+ else if (state == st_lt)
+ {
+ if (ch == '<')
+ {
+ val = "<<";
+ type = tt_dict_open;
+ state = st_token_ready;
+ }
+ else
+ {
+ handled = false;
+ state = st_in_hexstring;
+ }
+ }
+ else if (state == st_gt)
+ {
+ if (ch == '>')
+ {
+ val = ">>";
+ type = tt_dict_close;
+ state = st_token_ready;
+ }
+ else
+ {
+ val = ">";
+ type = tt_bad;
+ QTC::TC("qpdf", "QPDF_Tokenizer bad >");
+ error_message = "unexpected >";
+ unread_char = true;
+ char_to_unread = ch;
+ state = st_token_ready;
+ }
+ }
+ else if (state == st_in_string)
+ {
+ if (string_ignoring_newline && (! ((ch == '\r') || (ch == '\n'))))
+ {
+ string_ignoring_newline = false;
+ }
+
+ unsigned int bs_num_count = strlen(bs_num_register);
+ bool ch_is_octal = ((ch >= '0') && (ch <= '7'));
+ if ((bs_num_count == 3) || ((bs_num_count > 0) && (! ch_is_octal)))
+ {
+ // We've accumulated \ddd. PDF Spec says to ignore
+ // high-order overflow.
+ val += (char) strtol(bs_num_register, 0, 8);
+ memset(bs_num_register, '\0', sizeof(bs_num_register));
+ bs_num_count = 0;
+ }
+
+ if (string_ignoring_newline && ((ch == '\r') || (ch == '\n')))
+ {
+ // ignore
+ }
+ else if (ch_is_octal && (last_char_was_bs || (bs_num_count > 0)))
+ {
+ bs_num_register[bs_num_count++] = ch;
+ }
+ else if (last_char_was_bs)
+ {
+ switch (ch)
+ {
+ case 'n':
+ val += '\n';
+ break;
+
+ case 'r':
+ val += '\r';
+ break;
+
+ case 't':
+ val += '\t';
+ break;
+
+ case 'b':
+ val += '\b';
+ break;
+
+ case 'f':
+ val += '\f';
+ break;
+
+ case '\r':
+ case '\n':
+ string_ignoring_newline = true;
+ break;
+
+ default:
+ // PDF spec says backslash is ignored before anything else
+ val += ch;
+ break;
+ }
+ }
+ else if (ch == '\\')
+ {
+ // last_char_was_bs is set/cleared below as appropriate
+ if (bs_num_count)
+ {
+ throw QEXC::Internal("QPDFTokenizer: bs_num_count != 0 "
+ "when ch == '\\'");
+ }
+ }
+ else if (ch == '(')
+ {
+ val += ch;
+ ++string_depth;
+ }
+ else if ((ch == ')') && (--string_depth == 0))
+ {
+ type = tt_string;
+ state = st_token_ready;
+ }
+ else
+ {
+ val += ch;
+ }
+
+ last_char_was_bs = ((! last_char_was_bs) && (ch == '\\'));
+ }
+ else if (state == st_literal)
+ {
+ if (strchr(" \t\n\v\f\r()<>[]{}/%", ch) != 0)
+ {
+ // A C-loacle whitespace character or delimiter terminates
+ // token. It is important to unread the whitespace
+ // character even though it is ignored since it may be the
+ // newline after a stream keyword. Removing it here could
+ // make the stream-reading code break on some files,
+ // though not on any files in the test suite as of this
+ // writing.
+
+ type = tt_word;
+ unread_char = true;
+ char_to_unread = ch;
+ state = st_token_ready;
+ }
+ else
+ {
+ val += ch;
+ }
+ }
+ else
+ {
+ handled = false;
+ }
+
+
+ if (handled)
+ {
+ // okay
+ }
+ else if (state == st_in_hexstring)
+ {
+ if (ch == '>')
+ {
+ type = tt_string;
+ state = st_token_ready;
+ if (val.length() % 2)
+ {
+ // PDF spec says odd hexstrings have implicit
+ // trailing 0.
+ val += '0';
+ }
+ char num[3];
+ num[2] = '\0';
+ std::string nval;
+ for (unsigned int i = 0; i < val.length(); i += 2)
+ {
+ num[0] = val[i];
+ num[1] = val[i+1];
+ char nch = (char)(strtol(num, 0, 16));
+ nval += nch;
+ }
+ val = nval;
+ }
+ else if (is_hex_digit(ch))
+ {
+ val += ch;
+ }
+ else if (strchr(" \t\n\v\f\r", ch))
+ {
+ // ignore
+ }
+ else
+ {
+ type = tt_bad;
+ QTC::TC("qpdf", "QPDF_Tokenizer bad (");
+ error_message = std::string("invalid character (") +
+ ch + ") in hexstring";
+ state = st_token_ready;
+ }
+ }
+ else
+ {
+ throw QEXC::Internal("invalid state while reading token");
+ }
+
+ if ((state == st_token_ready) && (type == tt_word))
+ {
+ if ((val.length() > 0) && (val[0] == '/'))
+ {
+ type = tt_name;
+ // Deal with # in name token. Note: '/' by itself is a
+ // valid name, so don't strip leading /. That way we
+ // don't have to deal with the empty string as a name.
+ std::string nval = "/";
+ char const* valstr = val.c_str() + 1;
+ for (char const* p = valstr; *p; ++p)
+ {
+ if ((*p == '#') && this->pound_special_in_name)
+ {
+ if (p[1] && p[2] &&
+ is_hex_digit(p[1]) && is_hex_digit(p[2]))
+ {
+ char num[3];
+ num[0] = p[1];
+ num[1] = p[2];
+ num[2] = '\0';
+ char ch = (char)(strtol(num, 0, 16));
+ if (ch == '\0')
+ {
+ type = tt_bad;
+ QTC::TC("qpdf", "QPDF_Tokenizer null in name");
+ error_message =
+ "null character not allowed in name token";
+ nval += "#00";
+ }
+ else
+ {
+ nval += ch;
+ }
+ p += 2;
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF_Tokenizer bad name");
+ type = tt_bad;
+ error_message = "invalid name token";
+ nval += *p;
+ }
+ }
+ else
+ {
+ nval += *p;
+ }
+ }
+ val = nval;
+ }
+ else if (num_re.match(val.c_str()))
+ {
+ if (val.find('.') != std::string::npos)
+ {
+ type = tt_real;
+ }
+ else
+ {
+ type = tt_integer;
+ }
+ }
+ else if ((val == "true") || (val == "false"))
+ {
+ type = tt_bool;
+ }
+ else if (val == "null")
+ {
+ type = tt_null;
+ }
+ else
+ {
+ // I don't really know what it is, so leave it as tt_word.
+ // Lots of cases ($, #, etc.) other than actual words fall
+ // into this category, but that's okay at least for now.
+ type = tt_word;
+ }
+ }
+
+ if (! (betweenTokens() || ((state == st_token_ready) && unread_char)))
+ {
+ this->raw_val += orig_ch;
+ }
+}
+
+void
+QPDFTokenizer::presentEOF()
+{
+ switch (state)
+ {
+ case st_token_ready:
+ case st_top:
+ // okay
+ break;
+
+ case st_in_comment:
+ state = st_top;
+ break;
+
+ default:
+ type = tt_bad;
+ error_message = "EOF while reading token";
+ state = st_token_ready;
+ }
+}
+
+bool
+QPDFTokenizer::getToken(Token& token, bool& unread_char, char& ch)
+{
+ bool ready = (this->state == st_token_ready);
+ unread_char = this->unread_char;
+ ch = this->char_to_unread;
+ if (ready)
+ {
+ token = Token(type, val, raw_val, error_message);
+ reset();
+ }
+ return ready;
+}
+
+bool
+QPDFTokenizer::betweenTokens()
+{
+ return ((state == st_top) || (state == st_in_comment));
+}
diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc
new file mode 100644
index 00000000..0a611eb9
--- /dev/null
+++ b/libqpdf/QPDFWriter.cc
@@ -0,0 +1,2021 @@
+
+#include <qpdf/QPDFWriter.hh>
+
+#include <assert.h>
+#include <qpdf/Pl_StdioFile.hh>
+#include <qpdf/Pl_Count.hh>
+#include <qpdf/Pl_Discard.hh>
+#include <qpdf/Pl_Buffer.hh>
+#include <qpdf/Pl_RC4.hh>
+#include <qpdf/Pl_Flate.hh>
+#include <qpdf/Pl_PNGFilter.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/MD5.hh>
+#include <qpdf/RC4.hh>
+#include <qpdf/QTC.hh>
+
+#include <qpdf/QPDF.hh>
+#include <qpdf/QPDFObjectHandle.hh>
+#include <qpdf/QPDF_Name.hh>
+#include <qpdf/QPDF_String.hh>
+
+QPDFWriter::QPDFWriter(QPDF& pdf, char const* filename) :
+ pdf(pdf),
+ filename(filename),
+ file(0),
+ close_file(false),
+ normalize_content_set(false),
+ normalize_content(false),
+ stream_data_mode_set(false),
+ stream_data_mode(s_compress),
+ qdf_mode(false),
+ static_id(false),
+ direct_stream_lengths(true),
+ encrypted(false),
+ preserve_encryption(true),
+ linearized(false),
+ object_stream_mode(o_preserve),
+ encryption_dict_objid(0),
+ next_objid(1),
+ cur_stream_length_id(0),
+ cur_stream_length(0),
+ added_newline(false),
+ max_ostream_index(0)
+{
+ if (filename == 0)
+ {
+ this->filename = "standard output";
+ QTC::TC("qpdf", "QPDFWriter write to stdout");
+ file = stdout;
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDFWriter write to file");
+ file = QUtil::fopen_wrapper(std::string("open ") + filename,
+ fopen(filename, "wb+"));
+ close_file = true;
+ }
+ Pipeline* p = new Pl_StdioFile("qdf output", file);
+ to_delete.push_back(p);
+ pipeline = new Pl_Count("qdf count", p);
+ to_delete.push_back(pipeline);
+ pipeline_stack.push_back(pipeline);
+}
+
+QPDFWriter::~QPDFWriter()
+{
+ if (file)
+ {
+ fclose(file);
+ }
+}
+
+void
+QPDFWriter::setObjectStreamMode(object_stream_e mode)
+{
+ this->object_stream_mode = mode;
+}
+
+void
+QPDFWriter::setStreamDataMode(stream_data_e mode)
+{
+ this->stream_data_mode_set = true;
+ this->stream_data_mode = mode;
+}
+
+void
+QPDFWriter::setContentNormalization(bool val)
+{
+ this->normalize_content_set = true;
+ this->normalize_content = val;
+}
+
+void
+QPDFWriter::setQDFMode(bool val)
+{
+ this->qdf_mode = val;
+}
+
+void
+QPDFWriter::setStaticID(bool val)
+{
+ this->static_id = val;
+}
+
+void
+QPDFWriter::setPreserveEncryption(bool val)
+{
+ this->preserve_encryption = val;
+}
+
+void
+QPDFWriter::setLinearization(bool val)
+{
+ this->linearized = val;
+}
+
+void
+QPDFWriter::setR2EncryptionParameters(
+ char const* user_password, char const* owner_password,
+ bool allow_print, bool allow_modify,
+ bool allow_extract, bool allow_annotate)
+{
+ std::set<int> clear;
+ if (! allow_print)
+ {
+ clear.insert(3);
+ }
+ if (! allow_modify)
+ {
+ clear.insert(4);
+ }
+ if (! allow_extract)
+ {
+ clear.insert(5);
+ }
+ if (! allow_annotate)
+ {
+ clear.insert(6);
+ }
+
+ this->min_pdf_version = "1.3";
+ setEncryptionParameters(user_password, owner_password, 1, 2, 5, clear);
+}
+
+void
+QPDFWriter::setR3EncryptionParameters(
+ char const* user_password, char const* owner_password,
+ bool allow_accessibility, bool allow_extract,
+ r3_print_e print, r3_modify_e modify)
+{
+ // Acrobat 5 security options:
+
+ // Checkboxes:
+ // Enable Content Access for the Visually Impaired
+ // Allow Content Copying and Extraction
+
+ // Allowed changes menu:
+ // None
+ // Only Document Assembly
+ // Only Form Field Fill-in or Signing
+ // Comment AUthoring, Form Field Fill-in or Signing
+ // General Editing, Comment and Form Field Authoring
+
+ // Allowed printing menu:
+ // None
+ // Low Resolution
+ // Full printing
+
+ std::set<int> clear;
+ if (! allow_accessibility)
+ {
+ clear.insert(10);
+ }
+ if (! allow_extract)
+ {
+ clear.insert(5);
+ }
+
+ // Note: these switch statements all "fall through" (no break
+ // statements). Each option clears successively more access bits.
+ switch (print)
+ {
+ case r3p_none:
+ clear.insert(3); // any printing
+
+ case r3p_low:
+ clear.insert(12); // high resolution printing
+
+ case r3p_full:
+ break;
+
+ // no default so gcc warns for missing cases
+ }
+
+ switch (modify)
+ {
+ case r3m_none:
+ clear.insert(11); // document essembly
+
+ case r3m_assembly:
+ clear.insert(9); // filling in form fields
+
+ case r3m_form:
+ clear.insert(6); // modify annotations, fill in form fields
+
+ case r3m_annotate:
+ clear.insert(4); // other modifications
+
+ case r3m_all:
+ break;
+
+ // no default so gcc warns for missing cases
+ }
+
+ this->min_pdf_version = "1.4";
+ setEncryptionParameters(user_password, owner_password, 2, 3, 16, clear);
+}
+
+void
+QPDFWriter::setEncryptionParameters(
+ char const* user_password, char const* owner_password,
+ int V, int R, int key_len, std::set<int>& bits_to_clear)
+{
+ // PDF specification refers to bits with the low bit numbered 1.
+ // We have to convert this into a bit field.
+
+ // Specification always requirse bits 1 and 2 to be cleared.
+ bits_to_clear.insert(1);
+ bits_to_clear.insert(2);
+
+ unsigned long P = 0;
+ // Create the complement of P, then invert.
+ for (std::set<int>::iterator iter = bits_to_clear.begin();
+ iter != bits_to_clear.end(); ++iter)
+ {
+ P |= (1 << (*iter) - 1);
+ }
+ P = ~P;
+
+ generateID();
+ std::string O;
+ std::string U;
+ QPDF::compute_encryption_O_U(
+ user_password, owner_password, V, R, key_len, P, this->id1, O, U);
+ setEncryptionParametersInternal(
+ V, R, key_len, P, O, U, this->id1, user_password);
+}
+
+void
+QPDFWriter::copyEncryptionParameters()
+{
+ generateID();
+ QPDFObjectHandle trailer = this->pdf.getTrailer();
+ if (trailer.hasKey("/Encrypt"))
+ {
+ QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
+ int V = encrypt.getKey("/V").getIntValue();
+ int key_len = 5;
+ if (V > 1)
+ {
+ key_len = encrypt.getKey("/Length").getIntValue() / 8;
+ }
+ setEncryptionParametersInternal(
+ V,
+ encrypt.getKey("/R").getIntValue(),
+ key_len,
+ encrypt.getKey("/P").getIntValue(),
+ encrypt.getKey("/O").getStringValue(),
+ encrypt.getKey("/U").getStringValue(),
+ this->id1, // this->id1 == the other file's id1
+ pdf.getUserPassword());
+ }
+}
+
+void
+QPDFWriter::setEncryptionParametersInternal(
+ int V, int R, int key_len, long P,
+ std::string const& O, std::string const& U,
+ std::string const& id1, std::string const& user_password)
+{
+ encryption_dictionary["/Filter"] = "/Standard";
+ encryption_dictionary["/V"] = QUtil::int_to_string(V);
+ encryption_dictionary["/Length"] = QUtil::int_to_string(key_len * 8);
+ encryption_dictionary["/R"] = QUtil::int_to_string(R);
+ encryption_dictionary["/P"] = QUtil::int_to_string(P);
+ encryption_dictionary["/O"] = QPDF_String(O).unparse(true);
+ encryption_dictionary["/U"] = QPDF_String(U).unparse(true);
+ this->encrypted = true;
+ QPDF::EncryptionData encryption_data(V, R, key_len, P, O, U, this->id1);
+ this->encryption_key = QPDF::compute_encryption_key(
+ user_password, encryption_data);
+}
+
+void
+QPDFWriter::setDataKey(int objid)
+{
+ this->cur_data_key = QPDF::compute_data_key(
+ this->encryption_key, objid, 0);
+}
+
+int
+QPDFWriter::bytesNeeded(unsigned long n)
+{
+ int bytes = 0;
+ while (n)
+ {
+ ++bytes;
+ n >>= 8;
+ }
+ return bytes;
+}
+
+void
+QPDFWriter::writeBinary(unsigned long val, unsigned int bytes)
+{
+ assert(bytes <= sizeof(unsigned long));
+ unsigned char data[sizeof(unsigned long)];
+ for (unsigned int i = 0; i < bytes; ++i)
+ {
+ data[bytes - i - 1] = (unsigned char)(val & 0xff);
+ val >>= 8;
+ }
+ this->pipeline->write(data, bytes);
+}
+
+void
+QPDFWriter::writeString(std::string const& str)
+{
+ this->pipeline->write((unsigned char*)str.c_str(), str.length());
+}
+
+void
+QPDFWriter::writeBuffer(PointerHolder<Buffer>& b)
+{
+ this->pipeline->write(b.getPointer()->getBuffer(),
+ b.getPointer()->getSize());
+}
+
+void
+QPDFWriter::writeStringQDF(std::string const& str)
+{
+ if (this->qdf_mode)
+ {
+ writeString(str);
+ }
+}
+
+void
+QPDFWriter::writeStringNoQDF(std::string const& str)
+{
+ if (! this->qdf_mode)
+ {
+ writeString(str);
+ }
+}
+
+Pipeline*
+QPDFWriter::pushPipeline(Pipeline* p)
+{
+ assert(dynamic_cast<Pl_Count*>(p) == 0);
+ this->pipeline_stack.push_back(p);
+ return p;
+}
+
+void
+QPDFWriter::activatePipelineStack()
+{
+ Pl_Count* c = new Pl_Count("count", this->pipeline_stack.back());
+ this->pipeline_stack.push_back(c);
+ this->pipeline = c;
+}
+
+void
+QPDFWriter::popPipelineStack(PointerHolder<Buffer>* bp)
+{
+ assert(this->pipeline_stack.size() >= 2);
+ this->pipeline->finish();
+ assert(dynamic_cast<Pl_Count*>(this->pipeline_stack.back()) ==
+ this->pipeline);
+ delete this->pipeline_stack.back();
+ this->pipeline_stack.pop_back();
+ while (dynamic_cast<Pl_Count*>(this->pipeline_stack.back()) == 0)
+ {
+ Pipeline* p = this->pipeline_stack.back();
+ this->pipeline_stack.pop_back();
+ Pl_Buffer* buf = dynamic_cast<Pl_Buffer*>(p);
+ if (bp && buf)
+ {
+ *bp = buf->getBuffer();
+ }
+ delete p;
+ }
+ this->pipeline = dynamic_cast<Pl_Count*>(this->pipeline_stack.back());
+}
+
+void
+QPDFWriter::pushEncryptionFilter()
+{
+ if (this->encrypted && (! this->cur_data_key.empty()))
+ {
+ Pipeline* p =
+ new Pl_RC4("stream encryption", this->pipeline,
+ (unsigned char*) this->cur_data_key.c_str(),
+ this->cur_data_key.length());
+ pushPipeline(p);
+ }
+ // Must call this unconditionally so we can call popPipelineStack
+ // to balance pushEncryptionFilter().
+ activatePipelineStack();
+}
+
+void
+QPDFWriter::pushDiscardFilter()
+{
+ pushPipeline(new Pl_Discard());
+ activatePipelineStack();
+}
+
+int
+QPDFWriter::openObject(int objid)
+{
+ if (objid == 0)
+ {
+ objid = this->next_objid++;
+ }
+ this->xref[objid] = QPDFXRefEntry(1, pipeline->getCount(), 0);
+ writeString(QUtil::int_to_string(objid));
+ writeString(" 0 obj\n");
+ return objid;
+}
+
+void
+QPDFWriter::closeObject(int objid)
+{
+ // Write a newline before endobj as it makes the file easier to
+ // repair.
+ writeString("\nendobj\n");
+ writeStringQDF("\n");
+ this->lengths[objid] = pipeline->getCount() - this->xref[objid].getOffset();
+}
+
+void
+QPDFWriter::assignCompressedObjectNumbers(int objid)
+{
+ if (this->object_stream_to_objects.count(objid) == 0)
+ {
+ return;
+ }
+
+ // Reserve numbers for the objects that belong to this object
+ // stream.
+ for (std::set<int>::iterator iter =
+ this->object_stream_to_objects[objid].begin();
+ iter != this->object_stream_to_objects[objid].end();
+ ++iter)
+ {
+ obj_renumber[*iter] = next_objid++;
+ }
+}
+
+void
+QPDFWriter::enqueueObject(QPDFObjectHandle object)
+{
+ if (object.isIndirect())
+ {
+ if (object.isNull())
+ {
+ // This is a place-holder object for an object stream
+ }
+ else if (object.isScalar())
+ {
+ throw QEXC::Internal(
+ "QPDFWriter::enqueueObject: indirect scalar: " +
+ std::string(this->filename) + " " +
+ QUtil::int_to_string(object.getObjectID()) + " " +
+ QUtil::int_to_string(object.getGeneration()));
+ }
+ int objid = object.getObjectID();
+
+ if (obj_renumber.count(objid) == 0)
+ {
+ if (this->object_to_object_stream.count(objid))
+ {
+ // This is in an object stream. Don't process it
+ // here. Instead, enqueue the object stream.
+ int stream_id = this->object_to_object_stream[objid];
+ enqueueObject(this->pdf.getObjectByID(stream_id, 0));
+ }
+ else
+ {
+ object_queue.push_back(object);
+ obj_renumber[objid] = next_objid++;
+
+ if (this->object_stream_to_objects.count(objid))
+ {
+ // For linearized files, uncompressed objects go
+ // at end, and we take care of assigning numbers
+ // to them elsewhere.
+ if (! this->linearized)
+ {
+ assignCompressedObjectNumbers(objid);
+ }
+ }
+ else if ((! this->direct_stream_lengths) && object.isStream())
+ {
+ // reserve next object ID for length
+ ++next_objid;
+ }
+ }
+ }
+ }
+ else if (object.isArray())
+ {
+ int n = object.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ if (! this->linearized)
+ {
+ enqueueObject(object.getArrayItem(i));
+ }
+ }
+ }
+ else if (object.isDictionary())
+ {
+ std::set<std::string> keys = object.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ if (! this->linearized)
+ {
+ enqueueObject(object.getKey(*iter));
+ }
+ }
+ }
+ else
+ {
+ // ignore
+ }
+}
+
+void
+QPDFWriter::unparseChild(QPDFObjectHandle child, int level, int flags)
+{
+ if (! this->linearized)
+ {
+ enqueueObject(child);
+ }
+ if (child.isIndirect())
+ {
+ if (child.isScalar())
+ {
+ throw QEXC::Internal(
+ "QPDFWriter::unparseChild: indirect scalar: " +
+ QUtil::int_to_string(child.getObjectID()) + " " +
+ QUtil::int_to_string(child.getGeneration()));
+ }
+ int old_id = child.getObjectID();
+ int new_id = obj_renumber[old_id];
+ writeString(QUtil::int_to_string(new_id));
+ writeString(" 0 R");
+ }
+ else
+ {
+ unparseObject(child, level, flags);
+ }
+}
+
+void
+QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream, int prev)
+{
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ if (! xref_stream)
+ {
+ writeString("trailer <<");
+ }
+ writeStringQDF("\n");
+ if (which == t_lin_second)
+ {
+ writeString(" /Size ");
+ writeString(QUtil::int_to_string(size));
+ }
+ else
+ {
+ std::set<std::string> keys = trailer.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ writeStringQDF(" ");
+ writeStringNoQDF(" ");
+ writeString(QPDF_Name::normalizeName(key));
+ writeString(" ");
+ if (key == "/Size")
+ {
+ writeString(QUtil::int_to_string(size));
+ if (which == t_lin_first)
+ {
+ writeString(" /Prev ");
+ int pos = this->pipeline->getCount();
+ writeString(QUtil::int_to_string(prev));
+ int nspaces = pos + 11 - this->pipeline->getCount();
+ assert(nspaces >= 0);
+ for (int i = 0; i < nspaces; ++i)
+ {
+ writeString(" ");
+ }
+ }
+ }
+ else
+ {
+ unparseChild(trailer.getKey(key), 1, 0);
+ }
+ writeStringQDF("\n");
+ }
+ }
+
+ // Write ID
+ writeStringQDF(" ");
+ writeString(" /ID [");
+ writeString(QPDF_String(this->id1).unparse(true));
+ writeString(QPDF_String(this->id2).unparse(true));
+ writeString("]");
+
+ if (which != t_lin_second)
+ {
+ // Write reference to encryption dictionary
+ if (this->encrypted)
+ {
+ writeString(" /Encrypt ");
+ writeString(QUtil::int_to_string(this->encryption_dict_objid));
+ writeString(" 0 R");
+ }
+ }
+
+ writeStringQDF("\n");
+ writeStringNoQDF(" ");
+ writeString(">>");
+}
+
+void
+QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
+ unsigned int flags)
+{
+ unparseObject(object, level, flags, 0, false);
+}
+
+void
+QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
+ unsigned int flags, int stream_length, bool compress)
+{
+ unsigned int child_flags = flags & ~f_stream;
+
+ std::string indent;
+ for (int i = 0; i < level; ++i)
+ {
+ indent += " ";
+ }
+
+ if (object.isArray())
+ {
+ // Note: PDF spec 1.4 implementation note 121 states that
+ // Acrobat requires a space after the [ in the /H key of the
+ // linearization parameter dictionary. We'll do this
+ // unconditionally for all arrays because it looks nicer and
+ // doesn't make the files that much bigger.
+ writeString("[");
+ writeStringQDF("\n");
+ int n = object.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ writeStringQDF(indent);
+ writeStringQDF(" ");
+ writeStringNoQDF(" ");
+ unparseChild(object.getArrayItem(i), level + 1, child_flags);
+ writeStringQDF("\n");
+ }
+ writeStringQDF(indent);
+ writeStringNoQDF(" ");
+ writeString("]");
+ }
+ else if (object.isDictionary())
+ {
+ writeString("<<");
+ writeStringQDF("\n");
+ std::set<std::string> keys = object.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ if ((flags & f_filtered) &&
+ ((key == "/Filter") ||
+ (key == "/DecodeParms")))
+ {
+ continue;
+ }
+ if ((flags & f_stream) && (key == "/Length"))
+ {
+ continue;
+ }
+ writeStringQDF(indent);
+ writeStringQDF(" ");
+ writeStringNoQDF(" ");
+ writeString(QPDF_Name::normalizeName(key));
+ writeString(" ");
+ unparseChild(object.getKey(key), level + 1, child_flags);
+ writeStringQDF("\n");
+ }
+
+ if (flags & f_stream)
+ {
+ writeStringQDF(indent);
+ writeStringQDF(" ");
+ writeString(" /Length ");
+
+ if (this->direct_stream_lengths)
+ {
+ writeString(QUtil::int_to_string(stream_length));
+ }
+ else
+ {
+ writeString(
+ QUtil::int_to_string(this->cur_stream_length_id));
+ writeString(" 0 R");
+ }
+ writeStringQDF("\n");
+ if (compress && (flags & f_filtered))
+ {
+ writeStringQDF(indent);
+ writeStringQDF(" ");
+ writeString(" /Filter /FlateDecode");
+ writeStringQDF("\n");
+ }
+ }
+
+ writeStringQDF(indent);
+ writeStringNoQDF(" ");
+ writeString(">>");
+ }
+ else if (object.isStream())
+ {
+ // Write stream data to a buffer.
+ int old_id = object.getObjectID();
+ int new_id = obj_renumber[old_id];
+ if (! this->direct_stream_lengths)
+ {
+ this->cur_stream_length_id = new_id + 1;
+ }
+ QPDFObjectHandle stream_dict = object.getDict();
+
+ bool filter = (this->stream_data_mode != s_preserve);
+ if (this->stream_data_mode == s_compress)
+ {
+ // Don't filter if the stream is already compressed with
+ // FlateDecode. We don't want to make it worse by getting
+ // rid of a predictor or otherwising messing with it. We
+ // should also avoid messing with anything that's
+ // compressed with a lossy compression scheme, but we
+ // don't support any of those right now.
+ QPDFObjectHandle filter_obj = stream_dict.getKey("/Filter");
+ if (filter_obj.isName() && (filter_obj.getName() == "/FlateDecode"))
+ {
+ QTC::TC("qpdf", "QPDFWriter not recompressing /FlateDecode");
+ filter = false;
+ }
+ }
+ bool normalize = false;
+ bool compress = false;
+ if (this->normalize_content && normalized_streams.count(old_id))
+ {
+ normalize = true;
+ filter = true;
+ }
+ else if (filter && (this->stream_data_mode == s_compress))
+ {
+ compress = true;
+ QTC::TC("qpdf", "QPDFWriter compressing uncompressed stream");
+ }
+
+ flags |= f_stream;
+
+ pushPipeline(new Pl_Buffer("stream data"));
+ activatePipelineStack();
+ bool filtered =
+ object.pipeStreamData(this->pipeline, filter, normalize, compress);
+ PointerHolder<Buffer> stream_data;
+ popPipelineStack(&stream_data);
+ if (filtered)
+ {
+ flags |= f_filtered;
+ }
+ else
+ {
+ compress = false;
+ }
+
+ this->cur_stream_length = stream_data.getPointer()->getSize();
+ unparseObject(stream_dict, 0, flags, this->cur_stream_length, compress);
+ writeString("\nstream\n");
+ pushEncryptionFilter();
+ writeBuffer(stream_data);
+ popPipelineStack();
+
+ if (this->qdf_mode)
+ {
+ if (this->pipeline->getLastChar() != '\n')
+ {
+ writeString("\n");
+ this->added_newline = true;
+ }
+ else
+ {
+ this->added_newline = false;
+ }
+ }
+ writeString("endstream");
+ }
+ else if (object.isString())
+ {
+ std::string val;
+ if (this->encrypted &&
+ (! (flags & f_in_ostream)) &&
+ (! this->cur_data_key.empty()))
+ {
+ val = object.getStringValue();
+ char* tmp = QUtil::copy_string(val);
+ unsigned int vlen = val.length();
+ RC4 rc4((unsigned char const*)this->cur_data_key.c_str(),
+ this->cur_data_key.length());
+ rc4.process((unsigned char*)tmp, vlen);
+ val = QPDF_String(std::string(tmp, vlen)).unparse();
+ delete [] tmp;
+ }
+ else
+ {
+ val = object.unparseResolved();
+ }
+ writeString(val);
+ }
+ else
+ {
+ writeString(object.unparseResolved());
+ }
+}
+
+void
+QPDFWriter::writeObjectStreamOffsets(std::vector<int>& offsets,
+ int first_obj)
+{
+ for (unsigned int i = 0; i < offsets.size(); ++i)
+ {
+ if (i != 0)
+ {
+ writeStringQDF("\n");
+ writeStringNoQDF(" ");
+ }
+ writeString(QUtil::int_to_string(i + first_obj));
+ writeString(" ");
+ writeString(QUtil::int_to_string(offsets[i]));
+ }
+ writeString("\n");
+}
+
+void
+QPDFWriter::writeObjectStream(QPDFObjectHandle object)
+{
+ // Note: object might be null if this is a place-holder for an
+ // object stream that we are generating from scratch.
+
+ int old_id = object.getObjectID();
+ int new_id = obj_renumber[old_id];
+
+ std::vector<int> offsets;
+ int first = 0;
+
+ // Generate stream itself. We have to do this in two passes so we
+ // can calculate offsets in the first pass.
+ PointerHolder<Buffer> stream_buffer;
+ int first_obj = -1;
+ bool compressed = false;
+ for (int pass = 1; pass <= 2; ++pass)
+ {
+ if (pass == 1)
+ {
+ pushDiscardFilter();
+ }
+ else
+ {
+ // Adjust offsets to skip over comment before first object
+
+ first = offsets[0];
+ for (std::vector<int>::iterator iter = offsets.begin();
+ iter != offsets.end(); ++iter)
+ {
+ *iter -= first;
+ }
+
+ // Take one pass at writing pairs of numbers so we can get
+ // their size information
+ pushDiscardFilter();
+ writeObjectStreamOffsets(offsets, first_obj);
+ first += this->pipeline->getCount();
+ popPipelineStack();
+
+ // Set up a stream to write the stream data into a buffer.
+ Pipeline* next = pushPipeline(new Pl_Buffer("object stream"));
+ if (! ((this->stream_data_mode == s_uncompress) || this->qdf_mode))
+ {
+ compressed = true;
+ next = pushPipeline(
+ new Pl_Flate("compress object stream", next,
+ Pl_Flate::a_deflate));
+ }
+ activatePipelineStack();
+ writeObjectStreamOffsets(offsets, first_obj);
+ }
+
+ int count = 0;
+ for (std::set<int>::iterator iter =
+ this->object_stream_to_objects[old_id].begin();
+ iter != this->object_stream_to_objects[old_id].end();
+ ++iter, ++count)
+ {
+ int obj = *iter;
+ int new_obj = this->obj_renumber[obj];
+ if (first_obj == -1)
+ {
+ first_obj = new_obj;
+ }
+ if (this->qdf_mode)
+ {
+ writeString("%% Object stream: object " +
+ QUtil::int_to_string(new_obj) + ", index " +
+ QUtil::int_to_string(count) + "\n");
+ }
+ if (pass == 1)
+ {
+ offsets.push_back(this->pipeline->getCount());
+ }
+ writeObject(this->pdf.getObjectByID(obj, 0), count);
+
+ this->xref[new_obj] = QPDFXRefEntry(2, new_id, count);
+ }
+
+ // stream_buffer will be initialized only for pass 2
+ popPipelineStack(&stream_buffer);
+ }
+
+ // Write the object
+ openObject(new_id);
+ setDataKey(new_id);
+ writeString("<<");
+ writeStringQDF("\n ");
+ writeString(" /Type /ObjStm");
+ writeStringQDF("\n ");
+ writeString(" /Length " +
+ QUtil::int_to_string(stream_buffer.getPointer()->getSize()));
+ writeStringQDF("\n ");
+ if (compressed)
+ {
+ writeString(" /Filter /FlateDecode");
+ }
+ writeString(" /N " + QUtil::int_to_string(offsets.size()));
+ writeStringQDF("\n ");
+ writeString(" /First " + QUtil::int_to_string(first));
+ if (! object.isNull())
+ {
+ // If the original object has an /Extends key, preserve it.
+ QPDFObjectHandle dict = object.getDict();
+ QPDFObjectHandle extends = dict.getKey("/Extends");
+ if (extends.isIndirect())
+ {
+ QTC::TC("qpdf", "QPDFWriter copy Extends");
+ writeStringQDF("\n ");
+ writeString(" /Extends ");
+ unparseChild(extends, 1, f_in_ostream);
+ }
+ }
+ writeStringQDF("\n");
+ writeStringNoQDF(" ");
+ writeString(">>\nstream\n");
+ if (this->encrypted)
+ {
+ QTC::TC("qpdf", "QPDFWriter encrypt object stream");
+ }
+ pushEncryptionFilter();
+ writeBuffer(stream_buffer);
+ popPipelineStack();
+ writeString("endstream");
+ this->cur_data_key.clear();
+ closeObject(new_id);
+}
+
+void
+QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index)
+{
+ int old_id = object.getObjectID();
+
+ if ((object_stream_index == -1) &&
+ (this->object_stream_to_objects.count(old_id)))
+ {
+ writeObjectStream(object);
+ return;
+ }
+
+ int new_id = obj_renumber[old_id];
+ if (this->qdf_mode)
+ {
+ if (this->page_object_to_seq.count(old_id))
+ {
+ writeString("%% Page ");
+ writeString(
+ QUtil::int_to_string(
+ this->page_object_to_seq[old_id]));
+ writeString("\n");
+ }
+ if (this->contents_to_page_seq.count(old_id))
+ {
+ writeString("%% Contents for page ");
+ writeString(
+ QUtil::int_to_string(
+ this->contents_to_page_seq[old_id]));
+ writeString("\n");
+ }
+ }
+ if (object_stream_index == -1)
+ {
+ openObject(new_id);
+ setDataKey(new_id);
+ unparseObject(object, 0, 0);
+ this->cur_data_key.clear();
+ closeObject(new_id);
+ }
+ else
+ {
+ unparseObject(object, 0, f_in_ostream);
+ writeString("\n");
+ }
+
+ if ((! this->direct_stream_lengths) && object.isStream())
+ {
+ if (this->qdf_mode)
+ {
+ if (this->added_newline)
+ {
+ writeString("%QDF: ignore_newline\n");
+ }
+ }
+ openObject(new_id + 1);
+ writeString(QUtil::int_to_string(this->cur_stream_length));
+ closeObject(new_id + 1);
+ }
+}
+
+void
+QPDFWriter::generateID()
+{
+ // Note: we can't call generateID() at the time of construction
+ // since the caller hasn't yet had a chance to call setStaticID(),
+ // but we need to generate it before computing encryption
+ // dictionary parameters. This is why we call this function both
+ // from setEncryptionParameters() and from write() and return
+ // immediately if the ID has already been generated.
+
+ if (! this->id2.empty())
+ {
+ return;
+ }
+
+ QPDFObjectHandle trailer = pdf.getTrailer();
+
+ std::string result;
+
+ if (this->static_id)
+ {
+ // For test suite use only...
+ static char tmp[] = {0x31, 0x41, 0x59, 0x26,
+ 0x53, 0x58, 0x97, 0x93,
+ 0x23, 0x84, 0x62, 0x64,
+ 0x33, 0x83, 0x27, 0x95,
+ 0x00};
+ result = tmp;
+ }
+ else
+ {
+ // The PDF specification has guidelines for creating IDs, but it
+ // states clearly that the only thing that's really important is
+ // that it is very likely to be unique. We can't really follow
+ // the guidelines in the spec exactly because we haven't written
+ // the file yet. This scheme should be fine though.
+
+ std::string seed;
+ seed += QUtil::int_to_string((int)time(0));
+ seed += " QPDF ";
+ seed += filename;
+ seed += " ";
+ if (trailer.hasKey("/Info"))
+ {
+ std::set<std::string> keys = trailer.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ QPDFObjectHandle obj = trailer.getKey(*iter);
+ if (obj.isString())
+ {
+ seed += " ";
+ seed += obj.getStringValue();
+ }
+ }
+ }
+
+ MD5 m;
+ m.encodeString(seed.c_str());
+ MD5::Digest digest;
+ m.digest(digest);
+ result = std::string((char*)digest, sizeof(MD5::Digest));
+ }
+
+ // If /ID already exists, follow the spec: use the original first
+ // word and generate a new second word. Otherwise, we'll use the
+ // generated ID for both.
+
+ this->id2 = result;
+ if (trailer.hasKey("/ID"))
+ {
+ // Note: keep /ID from old file even if --static-id was given.
+ this->id1 = trailer.getKey("/ID").getArrayItem(0).getStringValue();
+ }
+ else
+ {
+ this->id1 = this->id2;
+ }
+}
+
+void
+QPDFWriter::initializeSpecialStreams()
+{
+ // Mark all page content streams in case we are filtering or
+ // normalizing.
+ std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
+ int num = 0;
+ for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
+ iter != pages.end(); ++iter)
+ {
+ QPDFObjectHandle& page = *iter;
+ this->page_object_to_seq[page.getObjectID()] = ++num;
+ QPDFObjectHandle contents = page.getKey("/Contents");
+ std::vector<int> contents_objects;
+ if (contents.isArray())
+ {
+ int n = contents.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ contents_objects.push_back(
+ contents.getArrayItem(i).getObjectID());
+ }
+ }
+ else if (contents.isStream())
+ {
+ contents_objects.push_back(contents.getObjectID());
+ }
+
+ for (std::vector<int>::iterator iter = contents_objects.begin();
+ iter != contents_objects.end(); ++iter)
+ {
+ this->contents_to_page_seq[*iter] = num;
+ this->normalized_streams.insert(*iter);
+ }
+ }
+}
+
+void
+QPDFWriter::preserveObjectStreams()
+{
+ this->pdf.getObjectStreamData(this->object_to_object_stream);
+}
+
+void
+QPDFWriter::generateObjectStreams()
+{
+ // Basic strategy: make a list of objects that can go into an
+ // object stream. Then figure out how many object streams are
+ // needed so that we can distribute objects approximately evenly
+ // without having any object stream exceed 100 members. We don't
+ // have to worry about linearized files here -- if the file is
+ // linearized, we take care of excluding things that aren't
+ // allowed here later.
+
+ // This code doesn't do anything with /Extends.
+
+ std::vector<int> const& eligible = this->pdf.getCompressibleObjects();
+ unsigned int n_object_streams = (eligible.size() + 99) / 100;
+ unsigned int n_per = eligible.size() / n_object_streams;
+ if (n_per * n_object_streams < eligible.size())
+ {
+ ++n_per;
+ }
+ unsigned int n = 0;
+ int cur_ostream = 0;
+ for (std::vector<int>::const_iterator iter = eligible.begin();
+ iter != eligible.end(); ++iter)
+ {
+ if ((n % n_per) == 0)
+ {
+ if (n > 0)
+ {
+ QTC::TC("qpdf", "QPDFWriter generate >1 ostream");
+ }
+ n = 0;
+ }
+ if (n == 0)
+ {
+ // Construct a new null object as the "original" object
+ // stream. The rest of the code knows that this means
+ // we're creating the object stream from scratch.
+ cur_ostream = this->pdf.makeIndirectObject(
+ QPDFObjectHandle::newNull()).getObjectID();
+ }
+ this->object_to_object_stream[*iter] = cur_ostream;
+ ++n;
+ }
+}
+
+void
+QPDFWriter::write()
+{
+ // Do preliminary setup
+
+ if (this->linearized)
+ {
+ this->qdf_mode = false;
+ }
+
+ if (this->qdf_mode)
+ {
+ if (! this->normalize_content_set)
+ {
+ this->normalize_content = true;
+ }
+ if (! this->stream_data_mode_set)
+ {
+ this->stream_data_mode = s_uncompress;
+ }
+ }
+
+ if (this->encrypted)
+ {
+ // Encryption has been explicitly set
+ this->preserve_encryption = false;
+ }
+ else if (this->normalize_content ||
+ (this->stream_data_mode == s_uncompress) ||
+ this->qdf_mode)
+ {
+ // Encryption makes looking at contents pretty useless. If
+ // the user explicitly encrypted though, we still obey that.
+ this->preserve_encryption = false;
+ }
+
+ if (preserve_encryption)
+ {
+ copyEncryptionParameters();
+ }
+
+ if (this->qdf_mode || this->normalize_content ||
+ (this->stream_data_mode == s_uncompress))
+ {
+ initializeSpecialStreams();
+ }
+
+ if (this->qdf_mode)
+ {
+ // Generate indirect stream lengths for qdf mode since fix-qdf
+ // uses them for storing recomputed stream length data.
+ // Certain streams such as object streams, xref streams, and
+ // hint streams always get direct stream lengths.
+ this->direct_stream_lengths = false;
+ }
+
+ switch (this->object_stream_mode)
+ {
+ case o_disable:
+ // no action required
+ break;
+
+ case o_preserve:
+ preserveObjectStreams();
+ break;
+
+ case o_generate:
+ generateObjectStreams();
+ break;
+
+ // no default so gcc will warn for missing case tag
+ }
+
+ if (this->linearized)
+ {
+ // Page dictionaries are not allowed to be compressed objects.
+ std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
+ for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
+ iter != pages.end(); ++iter)
+ {
+ QPDFObjectHandle& page = *iter;
+ int objid = page.getObjectID();
+ if (this->object_to_object_stream.count(objid))
+ {
+ QTC::TC("qpdf", "QPDFWriter uncompressing page dictionary");
+ this->object_to_object_stream.erase(objid);
+ }
+ }
+ }
+
+ if (this->linearized || this->encrypted)
+ {
+ // The document catalog is not allowed to be compressed in
+ // linearized files either. It also appears that Adobe Reader
+ // 8.0.0 has a bug that prevents it from being able to handle
+ // encrypted files with compressed document catalogs, so we
+ // disable them in that case as well.
+ int objid = pdf.getRoot().getObjectID();
+ if (this->object_to_object_stream.count(objid))
+ {
+ QTC::TC("qpdf", "QPDFWriter uncompressing root");
+ this->object_to_object_stream.erase(objid);
+ }
+ }
+
+ // Generate reverse mapping from object stream to objects
+ for (std::map<int, int>::iterator iter =
+ this->object_to_object_stream.begin();
+ iter != this->object_to_object_stream.end(); ++iter)
+ {
+ int obj = (*iter).first;
+ int stream = (*iter).second;
+ this->object_stream_to_objects[stream].insert(obj);
+ this->max_ostream_index =
+ std::max(this->max_ostream_index,
+ (int)this->object_stream_to_objects[stream].size() - 1);
+ }
+
+ if (! this->object_stream_to_objects.empty())
+ {
+ this->min_pdf_version = "1.5";
+ }
+
+ generateID();
+
+ pdf.trimTrailerForWrite();
+ pdf.flattenScalarReferences();
+
+ if (this->linearized)
+ {
+ writeLinearized();
+ }
+ else
+ {
+ writeStandard();
+ }
+
+ this->pipeline->finish();
+ if (this->close_file)
+ {
+ fclose(this->file);
+ }
+ this->file = 0;
+}
+
+void
+QPDFWriter::enqueuePart(std::vector<QPDFObjectHandle>& part)
+{
+ for (std::vector<QPDFObjectHandle>::iterator iter = part.begin();
+ iter != part.end(); ++iter)
+ {
+ enqueueObject(*iter);
+ }
+}
+
+void
+QPDFWriter::writeEncryptionDictionary()
+{
+ this->encryption_dict_objid = openObject(this->encryption_dict_objid);
+ writeString("<<");
+ for (std::map<std::string, std::string>::iterator iter =
+ this->encryption_dictionary.begin();
+ iter != this->encryption_dictionary.end(); ++iter)
+ {
+ writeString(" ");
+ writeString((*iter).first);
+ writeString(" ");
+ writeString((*iter).second);
+ }
+ writeString(" >>");
+ closeObject(this->encryption_dict_objid);
+}
+
+void
+QPDFWriter::writeHeader()
+{
+ std::string version = pdf.getPDFVersion();
+ if (! this->min_pdf_version.empty())
+ {
+ float ov = atof(version.c_str());
+ float mv = atof(this->min_pdf_version.c_str());
+ if (mv > ov)
+ {
+ version = this->min_pdf_version;
+ }
+ }
+
+ writeString("%PDF-");
+ writeString(version);
+ // This string of binary characters would not be valid UTF-8, so
+ // it really should be treated as binary.
+ writeString("\n%¿÷¢þ\n");
+ writeStringQDF("%QDF-1.0\n\n");
+}
+
+void
+QPDFWriter::writeHintStream(int hint_id)
+{
+ PointerHolder<Buffer> hint_buffer;
+ int S = 0;
+ int O = 0;
+ pdf.generateHintStream(
+ this->xref, this->lengths, this->obj_renumber, hint_buffer, S, O);
+
+ openObject(hint_id);
+ setDataKey(hint_id);
+
+ unsigned char* hs = hint_buffer.getPointer()->getBuffer();
+ unsigned long hlen = hint_buffer.getPointer()->getSize();
+
+ writeString("<< /Filter /FlateDecode /S ");
+ writeString(QUtil::int_to_string(S));
+ if (O)
+ {
+ writeString(" /O ");
+ writeString(QUtil::int_to_string(O));
+ }
+ writeString(" /Length ");
+ writeString(QUtil::int_to_string(hlen));
+ writeString(" >>\nstream\n");
+
+ if (this->encrypted)
+ {
+ QTC::TC("qpdf", "QPDFWriter encrypted hint stream");
+ }
+ pushEncryptionFilter();
+ writeBuffer(hint_buffer);
+ popPipelineStack();
+
+ if (hs[hlen - 1] != '\n')
+ {
+ writeString("\n");
+ }
+ writeString("endstream");
+ closeObject(hint_id);
+}
+
+int
+QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size)
+{
+ return writeXRefTable(which, first, last, size, 0, false, 0, 0, 0);
+}
+
+int
+QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size,
+ int prev, bool suppress_offsets,
+ int hint_id, int hint_offset, int hint_length)
+{
+ writeString("xref\n");
+ writeString(QUtil::int_to_string(first));
+ writeString(" ");
+ writeString(QUtil::int_to_string(last - first + 1));
+ int space_before_zero = this->pipeline->getCount();
+ writeString("\n");
+ for (int i = first; i <= last; ++i)
+ {
+ if (i == 0)
+ {
+ writeString("0000000000 65535 f \n");
+ }
+ else
+ {
+ int offset = 0;
+ if (! suppress_offsets)
+ {
+ offset = this->xref[i].getOffset();
+ if ((hint_id != 0) &&
+ (i != hint_id) &&
+ (offset >= hint_offset))
+ {
+ offset += hint_length;
+ }
+ }
+ writeString(QUtil::int_to_string(offset, 10));
+ writeString(" 00000 n \n");
+ }
+ }
+ writeTrailer(which, size, false, prev);
+ writeString("\n");
+ return space_before_zero;
+}
+
+int
+QPDFWriter::writeXRefStream(int objid, int max_id, int max_offset,
+ trailer_e which, int first, int last, int size)
+{
+ return writeXRefStream(objid, max_id, max_offset,
+ which, first, last, size, 0, 0, 0, 0);
+}
+
+int
+QPDFWriter::writeXRefStream(int xref_id, int max_id, int max_offset,
+ trailer_e which, int first, int last, int size,
+ int prev, int hint_id,
+ int hint_offset, int hint_length)
+{
+ int xref_offset = this->pipeline->getCount();
+ int space_before_zero = xref_offset - 1;
+
+ // field 1 contains offsets and object stream identifiers
+ int f1_size = std::max(bytesNeeded(max_offset),
+ bytesNeeded(max_id));
+
+ // field 2 contains object stream indices
+ int f2_size = bytesNeeded(this->max_ostream_index);
+
+ unsigned int esize = 1 + f1_size + f2_size;
+
+ // Must store in xref table in advance of writing the actual data
+ // rather than waiting for openObject to do it.
+ this->xref[xref_id] = QPDFXRefEntry(1, pipeline->getCount(), 0);
+
+ Pipeline* p = pushPipeline(new Pl_Buffer("xref stream"));
+ bool compressed = false;
+ if (! ((this->stream_data_mode == s_uncompress) || this->qdf_mode))
+ {
+ compressed = true;
+ p = pushPipeline(
+ new Pl_Flate("compress xref", p, Pl_Flate::a_deflate));
+ p = pushPipeline(
+ new Pl_PNGFilter(
+ "pngify xref", p, Pl_PNGFilter::a_encode, esize, 0));
+ }
+ activatePipelineStack();
+ for (int i = first; i <= last; ++i)
+ {
+ QPDFXRefEntry& e = this->xref[i];
+ switch (e.getType())
+ {
+ case 0:
+ writeBinary(0, 1);
+ writeBinary(0, f1_size);
+ writeBinary(0, f2_size);
+ break;
+
+ case 1:
+ {
+ int offset = e.getOffset();
+ if ((hint_id != 0) &&
+ (i != hint_id) &&
+ (offset >= hint_offset))
+ {
+ offset += hint_length;
+ }
+ writeBinary(1, 1);
+ writeBinary(offset, f1_size);
+ writeBinary(0, f2_size);
+ }
+ break;
+
+ case 2:
+ writeBinary(2, 1);
+ writeBinary(e.getObjStreamNumber(), f1_size);
+ writeBinary(e.getObjStreamIndex(), f2_size);
+ break;
+
+ default:
+ throw QEXC::Internal("invalid type writing xref stream");
+ break;
+ }
+ }
+ PointerHolder<Buffer> xref_data;
+ popPipelineStack(&xref_data);
+
+ openObject(xref_id);
+ writeString("<<");
+ writeStringQDF("\n ");
+ writeString(" /Type /XRef");
+ writeStringQDF("\n ");
+ writeString(" /Length " +
+ QUtil::int_to_string(xref_data.getPointer()->getSize()));
+ if (compressed)
+ {
+ writeStringQDF("\n ");
+ writeString(" /Filter /FlateDecode");
+ writeStringQDF("\n ");
+ writeString(" /DecodeParms << /Columns " +
+ QUtil::int_to_string(esize) + " /Predictor 12 >>");
+ }
+ writeStringQDF("\n ");
+ writeString(" /W [ 1 " +
+ QUtil::int_to_string(f1_size) + " " +
+ QUtil::int_to_string(f2_size) + " ]");
+ if (! ((first == 0) && (last == size - 1)))
+ {
+ writeString(" /Index [ " +
+ QUtil::int_to_string(first) + " " +
+ QUtil::int_to_string(last - first + 1) + " ]");
+ }
+ writeTrailer(which, size, true, prev);
+ writeString("\nstream\n");
+ writeBuffer(xref_data);
+ writeString("\nendstream");
+ closeObject(xref_id);
+ return space_before_zero;
+}
+
+void
+QPDFWriter::writeLinearized()
+{
+ // Optimize file and enqueue objects in order
+
+ bool need_xref_stream = (! this->object_to_object_stream.empty());
+ pdf.optimize(this->object_to_object_stream);
+
+ std::vector<QPDFObjectHandle> part4;
+ std::vector<QPDFObjectHandle> part6;
+ std::vector<QPDFObjectHandle> part7;
+ std::vector<QPDFObjectHandle> part8;
+ std::vector<QPDFObjectHandle> part9;
+ pdf.getLinearizedParts(this->object_to_object_stream,
+ part4, part6, part7, part8, part9);
+
+ // Object number sequence:
+ //
+ // second half
+ // second half uncompressed objects
+ // second half xref stream, if any
+ // second half compressed objects
+ // first half
+ // linearization dictionary
+ // first half xref stream, if any
+ // part 4 uncompresesd objects
+ // encryption dictionary, if any
+ // hint stream
+ // part 6 uncompressed objects
+ // first half compressed objects
+ //
+
+ // Second half objects
+ int second_half_uncompressed = part7.size() + part8.size() + part9.size();
+ int second_half_first_obj = 1;
+ int after_second_half = 1 + second_half_uncompressed;
+ this->next_objid = after_second_half;
+ int second_half_xref = 0;
+ if (need_xref_stream)
+ {
+ second_half_xref = this->next_objid++;
+ }
+ // Assign numbers to all compressed objects in the second half.
+ std::vector<QPDFObjectHandle>* vecs2[] = {&part7, &part8, &part9};
+ for (int i = 0; i < 3; ++i)
+ {
+ for (std::vector<QPDFObjectHandle>::iterator iter = (*vecs2[i]).begin();
+ iter != (*vecs2[i]).end(); ++iter)
+ {
+ assignCompressedObjectNumbers((*iter).getObjectID());
+ }
+ }
+ int second_half_end = this->next_objid - 1;
+ int second_trailer_size = this->next_objid;
+
+ // First half objects
+ int first_half_start = this->next_objid;
+ int lindict_id = this->next_objid++;
+ int first_half_xref = 0;
+ if (need_xref_stream)
+ {
+ first_half_xref = this->next_objid++;
+ }
+ int part4_first_obj = this->next_objid;
+ this->next_objid += part4.size();
+ int after_part4 = this->next_objid;
+ if (this->encrypted)
+ {
+ this->encryption_dict_objid = this->next_objid++;
+ }
+ int hint_id = this->next_objid++;
+ int part6_first_obj = this->next_objid;
+ this->next_objid += part6.size();
+ int after_part6 = this->next_objid;
+ // Assign numbers to all compressed objects in the first half
+ std::vector<QPDFObjectHandle>* vecs1[] = {&part4, &part6};
+ for (int i = 0; i < 2; ++i)
+ {
+ for (std::vector<QPDFObjectHandle>::iterator iter = (*vecs1[i]).begin();
+ iter != (*vecs1[i]).end(); ++iter)
+ {
+ assignCompressedObjectNumbers((*iter).getObjectID());
+ }
+ }
+ int first_half_end = this->next_objid - 1;
+ int first_trailer_size = this->next_objid;
+
+ int part4_end_marker = part4.back().getObjectID();
+ int part6_end_marker = part6.back().getObjectID();
+ int space_before_zero = 0;
+ int file_size = 0;
+ int part6_end_offset = 0;
+ int first_half_max_obj_offset = 0;
+ int second_xref_offset = 0;
+ int first_xref_end = 0;
+ int second_xref_end = 0;
+
+ this->next_objid = part4_first_obj;
+ enqueuePart(part4);
+ assert(this->next_objid = after_part4);
+ this->next_objid = part6_first_obj;
+ enqueuePart(part6);
+ assert(this->next_objid == after_part6);
+ this->next_objid = second_half_first_obj;
+ enqueuePart(part7);
+ enqueuePart(part8);
+ enqueuePart(part9);
+ assert(this->next_objid == after_second_half);
+
+ int hint_length = 0;
+ PointerHolder<Buffer> hint_buffer;
+
+ // Write file in two passes. Part numbers refer to PDF spec 1.4.
+
+ for (int pass = 1; pass <= 2; ++pass)
+ {
+ if (pass == 1)
+ {
+ pushDiscardFilter();
+ }
+
+ // Part 1: header
+
+ writeHeader();
+
+ // Part 2: linearization parameter dictionary. Save enough
+ // space to write real dictionary. 150 characters is enough
+ // space if all numerical values in the parameter dictionary
+ // are 10 digits long plus a few extra characters for safety.
+
+ int pos = this->pipeline->getCount();
+ openObject(lindict_id);
+ writeString("<<");
+ if (pass == 2)
+ {
+ std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
+ int first_page_object = obj_renumber[pages[0].getObjectID()];
+ int npages = pages.size();
+
+ writeString(" /Linearized 1 /L ");
+ writeString(QUtil::int_to_string(file_size + hint_length));
+ // Implementation note 121 states that a space is
+ // mandatory after this open bracket.
+ writeString(" /H [ ");
+ writeString(QUtil::int_to_string(this->xref[hint_id].getOffset()));
+ writeString(" ");
+ writeString(QUtil::int_to_string(hint_length));
+ writeString(" ] /O ");
+ writeString(QUtil::int_to_string(first_page_object));
+ writeString(" /E ");
+ writeString(QUtil::int_to_string(part6_end_offset + hint_length));
+ writeString(" /N ");
+ writeString(QUtil::int_to_string(npages));
+ writeString(" /T ");
+ writeString(QUtil::int_to_string(space_before_zero + hint_length));
+ }
+ writeString(" >>");
+ closeObject(lindict_id);
+ static int const pad = 150;
+ int spaces = (pos + pad - this->pipeline->getCount());
+ assert(spaces >= 0);
+ for (int i = 0; i < spaces; ++i)
+ {
+ writeString(" ");
+ }
+ writeString("\n");
+
+ // Part 3: first page cross reference table and trailer.
+
+ int first_xref_offset = this->pipeline->getCount();
+ int hint_offset = 0;
+ if (pass == 2)
+ {
+ hint_offset = this->xref[hint_id].getOffset();
+ }
+ if (need_xref_stream)
+ {
+ // Must pad here too.
+ if (pass == 1)
+ {
+ // first_half_max_obj_offset is very likely to fall
+ // within the first 64K of the document (thus
+ // requiring two bytes for offsets) since it is the
+ // offset of the last uncompressed object in page 1.
+ // We allow for it to do otherwise though.
+ first_half_max_obj_offset = 65535;
+ }
+ pos = this->pipeline->getCount();
+ writeXRefStream(first_half_xref, first_half_end,
+ first_half_max_obj_offset,
+ t_lin_first, first_half_start, first_half_end,
+ first_trailer_size,
+ hint_length + second_xref_offset,
+ hint_id, hint_offset, hint_length);
+ int endpos = this->pipeline->getCount();
+ if (pass == 1)
+ {
+ // Pad so we have enough room for the real xref
+ // stream. In an extremely unlikely worst case,
+ // first_half_max_obj_offset could be enough larger to
+ // require two extra bytes beyond what we calculated
+ // in pass 1. This means we need to save two extra
+ // bytes for each xref entry. To that, we'll add 10
+ // extra bytes for number length increases.
+ int possible_extra =
+ 10 + (2 * (first_half_end - first_half_start + 1));
+ for (int i = 0; i < possible_extra; ++i)
+ {
+ writeString(" ");
+ }
+ first_xref_end = this->pipeline->getCount();
+ }
+ else
+ {
+ // Pad so that the next object starts at the same
+ // place as in pass 1.
+ for (int i = 0; i < first_xref_end - endpos; ++i)
+ {
+ writeString(" ");
+ }
+ assert(this->pipeline->getCount() == first_xref_end);
+ }
+ writeString("\n");
+ }
+ else
+ {
+ writeXRefTable(t_lin_first, first_half_start, first_half_end,
+ first_trailer_size, hint_length + second_xref_offset,
+ (pass == 1), hint_id, hint_offset, hint_length);
+ writeString("startxref\n0\n%%EOF\n");
+ }
+
+ // Parts 4 through 9
+
+ for (std::list<QPDFObjectHandle>::iterator iter =
+ this->object_queue.begin();
+ iter != this->object_queue.end(); ++iter)
+ {
+ QPDFObjectHandle cur_object = (*iter);
+ if (cur_object.getObjectID() == part6_end_marker)
+ {
+ first_half_max_obj_offset = this->pipeline->getCount();
+ }
+ writeObject(cur_object);
+ if (cur_object.getObjectID() == part4_end_marker)
+ {
+ if (this->encrypted)
+ {
+ writeEncryptionDictionary();
+ }
+ if (pass == 1)
+ {
+ this->xref[hint_id] =
+ QPDFXRefEntry(1, this->pipeline->getCount(), 0);
+ }
+ else
+ {
+ // Part 5: hint stream
+ writeBuffer(hint_buffer);
+ }
+ }
+ if (cur_object.getObjectID() == part6_end_marker)
+ {
+ part6_end_offset = this->pipeline->getCount();
+ }
+ }
+
+ // Part 10: overflow hint stream -- not used
+
+ // Part 11: main cross reference table and trailer
+
+ second_xref_offset = this->pipeline->getCount();
+ if (need_xref_stream)
+ {
+ space_before_zero =
+ writeXRefStream(second_half_xref,
+ second_half_end, second_xref_offset,
+ t_lin_second, 0, second_half_end,
+ second_trailer_size);
+ if (pass == 1)
+ {
+ // Add some padding -- we need an accurate file_size
+ // number, and this could change if the pass 2 xref
+ // stream compresses differently. There shouldn't be
+ // much difference, so we'll just pad 100 characters.
+ // This is unscientific though, and may not always
+ // work. The only way we could really get around this
+ // would be to seek back to the beginning of the file
+ // and update /L in the linearization dictionary, but
+ // that would be the only thing in the design that
+ // would require the output file to be seekable.
+ for (int i = 0; i < 99; ++i)
+ {
+ writeString(" ");
+ }
+ writeString("\n");
+ second_xref_end = this->pipeline->getCount();
+ }
+ else
+ {
+ // Make the file size the same.
+ int pos = this->pipeline->getCount();
+ while (pos < second_xref_end + hint_length - 1)
+ {
+ ++pos;
+ writeString(" ");
+ }
+ writeString("\n");
+ // If this assertion fails, maybe we didn't have
+ // enough padding above.
+ assert(this->pipeline->getCount() ==
+ second_xref_end + hint_length);
+ }
+ }
+ else
+ {
+ space_before_zero =
+ writeXRefTable(t_lin_second, 0, second_half_end,
+ second_trailer_size);
+ }
+ writeString("startxref\n");
+ writeString(QUtil::int_to_string(first_xref_offset));
+ writeString("\n%%EOF\n");
+
+ if (pass == 1)
+ {
+ // Close first pass pipeline
+ file_size = this->pipeline->getCount();
+ popPipelineStack();
+
+ // Save hint offset since it will be set to zero by
+ // calling openObject.
+ int hint_offset = this->xref[hint_id].getOffset();
+
+ // Write hint stream to a buffer
+ pushPipeline(new Pl_Buffer("hint buffer"));
+ activatePipelineStack();
+ writeHintStream(hint_id);
+ popPipelineStack(&hint_buffer);
+ hint_length = hint_buffer.getPointer()->getSize();
+
+ // Restore hint offset
+ this->xref[hint_id] = QPDFXRefEntry(1, hint_offset, 0);
+ }
+ }
+}
+
+void
+QPDFWriter::writeStandard()
+{
+ // Start writing
+
+ writeHeader();
+
+ // Put root first on queue.
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ enqueueObject(trailer.getKey("/Root"));
+
+ // Next place any other objects referenced from the trailer
+ // dictionary into the queue, handling direct objects recursively.
+ // Root is already there, so enqueuing it a second time is a
+ // no-op.
+ std::set<std::string> keys = trailer.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ enqueueObject(trailer.getKey(*iter));
+ }
+
+ // Now start walking queue, output each object
+ while (this->object_queue.size())
+ {
+ QPDFObjectHandle cur_object = this->object_queue.front();
+ this->object_queue.pop_front();
+ writeObject(cur_object);
+ }
+
+ // Write out the encryption dictionary, if any
+ if (this->encrypted)
+ {
+ writeEncryptionDictionary();
+ }
+
+ // Now write out xref. next_objid is now the number of objects.
+ off_t xref_offset = this->pipeline->getCount();
+ if (this->object_stream_to_objects.empty())
+ {
+ // Write regular cross-reference table
+ // Write regular cross-reference table
+ writeXRefTable(t_normal, 0, this->next_objid - 1, this->next_objid);
+ }
+ else
+ {
+ // Write cross-reference stream.
+ int xref_id = this->next_objid++;
+ writeXRefStream(xref_id, xref_id, xref_offset, t_normal,
+ 0, this->next_objid - 1, this->next_objid);
+ }
+ writeString("startxref\n");
+ writeString(QUtil::int_to_string(xref_offset));
+ writeString("\n%%EOF\n");
+}
diff --git a/libqpdf/QPDFXRefEntry.cc b/libqpdf/QPDFXRefEntry.cc
new file mode 100644
index 00000000..669a2f13
--- /dev/null
+++ b/libqpdf/QPDFXRefEntry.cc
@@ -0,0 +1,61 @@
+
+#include <qpdf/QPDFXRefEntry.hh>
+#include <qpdf/QPDFExc.hh>
+#include <qpdf/QUtil.hh>
+
+QPDFXRefEntry::QPDFXRefEntry() :
+ type(0),
+ field1(0),
+ field2(0)
+{
+}
+
+QPDFXRefEntry::QPDFXRefEntry(int type, int field1, int field2) :
+ type(type),
+ field1(field1),
+ field2(field2)
+{
+ if ((type < 1) || (type > 2))
+ {
+ throw QPDFExc("invalid xref type " + QUtil::int_to_string(type));
+ }
+}
+
+int
+QPDFXRefEntry::getType() const
+{
+ return this->type;
+}
+
+int
+QPDFXRefEntry::getOffset() const
+{
+ if (this->type != 1)
+ {
+ throw QPDFExc(
+ "getOffset called for xref entry of type != 1");
+ }
+ return this->field1;
+}
+
+int
+QPDFXRefEntry::getObjStreamNumber() const
+{
+ if (this->type != 2)
+ {
+ throw QPDFExc(
+ "getObjStreamNumber called for xref entry of type != 2");
+ }
+ return this->field1;
+}
+
+int
+QPDFXRefEntry::getObjStreamIndex() const
+{
+ if (this->type != 2)
+ {
+ throw QPDFExc(
+ "getObjStreamIndex called for xref entry of type != 2");
+ }
+ return this->field2;
+}
diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc
new file mode 100644
index 00000000..d1edbfdd
--- /dev/null
+++ b/libqpdf/QPDF_Array.cc
@@ -0,0 +1,51 @@
+
+#include <qpdf/QPDF_Array.hh>
+
+#include <qpdf/QEXC.hh>
+
+QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& items) :
+ items(items)
+{
+}
+
+QPDF_Array::~QPDF_Array()
+{
+}
+
+std::string
+QPDF_Array::unparse()
+{
+ std::string result = "[ ";
+ for (std::vector<QPDFObjectHandle>::iterator iter = this->items.begin();
+ iter != this->items.end(); ++iter)
+ {
+ result += (*iter).unparse();
+ result += " ";
+ }
+ result += "]";
+ return result;
+}
+
+int
+QPDF_Array::getNItems() const
+{
+ return this->items.size();
+}
+
+QPDFObjectHandle
+QPDF_Array::getItem(int n) const
+{
+ if ((n < 0) || (n >= (int)this->items.size()))
+ {
+ throw QEXC::Internal("bounds array accessing QPDF_Array element");
+ }
+ return this->items[n];
+}
+
+void
+QPDF_Array::setItem(int n, QPDFObjectHandle const& oh)
+{
+ // Call getItem for bounds checking
+ (void) getItem(n);
+ this->items[n] = oh;
+}
diff --git a/libqpdf/QPDF_Bool.cc b/libqpdf/QPDF_Bool.cc
new file mode 100644
index 00000000..2b50c4c2
--- /dev/null
+++ b/libqpdf/QPDF_Bool.cc
@@ -0,0 +1,23 @@
+
+#include <qpdf/QPDF_Bool.hh>
+
+QPDF_Bool::QPDF_Bool(bool val) :
+ val(val)
+{
+}
+
+QPDF_Bool::~QPDF_Bool()
+{
+}
+
+std::string
+QPDF_Bool::unparse()
+{
+ return (val ? "true" : "false");
+}
+
+bool
+QPDF_Bool::getVal() const
+{
+ return this->val;
+}
diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc
new file mode 100644
index 00000000..654df688
--- /dev/null
+++ b/libqpdf/QPDF_Dictionary.cc
@@ -0,0 +1,84 @@
+
+#include <qpdf/QPDF_Dictionary.hh>
+
+#include <qpdf/QPDF_Null.hh>
+#include <qpdf/QPDF_Name.hh>
+
+QPDF_Dictionary::QPDF_Dictionary(
+ std::map<std::string, QPDFObjectHandle> const& items) :
+ items(items)
+{
+}
+
+QPDF_Dictionary::~QPDF_Dictionary()
+{
+}
+
+std::string
+QPDF_Dictionary::unparse()
+{
+ std::string result = "<< ";
+ for (std::map<std::string, QPDFObjectHandle>::iterator iter =
+ this->items.begin();
+ iter != this->items.end(); ++iter)
+ {
+ result += QPDF_Name::normalizeName((*iter).first) +
+ " " + (*iter).second.unparse() + " ";
+ }
+ result += ">>";
+ return result;
+}
+
+bool
+QPDF_Dictionary::hasKey(std::string const& key)
+{
+ return ((this->items.count(key) > 0) &&
+ (! this->items[key].isNull()));
+}
+
+QPDFObjectHandle
+QPDF_Dictionary::getKey(std::string const& key)
+{
+ // PDF spec says fetching a non-existent key from a dictionary
+ // returns the null object.
+ if (this->items.count(key))
+ {
+ // May be a null object
+ return (*(this->items.find(key))).second;
+ }
+ else
+ {
+ return QPDFObjectHandle::newNull();
+ }
+}
+
+std::set<std::string>
+QPDF_Dictionary::getKeys()
+{
+ std::set<std::string> result;
+ for (std::map<std::string, QPDFObjectHandle>::const_iterator iter =
+ this->items.begin();
+ iter != this->items.end(); ++iter)
+ {
+ if (hasKey((*iter).first))
+ {
+ result.insert((*iter).first);
+ }
+ }
+ return result;
+}
+
+void
+QPDF_Dictionary::replaceKey(std::string const& key,
+ QPDFObjectHandle const& value)
+{
+ // add or replace value
+ this->items[key] = value;
+}
+
+void
+QPDF_Dictionary::removeKey(std::string const& key)
+{
+ // no-op if key does not exist
+ this->items.erase(key);
+}
diff --git a/libqpdf/QPDF_Integer.cc b/libqpdf/QPDF_Integer.cc
new file mode 100644
index 00000000..988519d0
--- /dev/null
+++ b/libqpdf/QPDF_Integer.cc
@@ -0,0 +1,25 @@
+
+#include <qpdf/QPDF_Integer.hh>
+
+#include <qpdf/QUtil.hh>
+
+QPDF_Integer::QPDF_Integer(int val) :
+ val(val)
+{
+}
+
+QPDF_Integer::~QPDF_Integer()
+{
+}
+
+std::string
+QPDF_Integer::unparse()
+{
+ return QUtil::int_to_string(this->val);
+}
+
+int
+QPDF_Integer::getVal() const
+{
+ return this->val;
+}
diff --git a/libqpdf/QPDF_Name.cc b/libqpdf/QPDF_Name.cc
new file mode 100644
index 00000000..f57ced04
--- /dev/null
+++ b/libqpdf/QPDF_Name.cc
@@ -0,0 +1,46 @@
+
+#include <qpdf/QPDF_Name.hh>
+
+QPDF_Name::QPDF_Name(std::string const& name) :
+ name(name)
+{
+}
+
+QPDF_Name::~QPDF_Name()
+{
+}
+
+std::string
+QPDF_Name::normalizeName(std::string const& name)
+{
+ std::string result;
+ char num[4];
+ result += name[0];
+ for (unsigned int i = 1; i < name.length(); ++i)
+ {
+ char ch = name[i];
+ // Don't use locale/ctype here; follow PDF spec guidlines.
+ if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126))
+ {
+ sprintf(num, "#%02x", (unsigned char) ch);
+ result += num;
+ }
+ else
+ {
+ result += ch;
+ }
+ }
+ return result;
+}
+
+std::string
+QPDF_Name::unparse()
+{
+ return normalizeName(this->name);
+}
+
+std::string
+QPDF_Name::getName() const
+{
+ return this->name;
+}
diff --git a/libqpdf/QPDF_Null.cc b/libqpdf/QPDF_Null.cc
new file mode 100644
index 00000000..57a78b7e
--- /dev/null
+++ b/libqpdf/QPDF_Null.cc
@@ -0,0 +1,12 @@
+
+#include <qpdf/QPDF_Null.hh>
+
+QPDF_Null::~QPDF_Null()
+{
+}
+
+std::string
+QPDF_Null::unparse()
+{
+ return "null";
+}
diff --git a/libqpdf/QPDF_Real.cc b/libqpdf/QPDF_Real.cc
new file mode 100644
index 00000000..87a19cb2
--- /dev/null
+++ b/libqpdf/QPDF_Real.cc
@@ -0,0 +1,23 @@
+
+#include <qpdf/QPDF_Real.hh>
+
+QPDF_Real::QPDF_Real(std::string const& val) :
+ val(val)
+{
+}
+
+QPDF_Real::~QPDF_Real()
+{
+}
+
+std::string
+QPDF_Real::unparse()
+{
+ return this->val;
+}
+
+std::string
+QPDF_Real::getVal()
+{
+ return this->val;
+}
diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc
new file mode 100644
index 00000000..9694f837
--- /dev/null
+++ b/libqpdf/QPDF_Stream.cc
@@ -0,0 +1,309 @@
+
+#include <qpdf/QPDF_Stream.hh>
+
+#include <qpdf/QEXC.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/Pipeline.hh>
+#include <qpdf/Pl_Flate.hh>
+#include <qpdf/Pl_PNGFilter.hh>
+#include <qpdf/Pl_RC4.hh>
+#include <qpdf/Pl_Buffer.hh>
+#include <qpdf/Pl_ASCII85Decoder.hh>
+#include <qpdf/Pl_ASCIIHexDecoder.hh>
+#include <qpdf/Pl_LZWDecoder.hh>
+
+#include <qpdf/QTC.hh>
+#include <qpdf/QPDF.hh>
+#include <qpdf/QPDFExc.hh>
+#include <qpdf/Pl_QPDFTokenizer.hh>
+
+QPDF_Stream::QPDF_Stream(QPDF* qpdf, int objid, int generation,
+ QPDFObjectHandle stream_dict,
+ off_t offset, int length) :
+ qpdf(qpdf),
+ objid(objid),
+ generation(generation),
+ stream_dict(stream_dict),
+ offset(offset),
+ length(length)
+{
+ if (! stream_dict.isDictionary())
+ {
+ throw QEXC::Internal("stream object instantiated with non-dictionary "
+ "object for dictionary");
+ }
+}
+
+QPDF_Stream::~QPDF_Stream()
+{
+}
+
+std::string
+QPDF_Stream::unparse()
+{
+ // Unparse stream objects as indirect references
+ return QUtil::int_to_string(this->objid) + " " +
+ QUtil::int_to_string(this->generation) + " R";
+}
+
+QPDFObjectHandle
+QPDF_Stream::getDict() const
+{
+ return this->stream_dict;
+}
+
+PointerHolder<Buffer>
+QPDF_Stream::getStreamData()
+{
+ Pl_Buffer buf("stream data buffer");
+ if (! pipeStreamData(&buf, true, false, false))
+ {
+ throw QPDFExc("getStreamData called on unfilterable stream");
+ }
+ return buf.getBuffer();
+}
+
+bool
+QPDF_Stream::filterable(std::vector<std::string>& filters,
+ int& predictor, int& columns,
+ bool& early_code_change)
+{
+ // Initialize values to their defaults as per the PDF spec
+ predictor = 1;
+ columns = 0;
+ early_code_change = true;
+
+ bool filterable = true;
+
+ // See if we can support any decode parameters that are specified.
+
+ QPDFObjectHandle decode_obj =
+ this->stream_dict.getKey("/DecodeParms");
+ if (decode_obj.isNull())
+ {
+ // no problem
+ }
+ else if (decode_obj.isDictionary())
+ {
+ std::set<std::string> keys = decode_obj.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ if (key == "/Predictor")
+ {
+ QPDFObjectHandle predictor_obj = decode_obj.getKey(key);
+ if (predictor_obj.isInteger())
+ {
+ predictor = predictor_obj.getIntValue();
+ if (! ((predictor == 1) || (predictor == 12)))
+ {
+ filterable = false;
+ }
+ }
+ else
+ {
+ filterable = false;
+ }
+ }
+ else if (key == "/EarlyChange")
+ {
+ QPDFObjectHandle earlychange_obj = decode_obj.getKey(key);
+ if (earlychange_obj.isInteger())
+ {
+ int earlychange = earlychange_obj.getIntValue();
+ early_code_change = (earlychange == 1);
+ if (! ((earlychange == 0) || (earlychange == 1)))
+ {
+ filterable = false;
+ }
+ }
+ else
+ {
+ filterable = false;
+ }
+ }
+ else if (key == "/Columns")
+ {
+ QPDFObjectHandle columns_obj = decode_obj.getKey(key);
+ if (columns_obj.isInteger())
+ {
+ columns = columns_obj.getIntValue();
+ }
+ else
+ {
+ filterable = false;
+ }
+ }
+ else
+ {
+ filterable = false;
+ }
+ }
+ }
+ else
+ {
+ throw QPDFExc(qpdf->getFilename(), this->offset,
+ "invalid decode parameters object type for this stream");
+ }
+
+ if ((predictor > 1) && (columns == 0))
+ {
+ // invalid
+ filterable = false;
+ }
+
+ if (! filterable)
+ {
+ return false;
+ }
+
+ // Check filters
+
+ QPDFObjectHandle filter_obj = this->stream_dict.getKey("/Filter");
+ bool filters_okay = true;
+
+ if (filter_obj.isNull())
+ {
+ // No filters
+ }
+ else if (filter_obj.isName())
+ {
+ // One filter
+ filters.push_back(filter_obj.getName());
+ }
+ else if (filter_obj.isArray())
+ {
+ // Potentially multiple filters
+ int n = filter_obj.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ QPDFObjectHandle item = filter_obj.getArrayItem(i);
+ if (item.isName())
+ {
+ filters.push_back(item.getName());
+ }
+ else
+ {
+ filters_okay = false;
+ }
+ }
+ }
+ else
+ {
+ filters_okay = false;
+ }
+
+ if (! filters_okay)
+ {
+ QTC::TC("qpdf", "QPDF_Stream invalid filter");
+ throw QPDFExc(qpdf->getFilename(), this->offset,
+ "invalid filter object type for this stream");
+ }
+
+ // `filters' now contains a list of filters to be applied in
+ // order. See which ones we can support.
+
+ for (std::vector<std::string>::iterator iter = filters.begin();
+ iter != filters.end(); ++iter)
+ {
+ std::string const& filter = *iter;
+ if (! ((filter == "/FlateDecode") ||
+ (filter == "/LZWDecode") ||
+ (filter == "/ASCII85Decode") ||
+ (filter == "/ASCIIHexDecode")))
+ {
+ filterable = false;
+ }
+ }
+
+ return filterable;
+}
+
+bool
+QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
+ bool normalize, bool compress)
+{
+ std::vector<std::string> filters;
+ int predictor = 1;
+ int columns = 0;
+ bool early_code_change = true;
+ if (filter)
+ {
+ filter = filterable(filters, predictor, columns, early_code_change);
+ }
+
+ if (pipeline == 0)
+ {
+ QTC::TC("qpdf", "QPDF_Stream pipeStreamData with null pipeline");
+ return filter;
+ }
+
+ // Construct the pipeline in reverse order. Force pipelines we
+ // create to be deleted when this function finishes.
+ std::vector<PointerHolder<Pipeline> > to_delete;
+
+ if (filter)
+ {
+ if (compress)
+ {
+ pipeline = new Pl_Flate("compress object stream", pipeline,
+ Pl_Flate::a_deflate);
+ to_delete.push_back(pipeline);
+ }
+
+ if (normalize)
+ {
+ pipeline = new Pl_QPDFTokenizer("normalizer", pipeline);
+ to_delete.push_back(pipeline);
+ }
+
+ for (std::vector<std::string>::reverse_iterator iter = filters.rbegin();
+ iter != filters.rend(); ++iter)
+ {
+ std::string const& filter = *iter;
+ if (filter == "/FlateDecode")
+ {
+ if (predictor == 12)
+ {
+ QTC::TC("qpdf", "QPDF_Stream PNG filter");
+ pipeline = new Pl_PNGFilter(
+ "png decode", pipeline, Pl_PNGFilter::a_decode,
+ columns, 0 /* not used */);
+ to_delete.push_back(pipeline);
+ }
+
+ pipeline = new Pl_Flate("stream inflate",
+ pipeline, Pl_Flate::a_inflate);
+ to_delete.push_back(pipeline);
+ }
+ else if (filter == "/ASCII85Decode")
+ {
+ pipeline = new Pl_ASCII85Decoder("ascii85 decode", pipeline);
+ to_delete.push_back(pipeline);
+ }
+ else if (filter == "/ASCIIHexDecode")
+ {
+ pipeline = new Pl_ASCIIHexDecoder("asciiHex decode", pipeline);
+ to_delete.push_back(pipeline);
+ }
+ else if (filter == "/LZWDecode")
+ {
+ pipeline = new Pl_LZWDecoder("lzw decode", pipeline,
+ early_code_change);
+ to_delete.push_back(pipeline);
+ }
+ else
+ {
+ throw QEXC::Internal("QPDFStream: unknown filter "
+ "encountered after check");
+ }
+ }
+ }
+
+ QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
+ this->offset, this->length,
+ this->stream_dict, pipeline);
+
+ return filter;
+}
diff --git a/libqpdf/QPDF_String.cc b/libqpdf/QPDF_String.cc
new file mode 100644
index 00000000..cc8ca042
--- /dev/null
+++ b/libqpdf/QPDF_String.cc
@@ -0,0 +1,178 @@
+
+#include <qpdf/QPDF_String.hh>
+
+#include <qpdf/QUtil.hh>
+// DO NOT USE ctype -- it is locale dependent for some things, and
+// it's not worth the risk of including it in case it may accidentally
+// be used.
+#include <string.h>
+
+// See above about ctype.
+static bool is_iso_latin1_printable(unsigned char ch)
+{
+ return (((ch >= 32) && (ch <= 126)) || (ch >= 160));
+}
+
+QPDF_String::QPDF_String(std::string const& val) :
+ val(val)
+{
+}
+
+QPDF_String::~QPDF_String()
+{
+}
+
+std::string
+QPDF_String::unparse()
+{
+ return unparse(false);
+}
+
+std::string
+QPDF_String::unparse(bool force_binary)
+{
+ bool use_hexstring = force_binary;
+ if (! use_hexstring)
+ {
+ unsigned int nonprintable = 0;
+ int consecutive_printable = 0;
+ for (unsigned int i = 0; i < this->val.length(); ++i)
+ {
+ char ch = this->val[i];
+ // Note: do not use locale to determine printability. The PDF
+ // specification accepts arbitrary binary data. Some locales
+ // imply multibyte characters. We'll consider something
+ // printable if it is printable in ISO-Latin-1. We'll code
+ // this manually rather than being rude and setting locale.
+ if ((ch == 0) || (! (is_iso_latin1_printable(ch) ||
+ strchr("\n\r\t\b\f", ch))))
+ {
+ ++nonprintable;
+ consecutive_printable = 0;
+ }
+ else
+ {
+ if (++consecutive_printable > 5)
+ {
+ // If there are more than 5 consecutive printable
+ // characters, I want to see them as such.
+ nonprintable = 0;
+ break;
+ }
+ }
+ }
+
+ // Use hex notation if more than 20% of the characters are not
+ // printable in the current locale. Uniformly distributed random
+ // characters will not pass this test even with ISO-Latin-1 in
+ // which 76% are either printable or in the set of standard
+ // escaped characters.
+ if (5 * nonprintable > val.length())
+ {
+ use_hexstring = true;
+ }
+ }
+ std::string result;
+ if (use_hexstring)
+ {
+ result += "<";
+ char num[3];
+ for (unsigned int i = 0; i < this->val.length(); ++i)
+ {
+ sprintf(num, "%02x", (unsigned char) this->val[i]);
+ result += num;
+ }
+ result += ">";
+ }
+ else
+ {
+ result += "(";
+ char num[5];
+ for (unsigned int i = 0; i < this->val.length(); ++i)
+ {
+ char ch = this->val[i];
+ switch (ch)
+ {
+ case '\n':
+ result += "\\n";
+ break;
+
+ case '\r':
+ result += "\\r";
+ break;
+
+ case '\t':
+ result += "\\t";
+ break;
+
+ case '\b':
+ result += "\\b";
+ break;
+
+ case '\f':
+ result += "\\f";
+ break;
+
+ case '(':
+ result += "\\(";
+ break;
+
+ case ')':
+ result += "\\)";
+ break;
+
+ case '\\':
+ result += "\\\\";
+ break;
+
+ default:
+ if (is_iso_latin1_printable(ch))
+ {
+ result += this->val[i];
+ }
+ else
+ {
+ sprintf(num, "\\%03o", (unsigned char)ch);
+ result += num;
+ }
+ break;
+ }
+ }
+ result += ")";
+ }
+
+ return result;
+}
+
+std::string
+QPDF_String::getVal() const
+{
+ return this->val;
+}
+
+std::string
+QPDF_String::getUTF8Val() const
+{
+ std::string result;
+ unsigned int len = this->val.length();
+ if ((len >= 2) && (len % 2 == 0) &&
+ (this->val[0] == '\xfe') && (this->val[1] == '\xff'))
+ {
+ // This is a Unicode string using big-endian UTF-16. This
+ // code is not actually correct as it doesn't properly handle
+ // characters past 0xffff.
+ for (unsigned int i = 2; i < len; i += 2)
+ {
+ result += QUtil::toUTF8(((unsigned char) this->val[i] << 8) +
+ ((unsigned char) this->val[i+1]));
+ }
+ }
+ else
+ {
+ for (unsigned int i = 0; i < len; ++i)
+ {
+ result += QUtil::toUTF8((unsigned char) this->val[i]);
+ }
+ }
+ return result;
+}
diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc
new file mode 100644
index 00000000..e5e2d8be
--- /dev/null
+++ b/libqpdf/QPDF_encryption.cc
@@ -0,0 +1,441 @@
+// This file implements methods from the QPDF class that involve
+// encryption.
+
+#include <qpdf/QPDF.hh>
+
+#include <qpdf/QPDFExc.hh>
+
+#include <qpdf/QUtil.hh>
+#include <qpdf/Pl_RC4.hh>
+#include <qpdf/RC4.hh>
+#include <qpdf/MD5.hh>
+
+static char const padding_string[] = {
+ 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
+ 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
+ 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
+ 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
+};
+
+static unsigned int const O_key_bytes = sizeof(MD5::Digest);
+static unsigned int const id_bytes = 16;
+static unsigned int const key_bytes = 32;
+
+void
+pad_or_truncate_password(std::string const& password, char k1[key_bytes])
+{
+ int password_bytes = std::min(key_bytes, password.length());
+ int pad_bytes = key_bytes - password_bytes;
+ memcpy(k1, password.c_str(), password_bytes);
+ memcpy(k1 + password_bytes, padding_string, pad_bytes);
+}
+
+void
+QPDF::trim_user_password(std::string& user_password)
+{
+ // Although unnecessary, this routine trims the padding string
+ // from the end of a user password. Its only purpose is for
+ // recovery of user passwords which is done in the test suite.
+ char const* cstr = user_password.c_str();
+ size_t len = user_password.length();
+ if (len < key_bytes)
+ {
+ return;
+ }
+
+ char* p = 0;
+ while ((p = strchr(cstr, '\x28')) != 0)
+ {
+ if (memcmp(p, padding_string, len - (p - cstr)) == 0)
+ {
+ user_password = user_password.substr(0, p - cstr);
+ return;
+ }
+ }
+}
+
+static std::string
+pad_or_truncate_password(std::string const& password)
+{
+ char k1[key_bytes];
+ pad_or_truncate_password(password, k1);
+ return std::string(k1, key_bytes);
+}
+
+static void
+iterate_md5_digest(MD5& md5, MD5::Digest& digest, int iterations)
+{
+ md5.digest(digest);
+
+ for (int i = 0; i < iterations; ++i)
+ {
+ MD5 m;
+ m.encodeDataIncrementally((char*)digest, sizeof(digest));
+ m.digest(digest);
+ }
+}
+
+
+static void
+iterate_rc4(unsigned char* data, int data_len,
+ unsigned char* okey, int key_len,
+ int iterations, bool reverse)
+{
+ unsigned char* key = new unsigned char[key_len];
+ for (int i = 0; i < iterations; ++i)
+ {
+ int const xor_value = (reverse ? iterations - 1 - i : i);
+ for (int j = 0; j < key_len; ++j)
+ {
+ key[j] = okey[j] ^ xor_value;
+ }
+ RC4 rc4(key, key_len);
+ rc4.process(data, data_len);
+ }
+ delete [] key;
+}
+
+std::string
+QPDF::compute_data_key(std::string const& encryption_key,
+ int objid, int generation)
+{
+ // Algorithm 3.1 from the PDF 1.4 Reference Manual
+
+ std::string result = encryption_key;
+
+ // Append low three bytes of object ID and low two bytes of generation
+ result += (char) (objid & 0xff);
+ result += (char) ((objid >> 8) & 0xff);
+ result += (char) ((objid >> 16) & 0xff);
+ result += (char) (generation & 0xff);
+ result += (char) ((generation >> 8) & 0xff);
+
+ MD5 md5;
+ md5.encodeDataIncrementally(result.c_str(), result.length());
+ MD5::Digest digest;
+ md5.digest(digest);
+ return std::string((char*) digest,
+ std::min(result.length(), (size_t) 16));
+}
+
+std::string
+QPDF::compute_encryption_key(
+ std::string const& password, EncryptionData const& data)
+{
+ // Algorithm 3.2 from the PDF 1.4 Reference Manual
+
+ MD5 md5;
+ md5.encodeDataIncrementally(
+ pad_or_truncate_password(password).c_str(), key_bytes);
+ md5.encodeDataIncrementally(data.O.c_str(), key_bytes);
+ char pbytes[4];
+ pbytes[0] = (char) (data.P & 0xff);
+ pbytes[1] = (char) ((data.P >> 8) & 0xff);
+ pbytes[2] = (char) ((data.P >> 16) & 0xff);
+ pbytes[3] = (char) ((data.P >> 24) & 0xff);
+ md5.encodeDataIncrementally(pbytes, 4);
+ md5.encodeDataIncrementally(data.id1.c_str(), id_bytes);
+ MD5::Digest digest;
+ iterate_md5_digest(md5, digest, ((data.R == 3) ? 50 : 0));
+ return std::string((char*)digest, data.Length_bytes);
+}
+
+static void
+compute_O_rc4_key(std::string const& user_password,
+ std::string const& owner_password,
+ QPDF::EncryptionData const& data,
+ unsigned char key[O_key_bytes])
+{
+ std::string password = owner_password;
+ if (password.empty())
+ {
+ password = user_password;
+ }
+ MD5 md5;
+ md5.encodeDataIncrementally(
+ pad_or_truncate_password(password).c_str(), key_bytes);
+ MD5::Digest digest;
+ iterate_md5_digest(md5, digest, ((data.R == 3) ? 50 : 0));
+ memcpy(key, digest, O_key_bytes);
+}
+
+static std::string
+compute_O_value(std::string const& user_password,
+ std::string const& owner_password,
+ QPDF::EncryptionData const& data)
+{
+ // Algorithm 3.3 from the PDF 1.4 Reference Manual
+
+ unsigned char O_key[O_key_bytes];
+ compute_O_rc4_key(user_password, owner_password, data, O_key);
+
+ char upass[key_bytes];
+ pad_or_truncate_password(user_password, upass);
+ iterate_rc4((unsigned char*) upass, key_bytes,
+ O_key, data.Length_bytes, (data.R == 3) ? 20 : 1, false);
+ return std::string(upass, key_bytes);
+}
+
+static
+std::string
+compute_U_value_R2(std::string const& user_password,
+ QPDF::EncryptionData const& data)
+{
+ // Algorithm 3.4 from the PDF 1.4 Reference Manual
+
+ std::string k1 = QPDF::compute_encryption_key(user_password, data);
+ char udata[key_bytes];
+ pad_or_truncate_password("", udata);
+ iterate_rc4((unsigned char*) udata, key_bytes,
+ (unsigned char*)k1.c_str(), data.Length_bytes, 1, false);
+ return std::string(udata, key_bytes);
+}
+
+static
+std::string
+compute_U_value_R3(std::string const& user_password,
+ QPDF::EncryptionData const& data)
+{
+ // Algorithm 3.5 from the PDF 1.4 Reference Manual
+
+ std::string k1 = QPDF::compute_encryption_key(user_password, data);
+ MD5 md5;
+ md5.encodeDataIncrementally(
+ pad_or_truncate_password("").c_str(), key_bytes);
+ md5.encodeDataIncrementally(data.id1.c_str(), data.id1.length());
+ MD5::Digest digest;
+ md5.digest(digest);
+ iterate_rc4(digest, sizeof(MD5::Digest),
+ (unsigned char*) k1.c_str(), data.Length_bytes, 20, false);
+ char result[key_bytes];
+ memcpy(result, digest, sizeof(MD5::Digest));
+ // pad with arbitrary data -- make it consistent for the sake of
+ // testing
+ for (unsigned int i = sizeof(MD5::Digest); i < key_bytes; ++i)
+ {
+ result[i] = (char)((i * i) % 0xff);
+ }
+ return std::string(result, key_bytes);
+}
+
+static std::string
+compute_U_value(std::string const& user_password,
+ QPDF::EncryptionData const& data)
+{
+ if (data.R == 3)
+ {
+ return compute_U_value_R3(user_password, data);
+ }
+
+ return compute_U_value_R2(user_password, data);
+}
+
+static bool
+check_user_password(std::string const& user_password,
+ QPDF::EncryptionData const& data)
+{
+ // Algorithm 3.6 from the PDF 1.4 Reference Manual
+
+ std::string u_value = compute_U_value(user_password, data);
+ int to_compare = ((data.R == 3) ? sizeof(MD5::Digest) : key_bytes);
+ return (memcmp(data.U.c_str(), u_value.c_str(), to_compare) == 0);
+}
+
+static bool
+check_owner_password(std::string& user_password,
+ std::string const& owner_password,
+ QPDF::EncryptionData const& data)
+{
+ // Algorithm 3.7 from the PDF 1.4 Reference Manual
+
+ unsigned char key[O_key_bytes];
+ compute_O_rc4_key(user_password, owner_password, data, key);
+ unsigned char O_data[key_bytes];
+ memcpy(O_data, (unsigned char*) data.O.c_str(), key_bytes);
+ iterate_rc4(O_data, key_bytes, key, data.Length_bytes,
+ (data.R == 3) ? 20 : 1, true);
+ std::string new_user_password =
+ std::string((char*)O_data, key_bytes);
+ bool result = false;
+ if (check_user_password(new_user_password, data))
+ {
+ result = true;
+ user_password = new_user_password;
+ }
+ return result;
+}
+
+void
+QPDF::initializeEncryption()
+{
+ if (this->encryption_initialized)
+ {
+ return;
+ }
+ this->encryption_initialized = true;
+
+ // After we initialize encryption parameters, we must used stored
+ // key information and never look at /Encrypt again. Otherwise,
+ // things could go wrong if someone mutates the encryption
+ // dictionary.
+
+ if (! this->trailer.hasKey("/Encrypt"))
+ {
+ return;
+ }
+
+ QPDFObjectHandle id_obj = this->trailer.getKey("/ID");
+ if (! (id_obj.isArray() &&
+ (id_obj.getArrayNItems() == 2) &&
+ id_obj.getArrayItem(0).isString()))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "invalid /ID in trailer dictionary");
+ }
+
+ std::string id1 = id_obj.getArrayItem(0).getStringValue();
+ if (id1.length() != id_bytes)
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "first /ID string in trailer dictionary has "
+ "incorrect length");
+ }
+
+ QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt");
+ if (! encryption_dict.isDictionary())
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "/Encrypt in trailer dictionary is not a dictionary");
+ }
+
+ if (! (encryption_dict.getKey("/Filter").isName() &&
+ (encryption_dict.getKey("/Filter").getName() == "/Standard")))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "unsupported encryption filter");
+ }
+
+ if (! (encryption_dict.getKey("/V").isInteger() &&
+ encryption_dict.getKey("/R").isInteger() &&
+ encryption_dict.getKey("/O").isString() &&
+ encryption_dict.getKey("/U").isString() &&
+ encryption_dict.getKey("/P").isInteger()))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "some encryption dictionary parameters are missing "
+ "or the wrong type");
+ }
+
+ int V = encryption_dict.getKey("/V").getIntValue();
+ int R = encryption_dict.getKey("/R").getIntValue();
+ std::string O = encryption_dict.getKey("/O").getStringValue();
+ std::string U = encryption_dict.getKey("/U").getStringValue();
+ unsigned int P = (unsigned int) encryption_dict.getKey("/P").getIntValue();
+
+ if (! (((R == 2) || (R == 3)) &&
+ ((V == 1) || (V == 2))))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "Unsupported /R or /V in encryption dictionary");
+ }
+
+ if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "incorrect length for /O and/or /P in "
+ "encryption dictionary");
+ }
+
+ int Length = 40;
+ if (encryption_dict.getKey("/Length").isInteger())
+ {
+ Length = encryption_dict.getKey("/Length").getIntValue();
+ if ((Length % 8) || (Length < 40) || (Length > 128))
+ {
+ throw QPDFExc(this->file.getName(), this->file.getLastOffset(),
+ "invalid /Length value in encryption dictionary");
+ }
+ }
+
+ EncryptionData data(V, R, Length / 8, P, O, U, id1);
+ if (check_owner_password(this->user_password, this->provided_password, data))
+ {
+ // password supplied was owner password; user_password has
+ // been initialized
+ }
+ else if (check_user_password(this->provided_password, data))
+ {
+ this->user_password = this->provided_password;
+ }
+ else
+ {
+ throw QPDFExc(this->file.getName() + ": invalid password");
+ }
+
+ this->encrypted = true;
+ this->encryption_key = compute_encryption_key(this->user_password, data);
+}
+
+std::string
+QPDF::getKeyForObject(int objid, int generation)
+{
+ if (! this->encrypted)
+ {
+ throw QEXC::Internal("request for encryption key in non-encrypted PDF");
+ }
+
+ if (! ((objid == this->cached_key_objid) &&
+ (generation == this->cached_key_generation)))
+ {
+ this->cached_object_encryption_key =
+ compute_data_key(this->encryption_key, objid, generation);
+ this->cached_key_objid = objid;
+ this->cached_key_generation = generation;
+ }
+
+ return this->cached_object_encryption_key;
+}
+
+void
+QPDF::decryptString(std::string& str, int objid, int generation)
+{
+ if (objid == 0)
+ {
+ return;
+ }
+ std::string key = getKeyForObject(objid, generation);
+ char* tmp = QUtil::copy_string(str);
+ unsigned int vlen = str.length();
+ RC4 rc4((unsigned char const*)key.c_str(), key.length());
+ rc4.process((unsigned char*)tmp, vlen);
+ str = std::string(tmp, vlen);
+ delete [] tmp;
+}
+
+void
+QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation,
+ std::vector<PointerHolder<Pipeline> >& heap)
+{
+ std::string key = getKeyForObject(objid, generation);
+ pipeline = new Pl_RC4("stream decryption", pipeline,
+ (unsigned char*) key.c_str(), key.length());
+ heap.push_back(pipeline);
+}
+
+void
+QPDF::compute_encryption_O_U(
+ char const* user_password, char const* owner_password,
+ int V, int R, int key_len, unsigned long P,
+ std::string const& id1, std::string& O, std::string& U)
+{
+ EncryptionData data(V, R, key_len, P, "", "", id1);
+ data.O = compute_O_value(user_password, owner_password, data);
+ O = data.O;
+ U = compute_U_value(user_password, data);
+}
+
+std::string const&
+QPDF::getUserPassword() const
+{
+ return this->user_password;
+}
diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc
new file mode 100644
index 00000000..6c0cf3be
--- /dev/null
+++ b/libqpdf/QPDF_linearization.cc
@@ -0,0 +1,2103 @@
+// See doc/linearization.
+
+#include <qpdf/QPDF.hh>
+
+#include <qpdf/QPDFExc.hh>
+#include <qpdf/QTC.hh>
+#include <qpdf/QUtil.hh>
+#include <qpdf/PCRE.hh>
+#include <qpdf/Pl_Buffer.hh>
+#include <qpdf/Pl_Flate.hh>
+#include <qpdf/Pl_Count.hh>
+#include <qpdf/BitWriter.hh>
+#include <qpdf/BitStream.hh>
+
+#include <iostream>
+#include <algorithm>
+#include <assert.h>
+#include <math.h>
+
+template <class T>
+static void
+load_vector_int(BitStream& bit_stream, int nitems, std::vector<T>& vec,
+ int bits_wanted, int T::*field)
+{
+ // nitems times, read bits_wanted from the given bit stream,
+ // storing results in the ith vector entry.
+
+ for (int i = 0; i < nitems; ++i)
+ {
+ vec[i].*field = bit_stream.getBits(bits_wanted);
+ }
+ // The PDF spec says that each hint table starts at a byte
+ // boundary. Each "row" actually must start on a byte boundary.
+ bit_stream.skipToNextByte();
+}
+
+template <class T>
+static void
+load_vector_vector(BitStream& bit_stream,
+ int nitems1, std::vector<T>& vec1, int T::*nitems2,
+ int bits_wanted, std::vector<int> T::*vec2)
+{
+ // nitems1 times, read nitems2 (from the ith element of vec1) items
+ // into the vec2 vector field of the ith item of vec1.
+ for (int i1 = 0; i1 < nitems1; ++i1)
+ {
+ for (int i2 = 0; i2 < vec1[i1].*nitems2; ++i2)
+ {
+ (vec1[i1].*vec2).push_back(bit_stream.getBits(bits_wanted));
+ }
+ }
+ bit_stream.skipToNextByte();
+}
+
+bool
+QPDF::checkLinearization()
+{
+ bool result = false;
+ try
+ {
+ readLinearizationData();
+ result = checkLinearizationInternal();
+ }
+ catch (QPDFExc& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ return result;
+}
+
+bool
+QPDF::isLinearized()
+{
+ // If the first object in the file is a dictionary with a suitable
+ // /Linearized key and has an /L key that accurately indicates the
+ // file size, initialize this->lindict and return true.
+
+ // A linearized PDF spec's first object will be contained within
+ // the first 1024 bytes of the file and will be a dictionary with
+ // a valid /Linearized key. This routine looks for that and does
+ // no additional validation.
+
+ // The PDF spec says the linearization dictionary must be
+ // completely contained within the first 1024 bytes of the file.
+ // Add a byte for a null terminator.
+ static int const tbuf_size = 1025;
+
+ char* buf = new char[tbuf_size];
+ this->file.seek(0, SEEK_SET);
+ PointerHolder<char> b(buf); // guarantee deletion
+ memset(buf, '\0', tbuf_size);
+ this->file.read(buf, tbuf_size - 1);
+
+ static PCRE lindict_re("(?s:(\\d+)\\s+0\\s+obj\\s*<<)");
+
+ off_t offset = -1;
+ int lindict_obj = 0;
+ char* p = buf;
+ while (lindict_obj == 0)
+ {
+ PCRE::Match m(lindict_re.match(p));
+ if (m)
+ {
+ offset = m.getOffset(0) + (p - buf);
+ lindict_obj = atoi(m.getMatch(1).c_str());
+ if (m.getMatch(0).find('\n') != std::string::npos)
+ {
+ QTC::TC("qpdf", "QPDF lindict found newline");
+ }
+ }
+ else
+ {
+ if ((p = (char*)memchr(p, '\0', tbuf_size - (p - buf))) != 0)
+ {
+ QTC::TC("qpdf", "QPDF lindict null found");
+ while ((p - buf < tbuf_size) && (*p == 0))
+ {
+ ++p;
+ }
+ if ((p - buf) == tbuf_size)
+ {
+ break;
+ }
+ QTC::TC("qpdf", "QPDF lindict searching after null");
+ }
+ }
+ }
+
+ if (lindict_obj == 0)
+ {
+ return false;
+ }
+
+ QPDFObjectHandle candidate = QPDFObjectHandle::Factory::newIndirect(
+ this, lindict_obj, 0);
+ if (! candidate.isDictionary())
+ {
+ return false;
+ }
+
+ QPDFObjectHandle linkey = candidate.getKey("/Linearized");
+ if (! (linkey.isNumber() && ((int)floor(linkey.getNumericValue()) == 1)))
+ {
+ return false;
+ }
+
+ QPDFObjectHandle L = candidate.getKey("/L");
+ if (L.isInteger())
+ {
+ int Li = L.getIntValue();
+ this->file.seek(0, SEEK_END);
+ if (Li != this->file.tell())
+ {
+ QTC::TC("qpdf", "QPDF /L mismatch");
+ return false;
+ }
+ else
+ {
+ this->linp.file_size = Li;
+ }
+ }
+
+ this->lindict = candidate;
+
+ return true;
+}
+
+void
+QPDF::readLinearizationData()
+{
+ // This function throws an exception (which is trapped by
+ // checkLinearization()) for any errors that prevent loading.
+
+ // Hint table parsing code needs at least 32 bits in a long.
+ assert(sizeof(long) >= 4);
+
+ if (! isLinearized())
+ {
+ throw QPDFExc(this->file.getName() + " is not linearized");
+ }
+
+ // /L is read and stored in linp by isLinearized()
+ QPDFObjectHandle H = lindict.getKey("/H");
+ QPDFObjectHandle O = lindict.getKey("/O");
+ QPDFObjectHandle E = lindict.getKey("/E");
+ QPDFObjectHandle N = lindict.getKey("/N");
+ QPDFObjectHandle T = lindict.getKey("/T");
+ QPDFObjectHandle P = lindict.getKey("/P");
+
+ if (! (H.isArray() &&
+ O.isInteger() &&
+ E.isInteger() &&
+ N.isInteger() &&
+ T.isInteger() &&
+ (P.isInteger() || P.isNull())))
+ {
+ throw QPDFExc("some keys in linearization dictionary are of "
+ "the wrong type");
+ }
+
+ // Hint table array: offset length [ offset length ]
+ unsigned int n_H_items = H.getArrayNItems();
+ if (! ((n_H_items == 2) || (n_H_items == 4)))
+ {
+ throw QPDFExc("H has the wrong number of items");
+ }
+
+ std::vector<int> H_items;
+ for (unsigned int i = 0; i < n_H_items; ++i)
+ {
+ QPDFObjectHandle oh(H.getArrayItem(i));
+ if (oh.isInteger())
+ {
+ H_items.push_back(oh.getIntValue());
+ }
+ else
+ {
+ throw QPDFExc("some H items are of the wrong type");
+ }
+ }
+
+ // H: hint table offset/length for primary and overflow hint tables
+ int H0_offset = H_items[0];
+ int H0_length = H_items[1];
+ int H1_offset = 0;
+ int H1_length = 0;
+ if (H_items.size() == 4)
+ {
+ // Acrobat doesn't read or write these (as PDF 1.4), so we
+ // don't have a way to generate a test case.
+ // QTC::TC("qpdf", "QPDF overflow hint table");
+ H1_offset = H_items[2];
+ H1_length = H_items[3];
+ }
+
+ // P: first page number
+ int first_page = 0;
+ if (P.isInteger())
+ {
+ QTC::TC("qpdf", "QPDF P present in lindict");
+ first_page = P.getIntValue();
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF P absent in lindict");
+ }
+
+ // Store linearization parameter data
+
+ // file_size initialized by isLinearized()
+ this->linp.first_page_object = O.getIntValue();
+ this->linp.first_page_end = E.getIntValue();
+ this->linp.npages = N.getIntValue();
+ this->linp.xref_zero_offset = T.getIntValue();
+ this->linp.first_page = first_page;
+ this->linp.H_offset = H0_offset;
+ this->linp.H_length = H0_length;
+
+ // Read hint streams
+
+ Pl_Buffer pb("hint buffer");
+ QPDFObjectHandle H0 = readHintStream(pb, H0_offset, H0_length);
+ if (H1_offset)
+ {
+ (void) readHintStream(pb, H1_offset, H1_length);
+ }
+
+ // PDF 1.4 hint tables that we ignore:
+
+ // /T thumbnail
+ // /A thread information
+ // /E named destination
+ // /V interactive form
+ // /I information dictionary
+ // /C logical structure
+ // /L page label
+
+ // Individual hint table offsets
+ QPDFObjectHandle HS = H0.getKey("/S"); // shared object
+ QPDFObjectHandle HO = H0.getKey("/O"); // outline
+
+ PointerHolder<Buffer> hbp = pb.getBuffer();
+ Buffer* hb = hbp.getPointer();
+ unsigned char const* h_buf = hb->getBuffer();
+ int h_size = hb->getSize();
+
+ readHPageOffset(BitStream(h_buf, h_size));
+
+ int HSi = HS.getIntValue();
+ readHSharedObject(BitStream(h_buf + HSi, h_size - HSi));
+
+ if (HO.isInteger())
+ {
+ int HOi = HO.getIntValue();
+ readHGeneric(BitStream(h_buf + HOi, h_size - HOi),
+ this->outline_hints);
+ }
+}
+
+QPDFObjectHandle
+QPDF::readHintStream(Pipeline& pl, off_t offset, size_t length)
+{
+ int obj;
+ int gen;
+ QPDFObjectHandle H = readObjectAtOffset(offset, 0, 0, obj, gen);
+ ObjCache& oc = this->obj_cache[ObjGen(obj, gen)];
+ off_t min_end_offset = oc.end_before_space;
+ off_t max_end_offset = oc.end_after_space;
+ if (! H.isStream())
+ {
+ throw QPDFExc("hint table is not a stream");
+ }
+
+ QPDFObjectHandle Hdict = H.getDict();
+
+ // Some versions of Acrobat make /Length indirect and place it
+ // immediately after the stream, increasing length to cover it,
+ // even though the specification says all objects in the
+ // linearization parameter dictionary must be direct. We have to
+ // get the file position of the end of length in this case.
+ QPDFObjectHandle length_obj = Hdict.getKey("/Length");
+ if (length_obj.isIndirect())
+ {
+ QTC::TC("qpdf", "QPDF hint table length indirect");
+ // Force resolution
+ (void) length_obj.getIntValue();
+ ObjCache& oc = this->obj_cache
+ [ObjGen(length_obj.getObjectID(),
+ length_obj.getGeneration())];
+ min_end_offset = oc.end_before_space;
+ max_end_offset = oc.end_after_space;
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF hint table length direct");
+ }
+ off_t computed_end = offset + length;
+ if ((computed_end < min_end_offset) ||
+ (computed_end > max_end_offset))
+ {
+ std::cout << "expected = " << computed_end
+ << "; actual = " << min_end_offset << ".."
+ << max_end_offset << std::endl;
+ throw QPDFExc("hint table length mismatch");
+ }
+ H.pipeStreamData(&pl, true, false, false);
+ return Hdict;
+}
+
+void
+QPDF::readHPageOffset(BitStream h)
+{
+ // All comments referring to the PDF spec refer to the spec for
+ // version 1.4.
+
+ HPageOffset& t = this->page_offset_hints;
+
+ t.min_nobjects = h.getBits(32); // 1
+ t.first_page_offset = h.getBits(32); // 2
+ t.nbits_delta_nobjects = h.getBits(16); // 3
+ t.min_page_length = h.getBits(32); // 4
+ t.nbits_delta_page_length = h.getBits(16); // 5
+ t.min_content_offset = h.getBits(32); // 6
+ t.nbits_delta_content_offset = h.getBits(16); // 7
+ t.min_content_length = h.getBits(32); // 8
+ t.nbits_delta_content_length = h.getBits(16); // 9
+ t.nbits_nshared_objects = h.getBits(16); // 10
+ t.nbits_shared_identifier = h.getBits(16); // 11
+ t.nbits_shared_numerator = h.getBits(16); // 12
+ t.shared_denominator = h.getBits(16); // 13
+
+ unsigned int nitems = this->linp.npages;
+ std::vector<HPageOffsetEntry>& entries = t.entries;
+ entries = std::vector<HPageOffsetEntry>(nitems);
+
+ load_vector_int(h, nitems, entries,
+ t.nbits_delta_nobjects,
+ &HPageOffsetEntry::delta_nobjects);
+ load_vector_int(h, nitems, entries,
+ t.nbits_delta_page_length,
+ &HPageOffsetEntry::delta_page_length);
+ load_vector_int(h, nitems, entries,
+ t.nbits_nshared_objects,
+ &HPageOffsetEntry::nshared_objects);
+ load_vector_vector(h, nitems, entries,
+ &HPageOffsetEntry::nshared_objects,
+ t.nbits_shared_identifier,
+ &HPageOffsetEntry::shared_identifiers);
+ load_vector_vector(h, nitems, entries,
+ &HPageOffsetEntry::nshared_objects,
+ t.nbits_shared_numerator,
+ &HPageOffsetEntry::shared_numerators);
+ load_vector_int(h, nitems, entries,
+ t.nbits_delta_content_offset,
+ &HPageOffsetEntry::delta_content_offset);
+ load_vector_int(h, nitems, entries,
+ t.nbits_delta_content_length,
+ &HPageOffsetEntry::delta_content_length);
+}
+
+void
+QPDF::readHSharedObject(BitStream h)
+{
+ HSharedObject& t = this->shared_object_hints;
+
+ t.first_shared_obj = h.getBits(32); // 1
+ t.first_shared_offset = h.getBits(32); // 2
+ t.nshared_first_page = h.getBits(32); // 3
+ t.nshared_total = h.getBits(32); // 4
+ t.nbits_nobjects = h.getBits(16); // 5
+ t.min_group_length = h.getBits(32); // 6
+ t.nbits_delta_group_length = h.getBits(16); // 7
+
+ QTC::TC("qpdf", "QPDF lin nshared_total > nshared_first_page",
+ (t.nshared_total > t.nshared_first_page) ? 1 : 0);
+
+ int nitems = t.nshared_total;
+ std::vector<HSharedObjectEntry>& entries = t.entries;
+ entries = std::vector<HSharedObjectEntry>(nitems);
+
+ load_vector_int(h, nitems, entries,
+ t.nbits_delta_group_length,
+ &HSharedObjectEntry::delta_group_length);
+ load_vector_int(h, nitems, entries,
+ 1, &HSharedObjectEntry::signature_present);
+ for (int i = 0; i < nitems; ++i)
+ {
+ if (entries[i].signature_present)
+ {
+ // Skip 128-bit MD5 hash. These are not supported by
+ // acrobat, so they should probably never be there. We
+ // have no test case for this.
+ for (int j = 0; j < 4; ++j)
+ {
+ (void) h.getBits(32);
+ }
+ }
+ }
+ load_vector_int(h, nitems, entries,
+ t.nbits_nobjects,
+ &HSharedObjectEntry::nobjects_minus_one);
+}
+
+void
+QPDF::readHGeneric(BitStream h, HGeneric& t)
+{
+ t.first_object = h.getBits(32); // 1
+ t.first_object_offset = h.getBits(32); // 2
+ t.nobjects = h.getBits(32); // 3
+ t.group_length = h.getBits(32); // 4
+}
+
+bool
+QPDF::checkLinearizationInternal()
+{
+ // All comments referring to the PDF spec refer to the spec for
+ // version 1.4.
+
+ std::list<std::string> errors;
+ std::list<std::string> warnings;
+
+ // Check all values in linearization parameter dictionary
+
+ LinParameters& p = this->linp;
+
+ // L: file size in bytes -- checked by isLinearized
+
+ // O: object number of first page
+ std::vector<QPDFObjectHandle> const& pages = getAllPages();
+ if (p.first_page_object != pages[0].getObjectID())
+ {
+ QTC::TC("qpdf", "QPDF err /O mismatch");
+ errors.push_back("first page object (/O) mismatch");
+ }
+
+ // N: number of pages
+ int npages = pages.size();
+ if (p.npages != npages)
+ {
+ // Not tested in the test suite
+ errors.push_back("page count (/N) mismatch");
+ }
+
+ for (int i = 0; i < npages; ++i)
+ {
+ QPDFObjectHandle const& page = pages[i];
+ ObjGen og(page.getObjectID(), page.getGeneration());
+ if (this->xref_table[og].getType() == 2)
+ {
+ errors.push_back("page dictionary for page " +
+ QUtil::int_to_string(i) + " is compressed");
+ }
+ }
+
+ // T: offset of whitespace character preceding xref entry for object 0
+ this->file.seek(p.xref_zero_offset, SEEK_SET);
+ while (1)
+ {
+ char ch;
+ this->file.read(&ch, 1);
+ if (! ((ch == ' ') || (ch == '\r') || (ch == '\n')))
+ {
+ this->file.seek(-1, SEEK_CUR);
+ break;
+ }
+ }
+ if (this->file.tell() != this->first_xref_item_offset)
+ {
+ QTC::TC("qpdf", "QPDF err /T mismatch");
+ errors.push_back("space before first xref item (/T) mismatch "
+ "(computed = " +
+ QUtil::int_to_string(this->first_xref_item_offset) +
+ "; file = " + QUtil::int_to_string(this->file.tell()));
+ }
+
+ // P: first page number -- Implementation note 124 says Acrobat
+ // ignores this value, so we will too.
+
+ // Check numbering of compressed objects in each xref section.
+ // For linearized files, all compressed objects are supposed to be
+ // at the end of the containing xref section if any object streams
+ // are in use.
+
+ if (this->uncompressed_after_compressed)
+ {
+ errors.push_back("linearized file contains an uncompressed object"
+ " after a compressed one in a cross-reference stream");
+ }
+
+ // Further checking requires optimization and order calculation.
+ // Don't allow optimization to make changes. If it has to, then
+ // the file is not properly linearized. We use the xref table to
+ // figure out which objects are compressed and which are
+ // uncompressed.
+ { // local scope
+ std::map<int, int> object_stream_data;
+ for (std::map<ObjGen, QPDFXRefEntry>::const_iterator iter =
+ this->xref_table.begin();
+ iter != this->xref_table.end(); ++iter)
+ {
+ ObjGen const& og = (*iter).first;
+ QPDFXRefEntry const& entry = (*iter).second;
+ if (entry.getType() == 2)
+ {
+ object_stream_data[og.obj] = entry.getObjStreamNumber();
+ }
+ }
+ optimize(object_stream_data, false);
+ calculateLinearizationData(object_stream_data);
+ }
+
+ // E: offset of end of first page -- Implementation note 123 says
+ // Acrobat includes on extra object here by mistake. pdlin fails
+ // to place thumbnail images in section 9, so when thumbnails are
+ // present, it also gets the wrong value for /E. It also doesn't
+ // count outlines here when it should even though it places them
+ // in part 6. This code fails to put thread information
+ // dictionaries in part 9, so it actually gets the wrong value for
+ // E when threads are present. In that case, it would probably
+ // agree with pdlin. As of this writing, the test suite doesn't
+ // contain any files with threads.
+
+ assert(! this->part6.empty());
+ int min_E = -1;
+ int max_E = -1;
+ for (std::vector<QPDFObjectHandle>::iterator iter = this->part6.begin();
+ iter != this->part6.end(); ++iter)
+ {
+ ObjGen og((*iter).getObjectID(), (*iter).getGeneration());
+ // All objects have to have been dereferenced to be classified.
+ assert(this->obj_cache.count(og) > 0);
+ ObjCache const& oc = this->obj_cache[og];
+ min_E = std::max(min_E, (int)oc.end_before_space);
+ max_E = std::max(max_E, (int)oc.end_after_space);
+ }
+ if ((p.first_page_end < min_E) || (p.first_page_end > max_E))
+ {
+ QTC::TC("qpdf", "QPDF warn /E mismatch");
+ warnings.push_back("end of first page section (/E) mismatch: /E = " +
+ QUtil::int_to_string(p.first_page_end) +
+ "; computed = " +
+ QUtil::int_to_string(min_E) + ".." +
+ QUtil::int_to_string(max_E));
+ }
+
+ // Check hint tables
+
+ std::map<int, int> shared_idx_to_obj;
+ checkHSharedObject(errors, warnings, pages, shared_idx_to_obj);
+ checkHPageOffset(errors, warnings, pages, shared_idx_to_obj);
+ checkHOutlines(warnings);
+
+ // Report errors
+
+ bool result = true;
+
+ if (! errors.empty())
+ {
+ result = false;
+ for (std::list<std::string>::iterator iter = errors.begin();
+ iter != errors.end(); ++iter)
+ {
+ std::cout << "ERROR: " << (*iter) << std::endl;
+ }
+ }
+
+ if (! warnings.empty())
+ {
+ result = false;
+ for (std::list<std::string>::iterator iter = warnings.begin();
+ iter != warnings.end(); ++iter)
+ {
+ std::cout << "WARNING: " << (*iter) << std::endl;
+ }
+ }
+
+ return result;
+}
+
+int
+QPDF::maxEnd(ObjUser const& ou)
+{
+ assert(this->obj_user_to_objects.count(ou) > 0);
+ std::set<ObjGen> const& ogs = this->obj_user_to_objects[ou];
+ int end = 0;
+ for (std::set<ObjGen>::iterator iter = ogs.begin();
+ iter != ogs.end(); ++iter)
+ {
+ ObjGen const& og = *iter;
+ assert(this->obj_cache.count(og) > 0);
+ end = std::max(
+ end, (int)(this->obj_cache[og].end_after_space));
+ }
+ return end;
+}
+
+int
+QPDF::getLinearizationOffset(ObjGen const& og)
+{
+ QPDFXRefEntry entry = this->xref_table[og];
+ int result = 0;
+ switch (entry.getType())
+ {
+ case 1:
+ result = entry.getOffset();
+ break;
+
+ case 2:
+ // For compressed objects, return the offset of the object
+ // stream that contains them.
+ result = getLinearizationOffset(ObjGen(entry.getObjStreamNumber(), 0));
+ break;
+
+ default:
+ throw QPDFExc(
+ this->file.getName(), 0,
+ "getLinearizationOffset called for xref entry not of type 1 or 2");
+ break;
+ }
+ return result;
+}
+
+QPDFObjectHandle
+QPDF::getUncompressedObject(QPDFObjectHandle& obj,
+ std::map<int, int> const& object_stream_data)
+{
+ if (obj.isNull() || (object_stream_data.count(obj.getObjectID()) == 0))
+ {
+ return obj;
+ }
+ else
+ {
+ int repl = (*(object_stream_data.find(obj.getObjectID()))).second;
+ return objGenToIndirect(ObjGen(repl, 0));
+ }
+}
+
+int
+QPDF::lengthNextN(int first_object, int n,
+ std::list<std::string>& errors)
+{
+ int length = 0;
+ for (int i = 0; i < n; ++i)
+ {
+ ObjGen og(first_object + i, 0);
+ if (this->xref_table.count(og) == 0)
+ {
+ errors.push_back(
+ "no xref table entry for " +
+ QUtil::int_to_string(first_object + i) + " 0");
+ }
+ else
+ {
+ assert(this->obj_cache.count(og) > 0);
+ length += this->obj_cache[og].end_after_space -
+ getLinearizationOffset(og);
+ }
+ }
+ return length;
+}
+
+void
+QPDF::checkHPageOffset(std::list<std::string>& errors,
+ std::list<std::string>& warnings,
+ std::vector<QPDFObjectHandle> const& pages,
+ std::map<int, int>& shared_idx_to_obj)
+{
+ // Implementation note 126 says Acrobat always sets
+ // delta_content_offset and delta_content_length in the page
+ // offset header dictionary to 0. It also states that
+ // min_content_offset in the per-page information is always 0,
+ // which is an incorrect value.
+
+ // Implementation note 127 explains that Acrobat always sets item
+ // 8 (min_content_length) to zero, item 9
+ // (nbits_delta_content_length) to the value of item 5
+ // (nbits_delta_page_length), and item 7 of each per-page hint
+ // table (delta_content_length) to item 2 (delta_page_length) of
+ // that entry. Acrobat ignores these values when reading files.
+
+ // Empirically, it also seems that Acrobat sometimes puts items
+ // under a page's /Resources dictionary in with shared objects
+ // even when they are private.
+
+ unsigned int npages = pages.size();
+ int table_offset = adjusted_offset(
+ this->page_offset_hints.first_page_offset);
+ ObjGen first_page_og(pages[0].getObjectID(), pages[0].getGeneration());
+ assert(this->xref_table.count(first_page_og) > 0);
+ int offset = getLinearizationOffset(first_page_og);
+ if (table_offset != offset)
+ {
+ warnings.push_back("first page object offset mismatch");
+ }
+
+ for (unsigned int pageno = 0; pageno < npages; ++pageno)
+ {
+ ObjGen page_og(pages[pageno].getObjectID(),
+ pages[pageno].getGeneration());
+ int first_object = page_og.obj;
+ assert(this->xref_table.count(page_og) > 0);
+ offset = getLinearizationOffset(page_og);
+
+ HPageOffsetEntry& he = this->page_offset_hints.entries[pageno];
+ CHPageOffsetEntry& ce = this->c_page_offset_data.entries[pageno];
+ int h_nobjects = he.delta_nobjects +
+ this->page_offset_hints.min_nobjects;
+ if (h_nobjects != ce.nobjects)
+ {
+ // This happens with pdlin when there are thumbnails.
+ warnings.push_back(
+ "object count mismatch for page " +
+ QUtil::int_to_string(pageno) + ": hint table = " +
+ QUtil::int_to_string(h_nobjects) + "; computed = " +
+ QUtil::int_to_string(ce.nobjects));
+ }
+
+ // Use value for number of objects in hint table rather than
+ // computed value if there is a discrepancy.
+ int length = lengthNextN(first_object, h_nobjects, errors);
+ int h_length = he.delta_page_length +
+ this->page_offset_hints.min_page_length;
+ if (length != h_length)
+ {
+ // This condition almost certainly indicates a bad hint
+ // table or a bug in this code.
+ errors.push_back(
+ "page length mismatch for page " +
+ QUtil::int_to_string(pageno) + ": hint table = " +
+ QUtil::int_to_string(h_length) + "; computed length = " +
+ QUtil::int_to_string(length) + " (offset = " +
+ QUtil::int_to_string(offset) + ")");
+ }
+
+ offset += h_length;
+
+ // Translate shared object indexes to object numbers.
+ std::set<int> hint_shared;
+ std::set<int> computed_shared;
+
+ if ((pageno == 0) && (he.nshared_objects > 0))
+ {
+ // pdlin and Acrobat both do this even though the spec
+ // states clearly and unambiguously that they should not.
+ warnings.push_back("page 0 has shared identifier entries");
+ }
+
+ for (int i = 0; i < he.nshared_objects; ++i)
+ {
+ int idx = he.shared_identifiers[i];
+ assert(shared_idx_to_obj.count(idx) > 0);
+ hint_shared.insert(shared_idx_to_obj[idx]);
+ }
+
+ for (int i = 0; i < ce.nshared_objects; ++i)
+ {
+ int idx = ce.shared_identifiers[i];
+ assert(idx < this->c_shared_object_data.nshared_total);
+ int obj = this->c_shared_object_data.entries[idx].object;
+ computed_shared.insert(obj);
+ }
+
+ for (std::set<int>::iterator iter = hint_shared.begin();
+ iter != hint_shared.end(); ++iter)
+ {
+ if (! computed_shared.count(*iter))
+ {
+ // pdlin puts thumbnails here even though it shouldn't
+ warnings.push_back(
+ "page " + QUtil::int_to_string(pageno) +
+ ": shared object " + QUtil::int_to_string(*iter) +
+ ": in hint table but not computed list");
+ }
+ }
+
+ for (std::set<int>::iterator iter = computed_shared.begin();
+ iter != computed_shared.end(); ++iter)
+ {
+ if (! hint_shared.count(*iter))
+ {
+ // Acrobat does not put some things including at least
+ // built-in fonts and procsets here, at least in some
+ // cases.
+ warnings.push_back(
+ "page " + QUtil::int_to_string(pageno) +
+ ": shared object " + QUtil::int_to_string(*iter) +
+ ": in computed list but not hint table");
+ }
+ }
+ }
+}
+
+void
+QPDF::checkHSharedObject(std::list<std::string>& errors,
+ std::list<std::string>& warnings,
+ std::vector<QPDFObjectHandle> const& pages,
+ std::map<int, int>& idx_to_obj)
+{
+ // Implementation note 125 says shared object groups always
+ // contain only one object. Implementation note 128 says that
+ // Acrobat always nbits_nobjects to zero. Implementation note 130
+ // says that Acrobat does not support more than one shared object
+ // per group. These are all consistent.
+
+ // Implementation note 129 states that MD5 signatures are not
+ // implemented in Acrobat, so signature_present must always be
+ // zero.
+
+ // Implementation note 131 states that first_shared_obj and
+ // first_shared_offset have meaningless values for single-page
+ // files.
+
+ // Empirically, Acrobat and pdlin generate incorrect values for
+ // these whenever there are no shared objects not referenced by
+ // the first page (i.e., nshared_total == nshared_first_page).
+
+ HSharedObject& so = this->shared_object_hints;
+ if (so.nshared_total < so.nshared_first_page)
+ {
+ errors.push_back("shared object hint table: ntotal < nfirst_page");
+ }
+ else
+ {
+ // The first nshared_first_page objects are consecutive
+ // objects starting with the first page object. The rest are
+ // consecutive starting from the first_shared_obj object.
+ int cur_object = pages[0].getObjectID();
+ for (int i = 0; i < so.nshared_total; ++i)
+ {
+ if (i == so.nshared_first_page)
+ {
+ QTC::TC("qpdf", "QPDF lin check shared past first page");
+ if (this->part8.empty())
+ {
+ errors.push_back(
+ "part 8 is empty but nshared_total > "
+ "nshared_first_page");
+ }
+ else
+ {
+ int obj = this->part8[0].getObjectID();
+ if (obj != so.first_shared_obj)
+ {
+ errors.push_back(
+ "first shared object number mismatch: "
+ "hint table = " +
+ QUtil::int_to_string(so.first_shared_obj) +
+ "; computed = " +
+ QUtil::int_to_string(obj));
+ }
+ }
+
+ cur_object = so.first_shared_obj;
+
+ ObjGen og(cur_object, 0);
+ assert(this->xref_table.count(og) > 0);
+ int offset = getLinearizationOffset(og);
+ int h_offset = adjusted_offset(so.first_shared_offset);
+ if (offset != h_offset)
+ {
+ errors.push_back(
+ "first shared object offset mismatch: hint table = " +
+ QUtil::int_to_string(h_offset) + "; computed = " +
+ QUtil::int_to_string(offset));
+ }
+ }
+
+ idx_to_obj[i] = cur_object;
+ HSharedObjectEntry& se = so.entries[i];
+ int nobjects = se.nobjects_minus_one + 1;
+ int length = lengthNextN(cur_object, nobjects, errors);
+ int h_length = so.min_group_length + se.delta_group_length;
+ if (length != h_length)
+ {
+ errors.push_back(
+ "shared object " + QUtil::int_to_string(i) +
+ " length mismatch: hint table = " +
+ QUtil::int_to_string(h_length) + "; computed = " +
+ QUtil::int_to_string(length));
+ }
+ cur_object += nobjects;
+ }
+ }
+}
+
+void
+QPDF::checkHOutlines(std::list<std::string>& warnings)
+{
+ // Empirically, Acrobat generates the correct value for the object
+ // number but incorrectly stores the next object number's offset
+ // as the offset, at least when outlines appear in part 6. It
+ // also generates an incorrect value for length (specifically, the
+ // length that would cover the correct number of objects from the
+ // wrong starting place). pdlin appears to generate correct
+ // values in those cases.
+
+ if (this->c_outline_data.nobjects == this->outline_hints.nobjects)
+ {
+ if (this->c_outline_data.nobjects == 0)
+ {
+ return;
+ }
+
+ if (this->c_outline_data.first_object ==
+ this->outline_hints.first_object)
+ {
+ // Check length and offset. Acrobat gets these wrong.
+ QPDFObjectHandle outlines = getRoot().getKey("/Outlines");
+ ObjGen og(outlines.getObjectID(), outlines.getGeneration());
+ assert(this->xref_table.count(og) > 0);
+ int offset = getLinearizationOffset(og);
+ ObjUser ou(ObjUser::ou_root_key, "/Outlines");
+ int length = maxEnd(ou) - offset;
+ int table_offset =
+ adjusted_offset(this->outline_hints.first_object_offset);
+ if (offset != table_offset)
+ {
+ warnings.push_back(
+ "incorrect offset in outlines table: hint table = " +
+ QUtil::int_to_string(table_offset) +
+ "; computed = " + QUtil::int_to_string(offset));
+ }
+ int table_length = this->outline_hints.group_length;
+ if (length != table_length)
+ {
+ warnings.push_back(
+ "incorrect length in outlines table: hint table = " +
+ QUtil::int_to_string(table_length) +
+ "; computed = " + QUtil::int_to_string(length));
+ }
+ }
+ else
+ {
+ warnings.push_back("incorrect first object number in outline "
+ "hints table.");
+ }
+ }
+ else
+ {
+ warnings.push_back("incorrect object count in outline hint table");
+ }
+}
+
+void
+QPDF::showLinearizationData()
+{
+ try
+ {
+ readLinearizationData();
+ checkLinearizationInternal();
+ dumpLinearizationDataInternal();
+ }
+ catch (QPDFExc& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+}
+
+void
+QPDF::dumpLinearizationDataInternal()
+{
+ std::cout << this->file.getName() << ": linearization data:" << std::endl
+ << std::endl;
+
+ std::cout
+ << "file_size: " << this->linp.file_size << std::endl
+ << "first_page_object: " << this->linp.first_page_object << std::endl
+ << "first_page_end: " << this->linp.first_page_end << std::endl
+ << "npages: " << this->linp.npages << std::endl
+ << "xref_zero_offset: " << this->linp.xref_zero_offset << std::endl
+ << "first_page: " << this->linp.first_page << std::endl
+ << "H_offset: " << this->linp.H_offset << std::endl
+ << "H_length: " << this->linp.H_length << std::endl
+ << std::endl;
+
+ std::cout << "Page Offsets Hint Table" << std::endl
+ << std::endl;
+ dumpHPageOffset();
+ std::cout << std::endl
+ << "Shared Objects Hint Table" << std::endl
+ << std::endl;
+ dumpHSharedObject();
+
+ if (this->outline_hints.nobjects > 0)
+ {
+ std::cout << std::endl
+ << "Outlines Hint Table" << std::endl
+ << std::endl;
+ dumpHGeneric(this->outline_hints);
+ }
+}
+
+int
+QPDF::adjusted_offset(int offset)
+{
+ // All offsets >= H_offset have to be increased by H_length
+ // since all hint table location values disregard the hint table
+ // itself.
+ if (offset >= this->linp.H_offset)
+ {
+ return offset + this->linp.H_length;
+ }
+ return offset;
+}
+
+
+void
+QPDF::dumpHPageOffset()
+{
+ HPageOffset& t = this->page_offset_hints;
+ std::cout
+ << "min_nobjects: " << t.min_nobjects
+ << std::endl
+ << "first_page_offset: " << adjusted_offset(t.first_page_offset)
+ << std::endl
+ << "nbits_delta_nobjects: " << t.nbits_delta_nobjects
+ << std::endl
+ << "min_page_length: " << t.min_page_length
+ << std::endl
+ << "nbits_delta_page_length: " << t.nbits_delta_page_length
+ << std::endl
+ << "min_content_offset: " << t.min_content_offset
+ << std::endl
+ << "nbits_delta_content_offset: " << t.nbits_delta_content_offset
+ << std::endl
+ << "min_content_length: " << t.min_content_length
+ << std::endl
+ << "nbits_delta_content_length: " << t.nbits_delta_content_length
+ << std::endl
+ << "nbits_nshared_objects: " << t.nbits_nshared_objects
+ << std::endl
+ << "nbits_shared_identifier: " << t.nbits_shared_identifier
+ << std::endl
+ << "nbits_shared_numerator: " << t.nbits_shared_numerator
+ << std::endl
+ << "shared_denominator: " << t.shared_denominator
+ << std::endl;
+
+ for (int i1 = 0; i1 < this->linp.npages; ++i1)
+ {
+ HPageOffsetEntry& pe = t.entries[i1];
+ std::cout
+ << "Page " << i1 << ":" << std::endl
+ << " nobjects: " << pe.delta_nobjects + t.min_nobjects
+ << std::endl
+ << " length: " << pe.delta_page_length + t.min_page_length
+ << std::endl
+ // content offset is relative to page, not file
+ << " content_offset: "
+ << pe.delta_content_offset + t.min_content_offset << std::endl
+ << " content_length: "
+ << pe.delta_content_length + t.min_content_length << std::endl
+ << " nshared_objects: " << pe.nshared_objects << std::endl;
+ for (int i2 = 0; i2 < pe.nshared_objects; ++i2)
+ {
+ std::cout << " identifier " << i2 << ": "
+ << pe.shared_identifiers[i2] << std::endl;
+ std::cout << " numerator " << i2 << ": "
+ << pe.shared_numerators[i2] << std::endl;
+ }
+ }
+}
+
+void
+QPDF::dumpHSharedObject()
+{
+ HSharedObject& t = this->shared_object_hints;
+ std::cout
+ << "first_shared_obj: " << t.first_shared_obj
+ << std::endl
+ << "first_shared_offset: " << adjusted_offset(t.first_shared_offset)
+ << std::endl
+ << "nshared_first_page: " << t.nshared_first_page
+ << std::endl
+ << "nshared_total: " << t.nshared_total
+ << std::endl
+ << "nbits_nobjects: " << t.nbits_nobjects
+ << std::endl
+ << "min_group_length: " << t.min_group_length
+ << std::endl
+ << "nbits_delta_group_length: " << t.nbits_delta_group_length
+ << std::endl;
+
+ for (int i = 0; i < t.nshared_total; ++i)
+ {
+ HSharedObjectEntry& se = t.entries[i];
+ std::cout << "Shared Object " << i << ":" << std::endl;
+ std::cout << " group length: "
+ << se.delta_group_length + t.min_group_length << std::endl;
+ // PDF spec says signature present nobjects_minus_one are
+ // always 0, so print them only if they have a non-zero value.
+ if (se.signature_present)
+ {
+ std::cout << " signature present" << std::endl;
+ }
+ if (se.nobjects_minus_one != 0)
+ {
+ std::cout << " nobjects: "
+ << se.nobjects_minus_one + 1 << std::endl;
+ }
+ }
+}
+
+void
+QPDF::dumpHGeneric(HGeneric& t)
+{
+ std::cout
+ << "first_object: " << t.first_object
+ << std::endl
+ << "first_object_offset: " << adjusted_offset(t.first_object_offset)
+ << std::endl
+ << "nobjects: " << t.nobjects
+ << std::endl
+ << "group_length: " << t.group_length
+ << std::endl;
+}
+
+QPDFObjectHandle
+QPDF::objGenToIndirect(ObjGen const& og)
+{
+ return getObjectByID(og.obj, og.gen);
+}
+
+void
+QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
+{
+ // This function calculates the ordering of objects, divides them
+ // into the appropriate parts, and computes some values for the
+ // linearization parameter dictionary and hint tables. The file
+ // must be optimized (via calling optimize()) prior to calling
+ // this function. Note that actual offsets and lengths are not
+ // computed here, but anything related to object ordering is.
+
+ if (this->object_to_obj_users.empty())
+ {
+ // Note that we can't call optimize here because we don't know
+ // whether it should be called with or without allow changes.
+ throw QEXC::Internal("QPDF::calculateLinearizationData "
+ "called before optimize()");
+ }
+
+ // Separate objects into the categories sufficient for us to
+ // determine which part of the linearized file should contain the
+ // object. This categorization is useful for other purposes as
+ // well. Part numbers refer to version 1.4 of the PDF spec.
+
+ // Parts 1, 3, 5, 10, and 11 don't contain any objects from the
+ // original file (except the trailer dictionary in part 11).
+
+ // Part 4 is the document catalog (root) and the following root
+ // keys: /ViewerPreferences, /PageMode, /Threads, /OpenAction,
+ // /AcroForm, /Encrypt. Note that Thread information dictionaries
+ // are supposed to appear in part 9, but we are disregarding that
+ // recommendation for now.
+
+ // Part 6 is the first page section. It includes all remaining
+ // objects referenced by the first page including shared objects
+ // but not including thumbnails. Additionally, if /PageMode is
+ // /Outlines, then information from /Outlines also appears here.
+
+ // Part 7 contains remaining objects private to pages other than
+ // the first page.
+
+ // Part 8 contains all remaining shared objects except those that
+ // are shared only within thumbnails.
+
+ // Part 9 contains all remaining objects.
+
+ // We sort objects into the following categories:
+
+ // * open_document: part 4
+
+ // * first_page_private: part 6
+
+ // * first_page_shared: part 6
+
+ // * other_page_private: part 7
+
+ // * other_page_shared: part 8
+
+ // * thumbnail_private: part 9
+
+ // * thumbnail_shared: part 9
+
+ // * other: part 9
+
+ // * outlines: part 6 or 9
+
+ QPDFObjectHandle root = getRoot();
+ bool outlines_in_first_page = false;
+ QPDFObjectHandle pagemode = root.getKey("/PageMode");
+ QTC::TC("qpdf", "QPDF categorize pagemode present",
+ pagemode.isName() ? 1 : 0);
+ if (pagemode.isName())
+ {
+ if (pagemode.getName() == "/UseOutlines")
+ {
+ if (root.hasKey("/Outlines"))
+ {
+ outlines_in_first_page = true;
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF UseOutlines but no Outlines");
+ }
+ }
+ QTC::TC("qpdf", "QPDF categorize pagemode outlines",
+ outlines_in_first_page ? 1 : 0);
+ }
+
+ std::set<std::string> open_document_keys;
+ open_document_keys.insert("/ViewerPreferences");
+ open_document_keys.insert("/PageMode");
+ open_document_keys.insert("/Threads");
+ open_document_keys.insert("/OpenAction");
+ open_document_keys.insert("/AcroForm");
+
+ std::set<ObjGen> lc_open_document;
+ std::set<ObjGen> lc_first_page_private;
+ std::set<ObjGen> lc_first_page_shared;
+ std::set<ObjGen> lc_other_page_private;
+ std::set<ObjGen> lc_other_page_shared;
+ std::set<ObjGen> lc_thumbnail_private;
+ std::set<ObjGen> lc_thumbnail_shared;
+ std::set<ObjGen> lc_other;
+ std::set<ObjGen> lc_outlines;
+ std::set<ObjGen> lc_root;
+
+ for (std::map<ObjGen, std::set<ObjUser> >::iterator oiter =
+ this->object_to_obj_users.begin();
+ oiter != this->object_to_obj_users.end(); ++oiter)
+ {
+ ObjGen const& og = (*oiter).first;
+
+ std::set<ObjUser>& ous = (*oiter).second;
+
+ bool in_open_document = false;
+ bool in_first_page = false;
+ int other_pages = 0;
+ int thumbs = 0;
+ int others = 0;
+ bool in_outlines = false;
+ bool is_root = false;
+
+ for (std::set<ObjUser>::iterator uiter = ous.begin();
+ uiter != ous.end(); ++uiter)
+ {
+ ObjUser const& ou = *uiter;
+ switch (ou.ou_type)
+ {
+ case ObjUser::ou_trailer_key:
+ if (ou.key == "/Encrypt")
+ {
+ in_open_document = true;
+ }
+ else
+ {
+ ++others;
+ }
+ break;
+
+ case ObjUser::ou_thumb:
+ ++thumbs;
+ break;
+
+ case ObjUser::ou_root_key:
+ if (open_document_keys.count(ou.key) > 0)
+ {
+ in_open_document = true;
+ }
+ else if (ou.key == "/Outlines")
+ {
+ in_outlines = true;
+ }
+ else
+ {
+ ++others;
+ }
+ break;
+
+ case ObjUser::ou_page:
+ if (ou.pageno == 0)
+ {
+ in_first_page = true;
+ }
+ else
+ {
+ ++other_pages;
+ }
+ break;
+
+ case ObjUser::ou_root:
+ is_root = true;
+ break;
+
+ case ObjUser::ou_bad:
+ throw QEXC::Internal("QPDF::calculateLinearizationData: "
+ "invalid user type");
+ break;
+ }
+ }
+
+ if (is_root)
+ {
+ lc_root.insert(og);
+ }
+ else if (in_outlines)
+ {
+ lc_outlines.insert(og);
+ }
+ else if (in_open_document)
+ {
+ lc_open_document.insert(og);
+ }
+ else if ((in_first_page) &&
+ (others == 0) && (other_pages == 0) && (thumbs == 0))
+ {
+ lc_first_page_private.insert(og);
+ }
+ else if (in_first_page)
+ {
+ lc_first_page_shared.insert(og);
+ }
+ else if ((other_pages == 1) && (others == 0) && (thumbs == 0))
+ {
+ lc_other_page_private.insert(og);
+ }
+ else if (other_pages > 1)
+ {
+ lc_other_page_shared.insert(og);
+ }
+ else if ((thumbs == 1) && (others == 0))
+ {
+ lc_thumbnail_private.insert(og);
+ }
+ else if (thumbs > 1)
+ {
+ lc_thumbnail_shared.insert(og);
+ }
+ else
+ {
+ lc_other.insert(og);
+ }
+ }
+
+ // Generate ordering for objects in the output file. Sometimes we
+ // just dump right from a set into a vector. Rather than
+ // optimizing this by going straight into the vector, we'll leave
+ // these phases separate for now. That way, this section can be
+ // concerned only with ordering, and the above section can be
+ // considered only with categorization. Note that sets of ObjGens
+ // are sorted by ObjGen. In a linearized file, objects appear in
+ // sequence with the possible exception of hints tables which we
+ // won't see here anyway. That means that running
+ // calculateLinearizationData() on a linearized file should give
+ // results identical to the original file ordering.
+
+ // We seem to traverse the page tree a lot in this code, but we
+ // can address this for a future code optimization if necessary.
+ // Premature optimization is the root of all evil.
+ std::vector<QPDFObjectHandle> pages;
+ { // local scope
+ // Map all page objects to the containing object stream. This
+ // should be a no-op in a properly linearized file.
+ std::vector<QPDFObjectHandle> t = getAllPages();
+ for (std::vector<QPDFObjectHandle>::iterator iter = t.begin();
+ iter != t.end(); ++iter)
+ {
+ pages.push_back(getUncompressedObject(*iter, object_stream_data));
+ }
+ }
+ unsigned int npages = pages.size();
+
+ // We will be initializing some values of the computed hint
+ // tables. Specifically, we can initialize any items that deal
+ // with object numbers or counts but not any items that deal with
+ // lengths or offsets. The code that writes linearized files will
+ // have to fill in these values during the first pass. The
+ // validation code can compute them relatively easily given the
+ // rest of the information.
+
+ this->c_linp.npages = npages;
+ this->c_page_offset_data.entries = std::vector<CHPageOffsetEntry>(npages);
+
+ // Part 4: open document objects. We don't care about the order.
+
+ assert(lc_root.size() == 1);
+ this->part4.push_back(objGenToIndirect(*(lc_root.begin())));
+ for (std::set<ObjGen>::iterator iter = lc_open_document.begin();
+ iter != lc_open_document.end(); ++iter)
+ {
+ this->part4.push_back(objGenToIndirect(*iter));
+ }
+
+ // Part 6: first page objects. Note: implementation note 124
+ // states that Acrobat always treats page 0 as the first page for
+ // linearization regardless of /OpenAction. pdlin doesn't provide
+ // any option to set this and also disregards /OpenAction. We
+ // will do the same.
+
+ // First, place the actual first page object itself.
+ ObjGen first_page_og(pages[0].getObjectID(), pages[0].getGeneration());
+ if (! lc_first_page_private.count(first_page_og))
+ {
+ throw QEXC::Internal("QPDF::calculateLinearizationData: first page "
+ "object not in lc_first_page_private");
+ }
+ lc_first_page_private.erase(first_page_og);
+ this->c_linp.first_page_object = pages[0].getObjectID();
+ this->part6.push_back(pages[0]);
+
+ // The PDF spec "recommends" an order for the rest of the objects,
+ // but we are going to disregard it except to the extent that it
+ // groups private and shared objects contiguously for the sake of
+ // hint tables.
+
+ for (std::set<ObjGen>::iterator iter = lc_first_page_private.begin();
+ iter != lc_first_page_private.end(); ++iter)
+ {
+ this->part6.push_back(objGenToIndirect(*iter));
+ }
+
+ for (std::set<ObjGen>::iterator iter = lc_first_page_shared.begin();
+ iter != lc_first_page_shared.end(); ++iter)
+ {
+ this->part6.push_back(objGenToIndirect(*iter));
+ }
+
+ // Place the outline dictionary if it goes in the first page section.
+ if (outlines_in_first_page)
+ {
+ pushOutlinesToPart(this->part6, lc_outlines, object_stream_data);
+ }
+
+ // Fill in page offset hint table information for the first page.
+ // The PDF spec says that nshared_objects should be zero for the
+ // first page. pdlin does not appear to obey this, but it fills
+ // in garbage values for all the shared object identifiers on the
+ // first page.
+
+ this->c_page_offset_data.entries[0].nobjects = this->part6.size();
+
+ // Part 7: other pages' private objects
+
+ // For each page in order:
+ for (unsigned int i = 1; i < npages; ++i)
+ {
+ // Place this page's page object
+
+ ObjGen page_og(pages[i].getObjectID(), pages[i].getGeneration());
+ if (! lc_other_page_private.count(page_og))
+ {
+ throw QEXC::Internal(
+ "QPDF::calculateLinearizationData: page object for page " +
+ QUtil::int_to_string(i) + " not in lc_other_page_private");
+ }
+ lc_other_page_private.erase(page_og);
+ this->part7.push_back(pages[i]);
+
+ // Place all non-shared objects referenced by this page,
+ // updating the page object count for the hint table.
+
+ this->c_page_offset_data.entries[i].nobjects = 1;
+
+ ObjUser ou(ObjUser::ou_page, i);
+ assert(this->obj_user_to_objects.count(ou) > 0);
+ std::set<ObjGen> ogs = this->obj_user_to_objects[ou];
+ for (std::set<ObjGen>::iterator iter = ogs.begin();
+ iter != ogs.end(); ++iter)
+ {
+ ObjGen const& og = (*iter);
+ if (lc_other_page_private.count(og))
+ {
+ lc_other_page_private.erase(og);
+ this->part7.push_back(objGenToIndirect(og));
+ ++this->c_page_offset_data.entries[i].nobjects;
+ }
+ }
+ }
+ // That should have covered all part7 objects.
+ if (! lc_other_page_private.empty())
+ {
+ throw QEXC::Internal(
+ "QPDF::calculateLinearizationData: lc_other_page_private is "
+ "not empty after generation of part7");
+ }
+
+ // Part 8: other pages' shared objects
+
+ // Order is unimportant.
+ for (std::set<ObjGen>::iterator iter = lc_other_page_shared.begin();
+ iter != lc_other_page_shared.end(); ++iter)
+ {
+ this->part8.push_back(objGenToIndirect(*iter));
+ }
+
+ // Part 9: other objects
+
+ // The PDF specification makes recommendations on ordering here.
+ // We follow them only to a limited extent. Specifically, we put
+ // the pages tree first, then private thumbnail objects in page
+ // order, then shared thumbnail objects, and then outlines (unless
+ // in part 6). After that, we throw all remaining objects in
+ // arbitrary order.
+
+ // Place the pages tree.
+ std::set<ObjGen> pages_ogs =
+ this->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")];
+ assert(! pages_ogs.empty());
+ for (std::set<ObjGen>::iterator iter = pages_ogs.begin();
+ iter != pages_ogs.end(); ++iter)
+ {
+ ObjGen const& og = *iter;
+ if (lc_other.count(og))
+ {
+ lc_other.erase(og);
+ this->part9.push_back(objGenToIndirect(og));
+ }
+ }
+
+ // Place private thumbnail images in page order. Slightly more
+ // information would be required if we were going to bother with
+ // thumbnail hint tables.
+ for (unsigned int i = 0; i < npages; ++i)
+ {
+ QPDFObjectHandle thumb = pages[i].getKey("/Thumb");
+ thumb = getUncompressedObject(thumb, object_stream_data);
+ if (! thumb.isNull())
+ {
+ // Output the thumbnail itself
+ ObjGen thumb_og(thumb.getObjectID(), thumb.getGeneration());
+ if (lc_thumbnail_private.count(thumb_og))
+ {
+ lc_thumbnail_private.erase(thumb_og);
+ this->part9.push_back(thumb);
+ }
+ else
+ {
+ // No internal error this time...there's nothing to
+ // stop this object from having been referred to
+ // somewhere else outside of a page's /Thumb, and if
+ // it had been, there's nothing to prevent it from
+ // having been in some set other than
+ // lc_thumbnail_private.
+ }
+ std::set<ObjGen>& ogs =
+ this->obj_user_to_objects[ObjUser(ObjUser::ou_thumb, i)];
+ for (std::set<ObjGen>::iterator iter = ogs.begin();
+ iter != ogs.end(); ++iter)
+ {
+ ObjGen const& og = *iter;
+ if (lc_thumbnail_private.count(og))
+ {
+ lc_thumbnail_private.erase(og);
+ this->part9.push_back(objGenToIndirect(og));
+ }
+ }
+ }
+ }
+ if (! lc_thumbnail_private.empty())
+ {
+ throw QEXC::Internal(
+ "QPDF::calculateLinearizationData: lc_thumbnail_private "
+ "not empty after placing thumbnails");
+ }
+
+ // Place shared thumbnail objects
+ for (std::set<ObjGen>::iterator iter = lc_thumbnail_shared.begin();
+ iter != lc_thumbnail_shared.end(); ++iter)
+ {
+ this->part9.push_back(objGenToIndirect(*iter));
+ }
+
+ // Place outlines unless in first page
+ if (! outlines_in_first_page)
+ {
+ pushOutlinesToPart(this->part9, lc_outlines, object_stream_data);
+ }
+
+ // Place all remaining objects
+ for (std::set<ObjGen>::iterator iter = lc_other.begin();
+ iter != lc_other.end(); ++iter)
+ {
+ this->part9.push_back(objGenToIndirect(*iter));
+ }
+
+ // Make sure we got everything exactly once.
+
+ unsigned int num_placed = this->part4.size() + this->part6.size() +
+ this->part7.size() + this->part8.size() + this->part9.size();
+ unsigned int num_wanted = this->object_to_obj_users.size();
+ if (num_placed != num_wanted)
+ {
+ throw QEXC::Internal("QPDF::calculateLinearizationData: wrong "
+ "number of objects placed (num_placed = " +
+ QUtil::int_to_string(num_placed) +
+ "; number of objects: " +
+ QUtil::int_to_string(num_wanted));
+ }
+
+ // Calculate shared object hint table information including
+ // references to shared objects from page offset hint data.
+
+ // The shared object hint table consists of all part 6 (whether
+ // shared or not) in order followed by all part 8 objects in
+ // order. Add the objects to shared object data keeping a map of
+ // object number to index. Then populate the shared object
+ // information for the pages.
+
+ // Note that two objects never have the same object number, so we
+ // can map from object number only without regards to generation.
+ std::map<int, int> obj_to_index;
+
+ this->c_shared_object_data.nshared_first_page = this->part6.size();
+ this->c_shared_object_data.nshared_total =
+ this->c_shared_object_data.nshared_first_page +
+ this->part8.size();
+
+ std::vector<CHSharedObjectEntry>& shared =
+ this->c_shared_object_data.entries;
+ for (std::vector<QPDFObjectHandle>::iterator iter = this->part6.begin();
+ iter != this->part6.end(); ++iter)
+ {
+ QPDFObjectHandle& oh = *iter;
+ int obj = oh.getObjectID();
+ obj_to_index[obj] = shared.size();
+ shared.push_back(CHSharedObjectEntry(obj));
+ }
+ QTC::TC("qpdf", "QPDF lin part 8 empty", this->part8.empty() ? 1 : 0);
+ if (! this->part8.empty())
+ {
+ this->c_shared_object_data.first_shared_obj =
+ this->part8[0].getObjectID();
+ for (std::vector<QPDFObjectHandle>::iterator iter =
+ this->part8.begin();
+ iter != this->part8.end(); ++iter)
+ {
+ QPDFObjectHandle& oh = *iter;
+ int obj = oh.getObjectID();
+ obj_to_index[obj] = shared.size();
+ shared.push_back(CHSharedObjectEntry(obj));
+ }
+ }
+ assert(this->c_shared_object_data.nshared_total ==
+ (int) this->c_shared_object_data.entries.size());
+
+ // Now compute the list of shared objects for each page after the
+ // first page.
+
+ for (unsigned int i = 1; i < npages; ++i)
+ {
+ CHPageOffsetEntry& pe = this->c_page_offset_data.entries[i];
+ ObjUser ou(ObjUser::ou_page, i);
+ assert(this->obj_user_to_objects.count(ou) > 0);
+ std::set<ObjGen> const& ogs = this->obj_user_to_objects[ou];
+ for (std::set<ObjGen>::const_iterator iter = ogs.begin();
+ iter != ogs.end(); ++iter)
+ {
+ ObjGen const& og = *iter;
+ if ((this->object_to_obj_users[og].size() > 1) &&
+ (obj_to_index.count(og.obj) > 0))
+ {
+ int idx = obj_to_index[og.obj];
+ ++pe.nshared_objects;
+ pe.shared_identifiers.push_back(idx);
+ }
+ }
+ }
+}
+
+void
+QPDF::pushOutlinesToPart(
+ std::vector<QPDFObjectHandle>& part,
+ std::set<ObjGen>& lc_outlines,
+ std::map<int, int> const& object_stream_data)
+{
+ QPDFObjectHandle root = getRoot();
+ QPDFObjectHandle outlines = root.getKey("/Outlines");
+ if (outlines.isNull())
+ {
+ return;
+ }
+ outlines = getUncompressedObject(outlines, object_stream_data);
+ ObjGen outlines_og(outlines.getObjectID(), outlines.getGeneration());
+ QTC::TC("qpdf", "QPDF lin outlines in part",
+ ((&part == (&this->part6)) ? 0
+ : (&part == (&this->part9)) ? 1
+ : 9999)); // can't happen
+ this->c_outline_data.first_object = outlines_og.obj;
+ this->c_outline_data.nobjects = 1;
+ lc_outlines.erase(outlines_og);
+ part.push_back(outlines);
+ for (std::set<ObjGen>::iterator iter = lc_outlines.begin();
+ iter != lc_outlines.end(); ++iter)
+ {
+ part.push_back(objGenToIndirect(*iter));
+ ++this->c_outline_data.nobjects;
+ }
+}
+
+void
+QPDF::getLinearizedParts(
+ std::map<int, int> const& object_stream_data,
+ std::vector<QPDFObjectHandle>& part4,
+ std::vector<QPDFObjectHandle>& part6,
+ std::vector<QPDFObjectHandle>& part7,
+ std::vector<QPDFObjectHandle>& part8,
+ std::vector<QPDFObjectHandle>& part9)
+{
+ calculateLinearizationData(object_stream_data);
+ part4 = this->part4;
+ part6 = this->part6;
+ part7 = this->part7;
+ part8 = this->part8;
+ part9 = this->part9;
+}
+
+static inline int nbits(int val)
+{
+ return (val == 0 ? 0 : (1 + nbits(val >> 1)));
+}
+
+int
+QPDF::outputLengthNextN(
+ int in_object, int n,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber)
+{
+ // Figure out the length of a series of n consecutive objects in
+ // the output file starting with whatever object in_object from
+ // the input file mapped to.
+
+ assert(obj_renumber.count(in_object) > 0);
+ int first = (*(obj_renumber.find(in_object))).second;
+ int length = 0;
+ for (int i = 0; i < n; ++i)
+ {
+ assert(lengths.count(first + i) > 0);
+ length += (*(lengths.find(first + i))).second;
+ }
+ return length;
+}
+
+void
+QPDF::calculateHPageOffset(
+ std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber)
+{
+ // Page Offset Hint Table
+
+ // We are purposely leaving some values set to their initial zero
+ // values.
+
+ std::vector<QPDFObjectHandle> const& pages = getAllPages();
+ unsigned int npages = pages.size();
+ CHPageOffset& cph = this->c_page_offset_data;
+ std::vector<CHPageOffsetEntry>& cphe = cph.entries;
+
+ // Calculate minimum and maximum values for number of objects per
+ // page and page length.
+
+ int min_nobjects = cphe[0].nobjects;
+ int max_nobjects = min_nobjects;
+ int min_length = outputLengthNextN(
+ pages[0].getObjectID(), min_nobjects, lengths, obj_renumber);
+ int max_length = min_length;
+ int max_shared = cphe[0].nshared_objects;
+
+ HPageOffset& ph = this->page_offset_hints;
+ std::vector<HPageOffsetEntry>& phe = ph.entries;
+ phe = std::vector<HPageOffsetEntry>(npages);
+
+ for (unsigned int i = 0; i < npages; ++i)
+ {
+ // Calculate values for each page, assigning full values to
+ // the delta items. They will be adjusted later.
+
+ // Repeat calculations for page 0 so we can assign to phe[i]
+ // without duplicating those assignments.
+
+ int nobjects = cphe[i].nobjects;
+ int length = outputLengthNextN(
+ pages[i].getObjectID(), nobjects, lengths, obj_renumber);
+ int nshared = cphe[i].nshared_objects;
+
+ min_nobjects = std::min(min_nobjects, nobjects);
+ max_nobjects = std::max(max_nobjects, nobjects);
+ min_length = std::min(min_length, length);
+ max_length = std::max(max_length, length);
+ max_shared = std::max(max_shared, nshared);
+
+ phe[i].delta_nobjects = nobjects;
+ phe[i].delta_page_length = length;
+ phe[i].nshared_objects = nshared;
+ }
+
+ ph.min_nobjects = min_nobjects;
+ int in_page0_id = pages[0].getObjectID();
+ int out_page0_id = (*(obj_renumber.find(in_page0_id))).second;
+ ph.first_page_offset = (*(xref.find(out_page0_id))).second.getOffset();
+ ph.nbits_delta_nobjects = nbits(max_nobjects - min_nobjects);
+ ph.min_page_length = min_length;
+ ph.nbits_delta_page_length = nbits(max_length - min_length);
+ ph.nbits_nshared_objects = nbits(max_shared);
+ ph.nbits_shared_identifier =
+ nbits(this->c_shared_object_data.nshared_total);
+ ph.shared_denominator = 4; // doesn't matter
+
+ // It isn't clear how to compute content offset and content
+ // length. Since we are not interleaving page objects with the
+ // content stream, we'll use the same values for content length as
+ // page length. We will use 0 as content offset because this is
+ // what Adobe does (implementation note 127) and pdlin as well.
+ ph.nbits_delta_content_length = ph.nbits_delta_page_length;
+ ph.min_content_length = ph.min_page_length;
+
+ for (unsigned int i = 0; i < npages; ++i)
+ {
+ // Adjust delta entries
+ assert(phe[i].delta_nobjects >= min_nobjects);
+ assert(phe[i].delta_page_length >= min_length);
+ phe[i].delta_nobjects -= min_nobjects;
+ phe[i].delta_page_length -= min_length;
+ phe[i].delta_content_length = phe[i].delta_page_length;
+
+ for (int j = 0; j < cphe[i].nshared_objects; ++j)
+ {
+ phe[i].shared_identifiers.push_back(
+ cphe[i].shared_identifiers[j]);
+ phe[i].shared_numerators.push_back(0);
+ }
+ }
+}
+
+void
+QPDF::calculateHSharedObject(
+ std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber)
+{
+ CHSharedObject& cso = this->c_shared_object_data;
+ std::vector<CHSharedObjectEntry>& csoe = cso.entries;
+ HSharedObject& so = this->shared_object_hints;
+ std::vector<HSharedObjectEntry>& soe = so.entries;
+ soe = std::vector<HSharedObjectEntry>(cso.nshared_total);
+
+ int min_length = outputLengthNextN(
+ csoe[0].object, 1, lengths, obj_renumber);
+ int max_length = min_length;
+
+ for (int i = 0; i < cso.nshared_total; ++i)
+ {
+ // Assign absolute numbers to deltas; adjust later
+ int length = outputLengthNextN(
+ csoe[i].object, 1, lengths, obj_renumber);
+ min_length = std::min(min_length, length);
+ max_length = std::max(max_length, length);
+ soe[i].delta_group_length = length;
+ }
+
+ so.nshared_total = cso.nshared_total;
+ so.nshared_first_page = cso.nshared_first_page;
+ if (so.nshared_total > so.nshared_first_page)
+ {
+ so.first_shared_obj =
+ (*(obj_renumber.find(cso.first_shared_obj))).second;
+ so.first_shared_offset =
+ (*(xref.find(so.first_shared_obj))).second.getOffset();
+ }
+ so.min_group_length = min_length;
+ so.nbits_delta_group_length = nbits(max_length - min_length);
+
+ for (int i = 0; i < cso.nshared_total; ++i)
+ {
+ // Adjust deltas
+ assert(soe[i].delta_group_length >= min_length);
+ soe[i].delta_group_length -= min_length;
+ }
+}
+
+void
+QPDF::calculateHOutline(
+ std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber)
+{
+ HGeneric& cho = this->c_outline_data;
+
+ if (cho.nobjects == 0)
+ {
+ return;
+ }
+
+ HGeneric& ho = this->outline_hints;
+
+ ho.first_object =
+ (*(obj_renumber.find(cho.first_object))).second;
+ ho.first_object_offset =
+ (*(xref.find(ho.first_object))).second.getOffset();
+ ho.nobjects = cho.nobjects;
+ ho.group_length = outputLengthNextN(
+ cho.first_object, ho.nobjects, lengths, obj_renumber);
+}
+
+template <class T>
+static void
+write_vector_int(BitWriter& w, int nitems, std::vector<T>& vec,
+ int bits, int T::*field)
+{
+ // nitems times, write bits bits from the given field of the ith
+ // vector to the given bit writer.
+
+ for (int i = 0; i < nitems; ++i)
+ {
+ w.writeBits(vec[i].*field, bits);
+ }
+ // The PDF spec says that each hint table starts at a byte
+ // boundary. Each "row" actually must start on a byte boundary.
+ w.flush();
+}
+
+template <class T>
+static void
+write_vector_vector(BitWriter& w,
+ int nitems1, std::vector<T>& vec1, int T::*nitems2,
+ int bits, std::vector<int> T::*vec2)
+{
+ // nitems1 times, write nitems2 (from the ith element of vec1) items
+ // from the vec2 vector field of the ith item of vec1.
+ for (int i1 = 0; i1 < nitems1; ++i1)
+ {
+ for (int i2 = 0; i2 < vec1[i1].*nitems2; ++i2)
+ {
+ w.writeBits((vec1[i1].*vec2)[i2], bits);
+ }
+ }
+ w.flush();
+}
+
+
+void
+QPDF::writeHPageOffset(BitWriter& w)
+{
+ HPageOffset& t = this->page_offset_hints;
+
+ w.writeBits(t.min_nobjects, 32); // 1
+ w.writeBits(t.first_page_offset, 32); // 2
+ w.writeBits(t.nbits_delta_nobjects, 16); // 3
+ w.writeBits(t.min_page_length, 32); // 4
+ w.writeBits(t.nbits_delta_page_length, 16); // 5
+ w.writeBits(t.min_content_offset, 32); // 6
+ w.writeBits(t.nbits_delta_content_offset, 16); // 7
+ w.writeBits(t.min_content_length, 32); // 8
+ w.writeBits(t.nbits_delta_content_length, 16); // 9
+ w.writeBits(t.nbits_nshared_objects, 16); // 10
+ w.writeBits(t.nbits_shared_identifier, 16); // 11
+ w.writeBits(t.nbits_shared_numerator, 16); // 12
+ w.writeBits(t.shared_denominator, 16); // 13
+
+ unsigned int nitems = getAllPages().size();
+ std::vector<HPageOffsetEntry>& entries = t.entries;
+
+ write_vector_int(w, nitems, entries,
+ t.nbits_delta_nobjects,
+ &HPageOffsetEntry::delta_nobjects);
+ write_vector_int(w, nitems, entries,
+ t.nbits_delta_page_length,
+ &HPageOffsetEntry::delta_page_length);
+ write_vector_int(w, nitems, entries,
+ t.nbits_nshared_objects,
+ &HPageOffsetEntry::nshared_objects);
+ write_vector_vector(w, nitems, entries,
+ &HPageOffsetEntry::nshared_objects,
+ t.nbits_shared_identifier,
+ &HPageOffsetEntry::shared_identifiers);
+ write_vector_vector(w, nitems, entries,
+ &HPageOffsetEntry::nshared_objects,
+ t.nbits_shared_numerator,
+ &HPageOffsetEntry::shared_numerators);
+ write_vector_int(w, nitems, entries,
+ t.nbits_delta_content_offset,
+ &HPageOffsetEntry::delta_content_offset);
+ write_vector_int(w, nitems, entries,
+ t.nbits_delta_content_length,
+ &HPageOffsetEntry::delta_content_length);
+}
+
+void
+QPDF::writeHSharedObject(BitWriter& w)
+{
+ HSharedObject& t = this->shared_object_hints;
+
+ w.writeBits(t.first_shared_obj, 32); // 1
+ w.writeBits(t.first_shared_offset, 32); // 2
+ w.writeBits(t.nshared_first_page, 32); // 3
+ w.writeBits(t.nshared_total, 32); // 4
+ w.writeBits(t.nbits_nobjects, 16); // 5
+ w.writeBits(t.min_group_length, 32); // 6
+ w.writeBits(t.nbits_delta_group_length, 16); // 7
+
+ QTC::TC("qpdf", "QPDF lin write nshared_total > nshared_first_page",
+ (t.nshared_total > t.nshared_first_page) ? 1 : 0);
+
+ int nitems = t.nshared_total;
+ std::vector<HSharedObjectEntry>& entries = t.entries;
+
+ write_vector_int(w, nitems, entries,
+ t.nbits_delta_group_length,
+ &HSharedObjectEntry::delta_group_length);
+ write_vector_int(w, nitems, entries,
+ 1, &HSharedObjectEntry::signature_present);
+ for (int i = 0; i < nitems; ++i)
+ {
+ // If signature were present, we'd have to write a 128-bit hash.
+ assert(entries[i].signature_present == 0);
+ }
+ write_vector_int(w, nitems, entries,
+ t.nbits_nobjects,
+ &HSharedObjectEntry::nobjects_minus_one);
+}
+
+void
+QPDF::writeHGeneric(BitWriter& w, HGeneric& t)
+{
+ w.writeBits(t.first_object, 32); // 1
+ w.writeBits(t.first_object_offset, 32); // 2
+ w.writeBits(t.nobjects, 32); // 3
+ w.writeBits(t.group_length, 32); // 4
+}
+
+void
+QPDF::generateHintStream(std::map<int, QPDFXRefEntry> const& xref,
+ std::map<int, size_t> const& lengths,
+ std::map<int, int> const& obj_renumber,
+ PointerHolder<Buffer>& hint_buffer,
+ int& S, int& O)
+{
+ // Populate actual hint table values
+ calculateHPageOffset(xref, lengths, obj_renumber);
+ calculateHSharedObject(xref, lengths, obj_renumber);
+ calculateHOutline(xref, lengths, obj_renumber);
+
+ // Write the hint stream itself into a compressed memory buffer.
+ // Write through a couter so we can get offsets.
+ Pl_Buffer hint_stream("hint stream");
+ Pl_Flate f("compress hint stream", &hint_stream, Pl_Flate::a_deflate);
+ Pl_Count c("count", &f);
+ BitWriter w(&c);
+
+ writeHPageOffset(w);
+ S = c.getCount();
+ writeHSharedObject(w);
+ O = 0;
+ if (this->outline_hints.nobjects > 0)
+ {
+ O = c.getCount();
+ writeHGeneric(w, this->outline_hints);
+ }
+ c.finish();
+
+ hint_buffer = hint_stream.getBuffer();
+}
diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc
new file mode 100644
index 00000000..8797445c
--- /dev/null
+++ b/libqpdf/QPDF_optimization.cc
@@ -0,0 +1,490 @@
+// See doc/optimization.
+
+#include <qpdf/QPDF.hh>
+
+#include <qpdf/QTC.hh>
+#include <qpdf/QPDFExc.hh>
+#include <qpdf/QPDF_Dictionary.hh>
+#include <qpdf/QPDF_Array.hh>
+#include <assert.h>
+
+QPDF::ObjUser::ObjUser() :
+ ou_type(ou_bad),
+ pageno(0)
+{
+}
+
+QPDF::ObjUser::ObjUser(user_e type) :
+ ou_type(type),
+ pageno(0)
+{
+ assert(type == ou_root);
+}
+
+QPDF::ObjUser::ObjUser(user_e type, int pageno) :
+ ou_type(type),
+ pageno(pageno)
+{
+ assert((type == ou_page) || (type == ou_thumb));
+}
+
+QPDF::ObjUser::ObjUser(user_e type, std::string const& key) :
+ ou_type(type),
+ pageno(0),
+ key(key)
+{
+ assert((type == ou_trailer_key) || (type == ou_root_key));
+}
+
+bool
+QPDF::ObjUser::operator<(ObjUser const& rhs) const
+{
+ if (this->ou_type < rhs.ou_type)
+ {
+ return true;
+ }
+ else if (this->ou_type == rhs.ou_type)
+ {
+ if (this->pageno < rhs.pageno)
+ {
+ return true;
+ }
+ else if (this->pageno == rhs.pageno)
+ {
+ return (this->key < rhs.key);
+ }
+ }
+
+ return false;
+}
+
+void
+QPDF::flattenScalarReferences()
+{
+ // Do a traversal of the entire PDF file structure replacing all
+ // indirect objects that are not arrays, streams, or dictionaries
+ // with direct objects.
+
+ std::list<QPDFObjectHandle> queue;
+ queue.push_back(this->trailer);
+ std::set<ObjGen> visited;
+
+ while (! queue.empty())
+ {
+ QPDFObjectHandle node = queue.front();
+ queue.pop_front();
+ if (node.isIndirect())
+ {
+ if (node.isScalar())
+ {
+ throw QEXC::Internal(
+ "flattenScalarReferences landed at indirect scalar");
+ }
+ ObjGen og(node.getObjectID(), node.getGeneration());
+ if (visited.count(og) > 0)
+ {
+ continue;
+ }
+ visited.insert(og);
+ }
+
+ if (node.isArray())
+ {
+ int nitems = node.getArrayNItems();
+ for (int i = 0; i < nitems; ++i)
+ {
+ QPDFObjectHandle oh = node.getArrayItem(i);
+ if (oh.isScalar())
+ {
+ QTC::TC("qpdf", "QPDF opt flatten array scalar");
+ oh.makeDirect();
+ node.setArrayItem(i, oh);
+ }
+ else
+ {
+ queue.push_back(oh);
+ }
+ }
+ }
+ else if (node.isDictionary() || node.isStream())
+ {
+ QPDFObjectHandle dict = node;
+ if (node.isStream())
+ {
+ dict = node.getDict();
+ }
+ std::set<std::string> keys = dict.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ QPDFObjectHandle oh = dict.getKey(key);
+ if (oh.isNull())
+ {
+ // QPDF_Dictionary.getKeys() never returns null
+ // keys.
+ throw QEXC::Internal("dictionary with null key found");
+ }
+ else if (oh.isScalar())
+ {
+ QTC::TC("qpdf", "QPDF opt flatten dict scalar");
+ oh.makeDirect();
+ dict.replaceKey(key, oh);
+ }
+ else
+ {
+ queue.push_back(oh);
+ }
+ }
+ }
+ }
+}
+
+void
+QPDF::optimize(std::map<int, int> const& object_stream_data,
+ bool allow_changes)
+{
+ if (! this->obj_user_to_objects.empty())
+ {
+ // already optimized
+ return;
+ }
+
+ // Traverse pages tree pushing all inherited resources down to the
+ // page level.
+
+ // key_ancestors is a mapping of page attribute keys to a stack of
+ // Pages nodes that contain values for them. pageno is the
+ // current page sequence number numbered from 0.
+ std::map<std::string, std::vector<QPDFObjectHandle> > key_ancestors;
+ int pageno = 0;
+ optimizePagesTree(this->trailer.getKey("/Root").getKey("/Pages"),
+ key_ancestors, pageno, allow_changes);
+ assert(key_ancestors.empty());
+
+ // Traverse document-level items
+ std::set<std::string> keys = this->trailer.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ if (key == "/Root")
+ {
+ // handled separately
+ }
+ else
+ {
+ updateObjectMaps(ObjUser(ObjUser::ou_trailer_key, key),
+ this->trailer.getKey(key));
+ }
+ }
+
+ QPDFObjectHandle root = getRoot();
+ keys = root.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ // Technically, /I keys from /Thread dictionaries are supposed
+ // to be handled separately, but we are going to disregard
+ // that specification for now. There is loads of evidence
+ // that pdlin and Acrobat both disregard things like this from
+ // time to time, so this is almost certain not to cause any
+ // problems.
+
+ std::string const& key = *iter;
+ updateObjectMaps(ObjUser(ObjUser::ou_root_key, key),
+ root.getKey(key));
+ }
+
+ ObjUser root_ou = ObjUser(ObjUser::ou_root);
+ ObjGen root_og = ObjGen(root.getObjectID(), root.getGeneration());
+ obj_user_to_objects[root_ou].insert(root_og);
+ object_to_obj_users[root_og].insert(root_ou);
+
+ filterCompressedObjects(object_stream_data);
+}
+
+void
+QPDF::optimizePagesTree(
+ QPDFObjectHandle cur_pages,
+ std::map<std::string, std::vector<QPDFObjectHandle> >& key_ancestors,
+ int& pageno, bool allow_changes)
+{
+ // Extract the underlying dictionary object
+ std::string type = cur_pages.getKey("/Type").getName();
+
+ if (type == "/Pages")
+ {
+ // Make a list of inheritable keys. Any key other than /Type,
+ // /Parent, Kids, or /Count is an inheritable attribute. Push
+ // this object onto the stack of pages nodes that have values
+ // for this attribute.
+
+ std::set<std::string> inheritable_keys;
+ std::set<std::string> keys = cur_pages.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ if (! ((key == "/Type") || (key == "/Parent") ||
+ (key == "/Kids") || (key == "/Count")))
+ {
+ if (! allow_changes)
+ {
+ throw QPDFExc(this->file.getName() +
+ ": optimize detected an "
+ "inheritable resource");
+ }
+
+ // This is an inheritable resource
+ inheritable_keys.insert(key);
+ QPDFObjectHandle oh = cur_pages.getKey(key);
+ QTC::TC("qpdf", "QPDF opt direct pages resource",
+ oh.isIndirect() ? 0 : 1);
+ if (! oh.isIndirect())
+ {
+ if (! oh.isScalar())
+ {
+ // Replace shared direct object non-scalar
+ // resources with indirect objects to avoid
+ // copying large structures around.
+ cur_pages.replaceKey(key, makeIndirectObject(oh));
+ oh = cur_pages.getKey(key);
+ }
+ else
+ {
+ // Don't defeat flattenScalarReferences which
+ // would have already been called by this
+ // time.
+ QTC::TC("qpdf", "QPDF opt inherited scalar");
+ }
+ }
+ key_ancestors[key].push_back(oh);
+ if (key_ancestors[key].size() > 1)
+ {
+ QTC::TC("qpdf", "QPDF opt key ancestors depth > 1");
+ }
+ // Remove this resource from this node. It will be
+ // reattached at the page level.
+ cur_pages.removeKey(key);
+ }
+ }
+
+ // Visit descendant nodes.
+ QPDFObjectHandle kids = cur_pages.getKey("/Kids");
+ int n = kids.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ optimizePagesTree(kids.getArrayItem(i), key_ancestors, pageno,
+ allow_changes);
+ }
+
+ // For each inheritable key, pop the stack. If the stack
+ // becomes empty, remove it from the map. That way, the
+ // invariant that the list of keys in key_ancestors is exactly
+ // those keys for which inheritable attributes are available.
+
+ if (! inheritable_keys.empty())
+ {
+ QTC::TC("qpdf", "QPDF opt inheritable keys");
+ for (std::set<std::string>::iterator iter =
+ inheritable_keys.begin();
+ iter != inheritable_keys.end(); ++iter)
+ {
+ std::string const& key = (*iter);
+ key_ancestors[key].pop_back();
+ if (key_ancestors[key].empty())
+ {
+ QTC::TC("qpdf", "QPDF opt erase empty key ancestor");
+ key_ancestors.erase(key);
+ }
+ }
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF opt no inheritable keys");
+ }
+ }
+ else if (type == "/Page")
+ {
+ // Add all available inheritable attributes not present in
+ // this object to this object.
+ for (std::map<std::string, std::vector<QPDFObjectHandle> >::iterator
+ iter = key_ancestors.begin();
+ iter != key_ancestors.end(); ++iter)
+ {
+ std::string const& key = (*iter).first;
+ if (! cur_pages.hasKey(key))
+ {
+ QTC::TC("qpdf", "QPDF opt resource inherited");
+ cur_pages.replaceKey(key, (*iter).second.back());
+ }
+ else
+ {
+ QTC::TC("qpdf", "QPDF opt page resource hides ancestor");
+ }
+ }
+
+ // Traverse from this point, updating the mappings of object
+ // users to objects and objects to object users.
+
+ updateObjectMaps(ObjUser(ObjUser::ou_page, pageno), cur_pages);
+
+ // Increment pageno so that its value will be correct for the
+ // next page.
+ ++pageno;
+ }
+ else
+ {
+ throw QPDFExc(this->file.getName() + ": invalid Type in page tree");
+ }
+}
+
+void
+QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh)
+{
+ std::set<ObjGen> visited;
+ updateObjectMapsInternal(ou, oh, visited, true);
+}
+
+void
+QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
+ std::set<ObjGen>& visited, bool top)
+{
+ // Traverse the object tree from this point taking care to avoid
+ // crossing page boundaries.
+
+ bool is_page_node = false;
+
+ if (oh.isDictionary() && oh.hasKey("/Type"))
+ {
+ std::string type = oh.getKey("/Type").getName();
+ if (type == "/Page")
+ {
+ is_page_node = true;
+ if (! top)
+ {
+ return;
+ }
+ }
+ }
+
+ if (oh.isIndirect())
+ {
+ ObjGen og(oh.getObjectID(), oh.getGeneration());
+ if (visited.count(og))
+ {
+ QTC::TC("qpdf", "QPDF opt loop detected");
+ return;
+ }
+ this->obj_user_to_objects[ou].insert(og);
+ this->object_to_obj_users[og].insert(ou);
+ visited.insert(og);
+ }
+
+ if (oh.isArray())
+ {
+ int n = oh.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ updateObjectMapsInternal(ou, oh.getArrayItem(i), visited, false);
+ }
+ }
+ else if (oh.isDictionary() || oh.isStream())
+ {
+ QPDFObjectHandle dict = oh;
+ if (oh.isStream())
+ {
+ dict = oh.getDict();
+ }
+
+ std::set<std::string> keys = dict.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ std::string const& key = *iter;
+ if (is_page_node && (key == "/Thumb"))
+ {
+ // Traverse page thumbnail dictionaries as a special
+ // case.
+ updateObjectMaps(ObjUser(ObjUser::ou_thumb, ou.pageno),
+ dict.getKey(key));
+ }
+ else if (is_page_node && (key == "/Parent"))
+ {
+ // Don't traverse back up the page tree
+ }
+ else
+ {
+ updateObjectMapsInternal(ou, dict.getKey(key),
+ visited, false);
+ }
+ }
+ }
+}
+
+void
+QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data)
+{
+ if (object_stream_data.empty())
+ {
+ return;
+ }
+
+ // Transform object_to_obj_users and obj_user_to_objects so that
+ // they refer only to uncompressed objects. If something is a
+ // user of a compressed object, then it is really a user of the
+ // object stream that contains it.
+
+ std::map<ObjUser, std::set<ObjGen> > t_obj_user_to_objects;
+ std::map<ObjGen, std::set<ObjUser> > t_object_to_obj_users;
+
+ for (std::map<ObjUser, std::set<ObjGen> >::iterator i1 =
+ this->obj_user_to_objects.begin();
+ i1 != this->obj_user_to_objects.end(); ++i1)
+ {
+ ObjUser const& ou = (*i1).first;
+ std::set<ObjGen> const& objects = (*i1).second;
+ for (std::set<ObjGen>::const_iterator i2 = objects.begin();
+ i2 != objects.end(); ++i2)
+ {
+ ObjGen const& og = (*i2);
+ std::map<int, int>::const_iterator i3 =
+ object_stream_data.find(og.obj);
+ if (i3 == object_stream_data.end())
+ {
+ t_obj_user_to_objects[ou].insert(og);
+ }
+ else
+ {
+ t_obj_user_to_objects[ou].insert(ObjGen((*i3).second, 0));
+ }
+ }
+ }
+
+ for (std::map<ObjGen, std::set<ObjUser> >::iterator i1 =
+ this->object_to_obj_users.begin();
+ i1 != this->object_to_obj_users.end(); ++i1)
+ {
+ ObjGen const& og = (*i1).first;
+ std::set<ObjUser> const& objusers = (*i1).second;
+ for (std::set<ObjUser>::const_iterator i2 = objusers.begin();
+ i2 != objusers.end(); ++i2)
+ {
+ ObjUser const& ou = (*i2);
+ std::map<int, int>::const_iterator i3 =
+ object_stream_data.find(og.obj);
+ if (i3 == object_stream_data.end())
+ {
+ t_object_to_obj_users[og].insert(ou);
+ }
+ else
+ {
+ t_object_to_obj_users[ObjGen((*i3).second, 0)].insert(ou);
+ }
+ }
+ }
+
+ this->obj_user_to_objects = t_obj_user_to_objects;
+ this->object_to_obj_users = t_object_to_obj_users;
+}
diff --git a/libqpdf/QTC.cc b/libqpdf/QTC.cc
new file mode 100644
index 00000000..b8328b2e
--- /dev/null
+++ b/libqpdf/QTC.cc
@@ -0,0 +1,46 @@
+
+#include <qpdf/QTC.hh>
+
+#include <set>
+#include <stdio.h>
+#include <qpdf/QUtil.hh>
+
+static bool tc_active(char const* const scope)
+{
+ std::string value;
+ return (QUtil::get_env("TC_SCOPE", &value) && (value == scope));
+}
+
+void QTC::TC(char const* const scope, char const* const ccase, int n)
+{
+ static std::set<std::pair<std::string, int> > cache;
+
+ if (! tc_active(scope))
+ {
+ return;
+ }
+
+ std::string filename;
+#ifdef _WIN32
+# define TC_ENV "TC_WIN_FILENAME"
+#else
+# define TC_ENV "TC_FILENAME"
+#endif
+ if (! QUtil::get_env(TC_ENV, &filename))
+ {
+ return;
+ }
+#undef TC_ENV
+
+ if (cache.count(std::make_pair(ccase, n)))
+ {
+ return;
+ }
+ cache.insert(std::make_pair(ccase, n));
+
+ FILE* tc =
+ QUtil::fopen_wrapper("open test coverage file (" + filename + ")",
+ fopen(filename.c_str(), "ab"));
+ fprintf(tc, "%s %d\n", ccase, n);
+ fclose(tc);
+}
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc
new file mode 100644
index 00000000..c0de95f7
--- /dev/null
+++ b/libqpdf/QUtil.cc
@@ -0,0 +1,198 @@
+
+#include <qpdf/QUtil.hh>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#ifdef _WIN32
+#include <Windows.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+std::string
+QUtil::int_to_string(int num, int fullpad)
+{
+ // This routine will need to be recompiled if an int can be longer than
+ // 49 digits.
+ char t[50];
+
+ // -2 or -1 to leave space for the possible negative sign and for NUL...
+ if (abs(fullpad) > (int)sizeof(t) - ((num < 0)?2:1))
+ {
+ throw QEXC::Internal("Util::int_to_string has been called with "
+ "a padding value greater than its internal "
+ "limit");
+ }
+
+ if (fullpad)
+ {
+ sprintf(t, "%0*d", fullpad, num);
+ }
+ else
+ {
+ sprintf(t, "%d", num);
+ }
+
+ return std::string(t);
+}
+
+std::string
+QUtil::double_to_string(double num, int decimal_places)
+{
+ // This routine will need to be recompiled if a double can be longer than
+ // 99 digits.
+ char t[100];
+
+ std::string lhs = int_to_string((int)num);
+
+ // lhs.length() gives us the length of the part on the right hand
+ // side of the dot + 1 for the dot + decimal_places: total size of
+ // the required string. -1 on the sizeof side to allow for NUL at
+ // the end.
+ //
+ // If decimal_places <= 0, it is as if no precision was provided
+ // so trust the buffer is big enough. The following test will
+ // always pass in those cases.
+ if (decimal_places + 1 + (int)lhs.length() > (int)sizeof(t) - 1)
+ {
+ throw QEXC::Internal("Util::double_to_string has been called with "
+ "a number and a decimal places specification "
+ "that would break an internal limit");
+ }
+
+ if (decimal_places)
+ {
+ sprintf(t, "%.*f", decimal_places, num);
+ }
+ else
+ {
+ sprintf(t, "%f", num);
+ }
+ return std::string(t);
+}
+
+int
+QUtil::os_wrapper(std::string const& description, int status) throw (QEXC::System)
+{
+ if (status == -1)
+ {
+ throw QEXC::System(description, errno);
+ }
+ return status;
+}
+
+FILE*
+QUtil::fopen_wrapper(std::string const& description, FILE* f) throw (QEXC::System)
+{
+ if (f == 0)
+ {
+ throw QEXC::System(description, errno);
+ }
+ return f;
+}
+
+char*
+QUtil::copy_string(std::string const& str)
+{
+ char* result = new char[str.length() + 1];
+ // Use memcpy in case string contains nulls
+ result[str.length()] = '\0';
+ memcpy(result, str.c_str(), str.length());
+ return result;
+}
+
+bool
+QUtil::get_env(std::string const& var, std::string* value)
+{
+ // This was basically ripped out of wxWindows.
+#ifdef _WIN32
+ // first get the size of the buffer
+ DWORD len = ::GetEnvironmentVariable(var.c_str(), NULL, 0);
+ if (len == 0)
+ {
+ // this means that there is no such variable
+ return false;
+ }
+
+ if (value)
+ {
+ char* t = new char[len + 1];
+ ::GetEnvironmentVariable(var.c_str(), t, len);
+ *value = t;
+ delete [] t;
+ }
+
+ return true;
+#else
+ char* p = getenv(var.c_str());
+ if (p == 0)
+ {
+ return false;
+ }
+ if (value)
+ {
+ *value = p;
+ }
+
+ return true;
+#endif
+}
+
+std::string
+QUtil::toUTF8(unsigned long uval)
+{
+ std::string result;
+
+ // A UTF-8 encoding of a Unicode value is a single byte for
+ // Unicode values <= 127. For larger values, the first byte of
+ // the UTF-8 encoding has '1' as each of its n highest bits and
+ // '0' for its (n+1)th highest bit where n is the total number of
+ // bytes required. Subsequent bytes start with '10' and have the
+ // remaining 6 bits free for encoding. For example, an 11-bit
+ // unicode value can be stored in two bytes where the first is
+ // 110zzzzz, the second is 10zzzzzz, and the z's represent the
+ // remaining bits.
+
+ if (uval > 0x7fffffff)
+ {
+ throw QEXC::General("bounds error in QUtil::toUTF8");
+ }
+ else if (uval < 128)
+ {
+ result += (char)(uval);
+ }
+ else
+ {
+ unsigned char bytes[7];
+ bytes[6] = '\0';
+ unsigned char* cur_byte = &bytes[5];
+
+ // maximum value that will fit in the current number of bytes
+ unsigned char maxval = 0x3f; // six bits
+
+ while (uval > maxval)
+ {
+ // Assign low six bits plus 10000000 to lowest unused
+ // byte position, then shift
+ *cur_byte = (unsigned char) (0x80 + (uval & 0x3f));
+ uval >>= 6;
+ // Maximum that will fit in high byte now shrinks by one bit
+ maxval >>= 1;
+ // Slide to the left one byte
+ --cur_byte;
+ if (cur_byte < bytes)
+ {
+ throw QEXC::Internal("QUtil::toUTF8: overflow error");
+ }
+ }
+ // If maxval is k bits long, the high (7 - k) bits of the
+ // resulting byte must be high.
+ *cur_byte = (unsigned char)((0xff - (1 + (maxval << 1))) + uval);
+
+ result += (char*)cur_byte;
+ }
+
+ return result;
+}
diff --git a/libqpdf/RC4.cc b/libqpdf/RC4.cc
new file mode 100644
index 00000000..74b538b5
--- /dev/null
+++ b/libqpdf/RC4.cc
@@ -0,0 +1,56 @@
+
+#include <qpdf/RC4.hh>
+
+#include <string.h>
+
+static void swap_byte(unsigned char &a, unsigned char &b)
+{
+ unsigned char t;
+
+ t = a;
+ a = b;
+ b = t;
+}
+
+RC4::RC4(unsigned char const* key_data, int key_len)
+{
+ if (key_len == -1)
+ {
+ key_len = strlen((char*)key_data);
+ }
+
+ for (int i = 0; i < 256; ++i)
+ {
+ key.state[i] = i;
+ }
+ key.x = 0;
+ key.y = 0;
+
+ int i1 = 0;
+ int i2 = 0;
+ for (int i = 0; i < 256; ++i)
+ {
+ i2 = (key_data[i1] + key.state[i] + i2) % 256;
+ swap_byte(key.state[i], key.state[i2]);
+ i1 = (i1 + 1) % key_len;
+ }
+}
+
+void
+RC4::process(unsigned char *in_data, int len, unsigned char* out_data)
+{
+ if (out_data == 0)
+ {
+ // Convert in place
+ out_data = in_data;
+ }
+
+ for (int i = 0; i < len; ++i)
+ {
+ key.x = (key.x + 1) % 256;
+ key.y = (key.state[key.x] + key.y) % 256;
+ swap_byte(key.state[key.x], key.state[key.y]);
+ int xor_index = (key.state[key.x] + key.state[key.y]) % 256;
+ out_data[i] = in_data[i] ^ key.state[xor_index];
+ }
+}
diff --git a/libqpdf/bits.icc b/libqpdf/bits.icc
new file mode 100644
index 00000000..465bf5b9
--- /dev/null
+++ b/libqpdf/bits.icc
@@ -0,0 +1,149 @@
+
+#ifndef __BITS_CC__
+#define __BITS_CC__
+
+#include <algorithm>
+#include <qpdf/QTC.hh>
+#include <qpdf/QEXC.hh>
+#include <qpdf/Pipeline.hh>
+
+// These functions may be run at places where the function call
+// overhead from test coverage testing would be too high. Therefore,
+// we make the test coverage cases conditional upon a preprocessor
+// symbol. BitStream.cc includes this file without defining the
+// symbol, and the specially designed test code that fully exercises
+// this code includes with the symbol defined.
+
+#ifdef BITS_READ
+static unsigned long
+read_bits(unsigned char const*& p, unsigned int& bit_offset,
+ unsigned int& bits_available, unsigned int bits_wanted)
+{
+ // View p as a stream of bits:
+
+ // 76543210 76543210 ....
+
+ // bit_offset is the bit number within the first byte that marks
+ // the first bit that we would read.
+
+ if (bits_wanted > bits_available)
+ {
+ throw QEXC::General("overflow reading bit stream");
+ }
+ if (bits_wanted > 32)
+ {
+ throw QEXC::Internal("read_bits: too many bits requested");
+ }
+
+ unsigned long result = 0;
+#ifdef BITS_TESTING
+ if (bits_wanted == 0)
+ {
+ QTC::TC("libtests", "bits zero bits wanted");
+ }
+#endif
+ while (bits_wanted > 0)
+ {
+ // Grab bits from the first byte clearing anything before
+ // bit_offset.
+ unsigned char byte = *p & ((1 << (bit_offset + 1)) - 1);
+
+ // There are bit_offset + 1 bits available in the first byte.
+ unsigned int to_copy = std::min(bits_wanted, bit_offset + 1);
+ unsigned int leftover = (bit_offset + 1) - to_copy;
+
+#ifdef BITS_TESTING
+ QTC::TC("libtests", "bits bit_offset",
+ ((bit_offset == 0) ? 0 :
+ (bit_offset == 7) ? 1 :
+ 2));
+ QTC::TC("libtests", "bits leftover", (leftover > 0) ? 1 : 0);
+#endif
+
+ // Right shift so that all the bits we want are right justified.
+ byte >>= leftover;
+
+ // Copy the bits into result
+ result <<= to_copy;
+ result |= byte;
+
+ // Update pointers
+ if (leftover)
+ {
+ bit_offset = leftover - 1;
+ }
+ else
+ {
+ bit_offset = 7;
+ ++p;
+ }
+ bits_wanted -= to_copy;
+ bits_available -= to_copy;
+
+#ifdef BITS_TESTING
+ QTC::TC("libtests", "bits iterations",
+ ((bits_wanted > 8) ? 0 :
+ (bits_wanted > 0) ? 1 :
+ 2));
+#endif
+ }
+
+ return result;
+}
+#endif
+
+#ifdef BITS_WRITE
+static void
+write_bits(unsigned char& ch, unsigned int& bit_offset,
+ unsigned long val, unsigned bits, Pipeline* pipeline)
+{
+ if (bits > 32)
+ {
+ throw QEXC::Internal("write_bits: too many bits requested");
+ }
+
+ // bit_offset + 1 is the number of bits left in ch
+#ifdef BITS_TESTING
+ if (bits == 0)
+ {
+ QTC::TC("libtests", "bits write zero bits");
+ }
+#endif
+ while (bits > 0)
+ {
+ int bits_to_write = std::min(bits, bit_offset + 1);
+ unsigned char newval =
+ (val >> (bits - bits_to_write)) & ((1 << bits_to_write) - 1);
+ int bits_left_in_ch = bit_offset + 1 - bits_to_write;
+ newval <<= bits_left_in_ch;
+ ch |= newval;
+ if (bits_left_in_ch == 0)
+ {
+#ifdef BITS_TESTING
+ QTC::TC("libtests", "bits write pipeline");
+#endif
+ pipeline->write(&ch, 1);
+ bit_offset = 7;
+ ch = 0;
+ }
+ else
+ {
+#ifdef BITS_TESTING
+ QTC::TC("libtests", "bits write leftover");
+#endif
+ bit_offset -= bits_to_write;
+ }
+ bits -= bits_to_write;
+#ifdef BITS_TESTING
+ QTC::TC("libtests", "bits write iterations",
+ ((bits > 8) ? 0 :
+ (bits > 0) ? 1 :
+ 2));
+#endif
+ }
+
+}
+#endif
+
+
+#endif // __BITS_CC__
diff --git a/libqpdf/build.mk b/libqpdf/build.mk
new file mode 100644
index 00000000..9733cb9f
--- /dev/null
+++ b/libqpdf/build.mk
@@ -0,0 +1,73 @@
+TARGETS_libqpdf = \
+ libqpdf/$(OUTPUT_DIR)/libqpdf.la
+
+INCLUDES_libqpdf = include libqpdf
+
+SRCS_libqpdf = \
+ libqpdf/BitStream.cc \
+ libqpdf/BitWriter.cc \
+ libqpdf/Buffer.cc \
+ libqpdf/MD5.cc \
+ libqpdf/PCRE.cc \
+ libqpdf/Pipeline.cc \
+ libqpdf/Pl_ASCII85Decoder.cc \
+ libqpdf/Pl_ASCIIHexDecoder.cc \
+ libqpdf/Pl_Buffer.cc \
+ libqpdf/Pl_Count.cc \
+ libqpdf/Pl_Discard.cc \
+ libqpdf/Pl_Flate.cc \
+ libqpdf/Pl_LZWDecoder.cc \
+ libqpdf/Pl_MD5.cc \
+ libqpdf/Pl_PNGFilter.cc \
+ libqpdf/Pl_QPDFTokenizer.cc \
+ libqpdf/Pl_RC4.cc \
+ libqpdf/Pl_StdioFile.cc \
+ libqpdf/QEXC.cc \
+ libqpdf/QPDF.cc \
+ libqpdf/QPDFExc.cc \
+ libqpdf/QPDFObject.cc \
+ libqpdf/QPDFObjectHandle.cc \
+ libqpdf/QPDFTokenizer.cc \
+ libqpdf/QPDFWriter.cc \
+ libqpdf/QPDFXRefEntry.cc \
+ libqpdf/QPDF_Array.cc \
+ libqpdf/QPDF_Bool.cc \
+ libqpdf/QPDF_Dictionary.cc \
+ libqpdf/QPDF_Integer.cc \
+ libqpdf/QPDF_Name.cc \
+ libqpdf/QPDF_Null.cc \
+ libqpdf/QPDF_Real.cc \
+ libqpdf/QPDF_Stream.cc \
+ libqpdf/QPDF_String.cc \
+ libqpdf/QPDF_encryption.cc \
+ libqpdf/QPDF_linearization.cc \
+ libqpdf/QPDF_optimization.cc \
+ libqpdf/QTC.cc \
+ libqpdf/QUtil.cc \
+ libqpdf/RC4.cc
+
+# -----
+
+OBJS_libqpdf = $(call src_to_lobj,$(SRCS_libqpdf))
+
+ifeq ($(GENDEPS),1)
+-include $(call lobj_to_dep,$(OBJS_libqpdf))
+endif
+
+$(OBJS_libqpdf): libqpdf/$(OUTPUT_DIR)/%.lo: libqpdf/%.cc
+ $(call libcompile,$<,$(INCLUDES_libqpdf))
+
+# Last three arguments to makelib are CURRENT,REVISION,AGE.
+#
+# * If any interfaces have been removed or changed, we are not binary
+# compatible. Increment CURRENT, and set AGE and REVISION to 0.
+#
+# * Otherwise, if any interfaces have been added since the last
+# public release, then increment CURRENT and AGE, and set REVISION
+# to 0.
+#
+# * Otherwise, increment REVISION
+
+libqpdf/$(OUTPUT_DIR)/libqpdf.la: $(OBJS_libqpdf)
+ $(call makelib,$(OBJS_libqpdf),$@,1,0,0)
+
diff --git a/libqpdf/qpdf/BitStream.hh b/libqpdf/qpdf/BitStream.hh
new file mode 100644
index 00000000..d02eea42
--- /dev/null
+++ b/libqpdf/qpdf/BitStream.hh
@@ -0,0 +1,23 @@
+// Read bits from a bit stream. See BitWriter for writing.
+
+#ifndef __BITSTREAM_HH__
+#define __BITSTREAM_HH__
+
+class BitStream
+{
+ public:
+ BitStream(unsigned char const* p, int nbytes);
+ void reset();
+ unsigned long getBits(int nbits);
+ void skipToNextByte();
+
+ private:
+ unsigned char const* start;
+ int nbytes;
+
+ unsigned char const* p;
+ unsigned int bit_offset;
+ unsigned int bits_available;
+};
+
+#endif // __BITSTREAM_HH__
diff --git a/libqpdf/qpdf/BitWriter.hh b/libqpdf/qpdf/BitWriter.hh
new file mode 100644
index 00000000..1efd498a
--- /dev/null
+++ b/libqpdf/qpdf/BitWriter.hh
@@ -0,0 +1,24 @@
+// Write bits into a bit stream. See BitStream for reading.
+
+#ifndef __THIS_FILE_Q__
+#define __THIS_FILE_Q__
+
+class Pipeline;
+
+class BitWriter
+{
+ public:
+ // Write bits to the pipeline. It is the caller's responsibility
+ // to eventually call finish on the pipeline.
+ BitWriter(Pipeline* pl);
+ void writeBits(unsigned long val, int bits);
+ // Force any partial byte to be written to the pipeline.
+ void flush();
+
+ private:
+ Pipeline* pl;
+ unsigned char ch;
+ unsigned int bit_offset;
+};
+
+#endif // __THIS_FILE_Q__
diff --git a/libqpdf/qpdf/MD5.hh b/libqpdf/qpdf/MD5.hh
new file mode 100644
index 00000000..0ae15da9
--- /dev/null
+++ b/libqpdf/qpdf/MD5.hh
@@ -0,0 +1,73 @@
+
+#ifndef __MD5_HH__
+#define __MD5_HH__
+
+#include <string>
+#include <qpdf/QEXC.hh>
+
+class MD5
+{
+ public:
+ typedef unsigned char Digest[16];
+
+ MD5();
+ void reset();
+
+ // encodes string and finalizes
+ void encodeString(char const* input_string);
+
+ // encodes file and finalizes
+ void encodeFile(char const* filename, int up_to_size = -1)
+ throw(QEXC::System);
+
+ // appends string to current md5 object
+ void appendString(char const* input_string);
+
+ // appends arbitrary data to current md5 object
+ void encodeDataIncrementally(char const* input_data, int len);
+
+ // computes a raw digest
+ void digest(Digest);
+
+ // prints the digest to stdout terminated with \r\n (primarily for
+ // testing)
+ void print();
+
+ // returns the digest as a hexademical string
+ std::string unparse();
+
+ // Convenience functions
+ static std::string getDataChecksum(char const* buf, int len);
+ static std::string getFileChecksum(char const* filename, int up_to_size = -1);
+ static bool checkDataChecksum(char const* const checksum,
+ char const* buf, int len);
+ static bool checkFileChecksum(char const* const checksum,
+ char const* filename, int up_to_size = -1);
+
+ private:
+ // POINTER defines a generic pointer type
+ typedef void *POINTER;
+
+ // UINT2 defines a two byte word
+ typedef unsigned short int UINT2;
+
+ // UINT4 defines a four byte word
+ typedef unsigned long int UINT4;
+
+ void init();
+ void update(unsigned char *, unsigned int);
+ void final();
+
+ static void transform(UINT4 [4], unsigned char [64]);
+ static void encode(unsigned char *, UINT4 *, unsigned int);
+ static void decode(UINT4 *, unsigned char *, unsigned int);
+
+ UINT4 state[4]; // state (ABCD)
+ UINT4 count[2]; // number of bits, modulo 2^64 (lsb first)
+ unsigned char buffer[64]; // input buffer
+
+ bool finalized;
+ Digest digest_val;
+};
+
+#endif // __MD5_HH__
diff --git a/libqpdf/qpdf/PCRE.hh b/libqpdf/qpdf/PCRE.hh
new file mode 100644
index 00000000..a226aa19
--- /dev/null
+++ b/libqpdf/qpdf/PCRE.hh
@@ -0,0 +1,107 @@
+// This is a C++ wrapper class around Philip Hazel's perl-compatible
+// regular expressions library.
+//
+
+#ifndef __PCRE_HH__
+#define __PCRE_HH__
+
+#include <pcre.h>
+#include <string>
+
+#include <qpdf/QEXC.hh>
+
+// Note: this class does not encapsulate all features of the PCRE
+// package -- only those that I actually need right now are here.
+
+class PCRE
+{
+ public:
+ class Exception: public QEXC::General
+ {
+ public:
+ Exception(std::string const& message);
+ virtual ~Exception() throw() {}
+ };
+
+ // This is thrown when an attempt is made to access a non-existent
+ // back reference.
+ class NoBackref: public Exception
+ {
+ public:
+ NoBackref();
+ virtual ~NoBackref() throw() {}
+ };
+
+ class Match
+ {
+ friend class PCRE;
+ public:
+ Match(int nbackrefs, char const* subject);
+ Match(Match const&);
+ Match& operator=(Match const&);
+ ~Match();
+ operator bool();
+
+ // All the back reference accessing routines may throw the
+ // special exception NoBackref (derived from Exception) if the
+ // back reference does not exist. Exception will be thrown
+ // for other error conditions. This allows callers to trap
+ // this condition explicitly when they care about the
+ // difference between a backreference matching an empty string
+ // and not matching at all.
+
+ // see getMatch flags below
+ std::string getMatch(int n, int flags = 0)
+ throw(QEXC::General, Exception);
+ void getOffsetLength(int n, int& offset, int& length) throw(Exception);
+ int getOffset(int n) throw(Exception);
+ int getLength(int n) throw(Exception);
+
+ // nMatches returns the number of available matches including
+ // match 0 which is the whole string. In other words, if you
+ // have one backreference in your expression and the
+ // expression matches, nMatches() will return 2, getMatch(0)
+ // will return the whole string, getMatch(1) will return the
+ // text that matched the backreference, and getMatch(2) will
+ // throw an exception because it is out of range.
+ int nMatches() const;
+
+ // Flags for getMatch
+
+ // getMatch on a substring that didn't match should return
+ // empty string instead of throwing an exception
+ static int const gm_no_substring_returns_empty = (1 << 0);
+
+ private:
+ void init(int nmatches, int nbackrefs, char const* subject);
+ void copy(Match const&);
+ void destroy();
+
+ int nbackrefs;
+ char const* subject;
+ int* ovector;
+ int ovecsize;
+ int nmatches;
+ };
+
+ // The value passed in as options is passed to pcre_exec. See man
+ // pcreapi for details.
+ PCRE(char const* pattern, int options = 0) throw(Exception);
+ ~PCRE();
+
+ Match match(char const* subject, int options = 0, int startoffset = 0,
+ int size = -1)
+ throw(QEXC::General, Exception);
+
+ static void test(int n = 0);
+
+ private:
+ // prohibit copying and assignment
+ PCRE(PCRE const&);
+ PCRE& operator=(PCRE const&);
+
+ pcre* code;
+ int nbackrefs;
+};
+
+#endif // __PCRE_HH__
diff --git a/libqpdf/qpdf/Pl_ASCII85Decoder.hh b/libqpdf/qpdf/Pl_ASCII85Decoder.hh
new file mode 100644
index 00000000..9883a58e
--- /dev/null
+++ b/libqpdf/qpdf/Pl_ASCII85Decoder.hh
@@ -0,0 +1,23 @@
+
+#ifndef __PL_ASCII85DECODER_HH__
+#define __PL_ASCII85DECODER_HH__
+
+#include <qpdf/Pipeline.hh>
+
+class Pl_ASCII85Decoder: public Pipeline
+{
+ public:
+ Pl_ASCII85Decoder(char const* identifier, Pipeline* next);
+ virtual ~Pl_ASCII85Decoder();
+ virtual void write(unsigned char* buf, int len);
+ virtual void finish();
+
+ private:
+ void flush();
+
+ char inbuf[5];
+ int pos;
+ int eod;
+};
+
+#endif // __PL_ASCII85DECODER_HH__
diff --git a/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh b/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh
new file mode 100644
index 00000000..36272328
--- /dev/null
+++ b/libqpdf/qpdf/Pl_ASCIIHexDecoder.hh
@@ -0,0 +1,23 @@
+
+#ifndef __PL_ASCIIHEXDECODER_HH__
+#define __PL_ASCIIHEXDECODER_HH__
+
+#include <qpdf/Pipeline.hh>
+
+class Pl_ASCIIHexDecoder: public Pipeline
+{
+ public:
+ Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next);
+ virtual ~Pl_ASCIIHexDecoder();
+ virtual void write(unsigned char* buf, int len);
+ virtual void finish();
+
+ private:
+ void flush();
+
+ char inbuf[3];
+ int pos;
+ bool eod;
+};
+
+#endif // __PL_ASCIIHEXDECODER_HH__
diff --git a/libqpdf/qpdf/Pl_LZWDecoder.hh b/libqpdf/qpdf/Pl_LZWDecoder.hh
new file mode 100644
index 00000000..95ec55b3
--- /dev/null
+++ b/libqpdf/qpdf/Pl_LZWDecoder.hh
@@ -0,0 +1,40 @@
+
+#ifndef __PL_LZWDECODER_HH__
+#define __PL_LZWDECODER_HH__
+
+#include <qpdf/Pipeline.hh>
+
+#include <qpdf/Buffer.hh>
+#include <vector>
+
+class Pl_LZWDecoder: public Pipeline
+{
+ public:
+ Pl_LZWDecoder(char const* identifier, Pipeline* next,
+ bool early_code_change);
+ virtual ~Pl_LZWDecoder();
+ virtual void write(unsigned char* buf, int len);
+ virtual void finish();
+
+ private:
+ void sendNextCode();
+ void handleCode(int code);
+ unsigned char getFirstChar(int code);
+ void addToTable(unsigned char next);
+
+ // members used for converting bits to codes
+ unsigned char buf[3];
+ int code_size;
+ int next;
+ int byte_pos;
+ int bit_pos; // left to right: 01234567
+ int bits_available;
+
+ // members used for handle LZW decompression
+ bool code_change_delta;
+ bool eod;
+ std::vector<Buffer> table;
+ int last_code;
+};
+
+#endif // __PL_LZWDECODER_HH__
diff --git a/libqpdf/qpdf/Pl_MD5.hh b/libqpdf/qpdf/Pl_MD5.hh
new file mode 100644
index 00000000..2d9d11fd
--- /dev/null
+++ b/libqpdf/qpdf/Pl_MD5.hh
@@ -0,0 +1,30 @@
+
+#ifndef __PL_MD5_HH__
+#define __PL_MD5_HH__
+
+// This pipeline sends its output to its successor unmodified. After
+// calling finish, the MD5 checksum of the data that passed through
+// the pipeline is available.
+
+// This pipeline is reusable; i.e., it is safe to call write() after
+// calling finish(). The first call to write() after a call to
+// finish() initializes a new MD5 object.
+
+#include <qpdf/Pipeline.hh>
+#include <qpdf/MD5.hh>
+
+class Pl_MD5: public Pipeline
+{
+ public:
+ Pl_MD5(char const* identifier, Pipeline* next);
+ virtual ~Pl_MD5();
+ virtual void write(unsigned char*, int);
+ virtual void finish();
+ std::string getHexDigest();
+
+ private:
+ bool in_progress;
+ MD5 md5;
+};
+
+#endif // __PL_MD5_HH__
diff --git a/libqpdf/qpdf/Pl_PNGFilter.hh b/libqpdf/qpdf/Pl_PNGFilter.hh
new file mode 100644
index 00000000..1ecc7060
--- /dev/null
+++ b/libqpdf/qpdf/Pl_PNGFilter.hh
@@ -0,0 +1,62 @@
+
+#ifndef __PL_PNGFILTER_HH__
+#define __PL_PNGFILTER_HH__
+
+// This pipeline applies or reverses the application of a PNG filter
+// as described in the PNG specification.
+
+// NOTE: In its initial implementation, it only encodes and decodes
+// filters "none" and "up". The primary motivation of this code is to
+// encode and decode PDF 1.5+ XRef streams which are often encoded
+// with Flate predictor 12, which corresponds to the PNG up filter.
+// At present, the bytes_per_pixel parameter is ignored, and an
+// exception is thrown if any row of the file has a filter of other
+// than 0 or 2. Finishing the implementation would not be difficult.
+// See chapter 6 of the PNG specification for a description of the
+// filter algorithms.
+
+#include <qpdf/Pipeline.hh>
+
+class Pl_PNGFilter: public Pipeline
+{
+ public:
+ class Exception: public Pipeline::Exception
+ {
+ public:
+ Exception(std::string const& message) :
+ Pipeline::Exception(message)
+ {
+ }
+
+ virtual ~Exception() throw ()
+ {
+ }
+ };
+
+ // Encoding is not presently supported
+ enum action_e { a_encode, a_decode };
+
+ Pl_PNGFilter(char const* identifier, Pipeline* next,
+ action_e action, unsigned int columns,
+ unsigned int bytes_per_pixel);
+ virtual ~Pl_PNGFilter();
+
+ virtual void write(unsigned char* data, int len);
+ virtual void finish();
+
+ private:
+ void processRow();
+ void encodeRow();
+ void decodeRow();
+
+ action_e action;
+ unsigned int columns;
+ unsigned char* cur_row;
+ unsigned char* prev_row;
+ unsigned char* buf1;
+ unsigned char* buf2;
+ int pos;
+ int incoming;
+};
+
+#endif // __PL_PNGFILTER_HH__
diff --git a/libqpdf/qpdf/Pl_QPDFTokenizer.hh b/libqpdf/qpdf/Pl_QPDFTokenizer.hh
new file mode 100644
index 00000000..448dbb18
--- /dev/null
+++ b/libqpdf/qpdf/Pl_QPDFTokenizer.hh
@@ -0,0 +1,40 @@
+
+#ifndef __PL_QPDFTOKENIZER_HH__
+#define __PL_QPDFTOKENIZER_HH__
+
+#include <qpdf/Pipeline.hh>
+
+#include <qpdf/QPDFTokenizer.hh>
+
+//
+// Treat incoming text as a stream consisting of valid PDF tokens, but
+// output bad tokens just the same. The idea here is to be able to
+// use pipeline for content streams to normalize newlines without
+// interfering with meaningful newlines such as those that occur
+// inside of strings.
+//
+
+class Pl_QPDFTokenizer: public Pipeline
+{
+ public:
+ Pl_QPDFTokenizer(char const* identifier, Pipeline* next);
+ virtual ~Pl_QPDFTokenizer();
+ virtual void write(unsigned char* buf, int len);
+ virtual void finish();
+
+ private:
+ void processChar(char ch);
+ void checkUnread();
+ void writeNext(char const*, int len);
+ void writeToken(QPDFTokenizer::Token&);
+
+ QPDFTokenizer tokenizer;
+ bool newline_after_next_token;
+ bool just_wrote_nl;
+ bool last_char_was_cr;
+ bool unread_char;
+ char char_to_unread;
+ bool pass_through;
+};
+
+#endif // __PL_QPDFTOKENIZER_HH__
diff --git a/libqpdf/qpdf/Pl_RC4.hh b/libqpdf/qpdf/Pl_RC4.hh
new file mode 100644
index 00000000..6bebe5aa
--- /dev/null
+++ b/libqpdf/qpdf/Pl_RC4.hh
@@ -0,0 +1,42 @@
+
+#ifndef __PL_RC4_HH__
+#define __PL_RC4_HH__
+
+#include <qpdf/Pipeline.hh>
+
+#include <qpdf/RC4.hh>
+
+class Pl_RC4: public Pipeline
+{
+ public:
+ class Exception: public Pipeline::Exception
+ {
+ public:
+ Exception(std::string const& message) :
+ Pipeline::Exception(message)
+ {
+ }
+
+ virtual ~Exception() throw()
+ {
+ }
+ };
+
+ static int const def_bufsize = 65536;
+
+ // key_len of -1 means treat key_data as a null-terminated string
+ Pl_RC4(char const* identifier, Pipeline* next,
+ unsigned char const* key_data, int key_len = -1,
+ int out_bufsize = def_bufsize);
+ virtual ~Pl_RC4();
+
+ virtual void write(unsigned char* data, int len);
+ virtual void finish();
+
+ private:
+ unsigned char* outbuf;
+ int out_bufsize;
+ RC4 rc4;
+};
+
+#endif // __PL_RC4_HH__
diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh
new file mode 100644
index 00000000..371be50e
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Array.hh
@@ -0,0 +1,24 @@
+
+#ifndef __QPDF_ARRAY_HH__
+#define __QPDF_ARRAY_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+#include <vector>
+#include <qpdf/QPDFObjectHandle.hh>
+
+class QPDF_Array: public QPDFObject
+{
+ public:
+ QPDF_Array(std::vector<QPDFObjectHandle> const& items);
+ virtual ~QPDF_Array();
+ virtual std::string unparse();
+ int getNItems() const;
+ QPDFObjectHandle getItem(int n) const;
+ void setItem(int, QPDFObjectHandle const&);
+
+ private:
+ std::vector<QPDFObjectHandle> items;
+};
+
+#endif // __QPDF_ARRAY_HH__
diff --git a/libqpdf/qpdf/QPDF_Bool.hh b/libqpdf/qpdf/QPDF_Bool.hh
new file mode 100644
index 00000000..06aca822
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Bool.hh
@@ -0,0 +1,19 @@
+
+#ifndef __QPDF_BOOL_HH__
+#define __QPDF_BOOL_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+class QPDF_Bool: public QPDFObject
+{
+ public:
+ QPDF_Bool(bool val);
+ virtual ~QPDF_Bool();
+ virtual std::string unparse();
+ bool getVal() const;
+
+ private:
+ bool val;
+};
+
+#endif // __QPDF_BOOL_HH__
diff --git a/libqpdf/qpdf/QPDF_Dictionary.hh b/libqpdf/qpdf/QPDF_Dictionary.hh
new file mode 100644
index 00000000..6a79fb69
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Dictionary.hh
@@ -0,0 +1,35 @@
+
+#ifndef __QPDF_DICTIONARY_HH__
+#define __QPDF_DICTIONARY_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+#include <set>
+#include <map>
+
+#include <qpdf/QPDFObjectHandle.hh>
+
+class QPDF_Dictionary: public QPDFObject
+{
+ public:
+ QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items);
+ virtual ~QPDF_Dictionary();
+ virtual std::string unparse();
+
+ // hasKey() and getKeys() treat keys with null values as if they
+ // aren't there. getKey() returns null for the value of a
+ // non-existent key. This is as per the PDF spec.
+ bool hasKey(std::string const&);
+ QPDFObjectHandle getKey(std::string const&);
+ std::set<std::string> getKeys();
+
+ // Repalce value of key, adding it if it does not exist
+ void replaceKey(std::string const& key, QPDFObjectHandle const&);
+ // Remove key, doing nothing if key does not exist
+ void removeKey(std::string const& key);
+
+ private:
+ std::map<std::string, QPDFObjectHandle> items;
+};
+
+#endif // __QPDF_DICTIONARY_HH__
diff --git a/libqpdf/qpdf/QPDF_Integer.hh b/libqpdf/qpdf/QPDF_Integer.hh
new file mode 100644
index 00000000..fb6360b2
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Integer.hh
@@ -0,0 +1,19 @@
+
+#ifndef __QPDF_INTEGER_HH__
+#define __QPDF_INTEGER_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+class QPDF_Integer: public QPDFObject
+{
+ public:
+ QPDF_Integer(int val);
+ virtual ~QPDF_Integer();
+ virtual std::string unparse();
+ int getVal() const;
+
+ private:
+ int val;
+};
+
+#endif // __QPDF_INTEGER_HH__
diff --git a/libqpdf/qpdf/QPDF_Name.hh b/libqpdf/qpdf/QPDF_Name.hh
new file mode 100644
index 00000000..a32f6f4f
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Name.hh
@@ -0,0 +1,22 @@
+
+#ifndef __QPDF_NAME_HH__
+#define __QPDF_NAME_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+class QPDF_Name: public QPDFObject
+{
+ public:
+ QPDF_Name(std::string const& name);
+ virtual ~QPDF_Name();
+ virtual std::string unparse();
+ std::string getName() const;
+
+ // Put # into strings with characters unsuitable for name token
+ static std::string normalizeName(std::string const& name);
+
+ private:
+ std::string name;
+};
+
+#endif // __QPDF_NAME_HH__
diff --git a/libqpdf/qpdf/QPDF_Null.hh b/libqpdf/qpdf/QPDF_Null.hh
new file mode 100644
index 00000000..60c1ae35
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Null.hh
@@ -0,0 +1,14 @@
+
+#ifndef __QPDF_NULL_HH__
+#define __QPDF_NULL_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+class QPDF_Null: public QPDFObject
+{
+ public:
+ virtual ~QPDF_Null();
+ std::string unparse();
+};
+
+#endif // __QPDF_NULL_HH__
diff --git a/libqpdf/qpdf/QPDF_Real.hh b/libqpdf/qpdf/QPDF_Real.hh
new file mode 100644
index 00000000..b950c569
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Real.hh
@@ -0,0 +1,20 @@
+
+#ifndef __QPDF_REAL_HH__
+#define __QPDF_REAL_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+class QPDF_Real: public QPDFObject
+{
+ public:
+ QPDF_Real(std::string const& val);
+ virtual ~QPDF_Real();
+ std::string unparse();
+ std::string getVal();
+
+ private:
+ // Store reals as strings to avoid roundoff errors.
+ std::string val;
+};
+
+#endif // __QPDF_REAL_HH__
diff --git a/libqpdf/qpdf/QPDF_Stream.hh b/libqpdf/qpdf/QPDF_Stream.hh
new file mode 100644
index 00000000..71381fd3
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_Stream.hh
@@ -0,0 +1,42 @@
+
+#ifndef __QPDF_STREAM_HH__
+#define __QPDF_STREAM_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+#include <qpdf/QPDFObjectHandle.hh>
+
+class Pipeline;
+class QPDF;
+
+class QPDF_Stream: public QPDFObject
+{
+ public:
+ QPDF_Stream(QPDF*, int objid, int generation,
+ QPDFObjectHandle stream_dict,
+ off_t offset, int length);
+ virtual ~QPDF_Stream();
+ virtual std::string unparse();
+ QPDFObjectHandle getDict() const;
+
+ // See comments in QPDFObjectHandle.hh
+ bool pipeStreamData(Pipeline*, bool filter,
+ bool normalize, bool compress);
+
+ // See comments in QPDFObjectHandle.hh
+ PointerHolder<Buffer> getStreamData();
+
+ private:
+ bool filterable(std::vector<std::string>& filters,
+ int& predictor, int& columns, bool& early_code_change);
+
+
+ QPDF* qpdf;
+ int objid;
+ int generation;
+ QPDFObjectHandle stream_dict;
+ off_t offset;
+ int length;
+};
+
+#endif // __QPDF_STREAM_HH__
diff --git a/libqpdf/qpdf/QPDF_String.hh b/libqpdf/qpdf/QPDF_String.hh
new file mode 100644
index 00000000..f3063c50
--- /dev/null
+++ b/libqpdf/qpdf/QPDF_String.hh
@@ -0,0 +1,23 @@
+
+#ifndef __QPDF_STRING_HH__
+#define __QPDF_STRING_HH__
+
+#include <qpdf/QPDFObject.hh>
+
+// QPDF_Strings may included embedded null characters.
+
+class QPDF_String: public QPDFObject
+{
+ public:
+ QPDF_String(std::string const& val);
+ virtual ~QPDF_String();
+ virtual std::string unparse();
+ std::string unparse(bool force_binary);
+ std::string getVal() const;
+ std::string getUTF8Val() const;
+
+ private:
+ std::string val;
+};
+
+#endif // __QPDF_STRING_HH__
diff --git a/libqpdf/qpdf/RC4.hh b/libqpdf/qpdf/RC4.hh
new file mode 100644
index 00000000..657bf35b
--- /dev/null
+++ b/libqpdf/qpdf/RC4.hh
@@ -0,0 +1,26 @@
+
+#ifndef __RC4_HH__
+#define __RC4_HH__
+
+class RC4
+{
+ public:
+ // key_len of -1 means treat key_data as a null-terminated string
+ RC4(unsigned char const* key_data, int key_len = -1);
+
+ // out_data = 0 means to encrypt/decrypt in place
+ void process(unsigned char* in_data, int len, unsigned char* out_data = 0);
+
+ private:
+ class RC4Key
+ {
+ public:
+ unsigned char state[256];
+ unsigned char x;
+ unsigned char y;
+ };
+
+ RC4Key key;
+};
+
+#endif // __RC4_HH__
diff --git a/libtests/Makefile b/libtests/Makefile
new file mode 100644
index 00000000..90899055
--- /dev/null
+++ b/libtests/Makefile
@@ -0,0 +1 @@
+include ../make/proxy.mk
diff --git a/libtests/ascii85.cc b/libtests/ascii85.cc
new file mode 100644
index 00000000..4b5fed13
--- /dev/null
+++ b/libtests/ascii85.cc
@@ -0,0 +1,36 @@
+#include <qpdf/Pl_ASCII85Decoder.hh>
+
+#include <qpdf/Pl_StdioFile.hh>
+#include <iostream>
+
+int main()
+{
+ Pl_StdioFile out("stdout", stdout);
+ Pl_ASCII85Decoder decode("decode", &out);
+
+ try
+ {
+ unsigned char buf[10000];
+ bool done = false;
+ while (! done)
+ {
+ int len = read(0, buf, sizeof(buf));
+ if (len <= 0)
+ {
+ done = true;
+ }
+ else
+ {
+ decode.write(buf, len);
+ }
+ }
+ decode.finish();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/libtests/bits.cc b/libtests/bits.cc
new file mode 100644
index 00000000..09f5d8e2
--- /dev/null
+++ b/libtests/bits.cc
@@ -0,0 +1,177 @@
+
+#include <qpdf/BitStream.hh>
+#include <qpdf/BitWriter.hh>
+#include <qpdf/Pl_Buffer.hh>
+#include <iostream>
+
+// See comments in bits.cc
+#define BITS_TESTING 1
+#define BITS_READ 1
+#define BITS_WRITE 1
+#include "../libqpdf/bits.icc"
+
+static void
+print_values(int byte_offset, unsigned int bit_offset,
+ unsigned int bits_available)
+{
+ std::cout << "byte offset = " << byte_offset << ", "
+ << "bit offset = " << bit_offset << ", "
+ << "bits available = " << bits_available << std::endl;
+}
+
+static void
+test_read_bits(unsigned char const* buf,
+ unsigned char const*& p, unsigned int& bit_offset,
+ unsigned int& bits_available, int bits_wanted)
+{
+ unsigned long result =
+ read_bits(p, bit_offset, bits_available, bits_wanted);
+
+ std::cout << "bits read: " << bits_wanted << ", result = " << result
+ << std::endl;
+ print_values(p - buf, bit_offset, bits_available);
+}
+
+static void
+test_write_bits(unsigned char& ch, unsigned int& bit_offset, unsigned long val,
+ int bits, Pl_Buffer* bp)
+{
+ write_bits(ch, bit_offset, val, bits, bp);
+ printf("ch = %02x, bit_offset = %d\n", (unsigned int) ch, bit_offset);
+}
+
+static void
+print_buffer(Pl_Buffer* bp)
+{
+ bp->finish();
+ Buffer* b = bp->getBuffer();
+ unsigned char const* p = b->getBuffer();
+ unsigned long l = b->getSize();
+ for (unsigned long i = 0; i < l; ++i)
+ {
+ printf("%02x%s", (unsigned int)(p[i]),
+ (i == l - 1) ? "\n" : " ");
+ }
+ printf("\n");
+ delete b;
+}
+
+static void
+test()
+{
+ // 11110101 00010101 01100101 01111001 00010010 10001001 01110101 01001011
+ // F5 15 65 79 12 89 75 4B
+
+ // Read tests
+
+ static unsigned char const buf[] = {
+ 0xF5, 0x15, 0x65, 0x79, 0x12, 0x89, 0x75, 0x4B
+ };
+
+ unsigned char const* p = buf;
+ unsigned int bit_offset = 7;
+ unsigned int bits_available = 64;
+
+ // 11110:101 0:001010:1 01100101: 01111001
+ // 0:00:1:0010 10001001 01110101 01001:011
+ print_values(p - buf, bit_offset, bits_available);
+ test_read_bits(buf, p, bit_offset, bits_available, 5);
+ test_read_bits(buf, p, bit_offset, bits_available, 4);
+ test_read_bits(buf, p, bit_offset, bits_available, 6);
+ test_read_bits(buf, p, bit_offset, bits_available, 9);
+ test_read_bits(buf, p, bit_offset, bits_available, 9);
+ test_read_bits(buf, p, bit_offset, bits_available, 2);
+ test_read_bits(buf, p, bit_offset, bits_available, 1);
+ test_read_bits(buf, p, bit_offset, bits_available, 0);
+ test_read_bits(buf, p, bit_offset, bits_available, 25);
+
+ try
+ {
+ test_read_bits(buf, p, bit_offset, bits_available, 4);
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "exception: " << e.what() << std::endl;
+ print_values(p - buf, bit_offset, bits_available);
+ }
+
+ test_read_bits(buf, p, bit_offset, bits_available, 3);
+ std::cout << std::endl;
+
+ // 11110101 00010101 01100101 01111001: 00010010 10001001 01110101 01001011
+
+ p = buf;
+ bit_offset = 7;
+ bits_available = 64;
+ print_values(p - buf, bit_offset, bits_available);
+ test_read_bits(buf, p, bit_offset, bits_available, 32);
+ test_read_bits(buf, p, bit_offset, bits_available, 32);
+ std::cout << std::endl;
+
+ BitStream b(buf, 8);
+ std::cout << b.getBits(32) << std::endl;
+ b.reset();
+ std::cout << b.getBits(32) << std::endl;
+ std::cout << b.getBits(32) << std::endl;
+ std::cout << std::endl;
+
+ b.reset();
+ std::cout << b.getBits(6) << std::endl;
+ b.skipToNextByte();
+ std::cout << b.getBits(8) << std::endl;
+ b.skipToNextByte();
+ std::cout << b.getBits(8) << std::endl;
+ std::cout << std::endl;
+
+ // Write tests
+
+ // 11110:101 0:001010:1 01100101: 01111001
+ // 0:00:1:0010 10001001 01110101 01001:011
+
+ unsigned char ch = 0;
+ bit_offset = 7;
+ Pl_Buffer* bp = new Pl_Buffer("buffer");
+
+ test_write_bits(ch, bit_offset, 30UL, 5, bp);
+ test_write_bits(ch, bit_offset, 10UL, 4, bp);
+ test_write_bits(ch, bit_offset, 10UL, 6, bp);
+ test_write_bits(ch, bit_offset, 16059UL, 0, bp);
+ test_write_bits(ch, bit_offset, 357UL, 9, bp);
+ print_buffer(bp);
+
+ test_write_bits(ch, bit_offset, 242UL, 9, bp);
+ test_write_bits(ch, bit_offset, 0UL, 2, bp);
+ test_write_bits(ch, bit_offset, 1UL, 1, bp);
+ test_write_bits(ch, bit_offset, 5320361UL, 25, bp);
+ test_write_bits(ch, bit_offset, 3UL, 3, bp);
+
+ print_buffer(bp);
+ test_write_bits(ch, bit_offset, 4111820153UL, 32, bp);
+ test_write_bits(ch, bit_offset, 310998347UL, 32, bp);
+ print_buffer(bp);
+
+ BitWriter bw(bp);
+ bw.writeBits(30UL, 5);
+ bw.flush();
+ bw.flush();
+ bw.writeBits(0xABUL, 8);
+ bw.flush();
+ print_buffer(bp);
+
+ delete bp;
+}
+
+int main()
+{
+ try
+ {
+ test();
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "unexpected exception: " << e.what() << std::endl;
+ exit(2);
+ }
+ std::cout << "done" << std::endl;
+ return 0;
+}
diff --git a/libtests/buffer.cc b/libtests/buffer.cc
new file mode 100644
index 00000000..6494c5c4
--- /dev/null
+++ b/libtests/buffer.cc
@@ -0,0 +1,61 @@
+
+#include <qpdf/Pl_Buffer.hh>
+#include <qpdf/Pl_Count.hh>
+#include <qpdf/Pl_Discard.hh>
+
+typedef unsigned char* uc;
+
+int main()
+{
+ try
+ {
+ Pl_Discard discard;
+ Pl_Count count("count", &discard);
+ Pl_Buffer bp1("bp1", &count);
+ bp1.write((uc)"12345", 5);
+ bp1.write((uc)"67890", 5);
+ bp1.finish();
+ std::cout << "count: " << count.getCount() << std::endl;
+ bp1.write((uc)"abcde", 5);
+ bp1.write((uc)"fghij", 6);
+ bp1.finish();
+ std::cout << "count: " << count.getCount() << std::endl;
+ Buffer* b = bp1.getBuffer();
+ std::cout << "size: " << b->getSize() << std::endl;
+ std::cout << "data: " << b->getBuffer() << std::endl;
+ delete b;
+ bp1.write((uc)"qwert", 5);
+ bp1.write((uc)"yuiop", 6);
+ bp1.finish();
+ std::cout << "count: " << count.getCount() << std::endl;
+ b = bp1.getBuffer();
+ std::cout << "size: " << b->getSize() << std::endl;
+ std::cout << "data: " << b->getBuffer() << std::endl;
+ delete b;
+
+ Pl_Buffer bp2("bp2");
+ bp2.write((uc)"moo", 3);
+ bp2.write((uc)"quack", 6);
+ try
+ {
+ delete bp2.getBuffer();
+ }
+ catch (std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ bp2.finish();
+ b = bp2.getBuffer();
+ std::cout << "size: " << b->getSize() << std::endl;
+ std::cout << "data: " << b->getBuffer() << std::endl;
+ delete b;
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "unexpected exception: " << e.what() << std::endl;
+ exit(2);
+ }
+
+ std::cout << "done" << std::endl;
+ return 0;
+}
diff --git a/libtests/build.mk b/libtests/build.mk
new file mode 100644
index 00000000..4a58fcaa
--- /dev/null
+++ b/libtests/build.mk
@@ -0,0 +1,40 @@
+BINS_libtests = \
+ ascii85 \
+ bits \
+ buffer \
+ flate \
+ hex \
+ lzw \
+ md5 \
+ pcre \
+ png_filter \
+ pointer_holder \
+ qexc \
+ qutil \
+ rc4
+
+TARGETS_libtests = $(foreach B,$(BINS_libtests),libtests/$(OUTPUT_DIR)/$(B))
+
+$(TARGETS_libtests): $(TARGETS_libqpdf)
+
+INCLUDES_libtests = include libqpdf
+
+TC_SRCS_libtests = $(wildcard libqpdf/*.cc) $(wildcard libtests/*.cc) \
+ libqpdf/bits.icc
+
+# -----
+
+$(foreach B,$(BINS_libtests),$(eval \
+ OBJS_$(B) = $(call src_to_obj,libtests/$(B).cc)))
+
+ifeq ($(GENDEPS),1)
+-include $(foreach B,$(BINS_libtests),$(call obj_to_dep,$(OBJS_$(B))))
+endif
+
+$(foreach B,$(BINS_libtests),$(eval \
+ $(OBJS_$(B)): libtests/$(OUTPUT_DIR)/%.o: libtests/$(B).cc ; \
+ $(call compile,libtests/$(B).cc,$(INCLUDES_libtests))))
+
+$(foreach B,$(BINS_libtests),$(eval \
+ libtests/$(OUTPUT_DIR)/$(B): $(OBJS_$(B)) ; \
+ $(call makebin,$(OBJS_$(B)),$$@)))
diff --git a/libtests/flate.cc b/libtests/flate.cc
new file mode 100644
index 00000000..0b5b8977
--- /dev/null
+++ b/libtests/flate.cc
@@ -0,0 +1,110 @@
+
+#include <qpdf/Pl_Flate.hh>
+#include <qpdf/Pl_StdioFile.hh>
+#include <qpdf/Pl_Count.hh>
+
+#include <iostream>
+#include <errno.h>
+
+FILE* safe_fopen(char const* filename, char const* mode)
+{
+ FILE* result = fopen(filename, mode);
+ if (result == 0)
+ {
+ std::cerr << "fopen " << filename << " failed: " << strerror(errno)
+ << std::endl;
+ }
+ return result;
+}
+
+void run(char const* filename)
+{
+ std::string n1 = std::string(filename) + ".1";
+ std::string n2 = std::string(filename) + ".2";
+ std::string n3 = std::string(filename) + ".3";
+
+ FILE* o1 = safe_fopen(n1.c_str(), "wb");
+ FILE* o2 = safe_fopen(n2.c_str(), "wb");
+ FILE* o3 = safe_fopen(n3.c_str(), "wb");
+ Pipeline* out1 = new Pl_StdioFile("o1", o1);
+ Pipeline* out2 = new Pl_StdioFile("o2", o2);
+ Pipeline* out3 = new Pl_StdioFile("o3", o3);
+
+ // Compress the file
+ Pipeline* def1 = new Pl_Flate("def1", out1, Pl_Flate::a_deflate);
+
+ // Decompress the file
+ Pipeline* inf2 = new Pl_Flate("inf2", out2, Pl_Flate::a_inflate);
+
+ // Count bytes written to o3
+ Pl_Count* count3 = new Pl_Count("count3", out3);
+
+ // Do both simultaneously
+ Pipeline* inf3 = new Pl_Flate("inf3", count3, Pl_Flate::a_inflate);
+ Pipeline* def3 = new Pl_Flate("def3", inf3, Pl_Flate::a_deflate);
+
+ FILE* in1 = safe_fopen(filename, "rb");
+ unsigned char buf[1024];
+ size_t len;
+ while ((len = fread(buf, 1, sizeof(buf), in1)) > 0)
+ {
+ // Write to the compression pipeline
+ def1->write(buf, len);
+
+ // Write to the both pipeline
+ def3->write(buf, len);
+ }
+
+ def1->finish();
+ delete def1;
+ delete out1;
+ fclose(o1);
+
+ def3->finish();
+
+ std::cout << "bytes written to o3: " << count3->getCount() << std::endl;
+
+
+ delete def3;
+ delete inf3;
+ delete count3;
+ delete out3;
+ fclose(o3);
+
+ // Now read the compressed data and write to the output uncompress pipeline
+ FILE* in2 = safe_fopen(n1.c_str(), "rb");
+ while ((len = fread(buf, 1, sizeof(buf), in2)) > 0)
+ {
+ inf2->write(buf, len);
+ }
+
+ inf2->finish();
+ delete inf2;
+ delete out2;
+ fclose(o2);
+
+ // At this point, filename, filename.2, and filename.3 should have
+ // identical contents. filename.1 should be a compressed version.
+
+ std::cout << "done" << std::endl;
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cerr << "Usage: pipeline filename" << std::endl;
+ exit(2);
+ }
+ char* filename = argv[1];
+
+ try
+ {
+ run(filename);
+ }
+ catch (QEXC::General& e)
+ {
+ std::cout << e.unparse() << std::endl;
+ }
+ return 0;
+}
diff --git a/libtests/hex.cc b/libtests/hex.cc
new file mode 100644
index 00000000..0bd6354a
--- /dev/null
+++ b/libtests/hex.cc
@@ -0,0 +1,36 @@
+#include <qpdf/Pl_ASCIIHexDecoder.hh>
+
+#include <qpdf/Pl_StdioFile.hh>
+#include <iostream>
+
+int main()
+{
+ Pl_StdioFile out("stdout", stdout);
+ Pl_ASCIIHexDecoder decode("decode", &out);
+
+ try
+ {
+ unsigned char buf[10000];
+ bool done = false;
+ while (! done)
+ {
+ int len = read(0, buf, sizeof(buf));
+ if (len <= 0)
+ {
+ done = true;
+ }
+ else
+ {
+ decode.write(buf, len);
+ }
+ }
+ decode.finish();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/libtests/libtests.testcov b/libtests/libtests.testcov
new file mode 100644
index 00000000..ddbccd24
--- /dev/null
+++ b/libtests/libtests.testcov
@@ -0,0 +1,18 @@
+ignored-scope: qpdf
+Pl_LZWDecoder intermediate reset 0
+Pl_LZWDecoder last was table size 0
+Pl_ASCII85Decoder ignore space 0
+Pl_ASCII85Decoder read z 0
+Pl_ASCII85Decoder no-op flush 0
+Pl_ASCII85Decoder partial flush 1
+bits leftover 1
+bits bit_offset 2
+bits iterations 2
+bits zero bits wanted 0
+bits write iterations 2
+bits write leftover 0
+bits write pipeline 0
+bits write zero bits 0
+Pl_ASCIIHexDecoder ignore space 0
+Pl_ASCIIHexDecoder no-op flush 0
+Pl_ASCIIHexDecoder partial flush 1
diff --git a/libtests/lzw.cc b/libtests/lzw.cc
new file mode 100644
index 00000000..38c8e541
--- /dev/null
+++ b/libtests/lzw.cc
@@ -0,0 +1,38 @@
+#include <qpdf/Pl_LZWDecoder.hh>
+
+#include <qpdf/Pl_StdioFile.hh>
+#include <iostream>
+
+int main()
+{
+ Pl_StdioFile out("stdout", stdout);
+ // We don't exercise LZWDecoder with early code change false
+ // because we have no way to generate such an LZW stream.
+ Pl_LZWDecoder decode("decode", &out, true);
+
+ try
+ {
+ unsigned char buf[10000];
+ bool done = false;
+ while (! done)
+ {
+ int len = read(0, buf, sizeof(buf));
+ if (len <= 0)
+ {
+ done = true;
+ }
+ else
+ {
+ decode.write(buf, len);
+ }
+ }
+ decode.finish();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/libtests/md5.cc b/libtests/md5.cc
new file mode 100644
index 00000000..e1c69bb6
--- /dev/null
+++ b/libtests/md5.cc
@@ -0,0 +1,74 @@
+
+#include <qpdf/MD5.hh>
+#include <qpdf/Pl_MD5.hh>
+#include <qpdf/Pl_Discard.hh>
+#include <iostream>
+
+static void test_string(char const* str)
+{
+ MD5 a;
+ a.encodeString(str);
+ a.print();
+}
+
+int main(int, char*[])
+{
+ test_string("");
+ test_string("a");
+ test_string("abc");
+ test_string("message digest");
+ test_string("abcdefghijklmnopqrstuvwxyz");
+ test_string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi"
+ "jklmnopqrstuvwxyz0123456789");
+ test_string("1234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890");
+ MD5 a;
+ a.encodeFile("md5.in");
+ std::cout << a.unparse() << std::endl;
+ MD5 b;
+ b.encodeFile("md5.in", 100);
+ std::cout << b.unparse() << std::endl;
+
+ std::cout
+ << MD5::checkDataChecksum("900150983cd24fb0d6963f7d28e17f72", "abc", 3)
+ << std::endl
+ << MD5::checkFileChecksum("5f4b4321873433daae578f85c72f9e74", "md5.in")
+ << std::endl
+ << MD5::checkFileChecksum("6f4b4321873433daae578f85c72f9e74", "md5.in")
+ << std::endl
+ << MD5::checkDataChecksum("000150983cd24fb0d6963f7d28e17f72", "abc", 3)
+ << std::endl
+ << MD5::checkFileChecksum("6f4b4321873433daae578f85c72f9e74", "glerbl")
+ << std::endl;
+
+
+ Pl_Discard d;
+ Pl_MD5 p("MD5", &d);
+ for (int i = 0; i < 2; ++i)
+ {
+ FILE* f = fopen("md5.in", "rb");
+ if (f)
+ {
+ // buffer size < size of md5.in
+ unsigned char buf[50];
+ bool done = false;
+ while (! done)
+ {
+ int len = fread(buf, 1, sizeof(buf), f);
+ if (len <= 0)
+ {
+ done = true;
+ }
+ else
+ {
+ p.write(buf, len);
+ }
+ }
+ fclose(f);
+ p.finish();
+ std::cout << p.getHexDigest() << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/libtests/pcre.cc b/libtests/pcre.cc
new file mode 100644
index 00000000..0df692a3
--- /dev/null
+++ b/libtests/pcre.cc
@@ -0,0 +1,30 @@
+
+#include <qpdf/PCRE.hh>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+ if ((argc == 2) && (strcmp(argv[1], "--unicode-classes-supported") == 0))
+ {
+ try
+ {
+ PCRE("^([\\p{L}]+)", PCRE_UTF8);
+ std::cout << "1" << std::endl;
+ }
+ catch (PCRE::Exception& e)
+ {
+ std::cout << "0" << std::endl;
+ }
+ return 0;
+ }
+
+ if ((argc == 2) && (strcmp(argv[1], "--unicode-classes") == 0))
+ {
+ PCRE::test(1);
+ }
+ else
+ {
+ PCRE::test();
+ }
+ return 0;
+}
diff --git a/libtests/png_filter.cc b/libtests/png_filter.cc
new file mode 100644
index 00000000..eef1aa3d
--- /dev/null
+++ b/libtests/png_filter.cc
@@ -0,0 +1,84 @@
+
+#include <qpdf/Pl_PNGFilter.hh>
+#include <qpdf/Pl_StdioFile.hh>
+
+#include <iostream>
+#include <errno.h>
+#include <assert.h>
+
+FILE* safe_fopen(char const* filename, char const* mode)
+{
+ FILE* result = fopen(filename, mode);
+ if (result == 0)
+ {
+ std::cerr << "fopen " << filename << " failed: " << strerror(errno)
+ << std::endl;
+ }
+ return result;
+}
+
+void run(char const* filename, bool encode, unsigned int columns)
+{
+ // Decode the file
+ FILE* in = safe_fopen(filename, "rb");
+ FILE* o1 = safe_fopen("out", "wb");
+ Pipeline* out = new Pl_StdioFile("out", o1);
+ Pipeline* pl = new Pl_PNGFilter(
+ "png", out,
+ encode ? Pl_PNGFilter::a_encode : Pl_PNGFilter::a_decode,
+ columns, 0 /* not used */);
+ assert((2 * (columns + 1)) < 1024);
+ unsigned char buf[1024];
+ size_t len;
+ while (true)
+ {
+ len = fread(buf, 1, (2 * columns) + 1, in);
+ if (len == 0)
+ {
+ break;
+ }
+ pl->write(buf, len);
+ len = fread(buf, 1, 1, in);
+ if (len == 0)
+ {
+ break;
+ }
+ pl->write(buf, len);
+ len = fread(buf, 1, 1, in);
+ if (len == 0)
+ {
+ break;
+ }
+ pl->write(buf, len);
+ }
+
+ pl->finish();
+ delete pl;
+ delete out;
+ fclose(o1);
+ fclose(in);
+
+ std::cout << "done" << std::endl;
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "Usage: pipeline {en,de}code filename columns" << std::endl;
+ exit(2);
+ }
+ bool encode = (strcmp(argv[1], "encode") == 0);
+ char* filename = argv[2];
+ int columns = atoi(argv[3]);
+
+ try
+ {
+ run(filename, encode, columns);
+ }
+ catch (QEXC::General& e)
+ {
+ std::cout << e.unparse() << std::endl;
+ }
+ return 0;
+}
diff --git a/libtests/pointer_holder.cc b/libtests/pointer_holder.cc
new file mode 100644
index 00000000..9176df17
--- /dev/null
+++ b/libtests/pointer_holder.cc
@@ -0,0 +1,81 @@
+
+#include <qpdf/PointerHolder.hh>
+
+#include <iostream>
+#include <stdlib.h>
+#include <list>
+
+#include <qpdf/QUtil.hh>
+
+class Object
+{
+ public:
+ Object();
+ ~Object();
+ void hello();
+
+ private:
+ static int next_id;
+ int id;
+};
+
+
+int Object::next_id = 0;
+
+Object::Object()
+{
+ this->id = ++next_id;
+ std::cout << "created Object, id " << this->id << std::endl;
+}
+
+Object::~Object()
+{
+ std::cout << "destroyed Object, id " << this->id << std::endl;
+}
+
+void
+Object::hello()
+{
+ std::cout << "calling Object::hello for " << this->id << std::endl;
+}
+
+typedef PointerHolder<Object> ObjectHolder;
+
+int main(int argc, char* argv[])
+{
+ std::list<ObjectHolder> ol1;
+
+ ObjectHolder oh0;
+ {
+ std::cout << "hello" << std::endl;
+ Object* o1 = new Object;
+ ObjectHolder oh1(o1);
+ ObjectHolder oh2(oh1);
+ ObjectHolder oh3(new Object);
+ ObjectHolder oh4;
+ ObjectHolder oh5;
+ if (oh4 == oh5)
+ {
+ std::cout << "nulls equal" << std::endl;
+ }
+ oh3 = oh1;
+ oh4 = oh2;
+ if (oh3 == oh4)
+ {
+ std::cout << "equal okay" << std::endl;
+ }
+ if ((! (oh3 < oh4)) && (! (oh4 < oh3)))
+ {
+ std::cout << "less than okay" << std::endl;
+ }
+ ol1.push_back(oh3);
+ ol1.push_back(oh3);
+ Object* o3 = new Object;
+ oh0 = o3;
+ }
+
+ ol1.front().getPointer()->hello();
+ ol1.pop_front();
+ std::cout << "goodbye" << std::endl;
+ return 0;
+}
diff --git a/libtests/qexc.cc b/libtests/qexc.cc
new file mode 100644
index 00000000..db12d39c
--- /dev/null
+++ b/libtests/qexc.cc
@@ -0,0 +1,65 @@
+
+#include <qpdf/QEXC.hh>
+#include <iostream>
+#include <errno.h>
+
+void do_terminate()
+{
+ try
+ {
+ throw;
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "uncaught exception: " << e.what() << std::endl;
+ exit(3);
+ }
+ exit(4);
+}
+
+void f(int n)
+{
+ switch (n)
+ {
+ case 0:
+ throw QEXC::General("general exception");
+ break;
+
+ case 1:
+ throw QEXC::Internal("internal error");
+ break;
+
+ case 2:
+ throw QEXC::System("doing something", EINVAL);
+ break;
+
+ case 3:
+ {
+ int a = -1;
+ new char[a];
+ }
+ break;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ std::set_terminate(do_terminate);
+ if (argc != 2)
+ {
+ std::cerr << "usage: qexc n" << std::endl;
+ exit(2);
+ }
+
+ try
+ {
+ f(atoi(argv[1]));
+ }
+ catch (QEXC::General& e)
+ {
+ std::cerr << "exception: " << e.unparse() << std::endl;
+ std::cerr << "what: " << e.what() << std::endl;
+ exit(2);
+ }
+ return 0;
+}
diff --git a/libtests/qtest/ascii85.test b/libtests/qtest/ascii85.test
new file mode 100644
index 00000000..07551bd1
--- /dev/null
+++ b/libtests/qtest/ascii85.test
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("ascii85") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('ascii85');
+
+$td->runtest("decode",
+ {$td->COMMAND => "ascii85 < base85.in"},
+ {$td->FILE => "binary.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("partial decode",
+ {$td->COMMAND => "echo '\@<5skEHbu7\$3~>' | ascii85"},
+ {$td->STRING => "asdfqwer\n",
+ $td->EXIT_STATUS => 0});
+
+$td->report(2);
diff --git a/libtests/qtest/ascii85/base85.in b/libtests/qtest/ascii85/base85.in
new file mode 100644
index 00000000..0237ac51
--- /dev/null
+++ b/libtests/qtest/ascii85/base85.in
@@ -0,0 +1,43 @@
+70!<9iWTSm7K<E>iWTSm7fWNCiWTSm8,rWHiWTSm8H8`MiWTSm8cSiRiWTSm
+9)nrWiWTSm9E5&\iWTSm9`P/aiWTSm:&k8fiWTSm:B1AkiWTSm:]LJpiWTSm
+;#gSuiWTSm;?-]%iWTSm;ZHf*iWTSm;uco/iWTSm<<*#4iWTSm<WE,9iWTSm
+<r`5>iWTSm=9&>CiWTSm=TAGHiWTSm=o\P&M<.ZglicMP!!!"'J]"ig!<A%A
+q#CBoL!k&HkhZ:>!9c9E!!)4J#6=g,>KOe_2$i.E#lc1Zi<9Je!!!$!,nT#=
+#\X2<!!)9As8W-!,o#;A#\XJD!!)91s8W-!,oGSE#\XbL!!)9!s8W-!,okkI
+#\Y%T!!)8fs8W-!,p;.M#\Y=\!!)8Vs8W-!,p_FQ#\YUd!!)8Fs8W-!,q.^U
+#\Yml!!)86s8W-!,qS!Y#\Z0t!!)8&s8W-!,r"9]#\ZI'!!)7ks8W-!,rFQa
+#\Za/!!)7[s8W-!,rjie#\[$7!!)7Ks8W-!,s:,i#\[<?!!)7;s8W-!,s^Dm
+#\[TG!!)7+s8W-!,t-\q#\[lO!!)6ps8W-!,tQtu#\\/W!!)6`s8W-!,u!8$
+#\\G_!!)9Qrr<#u,uEP(#\\_g!!)9Arr<#u,uih,#\]"o!!)91rr<#u-!9+0
+#\];"!!)9!rr<#u-!]C4#\]S*!!)8frr<#u-",[8#\]k2!!)8Vrr<#u-"Ps<
+#\^.:!!)8Frr<#u-"u6@#\^FB!!)86rr<#u-#DND#\^^J!!)8&rr<#u-#hfH
+#\_!R!!)7krr<#u-$8)L#\_9Z!!)7[rr<#u-$\AP#\_Qb!!)7Krr<#u-%+YT
+#\_ij!!)7;rr<#u-%OqX#\`,r!!)7+rr<#u-%t4\#\`E%!!)6prr<#u-&CL`
+#\`]-!!)6`rr<#u-&gdd#\`u5!!)9QrVuot-'7'h#\X2=!!)9ArVuot-'[?l
+#\XJE!!)91rVuot-(*Wp#\XbM!!)9!rVuot-(Not#\Y%U!!)8frVuot-(s3#
+#\Y=]!!)8VrVuot-)BK'#\YUe!!)8FrVuot-)fc+#\Ymm!!)86rVuot-*6&/
+#\Z0u!!)8&rVuot-*Z>3#\ZI(!!)7krVuot-+)V7#\Za0!!)7[rVuot-+Mn;
+#\[$8!!)7KrVuot-+r1?#\[<@!!)7;rVuot-,AIC#\[TH!!)7+rVuot-,eaG
+#\[lP!!)6prVuot--5$K#\\/X!!)6`rVuot--Y<O#\\G`!!)9Qr;Zfs-.(TS
+#\\_h!!)9Ar;Zfs-.LlW#\]"p!!)91r;Zfs-.q/[#\];#!!)9!r;Zfs-/@G_
+#\]S+!!)8fr;Zfs-/d_c#\]k3!!)8Vr;Zfs-04"g#\^.;!!)8Fr;Zfs-0X:k
+#\^FC!!)86r;Zfs-1'Ro#\^^K!!)8&r;Zfs-1Kjs#\_!S!!)7kr;Zfs-1p."
+#\_9[!!)7[r;Zfs-2?F&#\_Qc!!)7Kr;Zfs-2c^*#\_ik!!)7;r;Zfs,llp.
+#\`,s!!)7+r;Zfs,m<32#\`E&!!)6pr;Zfs,m`K6#\`].!!)6`r;Zfs,n/c:
+#\`u6!!)9Qqu?]r,nT&>#\X2>!!)9Aqu?]r,o#>B#\XJF!!)91qu?]r,oGVF
+#\XbN!!)9!qu?]r,oknJ#\Y%V!!)8fqu?]r,p;1N#\Y=^!!)8Vqu?]r,p_IR
+#\YUf!!)8Fqu?]r,q.aV#\Ymn!!)86qu?]r,qS$Z#\Z1!!!)8&qu?]r,r"<^
+#\ZI)!!)7kqu?]r,rFTb#\Za1!!)7[qu?]r,rjlf#\[$9!!)7Kqu?]r,s:/j
+#\[<A!!)7;qu?]r,s^Gn#\[TI!!)7+qu?]r,t-_r#\[lQ!!)6pqu?]r,tR#!
+#\\/Y!!)6`qu?]r,u!;%#\\Ga!!)9QqZ$Tq,uES)#\\_i!!)9AqZ$Tq,uik-
+#\]"q!!)91qZ$Tq-!9.1#\];$!!)9!qZ$Tq-!]F5#\]S,!!)8fqZ$Tq-",^9
+#\]k4!!)8VqZ$Tq-"Q!=#\^.<!!)8FqZ$Tq-"u9A#\^FD!!)86qZ$Tq-#DQE
+#\^^L!!)8&qZ$Tq-#hiI#\_!T!!)7kqZ$Tq-$8,M#\_9\!!)7[qZ$Tq-$\DQ
+#\_Qd!!)7KqZ$Qqzz!!!!Rm9YY.KB2Mu<)RB0Rfs(2&=Wh/;-%B"jobtRPPb
+C[oT5/rOH>QcOH>QcOH>Q(M<0BV#_5(Ziro\gF:@ITK>7VbLuJRDs3dTsiWT
+UG&;APTlc'+Liro\hahs3?M<0BV#b_gf"UKgtF:u(`!!!"Q^iTn'"=+Q:"UP
+.Tahs4%OH>QcOH>QcOH>Q(M<0BV(lLfgMbOV<:]u[VM+f0#a$_0]zM,Y`'M$
+,*fQi6sbahs4"F=$ufM<0BV#`0NHMd6aJF<h!IFU3mu"H-:`MZts>1!q`($,
+La&Mb=>67L4oV%#\-p0uu*'$.'3I^kop\iW4rW,`0m+F<h!Gls7MgF=%!]+Q
+Wb4<Jfgk^i]p@70oY2jTPoq_i8g>NP$V=!!!"m+QWb4<Jfgk^i^*[,io18K>
+7M_,io18?,Mb`F=$ufKYWH+F:?1n~>trailing garbage
diff --git a/libtests/qtest/ascii85/binary.out b/libtests/qtest/ascii85/binary.out
new file mode 100644
index 00000000..f33a0b43
--- /dev/null
+++ b/libtests/qtest/ascii85/binary.out
Binary files differ
diff --git a/libtests/qtest/bits.test b/libtests/qtest/bits.test
new file mode 100644
index 00000000..f5dac7b5
--- /dev/null
+++ b/libtests/qtest/bits.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("bits") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('bits');
+
+$td->runtest("bits",
+ {$td->COMMAND => "bits"},
+ {$td->FILE => "bits.out",
+ $td->EXIT_STATUS => 0});
+
+$td->report(1);
diff --git a/libtests/qtest/bits/bits.out b/libtests/qtest/bits/bits.out
new file mode 100644
index 00000000..73111536
--- /dev/null
+++ b/libtests/qtest/bits/bits.out
@@ -0,0 +1,59 @@
+byte offset = 0, bit offset = 7, bits available = 64
+bits read: 5, result = 30
+byte offset = 0, bit offset = 2, bits available = 59
+bits read: 4, result = 10
+byte offset = 1, bit offset = 6, bits available = 55
+bits read: 6, result = 10
+byte offset = 1, bit offset = 0, bits available = 49
+bits read: 9, result = 357
+byte offset = 3, bit offset = 7, bits available = 40
+bits read: 9, result = 242
+byte offset = 4, bit offset = 6, bits available = 31
+bits read: 2, result = 0
+byte offset = 4, bit offset = 4, bits available = 29
+bits read: 1, result = 1
+byte offset = 4, bit offset = 3, bits available = 28
+bits read: 0, result = 0
+byte offset = 4, bit offset = 3, bits available = 28
+bits read: 25, result = 5320361
+byte offset = 7, bit offset = 2, bits available = 3
+exception: overflow reading bit stream
+byte offset = 7, bit offset = 2, bits available = 3
+bits read: 3, result = 3
+byte offset = 8, bit offset = 7, bits available = 0
+
+byte offset = 0, bit offset = 7, bits available = 64
+bits read: 32, result = 4111820153
+byte offset = 4, bit offset = 7, bits available = 32
+bits read: 32, result = 310998347
+byte offset = 8, bit offset = 7, bits available = 0
+
+4111820153
+4111820153
+310998347
+
+61
+21
+101
+
+ch = f0, bit_offset = 2
+ch = 00, bit_offset = 6
+ch = 14, bit_offset = 0
+ch = 14, bit_offset = 0
+ch = 00, bit_offset = 7
+f5 15 65
+
+ch = 00, bit_offset = 6
+ch = 00, bit_offset = 4
+ch = 10, bit_offset = 3
+ch = 48, bit_offset = 2
+ch = 00, bit_offset = 7
+79 12 89 75 4b
+
+ch = 00, bit_offset = 7
+ch = 00, bit_offset = 7
+f5 15 65 79 12 89 75 4b
+
+f0 ab
+
+done
diff --git a/libtests/qtest/buffer.test b/libtests/qtest/buffer.test
new file mode 100644
index 00000000..83ce4643
--- /dev/null
+++ b/libtests/qtest/buffer.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("buffer") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('buffer');
+
+$td->runtest("buffer",
+ {$td->COMMAND => "buffer"},
+ {$td->FILE => "buffer.out",
+ $td->EXIT_STATUS => 0});
+
+$td->report(1);
diff --git a/libtests/qtest/buffer/buffer.out b/libtests/qtest/buffer/buffer.out
new file mode 100644
index 00000000..9ee2b545
--- /dev/null
+++ b/libtests/qtest/buffer/buffer.out
@@ -0,0 +1,11 @@
+count: 10
+count: 21
+size: 21
+data: 1234567890abcdefghij
+count: 32
+size: 11
+data: qwertyuiop
+INTERNAL ERROR: Pl_Buffer::getBuffer() called when not ready
+size: 9
+data: mooquack
+done
diff --git a/libtests/qtest/flate.test b/libtests/qtest/flate.test
new file mode 100644
index 00000000..fe850b3e
--- /dev/null
+++ b/libtests/qtest/flate.test
@@ -0,0 +1,73 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+use File::Copy;
+use Digest::MD5;
+
+chdir("flate") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+cleanup();
+
+my $td = new TestDriver('flate');
+
+cleanup();
+
+open(F, ">farbage") or die;
+print F "q" x 10000, "\n";
+print F "w" x 10000, "\n";
+print F "e" x 10000, "\n";
+print F "r" x 10000, "\n";
+print F "t" x 10000, "\n";
+print F "y" x 10000, "\n";
+print F "u" x 10000, "\n";
+print F "i" x 10000, "\n";
+print F "o" x 10000, "\n";
+print F "p" x 10000, "\n";
+close(F);
+
+check_file("farbage", "a6449c61db5b0645c0693b7560b77a60");
+
+$td->runtest("run driver",
+ {$td->COMMAND => "flate farbage"},,
+ {$td->STRING => "bytes written to o3: 100010\ndone\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+check_file("farbage", "a6449c61db5b0645c0693b7560b77a60");
+
+$td->runtest("compressed file correct",
+ {$td->FILE => "farbage.1"},
+ {$td->FILE => "compressed"});
+
+$td->runtest("uncompress filter works",
+ {$td->FILE => "farbage"},
+ {$td->FILE => "farbage.2"});
+
+$td->runtest("double filter works",
+ {$td->FILE => "farbage"},
+ {$td->FILE => "farbage.3"});
+
+cleanup();
+
+$td->report(6);
+
+sub cleanup
+{
+ system("rm -f farbage*");
+}
+
+sub check_file
+{
+ my ($file, $sum) = @_;
+ open(F, "<$file") or die "open $file";
+ my $md5 = new Digest::MD5;
+ $md5->addfile(*F);
+ close(F);
+ my $result = $md5->hexdigest;
+ $td->runtest("check $file",
+ {$td->STRING => "$result\n"},
+ {$td->STRING => "$sum\n"});
+}
diff --git a/libtests/qtest/flate/compressed b/libtests/qtest/flate/compressed
new file mode 100644
index 00000000..79b2da1b
--- /dev/null
+++ b/libtests/qtest/flate/compressed
Binary files differ
diff --git a/libtests/qtest/hex.test b/libtests/qtest/hex.test
new file mode 100644
index 00000000..32ec84b5
--- /dev/null
+++ b/libtests/qtest/hex.test
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("hex") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('hex');
+
+$td->runtest("decode",
+ {$td->COMMAND => "hex < hex.in"},
+ {$td->FILE => "binary.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("partial decode",
+ {$td->COMMAND => "echo '7a65726F203D203>' | hex"},
+ {$td->STRING => "zero = 0",
+ $td->EXIT_STATUS => 0});
+
+$td->report(2);
diff --git a/libtests/qtest/hex/binary.out b/libtests/qtest/hex/binary.out
new file mode 100644
index 00000000..f33a0b43
--- /dev/null
+++ b/libtests/qtest/hex/binary.out
Binary files differ
diff --git a/libtests/qtest/hex/hex.in b/libtests/qtest/hex/hex.in
new file mode 100644
index 00000000..9721a35a
--- /dev/null
+++ b/libtests/qtest/hex/hex.in
@@ -0,0 +1,70 @@
+45000028e20508074600002ce205080747000030e205080748000034e20
+5080749000038e20508074a00003ce20508074b000040e20508074c0000
+44e20508074d000048e20508074e00004ce20508074f000050e20508075
+0000054e205080751000058e20508075200005ce205080753000060e205
+080754000064e205080755000068e20508075600006ce20508075700007
+0e205080758000074e205080759000078e20508075a00005589e55383ec
+04e8000000005b81c3b44c01008b93f8ffffff85d27405e8de000000e83
+5060000e840070100585bc9c3ff3508e10508ff250ce1050800000000ff
+2510e105086800000000e9e0ffffffff2514e105086808000000e9d0fff
+fffff2518e105086810000000e9c0ffffffff251ce105086818000000e9
+b0ffffffff2520e105086820000000e9a0ffffffff2524e105086828000
+000e990ffffffff2528e105086830000000e980ffffffff252ce1050868
+38000000e970ffffffff2530e105086840000000e960ffffffff2534e10
+5086848000000e950ffffffff2538e105086850000000e940ffffffff25
+3ce105086858000000e930ffffffff2540e105086860000000e920fffff
+fff2544e105086868000000e910ffffffff2548e105086870000000e900
+ffffffff254ce105086878000000e9f0feffffff2550e10508688000000
+0e9e0feffffff2554e105086888000000e9d0feffffff2558e105086890
+000000e9c0feffffff255ce105086898000000e9b0feffffff2560e1050
+868a0000000e9a0feffffff2564e1050868a8000000e990feffffff2568
+e1050868b0000000e980feffffff256ce1050868b8000000e970fefffff
+f2570e1050868c0000000e960feffffff2574e1050868c8000000e950fe
+ffffff2578e1050868d0000000e940feffffff257ce1050868d8000000e
+930feffffff2580e1050868e0000000e920feffffff2584e1050868e800
+0000e910feffffff2588e1050868f0000000e900feffffff258ce105086
+8f8000000e9f0fdffffff2590e105086800010000e9e0fdffffff2594e1
+05086808010000e9d0fdffffff2598e105086810010000e9c0fdffffff2
+59ce105086818010000e9b0fdffffff25a0e105086820010000e9a0fdff
+ffff25a4e105086828010000e990fdffffff25a8e105086830010000e98
+0fdffffff25ace105086838010000e970fdffffff25b0e1050868400100
+00e960fdffffff25b4e105086848010000e950fdffffff25b8e10508685
+0010000e940fdffffff25bce105086858010000e930fdffffff25c0e105
+086860010000e920fdffffff25c4e105086868010000e910fdffffff25c
+8e105086870010000e900fdffffff25cce105086878010000e9f0fcffff
+FF25D0E105086880010000E9E0FCFFFFFF25D4E105086888010000E9D0F
+CFFFFFF25D8E105086890010000E9C0FCFFFFFF25DCE105086898010000
+E9B0FCFFFFFF25E0E1050868A0010000E9A0FCFFFFFF25E4E1050868A80
+10000E990FCFFFFFF25E8E1050868B0010000E980FCFFFFFF25ECE10508
+68B8010000E970FCFFFFFF25F0E1050868C0010000E960FCFFFFFF25F4E
+1050868C8010000E950FCFFFFFF25F8E1050868D0010000E940FCFFFFFF
+25FCE1050868D801 0000E930FCFFFFFF2500E2050868E0010000E920FCF
+FFFFF2504E2050868E8010000E910FCFFFFFF2508E2050868F0010000E9
+00FCFFFFFF250CE2050868F8010000E9F0FBFFFFFF2510E205086800020
+000E9E0FBFFFFFF2514E205086808020000E9D0FBFFFFFF2518E2050868
+10020000E9C0FBFFFFFF251CE205086818020000E9B0FBFFFFFF2520E20
+5086820020000E9A0FBFFFFFF2524E205086828020000E990FBFFFFFF25
+28E2050 8683 0020000E980FBFFFFFF252CE205086838020000E970FBFFF
+FFF2530E205086840020000E960FBFFFFFF2534E205086848020000E950
+FBFFFFFF2538E205086850020000E940FBFFFFFF253CE20508685802000
+0E930FBFFFFFF2540E205086860020000E920FBFFFFFF2544E205086868
+020000E910FBFFFFFF2548E205086870020000E900FBFFFFFF254CE2050
+86878020000E9F0FAFFFFFF2550E205086880020000E9E0FAFFFFFF2554
+e205086888020000e9d0faffffff2558e205086890020000e9c0fafffff
+f255ce205086898020000e9b0faffffff2560e2050868a0020000e9a0fa
+ffffff2564e2050868a8020000e990faffffff2568e2050868b0020000e
+980faffffff256ce2050868b8020000e970faffffff2570e2050868c002
+0000e960faffffff2574e2050868c8020000e950faffffff2578e205086
+8d0020000e940faffff00000000000000000000000031ed5e89e183e4f0
+50545268009b050868109b0508515668f0e60408e893fbfffff49090909
+0909090909090909090905589e583ec08803dc8e3050800740ceb1c83c0
+04a388e20508ffd2a188e205088b1085d275ebc605c8e3050801c9c3905
+589e583ec08a110e0050885c07412b80000000085c07409c7042410e005
+08ffd0c9c3909090909090909090909090905589e583ec188b45088b4d0
+c8b50048b00894c2408c744240c0000000089542404890424e897fe0000
+c9c3908d7426005589e583ec08891c248b5d0c897424048b75088b4b048
+b56048b06330331d131d209c1751a8b4b088b46088b5b0c8b560c31c831
+da09d00f94c089c283e2018b1c2489d08b74240489ec5dc38d742600a12
+0e505085589e585c075088b4508a320e505085dc38d76008dbc27000000
+00a120e505085589e585c0750da124e5050883c001a324e505085dc3908
+d7426005584c089e5740cc705>trailing farbage
diff --git a/libtests/qtest/lzw.test b/libtests/qtest/lzw.test
new file mode 100644
index 00000000..abb412d4
--- /dev/null
+++ b/libtests/qtest/lzw.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("lzw") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('lzw');
+
+$td->runtest("decode",
+ {$td->COMMAND => "lzw < lzw1.in"},
+ {$td->FILE => "lzw1.out",
+ $td->EXIT_STATUS => 0});
+
+$td->report(1);
diff --git a/libtests/qtest/lzw/lzw1.in b/libtests/qtest/lzw/lzw1.in
new file mode 100644
index 00000000..d95d596c
--- /dev/null
+++ b/libtests/qtest/lzw/lzw1.in
Binary files differ
diff --git a/libtests/qtest/lzw/lzw1.out b/libtests/qtest/lzw/lzw1.out
new file mode 100644
index 00000000..21b5a277
--- /dev/null
+++ b/libtests/qtest/lzw/lzw1.out
@@ -0,0 +1,4299 @@
+This is a test to see if I can use libtiff to get lzw.
+wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+Let's make something very long.
+‹
+ŒFK™;åØk'imÙrÜqÇvâN›T’à" 
+Ѭ
+ñž«Jm•P¶ÒvðºÑ…—^«0¹, aB<“ËôÙEm&µ6êäf¤üy캸DzŸ|ûæ£;ÊpitT,ç<tÃez0 °@YÚ&×\7rz Wk›I!«óJµq¶t¶ Ù–M5m\ì²_£C€%Ï+å–¬Öíd°ípÀ¶hÆÑñµ#ãtWÆvkÆé®;NwݱÝuÇvǽNµî€Ý…7:wÞH»Ø’·÷¸?¯½kvØ81ÓεêwæÝRkïúVzÙ¬]mÁu]O”÷΋vGÆéÝÝøZiTŒêäqßÙ–[ÛڽϓëC¡A–ê_Òlj׊IQ¸9܈¸«kåó×M(ížWʨݼ» û…Z ÚâàQy+Í9Ûo Fº¾ÆI¥¿Æ-¥ÿlKúk ÷Qú{[ÒÿyKúÏ·¤¿¿%ý_nBßT÷èï&¤mélE<î¬.]¥ÆL¢ní ¿7!¼Tó’ïooE}#d.©o„Kï šÀiŽSZ¸¼ÂŠ²¥šôó^çXD‚ñ2:Ÿ³Ìe??g5o¯ã™RFÂ.‰z¸û\ï'³pILÏ]êã§Ïž¿¿Šƒ¿_Š“‡âwZí‚!z]ƇLuð?¤KjÞe9ÍBÔâðo^?ûáˆüJôãZeÏFbÿ‹ƒzÿH8/*­O;[©ZL– $¨tH36ìòÅÙWËG¥qAžmÒzk@wx¸Æõ&?úíd2 Gâ¯âD<·7Ù>Àô1–Ò_¿ÏX4Ì‘µƒ±Ž†å_÷þ”¤g·Ä'Ÿ0mº;bŠDG?­GÖûõQ¹°1ZgÍâG»ÿ‰çOe0?}PBóÞ@´ÆžÉ—ŧ°æõ—ú~x3Dúüê{úZH[‰—/DÑEa^¾¸Ê¥ÿ•7e.õ¸†_}Û¿g¹u¿ó$úèÍéóç_«ùEiŽ—^*½tWˆñ©%&Ü@‘“HïßK”#ñâŸï†ËM!Ç,åé<zYFÑë8èÒ
+WüL¯„8©òpƒ6=¨y\Þy%z¨âì­H@,a–I‰·P Î;C»"ì%!:~âDp t¤CÔB{è!-‰Ø_~Iß¿ VBØOÖÝ·Î7Ò`¸Þ‡xÒõ¶îhÆÏvu6høYÐD³¶Ç† FºìŒô8\rêeUÃØ1ä~Õ¨¦HºÅl–
+L¸Mâr¦%A]vT? µžŸ“ôÊ!x­‹¨®¶céY0ìò<¦Ç^M•¥‚ή!¯Ïa%Ð7âûÉË‘˜¼K&™œi½k­L…@†Ù•1ô GÀã!+“¶¡BŒ@^bÕäa”ÆÖc‚ yq¡TKæ“¡% YJM'¤E«ú¥MÈаŒá0Lp#Jõ™>ѲY’
+„'j^B²o ƒû7#±p]²*¦ÑN
+~mA=tÈh-{,!)
+3 Ñf½ª\2™æ¤Þ0öU2GÏ1ÁùþšäžzòOÅS$<.Ø©ŽgP=Àí”2éÜÏÂw©p’æ‚^y±¸¡ OŽ?ç–67ãÉr©$åô+à ÂeIzÄ!ôù=“ѧ×¹žY
+ ¯ПþË©=®O"
+RRdÐZÂÁ
+BÌŒõÈ1
+ÌA`8‘¡¼•]Øt"ŒK¬é$ùlRpSþ³% T×,ž
+úvå]ˆä‹»Ü†ˆ®zj{V »ÙMT½¤ýH\ÒþÊ÷¾t
+³5öÙEÀ•g¤»ì=´Ókê- Ï•ésÈ•
+­Z.ÁLr²³T„ªmhÁ
+ú ›¶©"H ’v4N AeÒV@Dùš>ú>᪞¥¡ 5輟òVEù‘¡m ÀÔè8îÇW|*PðAòÅ»’Щn>ð ^e ¸¨›ˆ‚KÞ&X·/’ Ùû|*oR
+Ø¢ºkêÅv^ö=[kad6¼©ðˆ0cfdÂ2µÌ—¶‰¾Ê(€ Vh°^*×Ãvv#ò¥;_h"¹úu¤|?`
+q^›sãhrÚº[åæ?
+”£Yä¤fÍFŽÅ’8½e–È'™©Ãþ-®äÓÃD’HÙPKð_j1~Ã-@Ö‹¬•ø/÷à 1Ü™ýÝïgŸqð¼ášëK⌦|Øn0}µ…hqF#4Ø,[
+ûÊñý/â bªÐ<>öêKŠô†8Y}[f]@–r˜¯EµìSب{‡i7…ž&—eߢ尓r¢…ÄJ%¹^ì¶Ð: ;ç…œtbÃz%²°g©JJáÑ€ÕSófÛl­¶ì40|Ð[÷p1Î5‰YF1ц
+q²mô5Süv) Æð ¹nÀ'÷úOVþl‹°) XË0q´*`M_¿4%Òxß-×ó¥ð²à8yYbîÆáoC/\ˆ
+–2~-@ “v5°Ì-a<APÛâ'1ÅKv†¿3²Aæ~Ãyà³NE!” óÑ…p£B:r¾¿ÂM|1²‡}ô’zm-2)gèî†k‘J“ Ô„/?60WŸ¼Ói(nNT\()¹««ƒŽç|€á5ïš’[¿5?8çnjN3¥/¯iôGš =õ¨k¿ÿnöÍ'ès«Ör©RB“@ç2œ‚&:Î’!3ð&~FÒXõ²ïÙK;¬ÕwÏjU
+­$y~¢ÑüÐ$³«Zy+6ëôSÊ‚Úãú㺃³ESŠ-^wû1
+b^kF3ÛÊ<ïÔo‚w2\4Ö[ÖÓ¡I2ìsw½ùþvço®®èÇñ:üÿäŸ!­­¬§™þe5ä*èãÑt¿Ï§\¹7hC X:
+»— J“Òç¢gý[ #€Z}–n"\»Å
+þvÈõØqrÍL!7Š#Îv {0x¶Â Ë>YHAŽ™‘ÝÐpu~Q_ÆFp·"Ê›pâ2‚×Êa }飼¼DE9/™ƒ`ËxÉ?kkÙaÊUßòà‹M»°³ˆ¶!¤¬„_ј£là˜£ë v®–ãkP¥P—^ÅDsû?Ó[%áYô©VÏùûã©a¦“³b˜Z$ä+NºŽ3-5‡h¬áÜYd Cvd-˜ÿÌŸaØ.»Sk×^¡Š·¯ñnγ‚[€¥5%a<+›]E±î*`Ö`­¦ã’½(Šœý0Nÿd«ø̼$|VÇCÛ»Æ7¼ÃP¤ÉL!|ÑÁç*â#.dF:9e—Žxu¹ûRs÷=ŸR7W›¥ËÑ¢úEØ%ç&%±è­ô
+з ±ÿ—m´óµç°ŠÀo?¯*î+¨×°y¤móYÔ5u6¥A&³Ó7茖FD ¶TYca¾Ù؆CDê?¶åi¾Ô(gÎÌ¡¢GÙ%Üßs–Õ„ ‹×³c±&s’FçÆâýìX,ýÙ€Sç9Ú·—VYµž_ÇЄ2óð÷!KÑþºb8I¾y“ }5«o:W[Ö†æñ%ÛáSò Âwœ§º“ŸòeŸ­\Zg+ÞþËû—yò6˜Ý1_‡BÜä¤á¿'&%X®äžgñÝœoñÒðY×2¢]‚Ÿe-(Zë¥Ôƒ–»[Ç“
+iücߢyáÛi 7÷cën™¾iÿ^p6ôY$ŽG©a{ü¾Ò>ëû‚=úh}s˜¡,”K²¥Û†·™³ÄL³òeDaÊ(—)º‡Œ âÿEÜ ¤µðdù@§æK• N
+"¸FxfÀ±\RŒ¬Š2ìúØ\é²ÚB< íÖ…ç ]TLÅ¥E¸ ‡¼ÙÓï¢`#ÓŽÙ->掑ysXNA¤ê*$¦ Ýîäà ükœÎÞ{d´èWH¼{ÆÓ‹âª{d[ÎàH‹” Ü7âÎШu ¸)ü2·e9‹ü—|?Ÿ;öSr=4•¹þ*‰à2£Û¢†Z3ŽÅávLÒÉëx?»Â/_Ä0Þâ^(}ꢡiY—‡tQB0$äSƒÚVµ•»ön¹¾óÕ¬ëâ2{¼œ–,?øyZš¦;~Ó ™kÝ0•SþÏ
+:×Á^|bçî튉sÂdØE·¶dšv&¿h_kë ‹@ì˼røžfw„&[•7.sJµö¥(_ß?–Þÿä8 ôU9äkK‡o;Ç'¯:'ûG»'o
+ÃQ6îx«s‚C¢gpù_N¥ ¿§¤vt]]­ñrÒsïPl³JÕ¸š>KÍ•™Ú{Yó“‰]Šèaò’=¯¾¶Œ@¯µüõ¶|c7)4yëΘg4%×:!øCf ͤwU_­Òúñ
+ù±ÛQöý2S¶“í jÎÒ³¦Ë™û<N®UÎÀêÎËÞÛmò^Ü)ñk6…I'Œ2]&*³¬ïCRÅrÂáDØYfƒrò’‘çÖQAÝŒ³4•ÊSWtòKê}½4TåÙ§d”RSœ© XjW 뙺ö:c¯jóKxÕe©lR_W0vØ\1â»t.Ú,·ð³uó–G“ÒaâÚ•`FF·
+ ¸qœ8 ž
+Ûñ²ì‹”:]ÊTÆx{¯S¾ âˆ3‡È¨™™¸rPø‡­2ûŽVƒ*uƒi´ë¯`QÔÒ¢ÕJPrù¯0¨ë2|’þ·~@h®šohËnÎ0æ‘ÎÐÒ!bDÎŽ—1ãªV,)O&¿Cêú«Ayvó"Ä‹jfFð™Æ>УYæ1s®ýzgö}üâÉúÀ~˜^x¹bîð@9Q‡ð-Ú<r£B,=ÄšñSÿGjŒBN̨8þO«Ýn¶¾iñW›í§­Ösˆÿól³ùÿç6>9ñÚÍææ_6ô»ÑØ?ÙY³4_ôŸW‘&LaÙœðoÌ8X´.ÀãÍ–«$€Ó`NrŠ™ÁöèR|èÀ³'ÄéÉÑîÁÉ1ˆÓÎÁáÞë÷¯ö_9ÁxŠJzÃúì½=üñà'
+ë#eÿ SÄðû,:§~‹5Àç—·GÿØ=zûþðU,®ì*N>I<ö,ÀFµn—,m>+Ð^Bõ¿ÛÝÛ7"ìðû ^†ÄUœ+MÛê·° Ã*¨››3*Q6ÐQq›í KÏ UÄ$ê«ý½×NTvH­±ßÔêdR4Cñ8áM,³”êKü%(8P‡ttdB”þbU~“h8ÞhwÄ-wlÙ
+$›ÏÆ’–7ÇŠ(tššD‘׫CT i6Â@×uœx¢D]èž>`]Y;S¹3ŒáØ  ÷Ll§F(
+¾³2œøöÝzÝꀊ˜¤(oOÚÝׯ EÐ ’¹F4°¡Õ·§†Ø%Ñ H®Ë! ÝÚð¬w2¢"0q†·÷aĪ6`£«hh”¢Âo¸³pŸ˜Lu– +G"js†EƒS^Â|"숒¡úÂøn9ÇügÍÁ¤JëRµ:Ô´Bq`Ä”(eÔ2ùÛÀ² ‘¿¶<²DÐËz(¢s83a9²•À¤9›ù‰5ƒ
+ûýKiï[_Œë߆iC¥Kx‘“ÑQ’ò{äÿ\³ÓIÔïÑíú'ÿÛÝ’Ó™\YíÍñ?÷Ô%º²º¨¶Q¯$±ÞÎ%¸-sƒËW!Íé\·¥»C*-ä]V•õy
+kÙüõ`XÝ©!võa¹¶Äó{™E>_ùã4qi2Ä€ }ÐÁ\…+Ïó†jA¤¢ h½±ñ’-}†ét3ÔÞˆì.—é7{Éšømàä¸â%wj…w4EO1“[]Þ8È2+ŒÀæâ3—£À‡D¼Åze cþ!®­Ñ_°Nò‚Ü7ÃÊÂETcÖ ˜u~Æ\e¹%wjŠ÷ç!K™ I
+léÂ,uKNaZôn§„é5ÝJ(\¬¶D" 8 ³q]‡Ö›Òqe„—÷T
+d,iÜÐ/ðçȸ2R¼¦F‘KyNÚkX-ä¹5GŸ‰IeŒâ€ ¡«D[ó¸ÖÒh³ZÄ^°3\¼©ýÁvxa‘ÙPwü·èôÓ|òLJzÝpó5ýÇ÷¶~ýCßeË4ò2ӈц Ê4ŠÑJjÿa9yã®Ë-Æ @KG¬QZ)/œðÐr]´Ôºþ°Í»·Ÿ¢ýßÕF{!`Åû¿§›OÛÏ!ÿÛ³Íç-þü¿Z|Sø°ÿ»Ïƒÿ×¢÷~¾Y3ç°²X¦mïŽì^ªª×WqÙÌV¯ón÷¤³ÿëÞþ»“‚=Û†ðS7KÀD˯öÜ}ÿ:ƒn±;Ñ¡#nצn[öRyòó_(ó°¦@O„*=˜ŒiG\ˆû»£ƒ7»Gÿ‚>ƒÏr>Ââp £Ž J¿ýáö÷N:{»{?ï‘[ ãŒäf÷"tãæÜ[
+ D‹mžÚm©3¾~7êÑé)N˜®ñ"î£A†‹›×{¯Ö³õSŽ=$('/`?¿Ãºàþ`<@z—Ÿw_½Þ_—øcÌ.ÐÑQtĉÄÈ[ÒÌå÷K4Üh³ÝwS®xÃȈÉÅ/"`§:v0sN«ú•=ubcÂvšŒ:
+0(þó
+Ž„˜Â‘+ÐC¡‘’·&P8ϸ¾:NeŒ*¼OS![´·Y:¥ò¾2z-}w„WO]úîh²Ð £‚p ROBq-8}ÛYŠ†}ØDëZ^Ä„!k+Û*uG?¡‹¶5Ù8Ùåå/ö’õsnåòZ?¸†xU@êù)„㋸'î”%á¿'Øt(!•Lã9 ’$¾ÒqÊfØsXè0JEä²Ï#s¯O»n˜V…A0z!Nî2XÒkαŸ(Ÿ•£‚`?ò-DbáõÕ¥n|áD´2¢8@(4Y,B“ßU"ñL.í NxF8 ÆùËuÈ•Í÷]«E²O•Ãàuö=kò‹ÖvDä-} ”Á•B±wL”³ælnÔ£³¤Å{#¸#/ê; µ÷š PNL¿ºžjþ®’䓸]µ-±~ÎØÖ0gÚõšV0Iý\ 97á}^Zö¼Î¨ú™¾è–p™’ùk/4?EË|‰³[lHX*4’éoiúµš¦‰A˜¦Á9¸#äO:™ Ž¼}õv ¼äùjw¤l 6-ð‰²à’£?- 6kˆäËÂU¤@N¨¥£H–ø¨dJ<iÜ*¶µ¾œ2DËf¶–f°hqMÀLÛ“Dˆ"è*ÜàU>B¾'ŒP)À¨Ålw‘¬[Ä°M’Qœ
+_W¹Iç_„K¯ÞvÁKt5v‘W„9ÇÓôqÐÏ©¤ 4}V“•E€ ‹Áø;.ZòøK›Sä<â=ÆD{PûöýÙzr@L°¨n±o͈ÂX7È«ƒ°òµ6aüß8Sd0 Iå Íi’† BÿëÆ—eÆѽÊŸ² äÈz؃µ@ÝÌ#HĵÊ·p¡(om38áÏ+7>mü—ºz
+Ò´dìÐd
+m¿@CË™P™ ¢¼{u÷Ù1A¶Q® £Xl*øUP¿: µ»¼=¶Œ°|êgá(kMØ‹ >?œ|PŽ…V¯}…ŒNµžA§4Ò¾âè",yôÒBë},ˆ„‘tVÁK÷àÕ¼Œ‹ÂÔöjþìÏd.Œ žÙÍ窒î}»ÌM&FOvOöÀm;<©9%i7Ajz &|jn6›u<ºL¸¼? Ù^ ÷_Áð´¦…<F]ˆúŽÀ¿+Þž8ˆ/„¼qvÆ g]4äÁ{¡ÌÃÙ8Ž 'ÿz·ßbçI<-Íe³;AëÊn _”ÊèÌ–•cPv•¦·Xwè‘r þ:&ˆtsõøÚktP6(>1&;KÒ 6`´vXÙ¥­f$²+ØxH{ÑPÍÔ'¬žëL|dÙXÆvPPÝàæ¼)ˆÓâÒì!´ “°€:À1È!67i²¼?YWF&ähùöÝp9¨Z‰æ6ÎHA×@ÈEµq(oì"CO¬ø[òý%5Y®‰â¹ÍEäX^Á†NÃóhíßTã‘ÉRéh|òÙíÂx9…CœÑd‹BÍiv+³t)Øî†Òü/ŽÑ)oòc‹ÎìþA´÷—;n¾H÷ÂO$l)µ_ÿ^YÐ d®Hï@3]¾*Äñ}ž¶mó ­¿ø&²ñƒð7 ˜°ñ
+[ÕºRœü M:MÑeéc²RzP‡-mÒÌýhÀ½° ¶5` W0†ïA.[Ö’‹°?ÂÝŒzX&õp&Vfæó`þöÕ^
+«oasêÍ<e\ïU‘ð \Â]‘‹0 ERµ”RªÉ!ÆrS8˜ü^‹¹‰³@@ò½’2SöÁ)‘ Çæ-'€ììmÙ¿'C°j\´€Ø)$zº
+1V
+ïKdÜsÊl"Rwñ5”Ê©Wâ.~v…ú:z>E<ËÊ<«Vî’$Í]”è½oYRo¼ “3|M-«’ý„¯K2ÅY"õ(EŸÀ3CN>\~Ò7äÁ4øUO†x -oå „Û10Ù^¯s]. Õa œªÁÂ[3vÂÌä~6¦@=Ì…8uçÌ`9‘ÃRUɶ*ýLÜ«riev Æ´ªâR>òS‹«6]}]q¬1›ÀR†B®Ö¬W ~ÛÒzv%,/gSéŸٵÀ-i0Õ¥O)ðÀ¨ªl§tÊ뫉{ sd\å€G¹¬a=’¼’s.ú·èŒ=¢k½šòÿ9ÙóîõîɾNDûç£÷{üûqýw—Y——Ù#q«B…´­i—ùŸ*­ ¾e¯V±ÓùáíÑëÝÃW{¯Šþ§O[uwW‹ã¯–Œ¿É#·Ù”,®hÂMEãf? •mI3<BÓd¨W[5WWëÚkHÓ¹i4Ç¢&α¾:BssÏ5#™Ì‰¥Ô‡¿ˆýŒ!ñ
+ó‰æ–ŽIâY?Áò`›He¦xq8茄‚o¬œ¶ å„ê-lç:hèÎ-€eƒ-g­% Üa»Re–]ö,V]i-pí¦p’uš’Y«É¸W0 _Ô+x••†Ró3EñÝÅ7G:¼šIjˆÌyYöÊ/Gç‘e`çð®N/hÙbaø׈/Y£‘–Q¾ M‘ÅÊïi=˽Â!Å ü1K¸Íd”2êW6I1Çú
+î$-´“+‰jjÛÔFÔ³ÎD4ŠmÆ!¼ÑÄPöÔÙë÷oͶœžF½”Ê7G&gãTc¶ÃºIrß-_¶—ýâøª³ÿë»×{'ÊŠÔ§‚N»¶“?µ—Ö Fú+’ð2Š'iÿš5\@ãKÅÒÀ
+ýGuà»àùê!lɨ¼™Œ'¹iR¤nT¨À‰è2mŠBGÌÛTT¢Qõ ÏYY¢–I¢£>0kÿµ
+':ý}ißMzóþdÿ×ÎÁáÁ‰=BXØL½MÆ›¼<0i<ªÏÕŸØê®Ã:Wþ”çòDвâøßív³ ùŸÚ›ígí§íÞ†ÏCüïÛø<Äÿ¾™ÜOžY³´  à—Pâdâ*ØlTz•ÀeÜQ˜Œ£0'x•èÚžtM…J:ƒãñ¿OvEË}Aœk.² Ã^iôìý££·G`jí½ höá[¾N½Úëî¾Ù§Ó=Dš¯É¸Øax;†Ë3¦yú’ðÚZ\Ç7Ž0 Ïd„‘àåjV~MĤöcC.LrK*Ie—kÒí§Ï 8^Q%£í›a›â‰i¸eâzÂZÚ›‡¾à»•[˜bŸæi¦±
+=³%Tï1w/7,Þå‡Ib°10ãà4âÆNÞøû¾j4IÎ ªºë!«O[0ä
+ÈúæàìŽê']5·ª«5ãàðäèàð˜ooD8×:Þp@îþjÜýæÁûãŸNðÝ=!e.š½SMÕÅÌTcA¶ÿˆe7Âh¶J|b÷Òp ·È÷Õ×]UÇ/åLYûf÷ûþàuM˜
+Éším>Ö¹Íþü³¨dR¹ä™SÒã.CË
+)hþ2°èZ¦ÔÂ3WÞýy3
+CÊ]Ê7ÄèÀ,êa8pî÷«m\ƒ
+qŽ¿Œz“ ÉBŒäBa*ÓEŠ Œƒ¸&°Óh G/E¨p®PtF1f>ìp˜ç¡ù Oý<÷ÒÚ䆣+³š³Ì8¤ñ
+Î ³#Q“· ±kÐÿ ­ÖQú#’á¿ùÈX(Id¾lç‹Ÿ1óú‚•ž¯æ¸©ž°^0~{ÞßTÙ‹ÇÁã{܇†ðÏþ<nd_àŸ ø'ЯOÕë@ø¨_wÕÃ1ü“ˆÒòu~GðϹú6Ö¯ÏUÀD@¾Æfcøç
+þ Eiùz¤jG&Öë‰zÓu^§ªÅ@½õk]1R¯•ž¯àHýã"y¥*&¢¶|óIAóè‹ô{rFÙþò˜¤¿µþî:'ÆX…‹-ð÷iãKƒbDñuÜ*ñT”h5U‘ÑE`iI(- æ´ ?Úe$œ¶„Óò½µU¦-á´[¢L/ç½l§Gc»ŒlgC¶ƒbÂ*³!álÈvú9ïe;è)c—‘ílÊvF\ Û¸lJ8›Îh2ì:eœg¢LêÿT¶ƒ¶{ˆžË2߉2û½åçò=ýû¡<kËRàÄc•á¯D™ Qæ*ç½ì îÛEž‰"Ïe3ŸÔ(~Ùž’½Wwðr,=ãÏ™Áp%Ra«¬&œjéAý‰õS;Ùâ²W< áhÿ3“‹Ág¥,Âl„·ü`ÑÃè§
+¨y1ÒÙþHMŽW¨£æ—ÜÔ#S¶­v^nºWÝÔÄ€vBÅÒ ²*„åPhµØµõ÷éaÛ®…YØUóØôâN[¿©®¬¾™ g! p\ÔÌ<1³@qRéi^n$‘‹¾'ÍÌ0ýYátŸH´œ\ð-|:é~L·DIŠÓ‡\gç6Ia«d"üÄl‰ò(òÍÏWS&¥']Ãx¸¦ ºP¥T[gìˆwE8Z§a7
+_oú“CªÊt—ž· aÀ—#ŒØŽ7ÒÁu…1«EgØÍÂÙá,çe¯®XZX1Ðä*"â°oÑ K[DÆòá~«I°!Å5ŠºEêKv•ÄÃs»%jàí„«Ôærób‡â§X²Ù¦u.’‘(˜qhÊéJ"(_1dù¢ÂêœÇh7uËZ¢^VkÉêër+‹U™±ÈàZ 3gj¢Tlžh3KóJ
+,·PkAõØþo˜Ä\…zÜ|ì׎OØ:ÉKü=·D
+BˆÝó˜ï3O¶sªâ²O]⣟ä…Á4IPÏ+wÿ]Üy’‡°3ýOò*$¡
+ûÿg-¸ÿ×n?m>ö´Å÷ÿÍÍg͇ýÿm|öÿ7wB¢.àêß;™U“ Ž)Õúx4áÈð¿|•¢û€i$Ý 
+1k4ëCîªâú0†ÜDp îíC†ÂsôÙEôÀè.ÄIÏíôšz È7 ëÄÌ”ò‡'ÈÂøjXb› /Gû|ë¾·_d™ÈôØæ7U¸Òþ-Rû@HqyæòCÔ‹87
+±ëÄÃþµÝ/7ëÔêªÊ~õåFFžzãzqLÈzã”ø%W%a%\'³*‹©[•Ly!‚—‘»%«ÄY®I;â`W Æëˆä ’²É3®ÞËÍ«l7\ÖïôƒÅз ã*ö—1©DàA>
+€S[5%îŠßõ­-³dc) ¿BU(‰ÍÓÑ.)¨ ßR®Sçx番 ß¿Ö↥p†/œg/ùB'N,uÿ…ÿ'SGz(
+¸ð“ô4fºµ%‘Û"CÉ@ʛ石Ÿ«Â> –e•Ó‚¾V:ÐÐF”
+ØÏÅAâ€J¡ÆN¤V5Ÿè\~
+ÞþǪ`Zx¶¶TØ^ØÇa Û4£ƒèÈÞ(à´„:v[Œ.œ’°ÉT¡ _VÇÊ¥^¡©‚­1¼úB¤hxþñp'v¨d¦‰=ç
+&Ø!Z*ÇîP[n &8OëJÙÏ]‰¸²‘Œ®Œb¾áÊ^?É€ üC&F§ D
+ u¾¶DrÜMÒ—Ó/¸ýœÅz
+œ"¾ì~ª‰Ugœøs‡è{½b¨vjP–Ð;#äÊY³ÛƒÄ&]žö![=èCÞz'1+×Ù.C31ŠSÎ’Ar½•mX³f1'bÊ@HWöë6Ä!RéU0ª“v/ê9¹œA
+j4qÃZÁòŽÅË †à†WµaÝLFE£yøvÿg™—Šè’At•n_/~S]zô.£ /e7Ó_á§hÿ?JøÞ²]u`YŸÝ dÿß~ÖÞ„óÿ§©p³ûÿæ3þçaÿ ŸÿÆø¿7ºõ7´×&ªˆ“Eºÿ«í©¿žÖà<¯{Tëýjß–Öd6§Iã‚|N9ìJÎìß½=Ùß;Ù…«oÑ¡½§ä­Ý&ÈÙ&§œ_ƒî¸c 9{Ëà}~
+»®o“¶…‹—ÜÅð…q”²ónwm“%ß:†áÂh„ñ2JÆ“ Ïþ“Ó~­þù‹µ­*AævZ£ýÞëâü r–‡nÓÎi•È`dÓë³ÚÉÖÖ
+/ÝÅ…¿.v19mÕNVXÜ`ª8SéÚ·€Çjq^ÖFuV±ãØ€=¥ƒw6ÿ–KãÇò%ÓPMØÑPxCk;Øcì,\üa¯¼Û”ÿEë¿O”Í¢®ÿ­öFó9¬ÿíͧ­ÍæÓ6ØÿŸm<¬ÿ·òyXÿÖÿ×ÿv!n±Xöñf^Wü4U 8(i/ ~Žãö(ˆy.Êãê J× {fNÁZ³Áš°žÅEDVQµn+¿^C n—AèŠÈ_è6!ï—·GÿØ=zûþðUMgÄi°¬µÑlÖ­QÉ¿ÔI~¯¨Õžôæê g+èƒÎLäRÿ8ü÷N¶Eþt™¥EÍX¶+…µL ѱÛÊTâ-¢ÞRºEDl ¿5?Øo¨'àG¦ ï°DœNk}àh6…(7™— Ãœ¸x'! Ç~}˦¾;‰5é²vkuQ“UžêÂi^šåLEÄÐHƒ‰Éu¶d»öØ :Ãð¨ñÒȪˆÏ/‚´#pO³oe´aÏÃ
+ÓÏ66é”#Ct†9ärZzòÄ‹vêb¿NW‡c+Ò¨z»E³/E BÍrk{^ h
+ŠËOŠ‡ŽÁãÃeJ—Á´ÄŒó*¤ø›Jô‚ÇDH‘ÃõgaÊ4ñ´ÓC`Úƒ–EÐ\¶@#=+ZÔoâã†( !((ï÷cÞk¾¬ð‚á5WÙ‡çì:—º1¶=£.ßvÕœZ¢èÚÓkøÖÖܱ.g ÔôÜqÁ^Á »Ì®lyÇñÙ¨ßtjÏÉá=¶×å DR%LHm ×íSú¢vH·Ð­Iµ”ž`V{OûV†#&¢ãúX¢yãEf8ƒ+€€àËyÍA™ã›C Y—¨@‰©ZlLAðŽ•óÁØL‚°UìŸë £±Ž Jé¶Ú§:+]íñ¯Ö2#ÞT(û®/a“:ç€ÐÖ–ãÄïukq›w°§Š>ˆ¥0tTÙ‡G¶ˆ™Úu‰Àru¯.+ÉP ‚¥Ízy&qmŽë¿cÐcÅ‘ˆzˆncÚ7 ú$sX Tæf>)ð¾Í•ää´6û¨¾ôUÄo+Ö‹›ì»’¶Ý sÝD¾X,4>ÑG}ÎS°%è¬ÜlX%hâçhôÁnTšlÜ Å©Ô–˜UyKž
+«‰ÊFÂ)ßð¸ðñb$²¼¥Ã@ÏÑ]_ag{½2˘õY²¢¦ç
++À•‘nÐïN0 LÝtŽ¦mÂ_¾ázÏ÷ùèŒÖ%¾ð 'ý¾S”iÇZõØq}Z$?ó2ùšÌy¢‘ÖTNñš­ÇvÛ´ÚiÉ”ih4vZ©PÖ§zQ Zµqíà4„ì§è{œÓ ¬Tù4ÊÃ|Žº!oËN·Q´·¤–‚àõ†Òj+5©½èIßêÕ¼ÖÄÆ‚)ž˜‹] 59|¬5…#²»¥®åÛÎ;hlZ¯£ôd’‚ÇÅÖ;“bà
+R \åf
+ ®£Jv­5a1°¹rõxäţ̢! ×ÝKƒÃ؇@Cì|ÄL•s†©¬>þ‘]ß©­’
+¼¶½JÄ€±é!’µnÞ–…&×v(¹'\—oV܃ÿÁAX…üâ†ú#Óô…µnCÚÃ
+"ÍÁi\á¨5ÄxÉå{Ê™­%üËEœm¸Âpje£ãL H˜gƒeH%êšÀÊoöà}¨F‘æjvÕl ¸‚øR9 Ãè’çš3m>®jÚ·³
+ õvßÌT˜Ý-ðºäªÛØðu”éÒ¼uÛ]GZ§¿·,úÊXoŽ—y(°Ã7úŠJiUÕ¼Y­cr;g6ñ ÝEK]E 1ØÚ²}^ø—íŸ4‹ë)£Ó bÈÅg<<¡Þî¬äÎw_áÉCÜ v},–…RW‹¿£¨#Ó»LÎà®pjq5 dp]Z&T\3¸l »¡âÊuÇ­«Á2oÐkHã DRòùÛ·]·ŒæM/,¾Î<amÃchx<µ \2þV.9´s±ª£¼¡ì’COьնÐPÄaxöÐØYGƒæ– ƒT$ÌË&(;µ ²Ë–Ù¤.”!ã(CþjÚš ªìÀv]pJ5 î^ü†3"8œÃaŠä*ËF)²2ÆÏtÖ´F›¦Ð8†lñrÖ{ú«ý;Y6Ž3 kÊ% !²
+ìØLÈŒL¨šŽP®®"®Bædl‹æ¼Ñ€%v͘£P^È'äGøËhwD
+$LÀ¸ªá(L—gÝ9:”´Ø”ëyl…Q3ê~Æ÷lƒ¯×mC=ýÖÌQ«DMAWÃ’.î´Ç5d7?Š@ËÆ.l¬Ûþ`^^ÞÏR­¶ZhjµOGlþR‰Hîc[d{‡ØÞ•FW>xɧÅ)âÁëjJ…˜”hÎ —n‹·¾b§î¶Ö%æ’?²zrKÞ<’El²ó÷êO9l~(æxPogQoW@½]‚z»
+êíéP·´»WmÚÛzüTþx°¡ ÉX¬‚Ž»Éˆ2¦£ÿe7î‹„îàÍÊÕq¾\ ë Ë.}ö¹
+Õ =󋶔°ö —a
+³µÿ-¨1K!çõÇðšs9\qËÜpët~:|¿×éÀý¶ c±0»ÏYCÜ,#ý]•Š†$@$sÙ¯ZâU&ªxÚÊ)èA-êP±5ó=ÓWÛ\ˆ?[~ŒÚùµ=µÑßla%Ž”Z¿mЙ’žŽÆœ’$–'KVÕ¶ªª¦ƒÁÓþªÅ„8[ó¨;A »ÁÿØ-¦LÐm¢M Ú’òV£âô´%­Ÿ/áÌE¿“¸lWkåðÓ.
+î¡X
+›¼¼|¥O
+)ZÑÖï·ýÙv0KçïW!%Œ@:¼0¢S”!}
+ök5Ö¨ª‚.dý¬ÃeU9ËbU´kï‚^»a¨\ÐΆ4œä,4ø@f7rÌ݈æmçXvGǬ-¦-PLa2É—&™æ]âæÈ?½]úl”Ó‡Ù"‘^ð•gj×8øÕvD +“6}ÊÍ–æÁ°Ú`M¨/~œxÅð2LÄ­óh(Ø]ÜÛ2YÍ¿
+ÂV;_÷á87
+ Ö*)ÙvoOgAy.¨êP(ÃÊ ‡Ù-ðŒçóFˆ›üóÔéG9Ç¢ƒŠÇŒƒiŽ9LjÔ耼«óuŠS·PˆÒ.šÄr¦ï`úU;ìU¬† XC¸¨sî¿üP6=ªØMç×gÞ²ãóeÉÒÄqµ-`ê$ëÞZeæe±|ËÕÛÏ/¹ëweåF[Ã8¨¬Šƒ×,Ú Ùpp$8:˲È<ª9ϼ¡fò”ÄkxUl
+Õ/ý«+
+bTÝVFH™+ÌÕ` ‚h¨ i–š·MY,cš¡<¯³\Ó †|YìÀezoÄ1PÃåÞ‘öw¡Á¼h-×ü‚†
+éÉ{ºUðº—Aõª¤Lz'hš-+(]—Ír̺&cŽð±£Q²ö¬–¨ ÷â¢CX_Û‰z¨z´WW·­VÎhKâÉùEžAœ³Wvpà \3riaÛõ£¨tf–ÏÒ­?&ƒQ>=á­Ñ"o}dßã*¯5Ì^YpÎe¢ò¶£\ÚVÑ™drºwæø›¯<Ø©Z<²n¬Œ7ƒ¹F©‚B}\¸Œ¨#CigÃx¸–„Ý _½¹–«7r î*êEHÝh½JÊŠ4Æ|m, ®@¸‹Q*âÖó$UK;©©JŸ%O`Ú^ñ´TÇ ®ËC²ÁN'cjµ`DÞCHé@òý2LÎøþ:%RLZ~2ô;î,
+UþêqÊùÏâ"ÈÙi‰[¹ã÷÷±zänø+´ÃwçÍYŒé®AÌÙçÔ¡î’ E˜Ö”L¸ªô9Í{p]xlf,&'CqTPÜGÁ2¢o;ýp»…d3%0žœÓ'ýòEÒVœ žÖ6´¹]µ°Ø47Ëë.¨W@ÃlU‰6¶z+ÉQvè‚#ÁaÌꆣ±c²üì=@‹püÁ˜àa hm‡††*Ô*ŸsøĘ=ôÄN|§C4ª3$cÉÀ×9²©Ìá¬>Æé}PäÓ³êX¡Ð1½h
+ºŠ“JÑC÷¨´‹ÓIÔ' 0#z¦vΫçñ–^1/e.sÑ$U™ä\Fw³Ëu³Æ­k¹èluÙ¯‘ãÎ…u<êH KŠZ?@˜2°ìnÚ¢P£X§ÂrU•_l±Ç\ 3zæÛâçà•Ûjù7‚lú1Ò¢\Ÿ°Àèã–?6ãì@ä~l‰à4`Æm´üI )u]ÆœÀ¹ê,3”~É–`T
+`¦’X%v¦ˆG02K62-²KˆbrmÝ Q,Ç
+œh~ú€m§#«ó ¸9MÆ"$%ÊÁ¼ Øáûׯ…{äÇÃsô5°é‚ÓÓóV³!%«Ž~?í;{¦Ž!˃0dÿÐ#¯:WÚ’9Nq*nnù>»h>›ˆ–!iøKÕì´³ÀÛ¨ÉɱP̦¤qõŽ`@rä2oèˆ8lPˆíÝÃWvà ;áˆu]§˜E?s˜x²âÄú£ÊŽÙ:Ð{öö
+3dùrN;º‰ñ—.l~AˆÉ€¸Ã]4ÜÑ>À•¿üñæëÕŠ)°VØ삽:Vþ `1 Ìh}7˜m‡YÂ'X“Í;†™rû÷9?gf° 2,wÉÆЉR¤äŒ¿â
+ræЩˆR Î@t,«#Øù&+Ó`™k%ÊÚŒÜò•–ÎÜySnD¾§r);:Αàoúžéw+õ7³C©`ƒ *¸¼ÁrTÍ<ã9V50skSˆþÞS?PÌoß7i™‘¯hC”3bYOˆrŽvgYNI&ÒAŽ®!eõeORaÙ3Uõ©&šYá}ÉÞãô|³û«_.çàéR$Rá;‚ùÈ*ˆHæÊEßÿƒ©DÓôc.E5W ðaT"È3Hé$°É#Ͳç$q¤½4gÇ0KK—¡Läí
+ÏtæÀ Ê?úŽ,†’¾¢YóôH¹Ë”öqÖe(Ï|ê4©#ÁÞ3 ¯Ðn¦¼ùûeûúba3»^_Í›m†ä¹*bº€Ü%³s:9E3>¥Ga7
+úÌ1®/ȹÔ1f•YbXõÙ›+a‹cf²çFŠ¬à–bƒ¶&ƒ—ç —Ïaè–laþ7Ù›]Á‹•WpmQ®” .)[òIÅU=|SúE•¸ŠùKåúnûöÐ}!B4È›$(Å«$Â@­îè¡óE$b"¬öO«&Bʸ¾Ê墠y®Á ‡'uBŠËšJ €Aá"`b%©
+Ž/‚&‹IšT€X~*- Y@tÏ-y§.voà„zÚ|½æ‘³š/pŠy/£!Z8¹fUåé(‡!
+FôÖç .Õ ÄýÈ¡œZ¢Ž1à €V I¤QÅŒ.,š‘éÎj
+øär“¾th±Y¿fm£É?Ï67áoëùÓ&þnÑoøö´ý´õM«¹Ñj7[íg­ošífûyëÖ\dGó>hŒ}sÎ{÷ŠÊñíïm t»Ÿ'+K þc{ñè:‰Î/Ƭ֭³ÖßÿþÝZ»Ùlëÿ‰/†ìMÐëÅ1K¿ÂAÌ¥@Ô¥˜ò Ï@BÞ$:о I'§„Ý1Æ̹ÔüxŒÇgã+(ñ:ê†C
+†× CϸÐÃú¯öö÷9Ë6×ÇŸÆ ƒ„Œ®Áûb<m=yruuµŽœ¼'çOœòuêÀ“¥%]ç
+uÞ²jaÀ= »p‚rI¯ ?¼Þ7ä¶=sD™rËÛ«oˆ6¾O$(^rG}µ¼wtðŽÐz—Ä—Q/L-¸N„'Äã
+÷¡–îGû?íÿÚùç¦ør¼¿{´÷sççwï–þÆ ÁIBY9#ó ­ŸgY@Þí› ˆ«”ÿõ¢‘ÇCêæ»ý~Ü5ä›M²ÔLX2â–õ Î{™Ë ŒÑéaG¸Ÿ¼°qRØì,³·¶™9ʤ Z…@+dÀ+pÿ Ÿ ÀN©cõ×H{Ò
+ÆÑÜ6xETY‡£Ä1Ó'KènÈŽýe8Œ0Œ5Î<ãó«ÒäðmçÇ÷‡{ ”:'ûoÞ½Þ=Ùï¼=âÓþàð'íÃQ
+6c®ðSTºß2À³8jŽR3&ä̳És˜,‰€tý˜´ç5dÃÒñU á;Ûá‹(Ü9à ™pÈ"…ÉUlVCLÖ·ŠÍ™™¡ã’èTYÖœ°â<óEÑˈ¾I`V¬2 æ›
+b
+ „ýãÿ°Ueç¤`ð¦n1¨_+JïN'J
+¤ö"Ϫq2ÃC}d]m+ãV­¾£)”*z‹ËŠö;ÓlbªÆ#œ_ï¿ß:ûô
+û-êç÷HkÎQ™!`|fg«è…èÏ7±¶•®þ3*Ê”ƒÕ$of‰+W–fUo]™ºnJKÉS¬TâšÛשnˆ™nžZ‚i0IJ3ÍŒWîvÆ9çÐÔ¤F§èâ®Êþ¢Ÿòóßó$Ísú[zþÛj¶6ìóßÖóçOÎoåópþ{sç¿ræ,öô ÎröûÓÑþ»ò“_UêFÎ}Í“§st»’—ÜÀ
+”f\t‚Ñ“EP&mF>sâbÛ¿'xHEÑ a»02”wIØΠ冤²Õ@è Vð
+áó˜ÅC lð[óƒHÉ`U¾æ ”£6x£p¯Rá { ¡tœ\ã@³yÙc“
+Ñ4™_nN»±µ›?ªgÖ¨'×€4̲¸‚6ìÂÆ®¸zŽÝ€WÊÞÀhåòÆrÑ
+#ž¨|oÂJ>*‰ð4ñu†êp“„3Ê· °-
+3à:ú‚©èÆ“Ÿ›’
+è•AKK‹§R?¼ÿé§uöNþõn¿óãîÞþIQЩh6‚‹ ÏyX²nƒù¢ñkÌIÛÖØTѽßÁ4gZÆQ>i—í0>òÒ‰ º_½èS½”m g´Š(ò%<èÇçcJYmð¼›­ÒÕÚ„ f»0rÏ™é;æ6ð3;Í“Ÿø>ó¸°a ý<˜ŒÁ“¬zÓXAuÌQxr›³vW•7WË( fªºµÕ‹;|ZDçÃÚ’yÖ’' Ê µU!ãÄ¥hpgÅœÔìF‰«N¯ç¡é9&ôb‡ábáÅÀòÏC´¸¿}}zG¢*ŒeO¦Ô ÷»ÛÊŠE2éŽ1×”ÝõgCØÈù3 ,>wIY(ïGgÇ^'qcî¨^ü°÷îlª,ë>ÿõWþ¼Î¦ØàgŠ:–„ì{ל
+i0üEIŠ¯Ö1ÔYŒ|ùŠI7“¬úŠû›#÷þ6« ªšû‡ãý‘sŠºTݤÈÿc²Ñ&RHšÍèR–ÿ?tò?´Ú­ÍÿÛøäø´›Í×ïYœ?¼“fQþßàÓy¿ÑÊ—pÞPäkí/|[Ù 8¥¡CA_ÅoX¢—8Ö fg`”Å…ë^Q¤ˆl“è*A R»“ÝG°Ô÷Öp]nÀjNõ1m¤W•L*ÃàDâ (‘\Ï…`\$Ã÷IB
+•Ðɶ¶x§Ž¯Ã¢Á×VFÒy¸vVÿŒWÿQí@}ÎßÅꀒ2š€f/é… % <@Uíhȸð$cЈ `K¤Q­ŒbËèß妑Fo¨—/Ù2¾”¨™IÆÄ£Úr®ƒÝ©Œ
+·uÖ­ÇtÎR  |Í¿ÓCá+“—+¾€¾B„ŠÃ# XOí‚:”‡U’Dòígü³s™ñ.Ôˆ6²Ã4a5µ! ]ÍI™Ê ÅÖù<8‹>Õê¢^2)UCÎÊ ˜ñº—à’ï$Åý¼íSî=æ‚—3,^³cXpt!¾2hŠ´ã 0Ê ú‘2€ë£ 3¶M ‡óküìÞ–À=O%8\ŠwÑ~vŽ˜óƒúI`Œþa¿)?3ŸìVqå‘ UûŒ’èRæ¸-ŸYt*N^V‹ íoÏ»\1¿ €\d—P¶‘L¥¬øB“Ÿs)ÌÕ¨žÆvœ›ÎòU¦á¯1Yya-rÈ‘ÔÖ–ô±ì’yÔ€]}N¯ÌTk™oÉäGjŸ-npÕ¼1ÎS ”A;½àB¼×“ðn‡¨ˆ±Ê¢ê£t‘)?¦êâƒ[I•ñ|.ƒþ$ÌÂ]8'”F›êã
+b®îuOh1,°Žaªjž8QYå,†ff ˆº ~­³ŠWXx<ZÂdByÂÎB¸J¡£kª†ÊZ·¤HiZÖˆT¨dQ 60Ý]4_eãÆ9EÜjúbܤv¼’i¦^§Ù“íÝ£)z'Z{T[‘:4–Ø6uOs‚Ë6Vj(gꎊ‚°¶ã±\3H(<³ºj«³ÝøªfªPÜMÀ$åwª9ËOY=ÆÀˆËL ©laZœˆêªE^Ó~P¨ÓÁO\d™`x@9@[ÇGÃÐZ<\»J8š<&SÂñýž #¾¥.%•’?+5‹1]1‚JbžÂadx[Ùa“ñÙwöûíÒªï÷TÝÖ³™*o´©º[†ã-ƒü£=>†<QIqµFÒƒEÃ’œ=…½ äòÞÈ,F´Æ±­J/¾ª(
+Ï Rà¬Ø2*V Tð¬;&…B× ÆU7ÍRÃöP~ßùÏ;Ž;ïO~l=+£ŠdËBšP¡»¦ˆ@•è1éxYƒˆQ˜ æĺ:¹þvò©TžFPÂ#H™óÙbÊV„º|ã´Ïl#fì/ª·f¢¡œ!UÅøxê[##äÖÀLÀ6û£nÜ uBûÀÆ),D?L`[DÑÆŒŸl•ÿ––#ƒ7|M=ï–º}–pׇ_Ÿjç¿ãøc8œý¸øüwãÙ&Ýÿ7ÎÛ›­‡ûÿ·òy8ÿ½©óßì¤Yø)°ÝÄŒgÁ'oÿ±8݉°§
+ùûenÜ™·Äpƒªùéé³&î½JÊÒë“ýã“ýWÝ“¯ø¼Y·
+óï“(í ,QRè‹w
+mü¦UZG‡Ù=„—‚å¦@Á9ïMë/á8LXp¦ðxX€Ï@ dø`É¢oᢠK" i*®ªÐ[
+ׯk&”3$ñ?/ €Ûlu5òXè³³]¶}p-ó“Ùkô›íîÞÂ@ƒx«-k4ë¿í~XÄ€Pqïp1Ô#5‰-ʧîPeÂbx:3½sžà%œ%³=³€3¹$ó‡5èeúÛᨼ֪³ï™åÆ)ŽžZx¬%ŠjZ0e–3ýíäá&-³S§ ô¥“nfà]çA˜”u6¥ôkéG‡Wæ- ¼¶›«†½¦Up[,œ!·ä¼¨»æuc´_{í"‡êõ¡ûª’×£¿ÊtþætÖËQj—E~ŽœÒ‡‚û2c¯X\mq!¡ø}ˆ÷4tuõÐ3£ªN¨)çÒ¢=5óó#;.ù2¼¢Ø7tÌ+¿d•Œ«e9ÉÊiX’ÔÙõïäT&v¢Ñ/}ñ†ÆOÉBI)Œp^ °¦lÒìZ++á¤x”@ç.^3 I¯ßi‰hÌu*®7—ªc/¼-OÔ2»Å­z¡–!“õ@-«1ƒ÷iá•>¨ÕlSÙσjæóWóAµ™=ã‰ê¼žÞµ²ó©À˜ÌKdÕã[„ìÖ«’S*}r]Se S8©2ŸcÞÝÒ*Ï®Ud©X$õþœô{0ŸÝkóÙ¢˜¸„‡KÌk÷Ži‹ U…vª[¢hÖŽå3cÝ?¢~V@½Bu|j¯·zEµÿæo
+gN
+^m¸súÝæ•E_|ðRÎë79>·t!¡ú¬×"æžU®HÜ›é0ÝÕ WÄL‘f¿&j³´[Fî®ï×Jß.öx_çš9M¹˜ÞÊ.~QÈ‹Zmï onÕm°éü5,·1l÷{1¾½éSe•¾wÓh¾ÕÚ½š ´XŸóö¬ŒN=Ð Ýس>Nou×Zv
+óµ®Èw´ðÞ#B~å»Ú{Gχ]n…övÆë~/´w¸žÞÃé²€]pá&øåK¾Ê¶üô0uŸjw’Àw™µzüô¯ýStÿ¿ÌóÝü”Äo>ú웵ÙÞxÚj·¾i¶ž=Ö|¸ÿŸœûÿ­¿ÿý»µv³Ù~0K
+’„©ÌLaæ ÙA’s%îFâ¾gÆÃðl2ÄíLŠeQ Óuv§Ýa
+ _^°!c¹Píî½~ÿjÿU&º€¯Œ\ :î¨?IáÿK¾ÜõAŸ.Þ÷bpÙ’ D4d{ìné§ù# ì½=üñà'Švà\q'ùÇWȳèܺÚW¼XR–vÀ},HâÉ°gß™÷Aþñ—³«^)n"MS>^B5@ý«ÚÑî/øz»TÜÓ0IDB•R| ~³{²÷sçÇ×»?çƒÔZÐâФ¾'ÁUç5BÀw»'ý_÷öß@c®_ ;á'ÓP>¼û¸y«8ZiÜ.N5j¼ ¸×¹_"?„• ñ/?ìryZF\¸ƒRžR¼ªôßqþ®Ÿ#{°§EL>lC¶N wïh_ÇN©
+—B¶ã³ƒ4cÎo<¡ßŠAgƒÚU£ÇOGûïªÀ?OÂQu¨èëݽr]ý¯ŸÝJ©àŒý£Ÿ*A„Éy9Üãw¯*©C|¯¹{2`O[ûaã¹€¹TòÉÚŠì™»}7’ÿ±¹ñ´ù\ÛÿZÏ!ÿãÆó§ö¿ÛøäÇÿ|0ýÍnúÓËÅœ@uI‹{Ä$ ûp‡‹S|êU
+é³á™®÷òØȈ‰'mwÅë§ÓþOoþ• Ô_Òwj½. *ÉqätG§})W‹Ë‹ ÓT6«²é2›uæô÷`g‰\?—p~Žp)?ç¿}¤é^H?Ø1žIÉÉøëb¾rkï-© 5¸ÏÔ  C ÂŒÁeå¶"À²4M­‹Û+*\WNÌ_§)Eç+≘Ü6(B”:”õR¹C 'âà8‹&̪˜„§Ñ°gÞ呃bäƒÀÔ‘ñµ4^@v„ŒAPR_ª ‹3¼9|)%ät‹™ì$ðBnÅqÜa² ?ƒ|»µe˜ÿ¡ÿЭS0iDqÐïyuTÃô
+BL9#¨šC$Ìì;àa÷ø˜kpo~à[ڃþ·{}ð¿(è}䦽ˆdX?É5¡Œ]†NÚ}×ËøÌŸÒóßN—v]sœ—è›OŸ=µÏÛͧñßoçó_{þËnA 4¦Îœz žØRäN”ÛC®Ê‰\ Lƒõb6Œõ (Ýóï_¯ûôAòRâƒ3ÅÉGî"ì
+'/³./¤^^]pž¨A1C7Y]MõÅj^Zßã¾bøì‹J65b/Ðt N•«˜×H8S£ÂzèoW¸ÑÊvKΠ̶^íヲ‹ã> ¸–?Lá̪–uh”¦ØeOì¨Ð9Å¢a]©3£
+§C·MùÉc¿‚F8ûv¸š9àsÛÓWª¿Ì$í!ú¬:
+3NŸìîý#Wÿ×ooÔYs!¾Sl!æM|$ö ´²ý#Œ{2Äg¸`À3Æ10)Dó2
+ÃOFñÊS<&ÚÖ]Aî©I¿Ç¸<“úñ¼•r²³ƒ~Fœ; Ô!G"ÑϺ…ç/E/^íÿ¸ûþ5ïÍkœVo ÿƒŒD,úðÙ¢Ö0¢‘R‡}+c'-½PZ&yW(v¤mQ>ÉB~Yc'žÌÏ •-°}š%äÞ¦8yHYÌ‚yâ†Ë†âaÜ M­~¯`Lx©&sw²”шbhG|Tõk#ÄÅvÞÂ#‘#H¦wâ ÎCaË^ÂwK¢Ä`4¾¦„"…™`PdÂ-q i§‚LÛgvhÄXøtü­¦ÓŠ¬°Ö3¸ŸDD¡:[ã{ rD>þ i!ûH=UC»ÌsncP D¬ZÑAÄ–¦ÂLÆHL|@2ßóf2äŽÂ‘ÃÊtµdŽ4;å€?Rª»,£¼ò9Ý &ŸDø¸í‚‚ÔKn[i›hÖt»`7x¶)·
+&Iø õâÑ!Zÿ
+®ÔU’½øUJf k•+ª¤¸{’8þQ÷“L"Y˜0ŸäGØóͯÌùšŽp³Œû¾:y{¼E¦®s¾¡æê“^6áŽ%d›AjÚë«(»c(Ì ¼,AÂvÛ©§VS‘aæÀXH r$mœ´0wC714–&åJ¼«òòrÝ›—z1ì«ôP‰)Öz&­–ÖPŽœžënŒ)*ƒ©FrT™_ýÝWzõœã¤è…ƒ¡h‹Î‘hq—‚ Wã­‡ |6¤/63¹*¥/3é­í
+{ã³Ì†Éq è:!™ßo›Ö’'™(ÑL:Â|ÿCœôaŠ@œŠ (WŸ5pÖü3J'E°xÖXR©‡8WóÍA4¾À©ƒ1µÇ‘ÚäÅ ĆŠª
+ »+i°Q¿3*¯×µ¼)À vœO€oÞÚÐJ¿e³FÃÍcwèõºª\Éka•œ¬Ì}‚RšjGÄgöD¦â;7ßs.éÀ®»µùëÉ;–U2š)uÌ°s™ÇD%yjâ›òNÎ@f]sï rÕ_€ÌKäW-Ÿyü€ûë’fNMˆÙ"κ“$ŠõpßäÍHä|ÐÀíåáüïMÂRTdœqÈS 
+34‰\
+$MÉ/K¼EXú9ܦ¿.°ÉéšáâyèpÈeE"b eâØyÁC–×m Þ‹ÕPë¢ËOŸ]DŸ5×úgO²t™£çFðÍ‹x9k0v_Z»„c-èúòünÕÅú¦ÒÞÝ g”䴫Ʀ­cõ?ñ.þTÔº­#ì^æý",üâdGßÕ¡z¦*¹ùbIiÖu~«»ø[S§žwSŠámªjSf»•fæ±l!Ò-ÏÒ’L|{‡7=ÊÙ<{{¾D{Óv ÷C:3 ‡‡˜§ÏßmôK°p<4OBÑ£à%•’Ï¢³šG¡†/3ùÖ±û"/:¦yƒ‹ÙÎY­1 UÍŽùÎfM“î4g±*ß=œöxvr¢[”ѯ+'D·š«†½'ºh™ÃÏâûâ¤è™¤‡œ.25ß2¾ôá"Ïš—“"×vÐÁ£®ê¬[ëF¶[ ±8„Âx"m¿FÎQð—[äP½>t_!S4?ÈŬ§yUä 9uè±aÂ&êšY
+1ëQRFjŒzl(  CéCÁz™×£+
+®¶¸PÌ.¼û=ü¹ºzè™NUgÓ”éÉŽšh]1´C>½Þ mœýù’=Y!™Êk_v‚Ë ê³?Wžä…[ÆãÎi|ªœMråxıoøXVzÉòV˲’’Qô¤c¾QÐï 'ý>'3ñ³Œ~蓇74€JJ2HQ„5e“~d×ZYù&…£:‡|tñšYDš.‰•£›6¶J¥œkÿ~Ë„™Ü0Mn¯Þïq•÷ä_ïöwßì3ˎ:$ã ø­BDQ•g÷P1ÎY';¬È²7gŽO^)s%4¤Ü ­¨ / Õžs¥è*HzV$“8ev£OÊtfRqµI¤sé%ÔèdV¦®±Ìô>^*nþ`8ÐßFƒ9)¨dÛ¢”ù¼Û¡´®Û>§aõ)°xe?96°Êƒì‰Ç;7ã
+¼(F0'ëü¸Ÿ$®š±R¸pMªt¹"P•5RAgÇ/o&—ÀÍ„mA´ó„tMx{ß-({þHgS(Þdêõù¯ß¡Ê²nøL'÷.kýƒ±îÎŒu‹âÐ-1æÝ;Ž,6‹å[Ån‰œY«™Ïhvÿ¨êXÌ
+Rù^e4 à×:Ë_²ªm2<6„Ì„¸®ì`ÂqŒCª­
+iÿz¦ [#ú¡±ƒn)à]„ù*kÒpŠ¸ÕœˆA”­•L3õ:©"Ù>š®ƒ¢ÁGµi÷ÂÛyÆÙÌJÍE M=òCXQÖv| –k&¢ã.ËêªmZêÆW5ÓäÑ„n °dˆòìæ³Óƒe¶Ôcy7†R`¯2ñò–§]?‘ß¼`?° kΦ~â–…‰Ù
+ÖÊB®—ù;âÛJÁ>u)o#ýØÚIçraV ¶üu¬žï@y²B€Å¡¸Ì1õh•5°|ïra´ÊËÔèI#ëÙy¶ÕxßaùÎç¥O}½¡¤Ë÷q~N5._ãt½ëñ½ýi[!áî}[ï Së}œŒÕÙw÷{ë³ð!IïÃÇ÷)ºÿÕUAŸæk£øþW{³ù¼eçÿh=oµ7îÝÆç6ã¿Íy쫹&æÍÓÿ¾{{|ð«TxɧmU†³:
+Ï÷?± >œ¬^†}v•£Q˜ä¦éÝ«’§×WhñÚ*'­šyÖ—DØŠ ÝãowÄQ†~AÏ×/¬ä­sÆq[Qeø<H!ÉYÊâaÿ‹†ÙbFEãk%ö™ Rá'åǾÝû–}¶r
+¹$’7]VØpBQÉ8z\wáC‹ö@\™·S` ä1—ÂU€2Îh )¶Å_ŒD[Ðø‹ /l>E:ïö_az² ¯°óÉ8Ýv§3`ó Èñ¼Ž' ;¤|è¸f¾µVµ]å4”w‹ªAø"µÓ]_" Çìzƒ±¨ñÈ ‡
+”¼ÈYȘL3,¿O 9¥X2褱æouIŽŒ‚„–Y84
+‹›pª(6N}à3Dÿ ²©V¦¼Äno!*@DLU &Hþiȇû¿žpÚî¿¢ç-õü`o÷xŸ¶ÕÃ÷Çï ‡›úáþ/¯©l«i–}·O͵õSHx¶©Ÿ½zÿæ<k7ÍÚ{o_¿Þ=A°›&¾Ç{»ï lçõÁñÉ1¼n™ýØtv_Ÿ˜fãG¯÷ùcó9j‘ãO?½­ÿiÀUÍìþò?4§¶ª
+¼úÃ+´žê¡=üçîÑOðì™ÆùäíÒ~ú´Al'òYáNôC!jä4BH'ow9ZTêA}Q Y·¼Jú‚bßðSØ-eß÷'?¼…q⟦ūü;ùF3ìñÉîÑ ±¾Ù8@ƒ¼N‹<ê(¼=‘ÁYb¢*Ö&EÆ:¬’åw
+ßrðN¯×ËÑýa÷Õ»]àÒö¶zC
+çÄ©T….ïk±±0Þ…2Åkôû¦ä Éÿµ<ð¥æÐ6]œ`é
+º°<‘!X¼
+@šþâS1&'IÀâ¦Blhë¢
+.‚ù_
+ºmãP´ïeP?íî¬z.»ø~(ÝéûáÙ˜ò~~ +QëÝîÑ>ÜÏúN‚z§T…”EƒÓ LPéïY¤~ÿ\
+ð;â›ìä2äsÖœLjصX ‘ףݚÜ­˜9bV𨽾…¦6°~˜ˆû.x9®Œ»âLg¥¡Aøàçb ëên- ÓÄYAnz}~_²ec/Å M½`Ç8½‘@Q¸ËÝÛ\$ÿÅCrhBŸê¿Ô2`]ÌJxƒF:c”Ün¿?<Ø{ûj_ì´^Eô5_ÐS$²^ñ~©þ™/
+¡¾v}…mƒÊK¤ ˆÌ(näÉ°"²‹Ñ©u•Ã„ë£dÄ
+50'Ò”y±ÀòÐ¶Æ UÍr¬{j©¼Sö¦2ðy;‰°\õnš~JFól‘]®ÐÐBº9_ïQ¾ÞgºÑÞûŽÐùf
+|
+ÀãÉ‹4.¯5wÕÎÌXj¥tMÂî$Ñòu>¢•¶oQlhØ´¤æ¡5­©* 1—ÒNj=åvèW ›# n¿¥¢æ,²oÂä<ô­
+Êöv3ƒgÖìÁXº‹YhÈ.B0H|eÙhƒ¢†—çòŽYå{DVþ x²m>ॶݻ.nÞz Q’õi,¼–³Ø2Ë©ð9tg±¨Õ?Sãì%¶I¾É¹#7…YWÖÊ.W…sõ¹FÇÑñ?"]œiò úç`yÏQ¶|/«¸4W´•ñIÎ ÉEñ·.†¤Ç›dŽ¢Pëv ¶fDy2Ð(Y#Š`vuŒ§­~û–aì5Èe¡B•p ©Ÿ)† ó#F,®„°æ¯\Øù V<ÊêD‹ õ3bAà \¨ õûBÚ™]ErZ¸ €ÄÅK2¬ÖéäLf&Ùlþý
+F=Úµ¦Å$­Ú‰%&Ãü2¾ â’³|–
+ó«Úç: þ¥”ÇUa
+Yä»q©BX#íèd—Yʉ]Ž¿ø.°:^Ýpâ–ÙÕ¾â³‡Ó 6݄ÇA¿cÎF÷!q°!ÞZÏ°Äggi8Ö“x$ŒPƒb®É0ù0ß³&=æ’ ~¯ítD®Œ¸š›«¢H;ÐÔÑ
+lÖvpUÁÅDó{qG0‘¯{ѺšÁºÑºšî&öѺ1­§Äò?Ù‘ôÌHPP°¢ R,¨%]×®pµ#Ÿz_ªÂ¨2dJ8%9CÒìØ¢AÍÿlɲ &är‡
+Y·R[Á²*Á;¸ˆ[b p¬5ͬ?&Ò¿}`5)m³ØgtŠñ`äD3åOØêK¨ž‰Ü;U!ó*—-ÓšY„\ß !­­•B‚"©dìW_t1I¢V½¹ÝrÌ´µ6M[kemjˆˆÀåšìaêË{õ‡ü–¶4ñ!úÓø64óé)N6ñTÊ
+ -p¢óDg–ÎbŽ{^äÑéAd_p!‹{^½¬x-ñWµE´(—·ÙÚ‹º–ƒ5ÕRjšYKj^SÉj_‡µÜó¾½%©]]l/ªÎðتD {Z(h<O4Ïí{à:hÏr•N ¯ø,vÛ¹e³œ¼bbç²]¬>NÀjÓ}Ð_Êòx\Ê~nÙÿ·Èÿ;±r”Îî^ìÿÝÚÜh=ÿïV»Ùj?Ûh}Ól7Ÿ=}þàÿ}Ÿÿïv³¹ñ—uý¾QÏïì¤YšÏÿû]_F½0u 3;×rž¶EߊŸïszõ—ÌxQëÍ“úB‘Ì•¶</³¸B\i·6)™}R^Y:1òHÓù
+Hèéo‰ÎMÕìTĵP®JÌI’R,€4O
+ ;b+"ë¬[I1v’é4ùw¡-ÓEVñ˜zƒ/ ‹¿5?¬ _#QÀzjLCpÚÊ”¤Çæñ¨°?—OÇe†©‘6²Ã4C5©i¯d’ïÉNÀ+ÌÊ÷ѧZ]ô«óRª†dzö§¼ÒËë^v‚K®qªóc/?Aûšì.xY1ÃÖ5ƒih¼!¾"O™õ 0Jüm†ñ¸œýÎpÒWˆ"«y5~voKàžÆ§œ¸×¥²ëˆ)¡gçE'–ÙI‚at;r.ÅÙm/ÌáY&yò²å毓Á®U“F¶Úõ~oÿUÈBä~óŽ°ƒ-U9Ì¿µ¥íMyK¦ 1Ùaþ•”eCšŽlK(g½®lºu|Ηh츳éBU¦¶Ñ#•nifB9æ<vuY³2S­e¶£jiW>“Q픦9臞IÅ•lã Òõ^À»Êl»í3†ªOÊ”ý˜J”X%¥ÊóÉ1¥.œÌÉ:ÿ§Èl¬>Ä<fçjŸ±8¨ß«/ûÑ6eæ…›;ŸKàzlÏüiV0×êfNsõtú4óžqtÕKÌ<ï+8SbùÜ”ò•ÓÈ«ùù²}Ôñ-YÓ%Ï·²çBU.Q Lï4£½ß¾þTñù]ûš’ÄûO Lv¸Ýôðyg¶%Ý*ù_ž^éhÆÙJ¯mé9•ª$€×@ª¥~w0Ê&}¯†Ui¢w/í}d$+•ï·fÈnë¡jq^[ωêmsöaó¦5­Ô‹¢Lµ‹ÌO«¹‘Ì´ý—“ö¦‡æÆsÍê ³7’*73¬m©¾ë㔯îSrþ“¹À–œÿµ7Û›:ÿk»ñŸÚ¼ØÃùß-|þkã?Ýô! Îœ¦€Uæ6\zÚ÷Ã.ïsñ1Ÿ*2ÿa]æür X8ÃòŽIÍT_È8h¬†J9Ž}ÄgÓì„W¶Õ*Ù±uh­L¿Šàø”BX¡ý}2‚{­1ëÇçœyûì<‰'#
+íM5NÁìÙ\{¶€½ù
+ Q•Òëa0þ„Žu§ðwk­§º4/8>óûʶž­m´táx„é|q‡s†3ý
+†]»å¯­Òâa% úGüä´iÀÎËŒi)’P@HÕáH4ìI¡z©ÚøÓ‡îŸY4ð¬”OÖë1œP>òUd:
+» aN‡qçô#x—‚…½Å^¼`ßåö–Cÿ½ÇkŒ¡³ñUØÓ0SÎÆß‹`ˆ(`„\z¦"“´
+¿GqôUnæ~È´*™Îî–•ï³&Ÿ»Ïñˆî­-åÈŽ»¥­-õVöM ælañNÕZx¶¨x'‹JA-ˆoôdÓЇ«x+‹vŠ*ùç ¯dAC¤e‹Ê—²°¥Öd‹ë×F¡ÃxK›RÂѼ¼C§
+•ÝÏ[Ï,cTÍj"~†É“”jwà­†/ea©ýgKⳘ|ã4‹±(ì,.ž!0…£±„dKÊ—™eÂ×¾)'åêá oì5"[ˆ?wÖ…lxá. žæÌbw½6xd:Û+¬±;ßö\²¤bîAÁÜ)?Åß»¶ÉÞæ§Èþ‚Ätþ›ñ$ Øþßl?o>ÓöÿÖóošíÖý`ÿ¿…OþýŸ…šþç´ü5†ÿì”Yà€ÞQJß\© dš}±#òÎö~Þ=¿NŽvNŽ‹N ü…oàÜÀx¢{k'dúÚ‰ µ;ÅÍ=MÀˆF!—VæÆ<ÇqC:7{šÒþË>¯èϦ÷‹0Xa§
+zÙ«µ¹ ï{¥ž o¼ÎË×þþ‹·e$H/âd¼((„2&v”Í]7«¦¹¹æÑXÊïÿ¢ m.€âõcãY3sÿ·Õ~ú°þßÆçáüÿæ.«™3§pžO¸`\³Ô©©ƒþyœDã‹A*±>‡ñ8Ä|ß`û†* 3»ƒ^˜ÈÌO(F¼¹£N¯©3€\ƒõb4ðJÅ•5¾jovOö~ÎU/ôÛ›¸F¬lr]sP–ð@œåR¼ñ•ðd„,ìt`à¥yn
+Xöê"æ´‹©"FÏYç\õû)äÔÌäØ\T|׿Œ«8øl·æ~ã×—TܘS=ª™ ˜¸Gj=£û¯Kî
+[¸&w y76Á»gÉÛ6
+
+'ÏøºVwÓA€Œ˜O6œ‹vp’„[,„+ê\2OE=BE0§l‘C|Ó ’ó $6dá§Ú·CUܽ±ãô­Jq$Â/’øª£¢×ÖÂOFêØ×(,]êhÚÎ{†OeÄÃ$¤t¶)«…b),¦ãˆÃ 9°Ol@ð|çƒÇ Ž_H®ìÔš"-d~«Ù(,³ýÖùS|åóåS=“4®f¡ÇÉèzN<ô?#šžˆOZéÐô¦ÀFC'±åå%}ñòÒL ËxªÔ¬®‘ Ãê«35’倢š)xŸÜQ0)oÒ}Щ b?èÔ[ÕdqM§ã@z`‘ׂ©“Î!jFwÌ*ËRänÛkªÜæòo{ï¹2òÏ}bsΉÝ‘¨Zò>ÈÝɨcL ±JÒDæK{5L:D+6Sy3ŒßzÊy½$QH!²µ5I£+ÚšòÍNíñÕãºÀ q¤:Ñýëý8Q¸‚«-_5ØòÕj‹*J4O£1Vö!ùxýñ–^Ò¸Ú)Û1±²â+íÔjgŠ Ü8ïì{f-óÉEÄk¾fÞŠŠw³¨'.s®ƃ×ȹPµòw®ˆå‘ˆ$FÕMŽ
+Tlá>GÃ} ÛˆM)ãC*ºÀ‹€Ôͤ#ÐxŠ¡Wq›°y †j–[jDü’3LÔZy)¾y±ëGï´F„ò%'áðùCX²; Ý>Õ¹À[cëì‰ –KìçäHiåPš¦mwògÀ}d«ª›Hè{Æ^
diff --git a/libtests/qtest/md5.test b/libtests/qtest/md5.test
new file mode 100644
index 00000000..4c0685cd
--- /dev/null
+++ b/libtests/qtest/md5.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("md5") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('md5');
+
+$td->runtest("md5",
+ {$td->COMMAND => "md5"},
+ {$td->FILE => "md5.out",
+ $td->EXIT_STATUS => 0});
+
+$td->report(1);
diff --git a/libtests/qtest/md5/md5.in b/libtests/qtest/md5/md5.in
new file mode 100644
index 00000000..408a68b4
--- /dev/null
+++ b/libtests/qtest/md5/md5.in
Binary files differ
diff --git a/libtests/qtest/md5/md5.out b/libtests/qtest/md5/md5.out
new file mode 100644
index 00000000..148b4e66
--- /dev/null
+++ b/libtests/qtest/md5/md5.out
@@ -0,0 +1,16 @@
+d41d8cd98f00b204e9800998ecf8427e
+0cc175b9c0f1b6a831c399e269772661
+900150983cd24fb0d6963f7d28e17f72
+f96b697d7cb7938d525a2f31aaf161d0
+c3fcd3d76192e4007dfb496cca67e13b
+d174ab98d277d9f5a5611c2c9f419d9f
+57edf4a22be3c955ac49da2e2107b67a
+5f4b4321873433daae578f85c72f9e74
+914b11f5990cf99f1161bfeb5865a4fc
+1
+1
+0
+0
+0
+5f4b4321873433daae578f85c72f9e74
+5f4b4321873433daae578f85c72f9e74
diff --git a/libtests/qtest/pcre.test b/libtests/qtest/pcre.test
new file mode 100644
index 00000000..cf0418da
--- /dev/null
+++ b/libtests/qtest/pcre.test
@@ -0,0 +1,34 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("pcre") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('pcre');
+
+$td->runtest("PCRE",
+ {$td->COMMAND => "pcre"},
+ {$td->FILE => "pcre.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+chop(my $supported = `pcre --unicode-classes-supported`);
+if ($supported)
+{
+ $td->runtest("unicode character classes",
+ {$td->COMMAND => "pcre --unicode-classes"},
+ {$td->FILE => "pcre-unicode-classes.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+}
+else
+{
+ $td->runtest("unicode classes are not supported",
+ {$td->STRING => "1"},
+ {$td->STRING => "1"});
+}
+
+$td->report(2);
diff --git a/libtests/qtest/pcre/pcre-unicode-classes.out b/libtests/qtest/pcre/pcre-unicode-classes.out
new file mode 100644
index 00000000..443febc5
--- /dev/null
+++ b/libtests/qtest/pcre/pcre-unicode-classes.out
@@ -0,0 +1,2 @@
+no utf8: ab
+utf8: abπdefq
diff --git a/libtests/qtest/pcre/pcre.out b/libtests/qtest/pcre/pcre.out
new file mode 100644
index 00000000..27e94e64
--- /dev/null
+++ b/libtests/qtest/pcre/pcre.out
@@ -0,0 +1,68 @@
+PCRE error: compilation of a** failed at offset 2: nothing to repeat
+3
+key: value one two three
+0
+25
+key
+0
+3
+value one two three
+5
+19
+PCRE error: no match
+PCRE error: no match
+2
+aaa
+aaa
+--
+hello
+PCRE error: no match
+qqqcqqq: no match
+ab,c: 0: ab,c
+ab,c: 0: 0, 4
+ab,c: 1: ab,c
+ab,c: 1: 0, 4
+ab,c: 2: ab
+ab,c: 2: 0, 2
+ab,c: 3: b
+ab,c: 3: 1, 1
+ab,c: 4: c
+ab,c: 4: 3, 1
+ab: 0: ab
+ab: 0: 0, 2
+ab: 1: ab
+ab: 1: 0, 2
+ab: 2: ab
+ab: 2: 0, 2
+ab: 3: b
+ab: 3: 1, 1
+a: 0: a
+a: 0: 0, 1
+a: 1: a
+a: 1: 0, 1
+a: 2: a
+a: 2: 0, 1
+a,c: 0: a,c
+a,c: 0: 0, 3
+a,c: 1: a,c
+a,c: 1: 0, 3
+a,c: 2: a
+a,c: 2: 0, 1
+a,c: 3: no backref (getMatch)
+a,c: 3: no backref (getOffsetLength)
+a,c: 4: c
+a,c: 4: 2, 1
+c: 0: c
+c: 0: 0, 1
+c: 1: c
+c: 1: 0, 1
+c: 2: no backref (getMatch)
+c: 2: no backref (getOffsetLength)
+c: 3: no backref (getMatch)
+c: 3: no backref (getOffsetLength)
+c: 4: no backref (getMatch)
+c: 4: no backref (getOffsetLength)
+c: 5: c
+c: 5: 0, 1
+: 0:
+: 0: 0, 0
diff --git a/libtests/qtest/ph.test b/libtests/qtest/ph.test
new file mode 100644
index 00000000..8e70efd5
--- /dev/null
+++ b/libtests/qtest/ph.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("ph") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('ph');
+
+$td->runtest("PointerHolder",
+ {$td->COMMAND => "pointer_holder"},
+ {$td->FILE => "ph.out",
+ $td->EXIT_STATUS => 0});
+
+$td->report(1);
diff --git a/libtests/qtest/ph/ph.out b/libtests/qtest/ph/ph.out
new file mode 100644
index 00000000..37f63822
--- /dev/null
+++ b/libtests/qtest/ph/ph.out
@@ -0,0 +1,12 @@
+hello
+created Object, id 1
+created Object, id 2
+nulls equal
+destroyed Object, id 2
+equal okay
+less than okay
+created Object, id 3
+calling Object::hello for 1
+goodbye
+destroyed Object, id 3
+destroyed Object, id 1
diff --git a/libtests/qtest/png_filter.test b/libtests/qtest/png_filter.test
new file mode 100644
index 00000000..5b75a208
--- /dev/null
+++ b/libtests/qtest/png_filter.test
@@ -0,0 +1,63 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+use File::Copy;
+use Digest::MD5;
+
+chdir("png_filter") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('png_filter');
+
+cleanup();
+
+$td->runtest("decode columns = 4",
+ {$td->COMMAND => "png_filter decode in1 4"},
+ {$td->STRING => "done\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("check output",
+ {$td->FILE => "out"},
+ {$td->FILE => "out1"});
+
+$td->runtest("decode columns = 5",
+ {$td->COMMAND => "png_filter decode in2 5"},
+ {$td->STRING => "done\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("check output",
+ {$td->FILE => "out"},
+ {$td->FILE => "out2"});
+
+$td->runtest("encode columns = 4",
+ {$td->COMMAND => "png_filter encode out1 4"},
+ {$td->STRING => "done\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("check output",
+ {$td->FILE => "out"},
+ {$td->FILE => "in1"});
+
+$td->runtest("encode columns = 5",
+ {$td->COMMAND => "png_filter encode out2 5"},
+ {$td->STRING => "done\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("check output",
+ {$td->FILE => "out"},
+ {$td->FILE => "in2"});
+
+cleanup();
+
+$td->report(8);
+
+sub cleanup
+{
+ unlink "out";
+}
diff --git a/libtests/qtest/png_filter/in1 b/libtests/qtest/png_filter/in1
new file mode 100644
index 00000000..bb830eca
--- /dev/null
+++ b/libtests/qtest/png_filter/in1
Binary files differ
diff --git a/libtests/qtest/png_filter/in2 b/libtests/qtest/png_filter/in2
new file mode 100644
index 00000000..430a0740
--- /dev/null
+++ b/libtests/qtest/png_filter/in2
Binary files differ
diff --git a/libtests/qtest/png_filter/out1 b/libtests/qtest/png_filter/out1
new file mode 100644
index 00000000..5625f331
--- /dev/null
+++ b/libtests/qtest/png_filter/out1
Binary files differ
diff --git a/libtests/qtest/png_filter/out2 b/libtests/qtest/png_filter/out2
new file mode 100644
index 00000000..dad129df
--- /dev/null
+++ b/libtests/qtest/png_filter/out2
Binary files differ
diff --git a/libtests/qtest/qexc.test b/libtests/qtest/qexc.test
new file mode 100644
index 00000000..b8632b9b
--- /dev/null
+++ b/libtests/qtest/qexc.test
@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("qexc") or die "chdir qexc failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('qexc');
+
+my @tests =
+ (['general exception', 2],
+ ['internal error', 3],
+ ['system exception', 2],
+ ['library exception', 3, "uncaught exception: .+\n"], # fails on VC7?
+ );
+
+for (my $i = 0; $i < scalar(@tests); ++$i)
+{
+ my $output = +((-f "test$i.out")
+ ? {$td->FILE => "test$i.out"}
+ : {$td->REGEXP => $tests[$i]->[2]});
+ $output->{$td->EXIT_STATUS} = $tests[$i]->[1];
+ $td->runtest($tests[$i]->[0],
+ {$td->COMMAND => "qexc $i"},
+ $output,
+ $td->NORMALIZE_NEWLINES);
+}
+
+$td->report(scalar(@tests));
diff --git a/libtests/qtest/qexc/test0.out b/libtests/qtest/qexc/test0.out
new file mode 100644
index 00000000..7a6dba88
--- /dev/null
+++ b/libtests/qtest/qexc/test0.out
@@ -0,0 +1,2 @@
+exception: general exception
+what: general exception
diff --git a/libtests/qtest/qexc/test1.out b/libtests/qtest/qexc/test1.out
new file mode 100644
index 00000000..cb18f40c
--- /dev/null
+++ b/libtests/qtest/qexc/test1.out
@@ -0,0 +1 @@
+uncaught exception: INTERNAL ERROR: internal error
diff --git a/libtests/qtest/qexc/test2.out b/libtests/qtest/qexc/test2.out
new file mode 100644
index 00000000..0f1994f7
--- /dev/null
+++ b/libtests/qtest/qexc/test2.out
@@ -0,0 +1,2 @@
+exception: doing something: Invalid argument
+what: doing something: Invalid argument
diff --git a/libtests/qtest/qutil.test b/libtests/qtest/qutil.test
new file mode 100644
index 00000000..e90692f8
--- /dev/null
+++ b/libtests/qtest/qutil.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("qutil") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('qutil');
+
+$td->runtest("QUtil",
+ {$td->COMMAND => "qutil"},
+ {$td->FILE => "qutil.out",
+ $td->EXIT_STATUS => 0});
+
+$td->report(1);
diff --git a/libtests/qtest/qutil/qutil.out b/libtests/qtest/qutil/qutil.out
new file mode 100644
index 00000000..f7af8903
--- /dev/null
+++ b/libtests/qtest/qutil/qutil.out
@@ -0,0 +1,30 @@
+16059
+0016059
+16059
+3.141590
+3.142
+1000.123000
+exception 1: INTERNAL ERROR: Util::int_to_string has been called with a padding value greater than its internal limit
+exception 2: INTERNAL ERROR: Util::int_to_string has been called with a padding value greater than its internal limit
+exception 3: INTERNAL ERROR: Util::int_to_string has been called with a padding value greater than its internal limit
+exception 4: INTERNAL ERROR: Util::double_to_string has been called with a number and a decimal places specification that would break an internal limit
+exception 5: INTERNAL ERROR: Util::double_to_string has been called with a number and a decimal places specification that would break an internal limit
+one
+7
+compare okay
+----
+before open
+exception: open file: No such file or directory
+----
+before fopen
+exception: fopen file: No such file or directory
+----
+IN_TESTSUITE: 1: 1
+HAGOOGAMAGOOGLE: 0
+----
+0x41 -> A
+0xf7 -> ÷
+0x3c0 -> π
+0x16059 -> f0 96 81 99
+0x7fffffff -> fd bf bf bf bf bf
+0x80000000: bounds error in QUtil::toUTF8
diff --git a/libtests/qtest/rc4.test b/libtests/qtest/rc4.test
new file mode 100644
index 00000000..0207317c
--- /dev/null
+++ b/libtests/qtest/rc4.test
@@ -0,0 +1,45 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+chdir("rc4") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('RC4');
+
+cleanup();
+
+my @tests = ('0123456789abcdef',
+ '0123456789abcdef',
+ '0000000000000000',
+ 'ef012345',
+ '0123456789abcdef');
+
+my $n = 0;
+foreach my $key (@tests)
+{
+ ++$n;
+ $td->runtest("test $n",
+ {$td->COMMAND => "rc4 $key test$n.in tmp1-$n.out"},
+ {$td->STRING => "", $td->EXIT_STATUS => 0});
+ $td->runtest("check output",
+ {$td->FILE => "tmp1-$n.out"},
+ {$td->FILE => "test$n.out"});
+ $td->runtest("test $n reverse",
+ {$td->COMMAND => "rc4 $key test$n.out tmp2-$n.out"},
+ {$td->STRING => "", $td->EXIT_STATUS => 0});
+ $td->runtest("check output",
+ {$td->FILE => "tmp2-$n.out"},
+ {$td->FILE => "test$n.in"});
+}
+
+cleanup();
+
+$td->report(4 * scalar(@tests));
+
+sub cleanup
+{
+ system("rm -f tmp*-*");
+}
diff --git a/libtests/qtest/rc4/test1.in b/libtests/qtest/rc4/test1.in
new file mode 100644
index 00000000..be687ec3
--- /dev/null
+++ b/libtests/qtest/rc4/test1.in
@@ -0,0 +1 @@
+#Eg‰«Íï \ No newline at end of file
diff --git a/libtests/qtest/rc4/test1.out b/libtests/qtest/rc4/test1.out
new file mode 100644
index 00000000..0a8617e0
--- /dev/null
+++ b/libtests/qtest/rc4/test1.out
@@ -0,0 +1 @@
+u·‡€™àÅ– \ No newline at end of file
diff --git a/libtests/qtest/rc4/test2.in b/libtests/qtest/rc4/test2.in
new file mode 100644
index 00000000..1b1cb4d4
--- /dev/null
+++ b/libtests/qtest/rc4/test2.in
Binary files differ
diff --git a/libtests/qtest/rc4/test2.out b/libtests/qtest/rc4/test2.out
new file mode 100644
index 00000000..9bdb590f
--- /dev/null
+++ b/libtests/qtest/rc4/test2.out
@@ -0,0 +1 @@
+t”ÂçKy \ No newline at end of file
diff --git a/libtests/qtest/rc4/test3.in b/libtests/qtest/rc4/test3.in
new file mode 100644
index 00000000..1b1cb4d4
--- /dev/null
+++ b/libtests/qtest/rc4/test3.in
Binary files differ
diff --git a/libtests/qtest/rc4/test3.out b/libtests/qtest/rc4/test3.out
new file mode 100644
index 00000000..11f99ca8
--- /dev/null
+++ b/libtests/qtest/rc4/test3.out
@@ -0,0 +1 @@
+Þ‰A£7]: \ No newline at end of file
diff --git a/libtests/qtest/rc4/test4.in b/libtests/qtest/rc4/test4.in
new file mode 100644
index 00000000..cb43b5ce
--- /dev/null
+++ b/libtests/qtest/rc4/test4.in
Binary files differ
diff --git a/libtests/qtest/rc4/test4.out b/libtests/qtest/rc4/test4.out
new file mode 100644
index 00000000..1394b334
--- /dev/null
+++ b/libtests/qtest/rc4/test4.out
@@ -0,0 +1 @@
+Ö¡A§ì<8ß½a \ No newline at end of file
diff --git a/libtests/qtest/rc4/test5.in b/libtests/qtest/rc4/test5.in
new file mode 100644
index 00000000..60e5cd06
--- /dev/null
+++ b/libtests/qtest/rc4/test5.in
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/libtests/qtest/rc4/test5.out b/libtests/qtest/rc4/test5.out
new file mode 100644
index 00000000..d64d1a49
--- /dev/null
+++ b/libtests/qtest/rc4/test5.out
Binary files differ
diff --git a/libtests/qutil.cc b/libtests/qutil.cc
new file mode 100644
index 00000000..3a1fc8aa
--- /dev/null
+++ b/libtests/qutil.cc
@@ -0,0 +1,199 @@
+
+#include <iostream>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <qpdf/QUtil.hh>
+
+#ifdef _WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+#endif
+
+void string_conversion_test()
+{
+ std::cout << QUtil::int_to_string(16059) << std::endl
+ << QUtil::int_to_string(16059, 7) << std::endl
+ << QUtil::int_to_string(16059, -7) << std::endl
+ << QUtil::double_to_string(3.14159) << std::endl
+ << QUtil::double_to_string(3.14159, 3) << std::endl
+ << QUtil::double_to_string(1000.123, -1024) << std::endl;
+
+ try
+ {
+ // int_to_string bounds error
+ std::cout << QUtil::int_to_string(1, 50) << std::endl;
+ }
+ catch(QEXC::Internal &e)
+ {
+ std::cout << "exception 1: " << e.unparse() << std::endl;
+ }
+
+ try
+ {
+ // QUtil::int_to_string bounds error
+ std::cout << QUtil::int_to_string(1, -50) << std::endl;
+ }
+ catch(QEXC::Internal &e)
+ {
+ std::cout << "exception 2: " << e.unparse() << std::endl;
+ }
+
+ try
+ {
+ // QUtil::int_to_string bounds error
+ std::cout << QUtil::int_to_string(-1, 49) << std::endl;
+ }
+ catch(QEXC::Internal &e)
+ {
+ std::cout << "exception 3: " << e.unparse() << std::endl;
+ }
+
+
+ try
+ {
+ // QUtil::double_to_string bounds error
+ std::cout << QUtil::double_to_string(3.14159, 1024) << std::endl;
+ }
+ catch(QEXC::Internal &e)
+ {
+ std::cout << "exception 4: " << e.unparse() << std::endl;
+ }
+
+ try
+ {
+ // QUtil::double_to_string bounds error
+ std::cout << QUtil::double_to_string(1000.0, 95) << std::endl;
+ }
+ catch(QEXC::Internal &e)
+ {
+ std::cout << "exception 5: " << e.unparse() << std::endl;
+ }
+
+ std::string embedded_null = "one";
+ embedded_null += '\0';
+ embedded_null += "two";
+ std::cout << embedded_null.c_str() << std::endl;
+ std::cout << embedded_null.length() << std::endl;
+ char* tmp = QUtil::copy_string(embedded_null);
+ if (memcmp(tmp, embedded_null.c_str(), 7) == 0)
+ {
+ std::cout << "compare okay" << std::endl;
+ }
+ else
+ {
+ std::cout << "compare failed" << std::endl;
+ }
+ delete [] tmp;
+}
+
+void os_wrapper_test()
+{
+ int fd = -1;
+ try
+ {
+ std::cout << "before open" << std::endl;
+ fd = QUtil::os_wrapper("open file",
+ open("/this/file/does/not/exist", O_RDONLY));
+ std::cout << "after open" << std::endl;
+ (void) close(fd);
+ }
+ catch (QEXC::System& s)
+ {
+ std::cout << "exception: " << s.unparse() << std::endl;
+ }
+}
+
+void fopen_wrapper_test()
+{
+ FILE* f = 0;
+ try
+ {
+ std::cout << "before fopen" << std::endl;
+ f = QUtil::fopen_wrapper("fopen file",
+ fopen("/this/file/does/not/exist", "r"));
+ std::cout << "after fopen" << std::endl;
+ (void) fclose(f);
+ }
+ catch (QEXC::System& s)
+ {
+ std::cout << "exception: " << s.unparse() << std::endl;
+ }
+}
+
+void getenv_test()
+{
+ std::string val;
+ std::cout << "IN_TESTSUITE: " << QUtil::get_env("IN_TESTSUITE", &val)
+ << ": " << val << std::endl;
+ // Hopefully this environment variable is not defined.
+ std::cout << "HAGOOGAMAGOOGLE: " << QUtil::get_env("HAGOOGAMAGOOGLE")
+ << std::endl;
+}
+
+static void print_utf8(unsigned long val)
+{
+ char t[20];
+ sprintf(t, "%lx", val);
+ std::string result = QUtil::toUTF8(val);
+ std::cout << "0x" << t << " ->";
+ if (val < 0xfffe)
+ {
+ std::cout << " " << result;
+ }
+ else
+ {
+ // Emacs has trouble with utf-8 encoding files with characters
+ // outside the 16-bit portion, so just show the character
+ // values.
+ for (std::string::iterator iter = result.begin();
+ iter != result.end(); ++iter)
+ {
+ char t[3];
+ sprintf(t, "%02x", (unsigned char) (*iter));
+ std::cout << " " << t;
+ }
+ }
+ std::cout << std::endl;
+}
+
+void to_utf8_test()
+{
+ print_utf8(0x41UL);
+ print_utf8(0xF7UL);
+ print_utf8(0x3c0UL);
+ print_utf8(0x16059UL);
+ print_utf8(0x7fffffffUL);
+ try
+ {
+ print_utf8(0x80000000UL);
+ }
+ catch (QEXC::General& e)
+ {
+ std::cout << "0x80000000: " << e.what() << std::endl;
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ string_conversion_test();
+ std::cout << "----" << std::endl;
+ os_wrapper_test();
+ std::cout << "----" << std::endl;
+ fopen_wrapper_test();
+ std::cout << "----" << std::endl;
+ getenv_test();
+ std::cout << "----" << std::endl;
+ to_utf8_test();
+ }
+ catch (std::exception& e)
+ {
+ std::cout << "unexpected exception: " << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/libtests/rc4.cc b/libtests/rc4.cc
new file mode 100644
index 00000000..34d779ad
--- /dev/null
+++ b/libtests/rc4.cc
@@ -0,0 +1,82 @@
+
+#include <qpdf/Pl_RC4.hh>
+#include <qpdf/Pl_StdioFile.hh>
+
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <stdlib.h>
+
+#ifdef _WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+#endif
+
+int main(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "Usage: rc4 hex-key infile outfile" << std::endl;
+ exit(2);
+ }
+
+ char* hexkey = argv[1];
+ char* infilename = argv[2];
+ char* outfilename = argv[3];
+ int hexkeylen = strlen(hexkey);
+ int keylen = hexkeylen / 2;
+ unsigned char* key = new unsigned char[keylen + 1];
+ key[keylen] = '\0';
+
+ FILE* infile = fopen(infilename, "rb");
+ if (infile == 0)
+ {
+ std::cerr << "can't open " << infilename << std::endl;
+ exit(2);
+ }
+
+ for (unsigned int i = 0; i < strlen(hexkey); i += 2)
+ {
+ char t[3];
+ t[0] = hexkey[i];
+ t[1] = hexkey[i + 1];
+ t[2] = '\0';
+
+ long val = strtol(t, 0, 16);
+ key[i/2] = (unsigned char) val;
+ }
+
+ FILE* outfile = fopen(outfilename, "wb");
+ if (outfile == 0)
+ {
+ std::cerr << "can't open " << outfilename << std::endl;
+ exit(2);
+ }
+ Pl_StdioFile* out = new Pl_StdioFile("stdout", outfile);
+ // Use a small buffer size (64) for testing
+ Pl_RC4* rc4 = new Pl_RC4("rc4", out, key, keylen, 64);
+ delete [] key;
+
+ // 64 < buffer size < 512, buffer_size is not a power of 2 for testing
+ unsigned char buf[100];
+ bool done = false;
+ while (! done)
+ {
+ int len = fread(buf, 1, sizeof(buf), infile);
+ if (len <= 0)
+ {
+ done = true;
+ }
+ else
+ {
+ rc4->write(buf, len);
+ }
+ }
+ rc4->finish();
+ delete rc4;
+ delete out;
+ fclose(infile);
+ fclose(outfile);
+ return 0;
+}
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100644
index 00000000..5def3516
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,6964 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION="1.5.26 Debian 1.5.26-1"
+TIMESTAMP=" (1.1220.2.493 2008/02/01 16:58:18)"
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ SP2NL='tr \040 \012'
+ NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ SP2NL='tr \100 \n'
+ NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+lt_env=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test \"\${$lt_var+set}\" = set; then
+ save_$lt_var=\$$lt_var
+ lt_env=\"$lt_var=\$$lt_var \$lt_env\"
+ $lt_var=C
+ export $lt_var
+ fi"
+done
+
+if test -n "$lt_env"; then
+ lt_env="env $lt_env"
+fi
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $mkdir "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || {
+ $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+ exit $EXIT_FAILURE
+ }
+ fi
+
+ $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ $SED -n -e '1,100{
+ / I /{
+ s,.*,import,
+ p
+ q
+ }
+ }'`
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ $echo "$modename: unable to infer tagged configuration"
+ $echo "$modename: specify a tag with \`--tag'" 1>&2
+ exit $EXIT_FAILURE
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+
+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+ exit $EXIT_FAILURE
+ fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ extracted_serial=`expr $extracted_serial + 1`
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir="$my_gentop/$my_xlib_u"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $exit_status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ ${rm}r unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd "$darwin_orig_dir"
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ tag)
+ tagname="$arg"
+ preserve_args="${preserve_args}=$arg"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $tagname in
+ CC)
+ # Don't test for the "default" C tag, as we know, it's there, but
+ # not specially marked.
+ ;;
+ *)
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+ else
+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ echo "\
+$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ exit $?
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+ done
+ exit $?
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit $?
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --tag)
+ prevopt="--tag"
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no)
+ ;;
+shared)
+ build_libtool_libs=no
+ build_old_libs=yes
+ ;;
+static)
+ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+ ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+ case $nonopt in
+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test -n "$libobj" ; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ * )
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ case $lastarg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
+ # in scan sets (worked around with variable expansion),
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # at all, so we specify them separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ base_compile="$base_compile $lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ $echo "$modename: you must specify an argument for -Xcompile"
+ exit $EXIT_FAILURE
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *)
+ # Get the name of the library object.
+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSifmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.ii) xform=ii ;;
+ *.class) xform=class ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.[fF][09]?) xform=[fF][09]. ;;
+ *.for) xform=for ;;
+ *.java) xform=java ;;
+ *.obj) xform=obj ;;
+ *.sx) xform=sx ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+ case $qlibobj in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qlibobj="\"$qlibobj\"" ;;
+ esac
+ test "X$libobj" != "X$qlibobj" \
+ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir=
+ else
+ xdir=$xdir/
+ fi
+ lobj=${xdir}$objdir/$objname
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+ $echo "$srcfile" > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+ case $qsrcfile in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qsrcfile="\"$qsrcfile\"" ;;
+ esac
+
+ $run $rm "$libobj" "${libobj}T"
+
+ # Create a libtool object file (analogous to a ".la" file),
+ # but don't create it if we're doing a dry run.
+ test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval $lt_env "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ $show "$mv $output_obj $lobj"
+ if $run $mv $output_obj $lobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the PIC object to the libtool object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval $lt_env "$command"; then :
+ else
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ base_compile="$nonopt $@"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ notinst_path= # paths that contain not-installed libtool libraries
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+ single_module="${wl}-single_module"
+
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ -static)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat $save_arg`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ done
+ else
+ $echo "$modename: link input file \`$save_arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ darwin_framework|darwin_framework_skip)
+ test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit $EXIT_FAILURE
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework|-arch|-isysroot)
+ case " $CC " in
+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
+ prev=darwin_framework_skip ;;
+ *) compiler_flags="$compiler_flags $arg"
+ prev=darwin_framework ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ notinst_path="$notinst_path $dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs -framework System"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ -model)
+ compile_command="$compile_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ finalize_command="$finalize_command $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -multi_module)
+ single_module="${wl}-multi_module"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m* pass through architecture-specific compiler args for GCC
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+ # -F/path gives path to uninstalled frameworks, gcc on darwin
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # and Darwin in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static | -static-libtool-libs)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d "$output_objdir"; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ case $host in
+ *cygwin* | *mingw* | *pw32*)
+ # don't eliminate duplications in $postdeps and $predeps
+ duplicate_compiler_generated_deps=yes
+ ;;
+ *)
+ duplicate_compiler_generated_deps=$duplicate_deps
+ ;;
+ esac
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link)
+ libs="$deplibs %DEPLIBS%"
+ test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+ ;;
+ esac
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ if test "$linkmode" = lib; then
+ searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+ else
+ searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+ fi
+ for searchdir in $searchdirs; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if (${SED} -e '2q' $lib |
+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ library_names=
+ old_library=
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $echo
+ $echo "*** Warning: Trying to link with static lib archive $deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because the file extensions .$libext of this argument makes me believe"
+ $echo "*** that it is just a static archive that I should not used here."
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the"
+ $echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { { test "$prefer_static_libs" = no ||
+ test "$prefer_static_libs,$installed" = "built,yes"; } ||
+ test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $absdir" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test "$use_static_libs" = built && test "$installed" = yes ; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on
+ # some systems (darwin)
+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
+ $echo
+ if test "$linkmode" = prog; then
+ $echo "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $echo "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $echo "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$extract_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$old_archive_from_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a module then we can not link against
+ # it, someone is ignoring the new warnings I added
+ if /usr/bin/file -L $add 2> /dev/null |
+ $EGREP ": [^:]* bundle" >/dev/null ; then
+ $echo "** Warning, lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $echo
+ $echo "** And there doesn't seem to be a static archive available"
+ $echo "** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $echo
+ $echo "*** Warning: This system can not link to static lib archive $lib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $echo "*** But as you try to build a module library, libtool will still create "
+ $echo "*** a static module, that should work as long as the dlopening application"
+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="$absdir"
+ fi
+ depdepl=
+ case $host in
+ *-*-darwin*)
+ # we do not want to link against static libs,
+ # but need to link against shared
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ eval deplibdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$deplibdir/$depdepl" ; then
+ depdepl="$deplibdir/$depdepl"
+ elif test -f "$path/$depdepl" ; then
+ depdepl="$path/$depdepl"
+ else
+ # Can't find it, oh well...
+ depdepl=
+ fi
+ # do not add paths which are already there
+ case " $newlib_search_path " in
+ *" $path "*) ;;
+ *) newlib_search_path="$newlib_search_path $path";;
+ esac
+ fi
+ path=""
+ ;;
+ *)
+ path="-L$path"
+ ;;
+ esac
+ ;;
+ -l*)
+ case $host in
+ *-*-darwin*)
+ # Again, we only want to link against shared libraries
+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+ for tmp in $newlib_search_path ; do
+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
+ eval depdepl="$tmp/lib$tmp_libs.dylib"
+ break
+ fi
+ done
+ path=""
+ ;;
+ *) continue ;;
+ esac
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ case " $deplibs " in
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 ;;
+ esac
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit $EXIT_FAILURE
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
+ $echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test "$#" -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$2"
+ number_minor="$3"
+ number_revision="$4"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows|none)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_minor"
+ lt_irix_increment=no
+ ;;
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ ;;
+ no)
+ current="$2"
+ revision="$3"
+ age="$4"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ if test "X$lt_irix_increment" = "Xno"; then
+ major=`expr $current - $age`
+ else
+ major=`expr $current - $age + 1`
+ fi
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$echo "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ if test -n "$removelist"; then
+ $show "${rm}r $removelist"
+ $run ${rm}r $removelist
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ #for path in $notinst_path; do
+ # lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+ # deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+ # dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+ #done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval $echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+ done
+ fi
+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
+ | grep . >/dev/null; then
+ $echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $echo
+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
+ $echo "*** a static module, that should work as long as the dlopening"
+ $echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $echo "*** The inter-library dependencies that have been dropped here will be"
+ $echo "*** automatically added whenever a program is linked with this library"
+ $echo "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $echo
+ $echo "*** Since this library must not contain undefined symbols,"
+ $echo "*** because either the platform does not support them or"
+ $echo "*** it was explicitly requested with -no-undefined,"
+ $echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ deplibs="$new_libs"
+
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ case $archive_cmds in
+ *\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;;
+ *) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;;
+ esac
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ linknames=
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ if len=`expr "X$cmd" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ $show "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" &&
+ len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise.
+ $echo "creating reloadable object files..."
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ delfiles=
+ last_robj=
+ k=1
+ output=$output_objdir/$output_la-${k}.$objext
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ if test "X$objlist" = X ||
+ { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; }; then
+ objlist="$objlist $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$output_la-${k}.$objext
+ objlist=$obj
+ len=1
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+ if ${skipped_export-false}; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+ fi
+
+ # Set up a command to remove the reloadable object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+ done
+
+ $echo "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+
+ # Append the command to remove the reloadable object files
+ # to the just-reset $cmds.
+ eval cmds=\"\$cmds~\$rm $delfiles\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 ;;
+ esac
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec and hope we can get by with
+ # turning comma into space..
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $run eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ if test "$tagname" = CXX ; then
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ fi
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$outputname.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ else
+ $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval '$echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+ case $host in
+ *cygwin* | *mingw* )
+ $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs */
+struct {
+"
+ ;;
+ * )
+ $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+ ;;
+ esac
+
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ case $host in
+ *cygwin* | *mingw* )
+ if test -f "$output_objdir/${outputname}.def" ; then
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ else
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ fi
+ ;;
+ * )
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ ;;
+ esac
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+ fi
+
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ exit_status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $exit_status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ output_name=`basename $output`
+ output_path=`dirname $output`
+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
+ cwrapper="$output_path/$output_name.exe"
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS. */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ DEBUG("(main) argv[0] : %s\n",argv[0]);
+ DEBUG("(main) program_name : %s\n",program_name);
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = find_executable(argv[0]);
+ if (newargz[1] == NULL)
+ lt_fatal("Couldn't find %s", argv[0]);
+ DEBUG("(main) found exe at : %s\n",newargz[1]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure newargz[1] doesn't end in .exe */
+ strendzap(newargz[1],".exe");
+ for (i = 1; i < argc; i++)
+ newargz[i+1] = xstrdup(argv[i]);
+ newargz[argc+1] = NULL;
+
+ for (i=0; i<argc+1; i++)
+ {
+ DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
+ ;
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",(char const **)newargz);
+EOF
+ ;;
+ *)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+ ;;
+ esac
+
+ cat >> $cwrappersource <<"EOF"
+ return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable(const char * path)
+{
+ struct stat st;
+
+ DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0) &&
+ (
+ /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+ ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+ ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+ ((st.st_mode & S_IXUSR) == S_IXUSR))
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+ int has_slash = 0;
+ const char* p;
+ const char* p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ int tmp_len;
+ char* concat_name;
+
+ DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char* path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char* q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR(*q))
+ break;
+ p_len = q - p;
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ $echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ $echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \$*\"
+ exit $EXIT_FAILURE
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "copying selected object files to avoid basename conflicts..."
+
+ if test -z "$gentop"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+ exit $exit_status
+ fi
+ fi
+
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ counter=`expr $counter + 1`
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ $run ln "$obj" "$gentop/$newobj" ||
+ $run cp "$obj" "$gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ for obj in $save_oldobjs
+ do
+ oldobjs="$objlist $obj"
+ objlist="$objlist $obj"
+ eval test_cmds=\"$old_archive_cmds\"
+ if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ eval cmd=\"$cmd\"
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o) prev=$arg ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test "$#" -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP`
+ else
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try `ln -sf' first, because the `ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=$postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir=`func_mktempdir`
+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=$old_postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ cmds=$finish_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit $EXIT_SUCCESS
+
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ $echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $echo " $libdir"
+ done
+ $echo
+ $echo "If you ever happen to want to link against installed libraries"
+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ $echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $echo
+ $echo "See any operating system documentation about shared libraries for"
+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit $EXIT_FAILURE
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ if test ! -f "$dir/$dlname"; then
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ fi"
+ done
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ cmds=$postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ cmds=$old_postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+ # Read the .lo file
+ . $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" \
+ && test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" \
+ && test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ noexename=`$echo $name|${SED} 's,.exe$,,'`
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$noexename
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+ exit $EXIT_SUCCESS
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/make/proxy.mk b/make/proxy.mk
new file mode 100644
index 00000000..16831862
--- /dev/null
+++ b/make/proxy.mk
@@ -0,0 +1,10 @@
+THIS=$(notdir $(abspath .))
+
+all:
+ $(MAKE) -C .. build_$(THIS)
+
+check:
+ $(MAKE) -C .. check_$(THIS)
+
+clean:
+ $(MAKE) -C .. clean_$(THIS)
diff --git a/make/rules.mk b/make/rules.mk
new file mode 100644
index 00000000..901534cd
--- /dev/null
+++ b/make/rules.mk
@@ -0,0 +1,63 @@
+
+# Usage: $(call src_to_obj,srcs)
+define src_to_obj
+$(foreach F,$(1),$(dir $(F))$(OUTPUT_DIR)/$(patsubst %.cc,%.o,$(notdir $(F))))
+endef
+
+# Usage: $(call src_to_lobj,srcs)
+define src_to_lobj
+$(foreach F,$(1),$(dir $(F))$(OUTPUT_DIR)/$(patsubst %.cc,%.lo,$(notdir $(F))))
+endef
+
+# Usage: $(call obj_to_dep,objs)
+define obj_to_dep
+$(patsubst %.o,%.dep,$(1))
+endef
+
+# Usage: $(call lobj_to_dep,objs)
+define lobj_to_dep
+$(patsubst %.lo,%.dep,$(1))
+endef
+
+# Usage: $(call depflags,$(basename obj))
+ifeq ($(GENDEPS),1)
+depflags=-MD -MF $(1).dep -MP
+else
+depflags=
+endif
+
+# 1 2
+# Usage: $(call compile,src,includes)
+define compile
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) \
+ $(call depflags,$(basename $(call src_to_obj,$(1)))) \
+ $(foreach I,$(2),-I$(I)) \
+ -c $(1) -o $(call src_to_obj,$(1))
+endef
+
+# 1 2
+# Usage: $(call libcompile,src,includes)
+define libcompile
+ $(LIBTOOL) --mode=compile \
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) \
+ $(call depflags,$(basename $(call src_to_obj,$(1)))) \
+ $(foreach I,$(2),-I$(I)) \
+ -c $(1) -o $(call src_to_obj,$(1))
+endef
+
+# 1 2 3 4 5
+# Usage: $(call makelib,objs,library,current,revision,age)
+define makelib
+ $(LIBTOOL) --mode=link \
+ $(CXX) $(CXXFLAGS) -o $(2) $(1) $(LDFLAGS) $(LIBS) \
+ -rpath $(libdir) -version-info $(3):$(4):$(5)
+endef
+
+# 1 2
+# Usage: $(call makebin,objs,binary)
+define makebin
+ $(LIBTOOL) --mode=link \
+ $(CXX) $(CXXFLAGS) $(1) -o $(2) $(LDFLAGS) \
+ -Llibqpdf/$(OUTPUT_DIR) -lqpdf $(LIBS)
+endef
+
diff --git a/make_dist b/make_dist
new file mode 100755
index 00000000..5ea2c646
--- /dev/null
+++ b/make_dist
@@ -0,0 +1,165 @@
+#!/usr/bin/env perl
+#
+# This program creates a source distribution of qpdf. For details,
+# see README.maintainer.
+#
+
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+use Cwd;
+use IO::File;
+
+my $whoami = ($0 =~ m,([^/\\]*)$,) ? $1 : $0;
+#my $dirname = ($0 =~ m,(.*)[/\\][^/\\]+$,) ? $1 : ".";
+
+usage() unless @ARGV >= 1;
+my $srcdir = shift(@ARGV);
+my $run_tests = 1;
+if (@ARGV)
+{
+ if ($ARGV[0] eq '--no-tests')
+ {
+ $run_tests = 0;
+ }
+ else
+ {
+ usage();
+ }
+}
+$srcdir =~ s,/$,,;
+usage() unless $srcdir =~ m/^qpdf-(\d+\.\d+(?:\.(a|b|rc)\d+)?)$/;
+my $version = $1;
+usage() unless -d $srcdir;
+
+my $pwd = getcwd();
+cd($srcdir);
+
+# Check versions
+my $fh = safe_open("configure.ac");
+my $config_version = 'unknown';
+while (<$fh>)
+{
+ if (m/^AC_INIT\(qpdf,([^\)]+)\)/)
+ {
+ $config_version = $1;
+ last;
+ }
+}
+$fh->close();
+
+$fh = safe_open("qpdf/qpdf.cc");
+my $code_version = 'unknown';
+while (<$fh>)
+{
+ if (m/whoami << \" version ([^\"]+)\"/)
+ {
+ $code_version = $1;
+ last;
+ }
+}
+$fh->close();
+
+$fh = safe_open("manual/qpdf-manual.xml");
+my $doc_version = 'unknown';
+while (<$fh>)
+{
+ if (m/swversion "([^\"]+)\"/)
+ {
+ $doc_version = $1;
+ last;
+ }
+}
+$fh->close();
+
+$fh = safe_open("qpdf.spec");
+my $spec_version = 'unknown';
+while (<$fh>)
+{
+ if (m/Version: (.*)$/)
+ {
+ $spec_version = $1;
+ last;
+ }
+}
+
+my $version_error = 0;
+if ($version ne $config_version)
+{
+ print "$whoami: configure.ac version = $config_version\n";
+ $version_error = 1;
+}
+if ($version ne $code_version)
+{
+ print "$whoami: qpdf.cc version = $code_version\n";
+ $version_error = 1;
+}
+if ($version ne $doc_version)
+{
+ print "$whoami: qpdf-manual.xml version = $doc_version\n";
+ $version_error = 1;
+}
+if ($version ne $spec_version)
+{
+ print "$whoami: qpdf.spec version = $spec_version\n";
+ $version_error = 1;
+}
+if ($version_error)
+{
+ die "$whoami: version numbers are not consistent\n";
+}
+
+run("autoconf");
+run("./configure --enable-doc-maintenance");
+run("make build_manual");
+run("make distclean");
+cd($pwd);
+run("tar czvf $srcdir.tar.gz-candidate $srcdir");
+if ($run_tests)
+{
+ cd($srcdir);
+ run("./configure");
+ run("make check");
+ cd($pwd);
+}
+rename "$srcdir.tar.gz-candidate", "$srcdir.tar.gz" or die;
+
+print "
+Source distribution created as $srcdir.tar.gz
+You can now remove $srcdir.
+If this is a release, don't forget to tag the version control system and
+make a backup of the release tar file.
+
+";
+
+sub safe_open
+{
+ my $file = shift;
+ my $fh = new IO::File("<$file") or die "$whoami: can't open $file: $!";
+ $fh;
+}
+
+sub run
+{
+ my $cmd = shift;
+ system($cmd) == 0 or die "$whoami: $cmd failed\n";
+}
+
+sub cd
+{
+ my $dir = shift;
+ chdir($dir) or die;
+}
+
+sub usage
+{
+ die "
+Usage: $whoami qpdf-version [ --no-tests ]
+
+qpdf-version must be a directory containing a pristine export of that
+version of qpdf from the version control system. Use of --no-tests
+can be used for internally testing releases, but do not use it for a
+real release.
+
+";
+}
diff --git a/manual/Makefile b/manual/Makefile
new file mode 100644
index 00000000..90899055
--- /dev/null
+++ b/manual/Makefile
@@ -0,0 +1 @@
+include ../make/proxy.mk
diff --git a/manual/README b/manual/README
new file mode 100644
index 00000000..88118ac0
--- /dev/null
+++ b/manual/README
@@ -0,0 +1,3 @@
+This directory contains sources to the documentation. If you are
+looking for pre-built documentation, please look in the "doc"
+directory.
diff --git a/manual/build.mk b/manual/build.mk
new file mode 100644
index 00000000..55c49652
--- /dev/null
+++ b/manual/build.mk
@@ -0,0 +1,43 @@
+INDOC = manual/qpdf-manual
+OUTDOC = manual/$(OUTPUT_DIR)/qpdf-manual
+
+TARGETS_manual := doc/qpdf.1 doc/fix-qdf.1 doc/zlib-flate.1
+ifeq ($(BUILD_HTML),1)
+TARGETS_manual += doc/qpdf-manual.html
+endif
+ifeq ($(BUILD_PDF),1)
+TARGETS_manual += doc/qpdf-manual.pdf
+endif
+
+VALIDATE=manual/$(OUTPUT_DIR)/validate
+
+ifeq ($(VALIDATE_DOC),1)
+
+$(VALIDATE): $(INDOC).xml
+ $(XMLLINT) --noout --dtdvalid $(DOCBOOKX_DTD) $<
+ touch $(VALIDATE)
+
+else
+
+$(VALIDATE):
+ touch $(VALIDATE)
+
+endif
+
+$(OUTDOC).pdf: $(OUTDOC).fo
+ $(FOP) $< -pdf $@
+
+$(OUTDOC).html: $(INDOC).xml manual/html.xsl $(VALIDATE)
+ $(XSLTPROC) --output $@ manual/html.xsl $<
+
+.PRECIOUS: $(OUTDOC).fo
+$(OUTDOC).fo: $(INDOC).xml manual/print.xsl $(VALIDATE)
+ $(XSLTPROC) --output $@ manual/print.xsl $<
+
+doc/%.1: manual/%.1.in
+ sed -e 's:@PACKAGE_VERSION@:$(PACKAGE_VERSION):g' \
+ -e 's:@docdir@:$(docdir):g' \
+ < $< > $@
+
+doc/%: manual/$(OUTPUT_DIR)/%
+ cp $< $@
diff --git a/manual/common.xsl b/manual/common.xsl
new file mode 100644
index 00000000..e564bfd8
--- /dev/null
+++ b/manual/common.xsl
@@ -0,0 +1,9 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:param name="variablelist.as.blocks" select="1"/>
+ <xsl:param name="body.start.indent">0pt</xsl:param>
+ <xsl:param name="xref.with.number.and.title" select="'yes'"/>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label" select="1"/>
+</xsl:stylesheet>
diff --git a/manual/fix-qdf.1.in b/manual/fix-qdf.1.in
new file mode 100644
index 00000000..e1f7f8cb
--- /dev/null
+++ b/manual/fix-qdf.1.in
@@ -0,0 +1,18 @@
+\" This file is not processed by autoconf, but rather by build.mk in
+\" the manual directory.
+.TH FIX-QDF "1" "April 2008" "fix-qdf version @PACKAGE_VERSION@" "User Commands"
+.SH NAME
+fix-qdf \- repair PDF files in QDF form after editing
+.SH SYNOPSIS
+.B qpdf
+< \fIinfilename\fR > \fIoutfilename\fR
+.SH DESCRIPTION
+The fix-qdf program is part of the qpdf package.
+.PP
+The fix-qdf program reads a PDF file in QDF form and writes out
+the same file with stream lengths, cross-reference table entries, and
+object stream offset tables regenerated.
+.PP
+For details about fix-qdf and about PDF files in QDF mode, please see
+the qpdf manual, which can be found in @docdir@/qpdf-manual.html or
+@docdir@/qpdf-manual.pdf.
diff --git a/manual/html.xsl.in b/manual/html.xsl.in
new file mode 100644
index 00000000..e96f0583
--- /dev/null
+++ b/manual/html.xsl.in
@@ -0,0 +1,8 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ version="1.0">
+ <xsl:import href="@DOCBOOK_XHTML@"/>
+ <xsl:import href="common.xsl"/>
+ <xsl:param name="html.stylesheet">stylesheet.css</xsl:param>
+</xsl:stylesheet>
diff --git a/manual/print.xsl.in b/manual/print.xsl.in
new file mode 100644
index 00000000..d712cb35
--- /dev/null
+++ b/manual/print.xsl.in
@@ -0,0 +1,69 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ version="1.0">
+ <xsl:import href="@DOCBOOK_FO@"/>
+ <xsl:import href="common.xsl"/>
+ <xsl:param name="local.l10n.xml" select="document('')"/>
+ <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+ <l:l10n language="en">
+ <l:context name="xref">
+ <l:template name="page.citation" text=", page %p"/>
+ </l:context>
+ </l:l10n>
+ </l:i18n>
+ <!-- This should give us bookmarks, but it's broken for fop -->
+ <!-- 0.94 and stylesheets 1.73.2. -->
+<!--
+ <xsl:param name="fop.extensions" select="1"/>
+-->
+ <xsl:param name="paper.type" select="'USLetter'"/>
+ <xsl:param name="insert.xref.page.number" select="'yes'"/>
+<!--
+ <xsl:param name="admon.graphics.path">
+ /tmp/z/docbook-xsl-1.73.2/images/
+ </xsl:param>
+ <xsl:param name="admon.graphics" select="1"/>
+-->
+ <xsl:param name="shade.verbatim" select="1"/>
+ <xsl:attribute-set name="shade.verbatim.style">
+ <xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
+ <xsl:attribute name="border-width">0.5pt</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-color">#575757</xsl:attribute>
+ <xsl:attribute name="padding">3pt</xsl:attribute>
+ </xsl:attribute-set>
+ <xsl:attribute-set name="xref.properties">
+ <xsl:attribute name="color">#00c</xsl:attribute>
+ </xsl:attribute-set>
+ <fo:page-sequence language="en"/>
+ <fo:block hyphenate="true"/>
+
+ <xsl:template match="property">
+ <xsl:call-template name="inline.boldseq"/>
+ </xsl:template>
+ <xsl:template match="classname">
+ <fo:inline font-family="sans-serif" font-weight="bold">
+ <xsl:call-template name="inline.italicseq"/>
+ </fo:inline>
+ </xsl:template>
+ <xsl:template match="filename">
+ <xsl:call-template name="inline.italicseq"/>
+ </xsl:template>
+ <xsl:template match="varname">
+ <xsl:call-template name="inline.italicseq"/>
+ </xsl:template>
+ <xsl:template match="function">
+ <xsl:call-template name="inline.italicseq"/>
+ </xsl:template>
+ <xsl:template match="envar">
+ <xsl:call-template name="inline.italicseq"/>
+ </xsl:template>
+ <xsl:template match="type">
+ <xsl:call-template name="inline.monoseq"/>
+ </xsl:template>
+ <xsl:template match="option">
+ <xsl:call-template name="inline.boldseq"/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml
new file mode 100644
index 00000000..9257f26f
--- /dev/null
+++ b/manual/qpdf-manual.xml
@@ -0,0 +1,1964 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE book [
+<!ENTITY ldquo "&#x201C;">
+<!ENTITY rdquo "&#x201D;">
+<!ENTITY mdash "&#x2014;">
+<!ENTITY ndash "&#x2013;">
+<!ENTITY nbsp "&#xA0;">
+<!ENTITY swversion "2.0">
+<!ENTITY lastreleased "April 29, 2008">
+]>
+<book>
+ <bookinfo>
+ <title>QPDF Manual</title>
+ <subtitle>For QPDF Version &swversion;, &lastreleased;</subtitle>
+ <author>
+ <firstname>Jay</firstname><surname>Berkenbilt</surname>
+ </author>
+ <copyright>
+ <year>2005&ndash;2008</year>
+ <holder>Jay Berkenbilt</holder>
+ </copyright>
+ </bookinfo>
+ <preface id="acknowledgments">
+ <title>General Information</title>
+ <para>
+ QPDF is a program that does structural, content-preserving
+ transformations on PDF files. QPDF's website is located at <ulink
+ url="http://qpdf.qbilt.org/">http://qpdf.qbilt.org/</ulink>.
+ </para>
+ <para>
+ QPDF has been released under the terms of <ulink
+ url="http://www.opensource.org/licenses/artistic-license-2.0.php">Version
+ 2.0 of the Artistic License</ulink>, a copy of which appears in the
+ file <filename>Artistic-2.0</filename> in the source distribution.
+ </para>
+ <para>
+ QPDF was originally created in 2001 and modified periodically
+ between 2001 and 2005 during my employment at <ulink
+ url="http://www.apexcovantage.com">Apex CoVantage</ulink>. Upon my
+ departure from Apex, the company graciously allowed me to take
+ ownership of the software and continue maintaining as an open
+ source project, a decision for which I am very grateful. I have
+ made considerable enhancements to it since that time. I feel
+ fortunate to have worked for people who would make such a decision.
+ This work would not have been possible without their support.
+ </para>
+ </preface>
+ <chapter id="ref.overview">
+ <title>What is QPDF?</title>
+ <para>
+ QPDF is a program that does structural, content-preserving
+ transformations on PDF files. It could have been called something
+ like <emphasis>pdf-to-pdf</emphasis>. It also provides many useful
+ capabilities to developers of PDF-producing software or for people
+ who just want to look at the innards of a PDF file to learn more
+ about how they work.
+ </para>
+ <para>
+ QPDF is <emphasis>not</emphasis> a PDF content creation library, a
+ PDF viewer, or a program capable of converting PDF into other
+ formats. In particular, QPDF knows nothing about the semantics of
+ PDF content streams. If you are looking for something that can do
+ that, you should look elsewhere. However, once you have a valid
+ PDF file, QPDF can be used to transform that file in ways perhaps
+ your original PDF creation can't handle. For example, programs
+ generate simple PDF files but can't password-protect them,
+ web-optimize them, or perform other transformations of that type.
+ </para>
+ </chapter>
+ <chapter id="ref.installing">
+ <title>Building and Installing QPDF</title>
+ <para>
+ This chapter describes how to build and install qpdf. Please see
+ also the <filename>README</filename> and
+ <filename>INSTALL</filename> files in the source distribution.
+ </para>
+ <sect1 id="ref.prerequisites">
+ <title>System Requirements</title>
+ <para>
+ The qpdf package has relatively few external dependencies. In
+ order to build qpdf, the following packages are required:
+ <itemizedlist>
+ <listitem>
+ <para>
+ zlib: <ulink url="http://www.zlib.net/">http://www.zlib.net/</ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ pcre: <ulink url="http://www.pcre.org/">http://www.pcre.org/</ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ gnu make 3.81 or newer: <ulink url="http://www.gnu.org/software/make">http://www.gnu.org/software/make</ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ perl version 5.8 or newer:
+ <ulink url="http://www.perl.org/">http://www.perl.org/</ulink>;
+ required for <command>fix-qdf</command> and the test suite.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ GNU diffutils (any version): <ulink
+ url="http://www.gnu.org/software/diffutils/">http://www.gnu.org/software/diffutils/</ulink>
+ is required to run the test suite. Note that this is the
+ version of diff present on virtually all GNU/Linux systems.
+ This is required because the test suite uses <command>diff
+ -u</command>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Part of qpdf's test suite does comparisons of the contents PDF
+ files by converting them images and comparing the images. You can
+ optionally disable this part of the test suite by running
+ <command>configure</command> with the
+ <option>--disable-test-compare-images</option> flag. If you leave
+ this enabled, the following additional requirements are required
+ by the test suite. Note that in no case are these items required
+ to use qpdf.
+ <itemizedlist>
+ <listitem>
+ <para>
+ libtiff: <ulink url="http://www.remotesensing.org/libtiff/">http://www.remotesensing.org/libtiff/</ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ GhostScript version 8.60 or newer: <ulink
+ url="http://pages.cs.wisc.edu/~ghost/">http://pages.cs.wisc.edu/~ghost/</ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ This option is primarily intended for use by packagers of qpdf so
+ that they can avoid having the qpdf packages depend on tiff and
+ ghostscript software.
+ </para>
+ <para>
+ If Adobe Reader is installed as <command>acroread</command>, some
+ additional test cases will be enabled. These test cases simply
+ verify that Adobe Reader can open the files that qpdf creates.
+ They require version 8.0 or newer to pass. However, in order to
+ avoid having qpdf depend on non-free (as in liberty) software, the
+ test suite will still pass without Adobe reader, and the test
+ suite still exercises the full functionality of the software.
+ </para>
+ <para>
+ Pre-built documentation is distributed with qpdf, so you should
+ generally not need to rebuild the documentation. In order to
+ build the documentation from its docbook sources, you need the
+ docbook XML style sheets (<ulink
+ url="http://downloads.sourceforge.net/docbook/">http://downloads.sourceforge.net/docbook/</ulink>).
+ To build the PDF version of the documentation, you need Apache fop
+ (<ulink
+ url="http://xml.apache.org/fop/">http://xml.apache.org/fop/</ulink>)
+ version 0.94 of higher.
+ </para>
+ </sect1>
+ <sect1 id="ref.building">
+ <title>Build Instructions</title>
+ <para>
+ Building qpdf on UNIX is generally just a matter of running
+
+ <programlisting>./configure
+make
+</programlisting>
+ You can also run <command>make check</command> to run the test
+ suite and <command>make install</command> to install. Please run
+ <command>./configure --help</command> for options on what can be
+ configured. You can also set the value of
+ <varname>DESTDIR</varname> during installation to install to a
+ temporary location, as is common with many open source packages.
+ Please see also the <filename>README</filename> and
+ <filename>INSTALL</filename> files in the source distribution.
+ </para>
+ <para>
+ There is currently no support for building qpdf on Windows. The
+ code is reasonably portable, however, and making it work on
+ Windows would probably be reasonably straightforward. A
+ significant amount of the code in QPDF has been known to work on
+ Windows in the past.
+ </para>
+ <para>
+ There are some other things you can do with the build. Although
+ qpdf uses <application>autoconf</application>, it does not use
+ <application>automake</application> but instead uses a
+ hand-crafted non-recursive Makefile that requires gnu make. If
+ you're really interested, please read the comments in the
+ top-level <filename>Makefile</filename>.
+ </para>
+ </sect1>
+ </chapter>
+ <chapter id="ref.using">
+ <title>Running QPDF</title>
+ <para>
+ This chapter describes how to run the qpdf program from the command
+ line.
+ </para>
+ <sect1 id="ref.invocation">
+ <title>Basic Invocation</title>
+ <para>
+ When running qpdf, the basic invocation is as follows:
+
+ <programlisting><command>qpdf</command><option> [ <replaceable>options</replaceable> ] <replaceable>infilename</replaceable> [ <replaceable>outfilename</replaceable> ]</option>
+</programlisting>
+ This converts PDF file <option>infilename</option> to PDF file
+ <option>outfilename</option>. The output file is functionally
+ identical to the input file but may have been structurally
+ reorganized. Also, orphaned objects will be removed from the
+ file. Many transformations are available as controlled by the
+ options below.
+ </para>
+ <para>
+ <option>outfilename</option> does not have to be seekable, even
+ when generating linearized files. Specifying
+ &ldquo;<option>-</option>&rdquo; as <option>outfilename</option>
+ means to write to standard output.
+ </para>
+ <para>
+ Most options require an output file, but some testing or
+ inspection commands do not. These are specifically noted.
+ </para>
+ </sect1>
+ <sect1 id="ref.basic-options">
+ <title>Basic Options</title>
+ <para>
+ The following options are the most common ones and perform
+ commonly needed transformations.
+ <variablelist>
+ <varlistentry>
+ <term><option>--password=password</option></term>
+ <listitem>
+ <para>
+ Specifies a password for accessing encrypted files.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--linearize</option></term>
+ <listitem>
+ <para>
+ Causes generation of a linearized (web optimized) output file.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--encrypt options --</option></term>
+ <listitem>
+ <para>
+ Causes generation an encrypted output file. Please see <xref
+ linkend="ref.encryption-options"/> for details on how to
+ specify encryption parameters.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--decrypt</option></term>
+ <listitem>
+ <para>
+ Removes any encryption on the file. A password must be
+ supplied if the file is password protected.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ Password-protected files may be opened by specifying a password.
+ By default, qpdf will preserve any encryption data associated with
+ a file. If <option>--decrypt</option> is specified, qpdf will
+ attempt to remove any encryption information. If
+ <option>--encrypt</option> is specified, qpdf will replace the
+ document's encryption parameters with whatever is specified.
+ </para>
+ <para>
+ Note that qpdf does not obey encryption restrictions already
+ imposed on the file. Doing so would be meaningless since qpdf can
+ be used to remove encryption from the file entirely. This
+ functionality is not intended to be used for bypassing copyright
+ restrictions or other restrictions placed on files by their
+ producers.
+ </para>
+ </sect1>
+ <sect1 id="ref.encryption-options">
+ <title>Encryption Options</title>
+ <para>
+ To change the encryption parameters of a file, use the --encrypt
+ flag. The syntax is
+
+ <programlisting><option>--encrypt <replaceable>user-password</replaceable> <replaceable>owner-password</replaceable> <replaceable>key-length</replaceable> [ <replaceable>restrictions</replaceable> ] --</option>
+</programlisting>
+ Note that &ldquo;<option>--</option>&rdquo; terminates parsing of
+ encryption flags and must be present even if no restrictions are
+ present.
+ </para>
+ <para>
+ Either or both of the user password and the owner password may be
+ empty strings.
+ </para>
+ <para>
+ The value for
+ <option><replaceable>key-length</replaceable></option> may be 40
+ or 128. The restriction flags are dependent upon key length.
+ When no additional restrictions are given, the default is to be
+ fully permissive.
+ </para>
+ <para>
+ If <option><replaceable>key-length</replaceable></option> is 40,
+ the following restriction options are available:
+ <variablelist>
+ <varlistentry>
+ <term><option>--print=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether or not to allow printing.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--modify=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether or not to allow document modification.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--extract=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether or not to allow text/image extraction.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--annotate=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether or not to allow comments and form fill-in
+ and signing.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ If <option><replaceable>key-length</replaceable></option> is 128,
+ the following restriction options are available:
+ <variablelist>
+ <varlistentry>
+ <term><option>--accessibility=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether or not to allow accessibility to visually
+ impaired.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--extract=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether or not to allow text/graphic extraction.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--print=<replaceable>print-opt</replaceable></option></term>
+ <listitem>
+ <para>
+ Controls printing access.
+ <option><replaceable>print-opt</replaceable></option> may be
+ one of the following:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <option>full</option>: allow full printing
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>low</option>: allow low-resolution printing only
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>none</option>: disallow printing
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--modify=<replaceable>modify-opt</replaceable></option></term>
+ <listitem>
+ <para>
+ Controls modify access.
+ <option><replaceable>modify-opt</replaceable></option> may be
+ one of the following:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <option>all</option>: allow full document modification
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>annotate</option>: allow comment authoring and form operations
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>form</option>: allow form field fill-in and signing
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>assembly</option>: allow document assembly only
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>none</option>: allow no modifications
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ The default for each permission option is to be fully permissive.
+ </para>
+ </sect1>
+ <sect1 id="ref.advanced-transformation">
+ <title>Advanced Transformation Options</title>
+ <para>
+ These transformation options control fine points of how qpdf
+ creates the output file. Mostly these are of use only to people
+ who are very familiar with the PDF file format or who are PDF
+ developers. The following options are available:
+ <variablelist>
+ <varlistentry>
+ <term><option>--stream-data=<replaceable>option</replaceable></option></term>
+ <listitem>
+ <para>
+ Controls transformation of stream data. The value of
+ <option><replaceable>option</replaceable></option> may be one
+ of the following:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <option>compress</option>: recompress stream data when
+ possible (default)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>preserve</option>: leave all stream data as is
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>uncompress</option>: uncompress stream data when
+ possible
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--normalize-content=[yn]</option></term>
+ <listitem>
+ <para>
+ Enables or disables normalization of content streams.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--suppress-recovery</option></term>
+ <listitem>
+ <para>
+ Prevents qpdf from attempting to recover damaged files.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--object-streams=<replaceable>mode</replaceable></option></term>
+ <listitem>
+ <para>
+ Controls handing of object streams. The value of
+ <option><replaceable>mode</replaceable></option> may be one of
+ the following:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <option>preserve</option>: preserve original object streams
+ (default)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>disable</option>: don't write any object streams
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <option>generate</option>: use object streams wherever
+ possible
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--ignore-xref-streams</option></term>
+ <listitem>
+ <para>
+ Tells qpdf to ignore any cross-reference streams.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--qdf</option></term>
+ <listitem>
+ <para>
+ Turns on QDF mode. For additional information on QDF, please
+ see <xref linkend="ref.qdf"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ By default, when a stream is encoded using non-lossy filters that
+ qpdf understands and is not already compressed using a good
+ compression scheme, qpdf will uncompress and recompress streams.
+ Assuming proper filter implements, this is safe and generally
+ results in smaller files. This behavior may also be explicitly
+ requested with <option>--stream-data=compress</option>.
+ </para>
+ <para>
+ When <option>--stream-data=preserve</option> is specified, qpdf
+ will never attempt to change the filtering of any stream data.
+ </para>
+ <para>
+ When <option>--stream-data=uncompress</option> is specified, qpdf
+ will attempt to remove any non-lossy filters that it supports.
+ This includes <literal>/FlateDecode</literal>,
+ <literal>/LZWDecode</literal>, <literal>/ASCII85Decode</literal>,
+ and <literal>/ASCIIHexDecode</literal>. This can be very useful
+ for inspecting the contents of various streams.
+ </para>
+ <para>
+ When <option>--normalize-content=y</option> is specified, qpdf
+ will attempt to normalize whitespace and newlines in page content
+ streams. This is generally safe but could, in some cases, cause
+ damage to the content streams. This option is intended for people
+ who wish to study PDF content streams or to debug PDF content.
+ You should not use this for &ldquo;production&rdquo; PDF files.
+ </para>
+ <para>
+ Ordinarily, qpdf will attempt to recover from certain types of
+ errors in PDF files. These include errors in the cross-reference
+ table, certain types of object numbering errors, and certain types
+ of stream length errors. Sometimes, qpdf may think it has
+ recovered but may not have actually recovered, so care should be
+ taken when using this option as some data loss is possible. The
+ <option>--suppress-recovery</option> option will prevent qpdf from
+ attempting recovery. In this case, it will fail on the first
+ error that it encounters.
+ </para>
+ <para>
+ Object streams, also known as compressed objects, were introduced
+ into the PDF specification at version 1.5, corresponding to
+ Acrobat 6. Some older PDF viewers may not support files with
+ object streams. qpdf can be used to transform files with object
+ streams to files without object streams or vice versa. As
+ mentioned above, there are three object stream modes:
+ <option>preserve</option>, <option>disable</option>, and
+ <option>generate</option>.
+ </para>
+ <para>
+ In <option>preserve</option> mode, the relationship to objects and
+ the streams that contain them is preserved from the original file.
+ In <option>disable</option> mode, all objects are written as
+ regular, uncompressed objects. The resulting file should be
+ readable by older PDF viewers. (Of course, the content of the
+ files may include features not supported by older viewers, but at
+ least the structure will be supported.) In
+ <option>generate</option> mode, qpdf will create its own object
+ streams. This will usually result in more compact PDF files,
+ though they may not be readable by older viewers. In this mode,
+ qpdf will also make sure the PDF version number in the header is
+ at least 1.5.
+ </para>
+ <para>
+ Ordinarily, qpdf reads cross-reference streams when they are
+ present in a PDF file. If <option>--ignore-xref-streams</option>
+ is specified, qpdf will ignore any cross-reference streams for
+ hybrid PDF files. The purpose of hybrid files is to make some
+ content available to viewers that are not aware of cross-reference
+ streams. It is almost never desirable to ignore them. The only
+ time when you might want to use this feature is if you are testing
+ creation of hybrid PDF files and wish to see how a PDF consumer
+ that doesn't understand object and cross-reference streams would
+ interpret such a file.
+ </para>
+ <para>
+ The <option>--qdf</option> flag turns on QDF mode, which changes
+ some of the defaults described above. Specifically, in QDF mode,
+ by default, stream data is uncompressed, content streams are
+ normalized, and encryption is removed. These defaults can still
+ be overridden by specifying the appropriate options as described
+ above. Additionally, in QDF mode, stream lengths are stored as
+ indirect objects, objects are laid out in a less efficient but
+ more readable fashion, and the documents are interspersed with
+ comments that make it easier for the user to find things and also
+ make it possible for <command>fix-qdf</command> to work properly.
+ QDF mode is intended for people, mostly developers, who wish to
+ inspect or modify PDF files in a text editor. For details, please
+ see <xref linkend="ref.qdf"/>.
+ </para>
+ </sect1>
+ <sect1 id="ref.testing-options">
+ <title>Testing, Inspection, and Debugging Options</title>
+ <para>
+ These options can be useful for digging into PDF files or for use
+ in automated test suites for software that uses the qpdf library.
+ When any of the options in this section are specified, no output
+ file should be given. The following options are available:
+ <variablelist>
+ <varlistentry>
+ <term><option>--static-id</option></term>
+ <listitem>
+ <para>
+ Causes generation of a fixed value for /ID. This is intended
+ for testing only. Never use it for production files.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-show-encryption</option></term>
+ <listitem>
+ <para>
+ Shows document encryption parameters. Also shows the
+ document's user password if the owner password is given.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-check-linearization</option></term>
+ <listitem>
+ <para>
+ Checks file integrity and linearization status.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-show-linearization</option></term>
+ <listitem>
+ <para>
+ Checks and displays all data in the linearization hint tables.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-show-xref</option></term>
+ <listitem>
+ <para>
+ Shows the contents of the cross-reference table in a
+ human-readable form. This is especially useful for files with
+ cross-reference streams which are stored in a binary format.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-show-object=obj[,gen]</option></term>
+ <listitem>
+ <para>
+ Show the contents of the given object. This is especially
+ useful for inspecting objects that are inside of object
+ streams (also known as &ldquo;compressed objects&rdquo;).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-raw-stream-data</option></term>
+ <listitem>
+ <para>
+ When used along with the <option>--show-object</option>
+ option, if the object is a stream, shows the raw stream data
+ instead of object's contents.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-filtered-stream-data</option></term>
+ <listitem>
+ <para>
+ When used along with the <option>--show-object</option>
+ option, if the object is a stream, shows the filtered stream
+ data instead of object's contents. If the stream is filtered
+ using filters that qpdf does not support, an error will be
+ issued.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-show-pages</option></term>
+ <listitem>
+ <para>
+ Shows the object and generation number for each page
+ dictionary object and for each content stream associated with
+ the page. Having this information makes it more convenient to
+ inspect objects from a particular page.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-with-images</option></term>
+ <listitem>
+ <para>
+ When used along with <option>--show-pages</option>, also shows
+ the object and generation numbers for the image objects on
+ each page. (At present, information about images in shared
+ resource dictionaries are not output by this command. This is
+ discussed in a comment in the source code.)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-check</option></term>
+ <listitem>
+ <para>
+ Checks file structure and well as encryption and
+ linearization. A file for which <option>--check</option>
+ reports no errors may still have errors in stream data but
+ should otherwise be otherwise structurally sound.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ The <option>--raw-stream-data</option> and
+ <option>--filtered-stream-data</option> options are ignored unless
+ <option>--show-object</option> is given. Either of these options
+ will cause the stream data to be written to standard output. In
+ order to avoid commingling of stream data with other output, it is
+ recommend that these objects not be combined with other
+ test/inspection options.
+ </para>
+ <para>
+ If <option>--filtered-stream-data</option> is given and
+ <option>--normalize-content=y</option> is also given, qpdf will
+ attempt to normalize the stream data as if it is a page content
+ stream. This attempt will be made even if it is not a page
+ content stream, in which case it will produce unusuable results.
+ </para>
+ </sect1>
+ </chapter>
+ <chapter id="ref.qdf">
+ <title>QDF Mode</title>
+ <para>
+ In QDF mode, qpdf creates PDF files in what we call <firstterm>QDF
+ form</firstterm>. A PDF file in QDF form, sometimes called a QDF
+ file, is a completely valid PDF file that has
+ <literal>%QDF-1.0</literal> as its third line (after the pdf header
+ and binary characters) and has certain other characteristics. The
+ purpose of QDF form is to make it possible to edit PDF files, with
+ some restrictions, in an ordinary text editor. This can be very
+ useful for experimenting with different PDF constructs or for
+ making one-off edits to PDF files (though there are other reasons
+ why this may not always work).
+ </para>
+ <para>
+ It is ordinarily very difficult to edit PDF files in a text editor
+ for two reasons: most meaningful data in PDF files is compressed,
+ and PDF files are full of offset and length information that makes
+ it hard to add or remove data. A QDF file is organized in a manner
+ such that, if edits are kept within certain constraints, the
+ <command>fix-qdf</command> program, distributed with qpdf, is able
+ to restore edited files to a correct state. The
+ <command>fix-qdf</command> program takes no command-line
+ arguments. It reads a possibly edited QDF file from standard input
+ and writes a repaired file to standard output.
+ </para>
+ <para>
+ The following attributes characterize a QDF file:
+ <itemizedlist>
+ <listitem>
+ <para>
+ All objects appear in numerical order in the PDF file, including
+ when objects appear in object streams.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Objects are printed in an easy-to-read format, and all line
+ endings are normalized to UNIX line endings.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Unless specifically overridden, streams appear uncompressed
+ (when qpdf supports the filters and they are compressed with a
+ non-lossy compression scheme), and most content streams are
+ normalized (line endings are converted to just a UNIX-style
+ linefeeds).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ All streams lengths are represented as indirect objects, and the
+ stream length object is always the next object after the stream.
+ If the stream data does not end with a newline, an extra newline
+ is inserted, and a special comment appears after the stream
+ indicating that this has been done.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the PDF file contains object streams, if object stream
+ <emphasis>n</emphasis> contains <emphasis>k</emphasis> objects,
+ those objects are numbered from <emphasis>n+1</emphasis> through
+ <emphasis>n+k</emphasis>, and the object number/offset pairs
+ appear on a separate line for each object. Additionally, each
+ object in the object stream is preceded by a comment indicating
+ its object number and index. This makes it very easy to find
+ objects in object streams.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ All beginnings of objects, <literal>stream</literal> tokens,
+ <literal>endstream</literal> tokens, and
+ <literal>endobj</literal> tokens appear on lines by themselves.
+ A blank line follows every <literal>endobj</literal> token.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If there is a cross-reference stream, it is unfiltered.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Page dictionaries and page content streams are marked with
+ special comments that make them easy to find.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ When editing a QDF file, any edits can be made as long as the above
+ constraints are maintained. This means that you can freely edit a
+ page's content without worrying about messing up the QDF file. It
+ is also possible to add new objects so long as those objects are
+ added after the last object in the file or subsequent objects are
+ renumbered. If a QDF file has object streams in it, you can always
+ add the new objects before the xref stream and then change the
+ number of the xref stream, since nothing generally ever references
+ it by number.
+ </para>
+ <para>
+ It is not generally practical to remove objects from QDF files
+ without messing up object numbering, but if you remove all
+ references to an object, you can run qpdf on the file (after
+ running <command>fix-qdf</command>), and qpdf will omit the
+ now-orphaned object.
+ </para>
+ <para>
+ When <command>fix-qdf</command> is run, it goes through the file
+ and recomputes the following parts of the file:
+ <itemizedlist>
+ <listitem>
+ <para>
+ the <literal>/N</literal>, <literal>/W</literal>, and
+ <literal>/First</literal> keys of all object stream dictionaries
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the pairs of numbers representing object numbers and offsets of
+ objects in object streams
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all stream lengths
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the cross-reference table or cross-reference stream
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the offset to the cross-reference table or cross-reference
+ stream following the <literal>startxref</literal> token
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </chapter>
+ <chapter id="ref.using-library">
+ <title>Using the QPDF Library</title>
+ <para>
+ The source tree for the qpdf package has an
+ <filename>examples</filename> directory that contains a few
+ example programs. The <filename>qpdf/qpdf.cc</filename> source
+ file also serves as a useful example since it exercises almost all
+ of the qpdf library's public interface. The best source of
+ documentation on the library itself is reading comments in
+ <filename>include/qpdf/QPDF.hh</filename>,
+ <filename>include/qpdf/QDFWriter.hh</filename>, and
+ <filename>include/qpdf/QPDFObjectHandle.hh</filename>.
+ </para>
+ <para>
+ All header files are installed in the <filename>include/qpdf</filename> directory. It
+ is recommend that you use <literal>#include
+ &lt;qpdf/QPDF.hh&gt;</literal> rather than adding
+ <filename>include/qpdf</filename> to your include path.
+ </para>
+ <para>
+ When linking against the qpdf library, you may also need to
+ specify <literal>-lpcre -lz</literal> on your link command. If
+ your system understands how to read libtool
+ <filename>.la</filename> files, this may not be necessary.
+ </para>
+ </chapter>
+ <chapter id="ref.design">
+ <title>Design and Library Notes</title>
+ <sect1 id="ref.design.intro">
+ <title>Introduction</title>
+ <para>
+ This section was written prior to the implementation of the qpdf
+ package and was subsequently modified to reflect the
+ implementation. In some cases, for purposes of explanation, it
+ may differ slightly from the actual implementation. As always,
+ the source code and test suite are authoritative. Even if there
+ are some errors, this document should serve as a road map to
+ understanding how this code works.
+ </para>
+ <para>
+ In general, one should adhere strictly to a specification when
+ writing but be liberal in reading. This way, the product of our
+ software will be accepted by the widest range of other programs,
+ and we will accept the widest range of input files. This library
+ attempts to conform to that philosophy whenever possible but also
+ aims to provide strict checking for people who want to validate
+ PDF files. If you don't want to see warnings and are trying to
+ write something that is tolerant, you can call
+ <literal>setSuppressWarnings(true)</literal>. If you want to fail
+ on the first error, you can call
+ <literal>setAttemptRecovery(false)</literal>. The default
+ behavior is to generating warnings for recoverable problems. Note
+ that recovery will not always produce the desired results even if
+ it is able to get through the file. Unlike most other PDF files
+ that produce generic warnings such as &ldquo;This file is
+ damaged,&rdquo;, qpdf generally issues a detailed error message
+ that would be most useful to a PDF developer. This is by design
+ as there seems to be a shortage of PDF validation tools out
+ there. (This was, in fact, one of the major motivations behind
+ the initial creation of qpdf.)
+ </para>
+ </sect1>
+ <sect1 id="ref.design-goals">
+ <title>Design Goals</title>
+ <para>
+ The QPDF package includes support for reading and rewriting PDF
+ files. It aims to hide from the user details involving object
+ locations, modified (appended) PDF files, the
+ directness/indirectness of objects, and stream filters including
+ encryption. It does not aim to hide knowledge of the object
+ hierarchy or content stream contents. Put another way, a user of
+ the qpdf library is expected to have knowledge about how PDF files
+ work, but is not expected to have to keep track of bookkeeping
+ details such as file positions.
+ </para>
+ <para>
+ A user of the library never has to care whether an object is
+ direct or indirect. All access to objects deals with this
+ transparently. All memory management details are also handled by
+ the library.
+ </para>
+ <para>
+ The <classname>PointerHolder</classname> object is used internally
+ by the library to deal with memory management. This is basically
+ a smart pointer object very similar in spirit to the Boost
+ library's <classname>shared_ptr</classname> object, but predating
+ it by several years. This library also makes use of a technique
+ for giving fine-grained access to methods in one class to other
+ classes by using public subclasses with friends and only private
+ members that in turn call private methods of the containing class.
+ See <classname>QPDFObjectHandle::Factory</classname> as an
+ example.
+ </para>
+ <para>
+ The top-level qpdf class is <classname>QPDF</classname>. A
+ <classname>QPDF</classname> object represents a PDF file. The
+ library provides methods for both accessing and mutating PDF
+ files.
+ </para>
+ <para>
+ <classname>QPDFObject</classname> is the basic PDF Object class.
+ It is an abstract base class from which are derived classes for
+ each type of PDF object. Clients do not interact with Objects
+ directly but instead interact with
+ <classname>QPDFObjectHandle</classname>.
+ </para>
+ <para>
+ <classname>QPDFObjectHandle</classname> contains
+ <classname>PointerHolder&lt;QPDFObject&gt;</classname> and
+ includes accessor methods that are type-safe proxies to the
+ methods of the derived object classes as well as methods for
+ querying object types. They can be passed around by value,
+ copied, stored in containers, etc. with very low overhead.
+ Instances of <classname>QPDFObjectHandle</classname> always
+ contain a reference back to the <classname>QPDF</classname> object
+ from which they were created. A
+ <classname>QPDFObjectHandle</classname> may be direct or indirect.
+ If indirect, the <classname>QPDFObject</classname> the
+ <classname>PointerHolder</classname> initially points to is a null
+ pointer. In this case, the first attempt to access the underlying
+ <classname>QPDFObject</classname> will result in the
+ <classname>QPDFObject</classname> being resolved via a call to the
+ referenced <classname>QPDF</classname> instance. This makes it
+ essentially impossible to make coding errors in which certain
+ things will work for some PDF files and not for others based on
+ which objects are direct and which objects are indirect.
+ </para>
+ <para>
+ There is no public interface for creating instances of
+ QPDFObjectHandle. They can be created only inside the QPDF
+ library. This is generally done through a call to the private
+ method <function>QPDF::readObject</function> which uses
+ <classname>QPDFTokenizer</classname> to read an indirect object at
+ a given file position and return a
+ <classname>QPDFObjectHandle</classname> that encapsulates it.
+ There are also internal methods to create fabricated indirect
+ objects from existing direct objects or to change an indirect
+ object into a direct object, though these steps are not performed
+ except to support rewriting.
+ </para>
+ <para>
+ When the <classname>QPDF</classname> class creates a new object,
+ it dynamically allocates the appropriate type of
+ <classname>QPDFObject</classname> and immediately hands the
+ pointer to an instance of <classname>QPDFObjectHandle</classname>.
+ The parser reads a token from the current file position. If the
+ token is a not either a dictionary or array opener, an object is
+ immediately constructed from the single token and the parser
+ returns. Otherwise, the parser is invoked recursively in a
+ special mode in which it accumulates objects until it finds a
+ balancing closer. During this process, the
+ &ldquo;<literal>R</literal>&rdquo; keyword is recognized and an
+ indirect <classname>QPDFObjectHandle</classname> may be
+ constructed.
+ </para>
+ <para>
+ The <function>QPDF::resolve()</function> method, which is used to
+ resolve an indirect object, may be invoked from the
+ <classname>QPDFObjectHandle</classname> class. It first checks a
+ cache to see whether this object has already been read. If not,
+ it reads the object from the PDF file and caches it. It the
+ returns the resulting <classname>QPDFObjectHandle</classname>.
+ The calling object handle then replaces its
+ <classname>PointerHolder&lt;QDFObject&gt;</classname> with the one
+ from the newly returned <classname>QPDFObjectHandle</classname>.
+ In this way, only a single copy of any direct object need exist
+ and clients can access objects transparently without knowing
+ caring whether they are direct or indirect objects. Additionally,
+ no object is ever read from the file more than once. That means
+ that only the portions of the PDF file that are actually needed
+ are ever read from the input file, thus allowing the qpdf package
+ to take advantage of this important design goal of PDF files.
+ </para>
+ <para>
+ If the requested object is inside of an object stream, the object
+ stream itself is first read into memory. Then the tokenizer reads
+ objects from the memory stream based on the offset information
+ stored in the stream. Those individual objects are cached, after
+ which the temporary buffer holding the object stream contents are
+ discarded. In this way, the first time an object in an object
+ stream is requested, all objects in the stream are cached.
+ </para>
+ <para>
+ An instance of <classname>QPDF</classname> is constructed by using
+ the class's default constructor. If desired, the
+ <classname>QPDF</classname> object may be configured with various
+ methods that change its default behavior. Then the
+ <function>QPDF::processFile()</function> method is passed the name
+ of a PDF file, which permanently associates the file with that
+ QPDF object. A password may also be given for access to
+ password-protected files. QPDF does not enforce encryption
+ parameters and will treat user and owner passwords equivalently.
+ Either password may be used to access an encrypted file.
+ <footnote>
+ <para>
+ As pointed out earlier, the intention is not for qpdf to be used
+ to bypass security on files. but as any open source PDF consumer
+ may be easily modified to bypass basic PDF document security,
+ and qpdf offers may transformations that can do this as well,
+ there seems to be little point in the added complexity of
+ conditionally enforcing document security.
+ </para>
+ </footnote>
+ <classname>QPDF</classname> will allow recovery of a user password
+ given an owner password. The input PDF file must be seekable.
+ (Output files written by <classname>QPDFWriter</classname> need
+ not be seekable, even when creating linearized files.) During
+ construction, <classname>QPDF</classname> validates the PDF file's
+ header, and then reads the cross reference tables and trailer
+ dictionaries. The <classname>QPDF</classname> class keeps only
+ the first trailer dictionary though it does read all of them so it
+ can check the <literal>/Prev</literal> key.
+ <classname>QPDF</classname> class users may request the root
+ object and the trailer dictionary specifically. The cross
+ reference table is kept private. Objects may then be requested by
+ number of by walking the object tree.
+ </para>
+ <para>
+ When a PDF file has a cross-reference stream instead of a
+ cross-reference table and trailer, requesting the document's
+ trailer dictionary returns the stream dictionary from the
+ cross-reference stream instead.
+ </para>
+ <para>
+ There are some convenience routines for very common operations
+ such as walking the page tree and returning a vector of all page
+ objects. For full details, please see the header file
+ <filename>QPDF.hh</filename>.
+ </para>
+ <para>
+ The following example should clarify how
+ <classname>QPDF</classname> processes a simple file.
+ <itemizedlist>
+ <listitem>
+ <para>
+ Client constructs <classname>QPDF</classname>
+ <varname>pdf</varname> and calls
+ <function>pdf.processFile("a.pdf");</function>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <classname>QPDF</classname> class checks the beginning of
+ <filename>a.pdf</filename> for
+ <literal>%!PDF-1.[0-9]+</literal>. It then reads the cross
+ reference table mentioned at the end of the file, ensuring that
+ it is looking before the last <literal>%%EOF</literal>. After
+ getting to <literal>trailer</literal> keyword, it invokes the
+ parser.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The parser sees &ldquo;<literal>&lt;&lt;</literal>&rdquo;, so
+ it calls itself recursively in dictionary creation mode.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In dictionary creation mode, the parser keeps accumulating
+ objects until it encounters
+ &ldquo;<literal>&gt;&gt;</literal>&rdquo;. Each object that is
+ read is pushed onto a stack. If
+ &ldquo;<literal>R</literal>&rdquo; is read, the last two
+ objects on the stack are inspected. If they are integers, they
+ are popped off the stack and their values are used to construct
+ an indirect object handle which is then pushed onto the stack.
+ When &ldquo;<literal>&gt;&gt;</literal>&rdquo; is finally read,
+ the stack is converted into a
+ <classname>QPDF_Dictionary</classname> which is placed in a
+ <classname>QPDFObjectHandle</classname> and returned.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The resulting dictionary is saved as the trailer dictionary.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <literal>/Prev</literal> key is searched. If present,
+ <classname>QPDF</classname> seeks to that point and repeats
+ except that the new trailer dictionary is not saved. If
+ <literal>/Prev</literal> is not present, the initial parsing
+ process is complete.
+ </para>
+ <para>
+ If there is an encryption dictionary, the document's encryption
+ parameters are initialized.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The client requests root object. The
+ <classname>QPDF</classname> class gets the value of root key
+ from trailer dictionary and returns it. It is an unresolved
+ indirect <classname>QPDFObjectHandle</classname>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The client requests the <literal>/Pages</literal> key from root
+ <classname>QPDFObjectHandle</classname>. The
+ <classname>QPDFObjectHandle</classname> notices that it is
+ indirect so it asks <classname>QPDF</classname> to resolve it.
+ <classname>QPDF</classname> looks in the object cache for an
+ object with the root dictionary's object ID and generation
+ number. Upon not seeing it, it checks the cross reference
+ table, gets the offset, and reads the object present at that
+ offset. It stores the result in the object cache and returns
+ the cached result. The calling
+ <classname>QPDFObjectHandle</classname> replaces its object
+ pointer with the one from the resolved
+ <classname>QPDFObjectHandle</classname>, verifies that it a
+ valid dictionary object, and returns the (unresolved indirect)
+ <classname>QPDFObject</classname> handle to the top of the
+ Pages hierarchy.
+ </para>
+ <para>
+ As the client continues to request objects, the same process is
+ followed for each new requested object.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect1>
+ <sect1 id="ref.encryption">
+ <title>Encryption</title>
+ <para>
+ Encryption is supported transparently by qpdf. When opening a PDF
+ file, if an encryption dictionary exists, the
+ <classname>QPDF</classname> object processes this dictionary using
+ the password (if any) provided. The primary decryption key is
+ computed and cached. No further access is made to the encryption
+ dictionary after that time. When an object is read from a file,
+ the object ID and generation of the object in which it is
+ contained is always known. Using this information along with the
+ stored encryption key, all stream and string objects are
+ transparently decrypted. Raw encrypted objects are never stored
+ in memory. This way, nothing in the library ever has to know or
+ care whether it is reading an encrypted file.
+ </para>
+ <para>
+ An interface is also provided for writing encrypted streams and
+ strings given an encryption key. This is used by
+ <classname>QPDFWriter</classname> when it rewrites encrypted
+ files.
+ </para>
+ </sect1>
+ <sect1 id="ref.rewriting">
+ <title>Writing PDF Files</title>
+ <para>
+ The qpdf library supports file writing of
+ <classname>QPDF</classname> objects to PDF files through the
+ <classname>QPDFWriter</classname> class. The
+ <classname>QPDFWriter</classname> class has two writing modes: one
+ for non-linearized files, and one for linearized files. See <xref
+ linkend="ref.linearization"/> for a description of linearization
+ is implemented. This section describes how we write
+ non-linearized files including the creation of QDF files (see
+ <xref linkend="ref.qdf"/>.
+ </para>
+ <para>
+ This outline was written prior to implementation and is not
+ exactly accurate, but it provides a correct &ldquo;notional&rdquo;
+ idea of how writing works. Look at the code in
+ <classname>QPDFWriter</classname> for exact details.
+ <itemizedlist>
+ <listitem>
+ <para>
+ Initialize state:
+ <itemizedlist>
+ <listitem>
+ <para>
+ next object number = 1
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ object queue = empty
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ renumber table: old object id/generation to new id/0 = empty
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ xref table: new id -> offset = empty
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Create a QPDF object from a file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Write header for new PDF file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Request the trailer dictionary.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ For each value that is an indirect object, grab the next object
+ number (via an operation that returns and increments the
+ number). Map object to new number in renumber table. Push
+ object onto queue.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ While there are more objects on the queue:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Pop queue.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Look up object's new number <emphasis>n</emphasis> in the
+ renumbering table.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Store current offset into xref table.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Write <literal><replaceable>n</replaceable> 0 obj</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If object is null, whether direct or indirect, write out
+ null, thus eliminating unresolvable indirect object
+ references.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the object is a stream stream, write stream contents,
+ piped through any filters as required, to a memory buffer.
+ Use this buffer to determine the stream length.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If object is not a stream, array, or dictionary, write out
+ its contents.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If object is an array or dictionary (including stream),
+ traverse its elements (for array) or values (for
+ dictionaries), handling recursive dictionaries and arrays,
+ looking for indirect objects. When an indirect object is
+ found, if it is not resolvable, ignore. (This case is
+ handled when writing it out.) Otherwise, look it up in the
+ renumbering table. If not found, grab the next available
+ object number, assign to the referenced object in the
+ renumbering table, and push the referenced object onto the
+ queue. As a special case, when writing out a stream
+ dictionary, replace length, filters, and decode parameters
+ as required.
+ </para>
+ <para>
+ Write out dictionary or array, replacing any unresolvable
+ indirect object references with null (pdf spec says
+ reference to non-existent object is legal and resolves to
+ null) and any resolvable ones with references to the
+ renumbered objects.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the object is a stream, write
+ <literal>stream\n</literal>, the stream contents (from the
+ memory buffer), and <literal>\nendstream\n</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ When done, write <literal>endobj</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Once we have finished the queue, all referenced objects will have
+ been written out and all deleted objects or unreferenced objects
+ will have been skipped. The new cross-reference table will
+ contain an offset for every new object number from 1 up to the
+ number of objects written. This can be used to write out a new
+ xref table. Finally we can write out the trailer dictionary with
+ appropriately computed /ID (see spec, 8.3, File Identifiers), the
+ cross reference table offset, and <literal>%%EOF</literal>.
+ </para>
+ </sect1>
+ <sect1 id="ref.filtered-streams">
+ <title>Filtered Streams</title>
+ <para>
+ Support for streams is implemented through the
+ <classname>Pipeline</classname> interface which was designed for
+ this package.
+ </para>
+ <para>
+ When reading streams, create a series of
+ <classname>Pipeline</classname> objects. The
+ <classname>Pipeline</classname> abstract base requires
+ implementation <function>write()</function> and
+ <function>finish()</function> and provides an implementation of
+ <function>getNext()</function>. Each pipeline object, upon
+ receiving data, does whatever it is going to do and then writes
+ the data (possibly modified) to its successor. Alternatively, a
+ pipeline may be an end-of-the-line pipeline that does something
+ like store its output to a file or a memory buffer ignoring a
+ successor. For additional details, look at
+ <filename>Pipeline.hh</filename>.
+ </para>
+ <para>
+ <classname>QPDF</classname> can read raw or filtered streams.
+ When reading a filtered stream, the <classname>QPDF</classname>
+ class creates a <classname>Pipeline</classname> object for one of
+ each appropriate filter object and chains them together. The last
+ filter should write to whatever type of output is required. The
+ <classname>QPDF</classname> class has an interface to write raw or
+ filtered stream contents to a given pipeline.
+ </para>
+ </sect1>
+ </chapter>
+ <chapter id="ref.linearization">
+ <title>Linearization</title>
+ <para>
+ This chapter describes how <classname>QPDF</classname> and
+ <classname>QPDFWriter</classname> implement creation and processing
+ of linearized PDFS.
+ </para>
+ <sect1 id="ref.linearization-strategy">
+ <title>Basic Strategy for Linearization</title>
+ <para>
+ To avoid the incestuous problem of having the qpdf library
+ validate its own linearized files, we have a special linearized
+ file checking mode which can be invoked via <command>qpdf
+ --check-linearization</command> (or <command>qpdf
+ --check</command>). This mode reads the linearization parameter
+ dictionary and the hint streams and validates that object
+ ordering, parameters, and hint stream contents are correct. The
+ validation code was first tested against linearized files created
+ by external tools (Acrobat and pdlin) and then used to validate
+ files created by <classname>QPDFWriter</classname> itself.
+ </para>
+ </sect1>
+ <sect1 id="ref.linearized.preparation">
+ <title>Preparing For Linearization</title>
+ <para>
+ Before creating a linearized PDF file from any other PDF file, the
+ PDF file must be altered such that all page attributes are
+ propagated down to the page level (and not inherited from parents
+ in the <literal>/Pages</literal> tree). We also have to know
+ which objects refer to which other objects, being concerned with
+ page boundaries and a few other cases. We refer to this part of
+ preparing the PDF file as <firstterm>optimization</firstterm>,
+ discussed in <xref linkend="ref.optimization"/>. Note the, in
+ this context, the term <firstterm>optimization</firstterm> is a
+ qpdf term, and the term <firstterm>linearization</firstterm> is a
+ term from the PDF specification. Do not be confused by the fact
+ that many applications refer to linearization as optimization or
+ web optimization.
+ </para>
+ <para>
+ When creating linearized PDF files from optimized PDF files, there
+ are really only a few issues that need to be dealt with:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Creation of hints tables
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Placing objects in the correct order
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Filling in offsets and byte sizes
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect1>
+ <sect1 id="ref.optimization">
+ <title>Optimization</title>
+ <para>
+ In order to perform various operations such as linearization and
+ splitting files into pages, it is necessary to know which objects
+ are referenced by which pages, page thumbnails, and root and
+ trailer dictionary keys. It is also necessary to ensure that all
+ page-level attributes appear directly at the page level and are
+ not inherited from parents in the pages tree.
+ </para>
+ <para>
+ We refer to the process of enforcing these constraints as
+ <firstterm>optimization</firstterm>. As mentioned above, note
+ that some applications refer to linearization as optimization.
+ Although this optimization was initially motivated by the need to
+ create linearized files, we are using these terms separately.
+ </para>
+ <para>
+ PDF file optimization is implemented in the
+ <filename>QPDF_optimization.cc</filename> source file. That file
+ is richly commented and serves as the primary reference for the
+ optimization process.
+ </para>
+ <para>
+ After optimization has been completed, the private member
+ variables <varname>obj_user_to_objects</varname> and
+ <varname>object_to_obj_users</varname> in
+ <classname>QPDF</classname> have been populated. Any object that
+ has more than one value in the
+ <varname>object_to_obj_users</varname> table is shared. Any
+ object that has exactly one value in the
+ <varname>object_to_obj_users</varname> table is private. To find
+ all the private objects in a page or a trailer or root dictionary
+ key, one merely has make this determination for each element in
+ the <varname>obj_user_to_objects</varname> table for the given
+ page or key.
+ </para>
+ <para>
+ Note that pages and thumbnails have different object user types,
+ so the above test on a page will not include objects referenced by
+ the page's thumbnail dictionary and nothing else.
+ </para>
+ </sect1>
+ <sect1 id="ref.linearization.writing">
+ <title>Writing Linearized Files</title>
+ <para>
+ We will create files with only primary hint streams. We will
+ never write overflow hint streams. (As of PDF version 1.4,
+ Acrobat doesn't either, and they are never necessary.) The hint
+ streams contain offset information to objects that point to where
+ they would be if the hint stream were not present. This means
+ that we have to calculate all object positions before we can
+ generate and write the hint table. This means that we have to
+ generate the file in two passes. To make this reliable,
+ <classname>QPDFWriter</classname> in linearization mode invokes
+ exactly the same code twice to write the file to a pipeline.
+ </para>
+ <para>
+ In the first pass, the target pipeline is a count pipeline chained
+ to a discard pipeline. The count pipeline simply passes its data
+ through to the next pipeline in the chain but can return the
+ number of bytes passed through it at any intermediate point. The
+ discard pipeline is an end of line pipeline that just throws its
+ data away. The hint stream is not written and dummy values with
+ adequate padding are stored in the first cross reference table,
+ linearization parameter dictionary, and /Prev key of the first
+ trailer dictionary. All the offset, length, object renumbering
+ information, and anything else we need for the second pass is
+ stored.
+ </para>
+ <para>
+ At the end of the first pass, this information is passed to the
+ <classname>QPDF</classname> class which constructs a compressed
+ hint stream in a memory buffer and returns it.
+ <classname>QPDFWriter</classname> uses this information to write a
+ complete hint stream object into a memory buffer. At this point,
+ the length of the hint stream is known.
+ </para>
+ <para>
+ In the second pass, the end of the pipeline chain is a regular
+ file instead of a discard pipeline, and we have known values for
+ all the offsets and lengths that we didn't have in the first pass.
+ We have to adjust offsets that appear after the start of the hint
+ stream by the length of the hint stream, which is known. Anything
+ that is of variable length is padded, with the padding code
+ surrounding any writing code that differs in the two passes. This
+ ensures that changes to the way things are represented never
+ results in offsets that were gathered during the first pass
+ becoming incorrect for the second pass.
+ </para>
+ <para>
+ Using this strategy, we can write linearized files to a
+ non-seekable output stream with only a single pass to disk or
+ wherever the output is going.
+ </para>
+ </sect1>
+ <sect1 id="ref.linearization-data">
+ <title>Calculating Linearization Data</title>
+ <para>
+ Once a file is optimized, we have information about which objects
+ access which other objects. We can then process these tables to
+ decide which part (as described in &ldquo;Linearized PDF Document
+ Structure&rdquo; in the PDF specification) each object is
+ contained within. This tells us the exact order in which objects
+ are written. The <classname>QPDFWriter</classname> class asks for
+ this information and enqueues objects for writing in the proper
+ order. It also turns on a check that causes an exception to be
+ thrown if an object is encountered that has not already been
+ queued. (This could happen only if there were a bug in the
+ traversal code used to calculate the linearization data.)
+ </para>
+ </sect1>
+ <sect1 id="ref.linearization-issues">
+ <title>Known Issues with Linearization</title>
+ <para>
+ There are a handful of known issues with this linearization code.
+ These issues do not appear to impact the behavior of linearized
+ files which still work as intended: it is possible for a web
+ browser to begin to display them before they are fully
+ downloaded. In fact, it seems that various other programs that
+ create linearized files have many of these same issues. These
+ items make reference to terminology used in the linearization
+ appendix of the PDF specification.
+ <itemizedlist>
+ <listitem>
+ <para>
+ Thread Dictionary information keys appear in part 4 with the
+ rest of Threads instead of in part 9. Objects in part 9 are
+ not grouped together functionally.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ We are not calculating numerators for shared object positions
+ within content streams or interleaving them within content
+ streams.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ We generate only page offset, shared object, and outline hint
+ tables. It would be relatively easy to add some additional
+ tables. We gather most of the information needed to create
+ thumbnail hint tables. There are comments in the code about
+ this.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect1>
+ <sect1 id="ref.linearization-debugging">
+ <title>Debugging Note</title>
+ <para>
+ The <command>qpdf --show-linearization</command> command can show
+ the complete contents of linearization hint streams. To look at
+ the raw data, you can extract the filtered contents of the
+ linearization hint tables using <command>qpdf --show-object=n
+ --filtered-stream-data</command>. Then, to convert this into a
+ bit stream (since linearization tables are bit streams written
+ without regard to byte boundaries), you can pipe the resulting
+ data through the following perl code:
+
+ <programlisting>use bytes;
+binmode STDIN;
+undef $/;
+my $a = &lt;STDIN&gt;;
+my @ch = split(//, $a);
+map { printf("%08b", ord($_)) } @ch;
+print "\n";
+</programlisting>
+ </para>
+ </sect1>
+ </chapter>
+ <chapter id="ref.object-and-xref-streams">
+ <title>Object and Cross-Reference Streams</title>
+ <para>
+ This chapter provides information about the implementation of
+ object stream and cross-reference stream support in qpdf.
+ </para>
+ <sect1 id="ref.object-streams">
+ <title>Object Streams</title>
+ <para>
+ Object streams can contain any regular object except the
+ following:
+ <itemizedlist>
+ <listitem>
+ <para>
+ stream objects
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ objects with generation &gt; 0
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the encryption dictionary
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ objects containing the /Length of another stream
+ </para>
+ </listitem>
+ </itemizedlist>
+ In addition, Adobe reader (at least as of version 8.0.0) appears
+ to not be able to handle having the document catalog appear in an
+ object stream if the file is encrypted, though this is not
+ specifically disallowed by the specification.
+ </para>
+ <para>
+ There are additional restrictions for linearized files. See <xref
+ linkend="ref.object-streams-linearization"/>for details.
+ </para>
+ <para>
+ The PDF specification refers to objects in object streams as
+ &ldquo;compressed objects&rdquo; regardless of whether the object
+ stream is compressed.
+ </para>
+ <para>
+ The generation number of every object in an object stream must be
+ zero. It is possible to delete and replace an object in an object
+ stream with a regular object.
+ </para>
+ <para>
+ The object stream dictionary has the following keys:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>/N</literal>: number of objects
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>/First</literal>: byte offset of first object
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>/Extends</literal>: indirect reference to stream that
+ this extends
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Stream collections are formed with <literal>/Extends</literal>.
+ They must form a directed acyclic graph. These can be used for
+ semantic information and are not meaningful to the PDF document's
+ syntactic structure. Although qpdf preserves stream collections,
+ it never generates them and doesn't make use of this information
+ in any way.
+ </para>
+ <para>
+ The specification recommends limiting the number of objects in
+ object stream for efficiency in reading and decoding. Acrobat 6
+ uses no more than objects per object stream for linearized files
+ and no more 200 objects per stream for non-linearized files.
+ <classname>QPDFWriter</classname>, in object stream generation
+ mode, never puts more than 100 objects in an object stream.
+ </para>
+ <para>
+ Object stream contents consists of <emphasis>N</emphasis> pairs of
+ integers, each of which is the object number and the byte offset
+ of the object relative to the first object in the stream, followed
+ by the objects themselves, concatenated.
+ </para>
+ </sect1>
+ <sect1 id="ref.xref-streams">
+ <title>Cross-Reference Streams</title>
+ <para>
+ For non-hybrid files, the value following
+ <literal>startxref</literal> is the byte offset to the xref stream
+ rather than the word <literal>xref</literal>.
+ </para>
+ <para>
+ For hybrid files (files containing both xref tables and
+ cross-reference streams), the xref table's trailer dictionary
+ contains the key <literal>/XRefStm</literal> whose value is the
+ byte offset to a cross-reference stream that supplements the xref
+ table. A PDF 1.5-compliant application should read the xref table
+ first. Then it should replace any object that it has already seen
+ with any defined in the xref stream. Then it should follow any
+ <literal>/Prev</literal> pointer in the original xref table's
+ trailer dictionary. The specification is not clear about what
+ should be done, if anything, with a <literal>/Prev</literal>
+ pointer in the xref stream referenced by an xref table. The
+ <classname>QPDF</classname> class ignores it, which is probably
+ reasonable since, if this case were to appear for any sensible PDF
+ file, the previous xref table would probably have a corresponding
+ <literal>/XRefStm</literal> pointer of its own. For example, if a
+ hybrid file were appended, the appended section would have its own
+ xref table and <literal>/XRefStm</literal>. The appended xref
+ table would point to the previous xref table which would point the
+ <literal>/XRefStm</literal>, meaning that the new
+ <literal>/XRefStm</literal> doesn't have to point to it.
+ </para>
+ <para>
+ Since xref streams must be read very early, they may not be
+ encrypted, and the may not contain indirect objects for keys
+ required to read them, which are these:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>/Type</literal>: value <literal>/XRef</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>/Size</literal>: value <emphasis>n+1</emphasis>: where
+ <emphasis>n</emphasis> is highest object number (same as
+ <literal>/Size</literal> in the trailer dictionary)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>/Index</literal> (optional): value
+ <literal>[<replaceable>n count</replaceable> ...]</literal>
+ used to determine which objects' information is stored in this
+ stream. The default is <literal>[0 /Size]</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>/Prev</literal>: value
+ <replaceable>offset</replaceable>: byte offset of previous xref
+ stream (same as <literal>/Prev</literal> in the trailer
+ dictionary)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>/W [...]</literal>: sizes of each field in the xref
+ table
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The other fields in the xref stream, which may be indirect if
+ desired, are the union of those from the xref table's trailer
+ dictionary.
+ </para>
+ <sect2 id="ref.xref-stream-data">
+ <title>Cross-Reference Stream Data</title>
+ <para>
+ The stream data is binary and encoded in big-endian byte order.
+ Entries are concatenated, and each entry has a length equal to
+ the total of the entries in <literal>/W</literal> above. Each
+ entry consists of one or more fields, the first of which is the
+ type of the field. The number of bytes for each field is given
+ by <literal>/W</literal> above. A 0 in <literal>/W</literal>
+ indicates that the field is omitted and has the default value.
+ The default value for the field type is
+ &ldquo;<literal>1</literal>&rdquo;. All other default values are
+ &ldquo;<literal>0</literal>&rdquo;.
+ </para>
+ <para>
+ PDF 1.5 has three field types:
+ <itemizedlist>
+ <listitem>
+ <para>
+ 0: for free objects. Format: <literal>0 obj
+ next-generation</literal>, same as the free table in a
+ traditional cross-reference table
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 1: regular non-compressed object. Format: <literal>1 offset
+ generation</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 2: for objects in object streams. Format: <literal>2
+ object-stream-number index</literal>, the number of object
+ stream containing the object and the index within the object
+ stream of the object.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ It seems standard to have the first entry in the table be
+ <literal>0 0 0</literal> instead of <literal>0 0 ffff</literal>
+ if there are no deleted objects.
+ </para>
+ </sect2>
+ </sect1>
+ <sect1 id="ref.object-streams-linearization">
+ <title>Implications for Linearized Files</title>
+ <para>
+ For linearized files, the linearization dictionary, document
+ catalog, and page objects may not be contained in object streams.
+ </para>
+ <para>
+ Objects stored within object streams are given the highest range
+ of object numbers within the main and first-page cross-reference
+ sections.
+ </para>
+ <para>
+ It is okay to use cross-reference streams in place of regular xref
+ tables. There are on special considerations.
+ </para>
+ <para>
+ Hint data refers to object streams themselves, not the objects in
+ the streams. Shared object references should also be made to the
+ object streams. There are no reference in any hint tables to the
+ object numbers of compressed objects (objects within object
+ streams).
+ </para>
+ <para>
+ When numbering objects, all shared objects within both the first
+ and second halves of the linearized files must be numbered
+ consecutively after all normal uncompressed objects in that half.
+ </para>
+ </sect1>
+ <sect1 id="ref.object-stream-implementation">
+ <title>Implementation Notes</title>
+ <para>
+ There are three modes for writing object streams:
+ <option>disable</option>, <option>preserve</option>, and
+ <option>generate</option>. In disable mode, we do not generate
+ any object streams, and we also generate an xref table rather than
+ xref streams. This can be used to generate PDF files that are
+ viewable with older readers. In preserve mode, we write object
+ streams such that written object streams contain the same objects
+ and <literal>/Extends</literal> relationships as in the original
+ file. This is equal to disable if the file has no object streams.
+ In generate, we create object streams ourselves by grouping
+ objects that are allowed in object streams together in sets of no
+ more than 100 objects. We also ensure that the PDF version is at
+ least 1.5 in generate mode, but we preserve the version header in
+ the other modes. The default is <option>preserve</option>.
+ </para>
+ <para>
+ We do not support creation of hybrid files. When we write files,
+ even in preserve mode, we will lose any xref tables and merge any
+ appended sections.
+ </para>
+ </sect1>
+ </chapter>
+</book>
diff --git a/manual/qpdf.1.in b/manual/qpdf.1.in
new file mode 100644
index 00000000..83fad225
--- /dev/null
+++ b/manual/qpdf.1.in
@@ -0,0 +1,19 @@
+\" This file is not processed by autoconf, but rather by build.mk in
+\" the manual directory.
+.TH QPDF "1" "April 2008" "qpdf version @PACKAGE_VERSION@" "User Commands"
+.SH NAME
+qpdf \- PDF transformation software
+.SH SYNOPSIS
+.B qpdf
+[ \fIoptions \fR] \fIinfilename outfilename\fR
+.SH DESCRIPTION
+The qpdf program is used to convert one PDF file to another equivalent
+PDF file. It is capable of performing a variety of transformations
+such as linearization (also known as web optimization or fast web
+viewing), encryption, and decryption of PDF files. It also has many
+options for inspecting or checking PDF files, some of which are
+useful primarily to PDF developers.
+.PP
+For a summary of qpdf's options, please run
+\fBqpdf --help\fR. A complete manual can be found in
+@docdir@/qpdf-manual.html or @docdir@/qpdf-manual.pdf.
diff --git a/manual/zlib-flate.1.in b/manual/zlib-flate.1.in
new file mode 100644
index 00000000..133dce7b
--- /dev/null
+++ b/manual/zlib-flate.1.in
@@ -0,0 +1,21 @@
+\" This file is not processed by autoconf, but rather by build.mk in
+\" the manual directory.
+.TH ZLIB-FLATE "1" "April 2008" "zlib-flate from qpdf version @PACKAGE_VERSION@" "User Commands"
+.SH NAME
+zlib-flate \- raw zlib compression program
+.SH SYNOPSIS
+.B qpdf
+\fI-compress | -uncompress\fR
+.SH DESCRIPTION
+The zlib-flate program is part of the qpdf package.
+.PP
+The zlib-flate program standard from input and writes to standard
+output either compressing or compressing its input using raw zlib
+compression. This program is provided primarily as a debugging tool.
+It can be used to uncompress or compress raw PDF streams.
+.PP
+This program should not be used as a general purpose compression
+tool. Use something like gzip(1) instead.
+.PP
+For details about qpdf, please see the qpdf manual, which can be found
+in @docdir@/qpdf-manual.html or @docdir@/qpdf-manual.pdf.
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 00000000..ef7e16fd
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,161 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2006-05-11.19
+
+# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+IFS=" "" $nl"
+errstatus=0
+dirmode=
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake@gnu.org>."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage"
+ exit $?
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --version)
+ echo "$0 $scriptversion"
+ exit $?
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
+# mkdir -p a/c at the same time, both will detect that a is missing,
+# one will create a, then the other will try to create a and die with
+# a "File exists" error. This is a problem when calling mkinstalldirs
+# from a parallel make. We use --version in the probe to restrict
+# ourselves to GNU mkdir, which is thread-safe.
+case $dirmode in
+ '')
+ if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ test -d ./-p && rmdir ./-p
+ test -d ./--version && rmdir ./--version
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
+ test ! -d ./--version; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ else
+ # Clean up after NextStep and OpenStep mkdir.
+ for d in ./-m ./-p ./--version "./$dirmode";
+ do
+ test -d $d && rmdir $d
+ done
+ fi
+ ;;
+esac
+
+for file
+do
+ case $file in
+ /*) pathcomp=/ ;;
+ *) pathcomp= ;;
+ esac
+ oIFS=$IFS
+ IFS=/
+ set fnord $file
+ shift
+ IFS=$oIFS
+
+ for d
+ do
+ test "x$d" = x && continue
+
+ pathcomp=$pathcomp$d
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp=$pathcomp/
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/qpdf.spec b/qpdf.spec
new file mode 100644
index 00000000..93fa50ac
--- /dev/null
+++ b/qpdf.spec
@@ -0,0 +1,93 @@
+Summary: Command-line tools and library for transforming PDF files
+Name: qpdf
+Version: 2.0
+Release: 1%{?dist}
+License: Artistic
+Group: System Environment/Libraries
+URL: http://sourceforge.net/projects/qpdf/
+
+Source: %{name}-%{version}.tar.gz
+
+Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root
+BuildRequires: zlib-devel
+BuildRequires: pcre-devel
+
+%description
+QPDF is a program that does structural, content-preserving
+transformations on PDF files. It could have been called something
+like pdf-to-pdf. It also provides many useful capabilities to
+developers of PDF-producing software or for people who just want to
+look at the innards of a PDF file to learn more about how they work.
+
+QPDF offers many capabilities such as linearization (web
+optimization), encrypt, and decription of PDF files. Note that QPDF
+does not have the capability to create PDF files from scratch; it is
+only used to create PDF files with special characteristics starting
+from other PDF files or to inspect or extract information from
+existing PDF files.
+
+%package devel
+Summary: Development files for qpdf PDF manipulation library
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release} zlib-devel pcre-devel
+
+%description devel
+The qpdf-devel package contains header files and libraries necessary
+for developing programs using the qpdf library.
+
+%package static
+Summary: Static QPDF library
+Group: Development/Libraries
+Requires: %{name}-devel = %{version}-%{release}
+
+%description static
+The qpdf-static package contains the static qpdf library.
+
+%prep
+%setup -q
+
+%build
+%configure --disable-test-compare-images --docdir='${datarootdir}'/doc/%{name}-%{version}
+make %{?_smp_mflags}
+make check
+
+%install
+rm -rf $RPM_BUILD_ROOT
+%makeinstall
+# %doc below clobbers our docdir, so we have to copy it to a safe
+# place so we can install it using %doc. We should still set docdir
+# properly when configuring so that it gets substituted properly by
+# autoconf.
+cp -a $RPM_BUILD_ROOT%{_datadir}/doc/%{name}-%{version} install-docs
+mkdir -p install-examples/examples
+cp -p examples/*.cc install-examples/examples
+# Red Hat doesn't ship .la files.
+rm -rf $RPM_BUILD_ROOT%{_libdir}/libqpdf.la
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root)
+%doc README TODO Artistic-2.0 install-docs/*
+%{_bindir}/*
+%{_libdir}/libqpdf*.so.*
+%{_mandir}/man1/*
+
+%files devel
+%defattr(-,root,root)
+%doc install-examples/examples
+%{_includedir}/*
+%{_libdir}/libqpdf*.so
+
+%files static
+%defattr(-,root,root)
+%{_libdir}/libqpdf*.a
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%changelog
+* Mon Apr 28 2008 Jay Berkenbilt <ejb@ql.org> - 2.0-1
+- Initial packaging
diff --git a/qpdf/Makefile b/qpdf/Makefile
new file mode 100644
index 00000000..90899055
--- /dev/null
+++ b/qpdf/Makefile
@@ -0,0 +1 @@
+include ../make/proxy.mk
diff --git a/qpdf/build.mk b/qpdf/build.mk
new file mode 100644
index 00000000..b6fc55c9
--- /dev/null
+++ b/qpdf/build.mk
@@ -0,0 +1,26 @@
+BINS_qpdf = qpdf test_driver
+
+TARGETS_qpdf = $(foreach B,$(BINS_qpdf),qpdf/$(OUTPUT_DIR)/$(B))
+
+$(TARGETS_qpdf): $(TARGETS_libqpdf)
+
+INCLUDES_qpdf = include
+
+TC_SRCS_qpdf = $(wildcard libqpdf/*.cc) $(wildcard qpdf/*.cc)
+
+# -----
+
+$(foreach B,$(BINS_qpdf),$(eval \
+ OBJS_$(B) = $(call src_to_obj,qpdf/$(B).cc)))
+
+ifeq ($(GENDEPS),1)
+-include $(foreach B,$(BINS_qpdf),$(call obj_to_dep,$(OBJS_$(B))))
+endif
+
+$(foreach B,$(BINS_qpdf),$(eval \
+ $(OBJS_$(B)): qpdf/$(OUTPUT_DIR)/%.o: qpdf/$(B).cc ; \
+ $(call compile,qpdf/$(B).cc,$(INCLUDES_qpdf))))
+
+$(foreach B,$(BINS_qpdf),$(eval \
+ qpdf/$(OUTPUT_DIR)/$(B): $(OBJS_$(B)) ; \
+ $(call makebin,$(OBJS_$(B)),$$@)))
diff --git a/qpdf/fix-qdf b/qpdf/fix-qdf
new file mode 100755
index 00000000..d3544d95
--- /dev/null
+++ b/qpdf/fix-qdf
@@ -0,0 +1,352 @@
+#!/usr/bin/env perl
+
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+my $whoami = ($0 =~ m,([^/\\]*)$,) ? $1 : $0;
+my $dirname = ($0 =~ m,(.*)[/\\][^/\\]+$,) ? $1 : ".";
+
+if ((@ARGV == 1) && ($ARGV[0] eq '--version'))
+{
+ exec "$dirname/qpdf", '--version';
+ exit 2;
+}
+
+my $offset = 0;
+my $last_offset = 0;
+
+my $file = shift(@ARGV);
+if (defined $file)
+{
+ open(F, "<$file") or die "$whoami: can't open $file: $!\n";
+}
+else
+{
+ $file = 'stdin';
+ open(F, "<&STDIN") or die "$whoami: can't dup stdin: $!\n";
+}
+binmode F;
+binmode STDOUT;
+
+my $line = get_line();
+if (! ((defined $line) && ($line =~ m/^%PDF-1\.\d+\b/)))
+{
+ die "$whoami: $file: not a pdf file\n";
+}
+print $line;
+$line = get_line();
+die "$whoami: $file: premature EOF\n" unless defined $line;
+print $line;
+$line = get_line();
+if (! ((defined $line) && ($line =~ m/^%QDF-1.\d+\b/)))
+{
+ die "$whoami: $file: not a qdf file\n";
+}
+print $line;
+
+my $last_obj = 0;
+my @xref = ();
+
+my $stream_start = 0;
+my $stream_length = 0;
+my $xref_offset = 0;
+my $xref_f1_nbytes = 0;
+my $xref_size = 0;
+
+my $cur_state = 0;
+my $st_top = ++$cur_state;
+my $st_in_obj = ++$cur_state;
+my $st_in_stream = ++$cur_state;
+my $st_after_stream = ++$cur_state;
+my $st_in_ostream_dict = ++$cur_state;
+my $st_in_ostream_offsets = ++$cur_state;
+my $st_in_ostream_outer = ++$cur_state;
+my $st_in_ostream_obj = ++$cur_state;
+my $st_in_xref_stream_dict = ++$cur_state;
+my $st_in_length = ++$cur_state;
+my $st_at_xref = ++$cur_state;
+my $st_before_trailer = ++$cur_state;
+my $st_in_trailer = ++$cur_state;
+my $st_done = ++$cur_state;
+
+my @ostream = ();
+my @ostream_offsets = ();
+my $ostream_idx = 0;
+my $ostream_id = 0;
+my $ostream_extends = "";
+
+my $state = $st_top;
+while (defined($line = get_line()))
+{
+ if ($state == $st_top)
+ {
+ if ($line =~ m/^(\d+) 0 obj$/)
+ {
+ check_obj_id($1);
+ $state = $st_in_obj;
+ }
+ elsif ($line =~ m/^xref$/)
+ {
+ $xref_offset = $last_offset;
+ $state = $st_at_xref;
+ }
+ print $line;
+ }
+ elsif ($state == $st_in_obj)
+ {
+ print $line;
+ if ($line =~ m/^stream$/)
+ {
+ $state = $st_in_stream;
+ $stream_start = $offset;
+ }
+ elsif ($line =~ m/^endobj$/)
+ {
+ $state = $st_top;
+ }
+ elsif ($line =~ m,/Type /ObjStm,)
+ {
+ $state = $st_in_ostream_dict;
+ $ostream_id = $last_obj;
+ }
+ elsif ($line =~ m,/Type /XRef,)
+ {
+ $xref_offset = $xref[-1][1];
+ $xref_f1_nbytes = 0;
+ my $t = $xref_offset;
+ while ($t)
+ {
+ $t >>= 8;
+ ++$xref_f1_nbytes;
+ }
+ my $esize = $xref_f1_nbytes + 2;
+ $xref_size = 1 + @xref;
+ my $length = $xref_size * $esize;
+ print " /Length $length\n";
+ print " /W [ 1 $xref_f1_nbytes 1 ]\n";
+ $state = $st_in_xref_stream_dict;
+ }
+ }
+ elsif ($state == $st_in_ostream_dict)
+ {
+ if ($line =~ m,/Extends (\d+ 0 R),)
+ {
+ $ostream_extends = $1;
+ }
+ elsif ($line =~ m/^stream/)
+ {
+ $state = $st_in_ostream_offsets;
+ }
+ # discard line
+ }
+ elsif ($state == $st_in_ostream_offsets)
+ {
+ if ($line =~ m/^\%\% Object stream: object (\d+)/)
+ {
+ check_obj_id($1);
+ $stream_start = $last_offset;
+ $state = $st_in_ostream_outer;
+ push(@ostream, $line);
+ }
+ # discard line
+ }
+ elsif ($state == $st_in_ostream_outer)
+ {
+ adjust_ostream_xref();
+ push(@ostream_offsets, $last_offset - $stream_start);
+ $state = $st_in_ostream_obj;
+ push(@ostream, $line);
+ }
+ elsif ($state == $st_in_ostream_obj)
+ {
+ push(@ostream, $line);
+ if ($line =~ m/^\%\% Object stream: object (\d+)/)
+ {
+ check_obj_id($1);
+ $state = $st_in_ostream_outer;
+ }
+ elsif ($line =~ m/^endstream/)
+ {
+ $stream_length = $last_offset - $stream_start;
+ write_ostream();
+ $state = $st_in_obj;
+ }
+ }
+ elsif ($state == $st_in_xref_stream_dict)
+ {
+ if ($line =~ m,/(Length|W) ,)
+ {
+ # already printed
+ }
+ elsif ($line =~ m,/Size ,)
+ {
+ my $size = 1 + @xref;
+ print " /Size $xref_size\n";
+ }
+ else
+ {
+ print $line;
+ }
+ if ($line =~ m/^stream\n/)
+ {
+ my $pack = "(C C$xref_f1_nbytes C)";
+ print pack($pack, 0, 0, 0);
+ foreach my $x (@xref)
+ {
+ my ($type, $f1, $f2) = @$x;
+ $f2 = 0 unless defined $f2;
+ my @f1 = ();
+ for (my $i = 0; $i < $xref_f1_nbytes; ++$i)
+ {
+ unshift(@f1, $f1 & 0xff);
+ $f1 >>= 8;
+ }
+ print pack($pack, $type, @f1, $f2);
+ }
+ print "\nendstream\nendobj\n\n";
+ print "startxref\n$xref_offset\n\%\%EOF\n";
+ $state = $st_done;
+ }
+ }
+ elsif ($state == $st_in_stream)
+ {
+ if ($line =~ m/^endstream$/)
+ {
+ $stream_length = $last_offset - $stream_start;
+ $state = $st_after_stream;
+ }
+ print $line;
+ }
+ elsif ($state == $st_after_stream)
+ {
+ if ($line =~ m/^\%QDF: ignore_newline$/)
+ {
+ --$stream_length;
+ }
+ elsif ($line =~ m/^(\d+) 0 obj$/)
+ {
+ check_obj_id($1);
+ $state = $st_in_length;
+ }
+ print $line;
+ }
+ elsif ($state == $st_in_length)
+ {
+ if ($line !~ m/^\d+$/)
+ {
+ die "$file:$.: expected integer\n";
+ }
+ my $new = "$stream_length\n";
+ $offset -= length($line);
+ $offset += length($new);
+ print $new;
+ $state = $st_top;
+ }
+ elsif ($state == $st_at_xref)
+ {
+ my $n = scalar(@xref);
+ print "0 ", $n+1, "\n0000000000 65535 f \n";
+ for (@xref)
+ {
+ my ($type, $f1, $f2) = @$_;
+ printf("%010d 00000 n \n", $f1);
+ }
+ $state = $st_before_trailer;
+ }
+ elsif ($state == $st_before_trailer)
+ {
+ if ($line =~ m/^trailer <</)
+ {
+ print $line;
+ $state = $st_in_trailer;
+ }
+ # no output
+ }
+ elsif ($state == $st_in_trailer)
+ {
+ if ($line =~ m/^ \/Size \d+$/)
+ {
+ print " /Size ", scalar(@xref) + 1, "\n";
+ }
+ else
+ {
+ print $line;
+ }
+ if ($line =~ m/^>>$/)
+ {
+ print "startxref\n$xref_offset\n\%\%EOF\n";
+ $state = $st_done;
+ }
+ }
+ elsif ($state == $st_done)
+ {
+ # ignore
+ }
+}
+
+die "$whoami: $file: premature EOF\n" unless $state == $st_done;
+
+sub get_line
+{
+ my $line = scalar(<F>);
+ if (defined $line)
+ {
+ $last_offset = $offset;
+ $offset += length($line);
+ }
+ $line;
+}
+
+sub check_obj_id
+{
+ my $cur_obj = shift;
+ if ($cur_obj != $last_obj + 1)
+ {
+ die "$file:$.: expected object ", $last_obj + 1, "\n";
+ }
+ $last_obj = $cur_obj;
+ push(@xref, [1, $last_offset]);
+}
+
+sub adjust_ostream_xref
+{
+ pop(@xref);
+ push(@xref, [2, $ostream_id, $ostream_idx++]);
+}
+
+sub write_ostream
+{
+ my $first = $ostream_offsets[0];
+ my $onum = $ostream_id;
+ my $offsets = "";
+ my $n = scalar(@ostream_offsets);
+ for (@ostream_offsets)
+ {
+ $_ -= $first;
+ ++$onum;
+ $offsets .= "$onum $_\n";
+ }
+ $first += length($offsets);
+ $stream_length += length($offsets);
+ print " /Length $stream_length\n";
+ print " /N $n\n";
+ print " /First $first\n";
+ if ($ostream_extends)
+ {
+ print " /Extends $ostream_extends\n";
+ }
+ print ">>\n";
+ print "stream\n";
+ print $offsets;
+ foreach (@ostream)
+ {
+ print $_;
+ }
+
+ $ostream_idx = 0;
+ $ostream_id = 0;
+ @ostream = ();
+ @ostream_offsets = ();
+ $ostream_extends = "";
+}
diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc
new file mode 100644
index 00000000..853767ed
--- /dev/null
+++ b/qpdf/qpdf.cc
@@ -0,0 +1,942 @@
+
+#include <iostream>
+#include <string.h>
+#include <stdlib.h>
+
+#include <qpdf/QUtil.hh>
+#include <qpdf/QTC.hh>
+#include <qpdf/Pl_StdioFile.hh>
+
+#include <qpdf/QPDF.hh>
+#include <qpdf/QPDFExc.hh>
+
+#include <qpdf/QPDFWriter.hh>
+
+static char const* whoami = 0;
+
+// Note: let's not be too noisy about documenting the fact that this
+// software purposely fails to enforce the distinction between user
+// and owner passwords. A user password is sufficient to gain full
+// access to the PDF file, so there is nothing this software can do
+// with an owner password that it couldn't do with a user password
+// other than changing the /P value in the encryption dictionary.
+// (Setting this value requires the owner password.) The
+// documentation discusses this as well.
+
+static char const* help = "\
+\n\
+Usage: qpdf [ options ] infilename outfilename\n\
+\n\
+An option summary appears below. Please see the documentation for details.\n\
+\n\
+\n\
+Basic Options\n\
+-------------\n\
+\n\
+--password=password specify a password for accessing encrypted files\n\
+--linearize generated a linearized (web optimized) file\n\
+--encrypt options -- generate an encrypted file\n\
+--decrypt remove any encryption on the file\n\
+\n\
+If neither --encrypt or --decrypt are given, qpdf will preserve any\n\
+encryption data associated with a file.\n\
+\n\
+\n\
+Encryption Options\n\
+------------------\n\
+\n\
+ --encrypt user-password owner-password key-length flags --\n\
+\n\
+Note that -- terminates parsing of encryption flags.\n\
+\n\
+Either or both of the user password and the owner password may be\n\
+empty strings.\n\
+\n\
+key-length may be 40 or 128\n\
+\n\
+Additional flags are dependent upon key length.\n\
+\n\
+ If 40:\n\
+\n\
+ --print=[yn] allow printing\n\
+ --modify=[yn] allow document modification\n\
+ --extract=[yn] allow text/graphic extraction\n\
+ --annotate=[yn] allow comments and form fill-in and signing\n\
+\n\
+ If 128:\n\
+\n\
+ --accessibility=[yn] allow accessibility to visually impaired\n\
+ --extract=[yn] allow other text/graphic extraction\n\
+ --print=print-opt control printing access\n\
+ --modify=modify-opt control modify access\n\
+\n\
+ print-opt may be:\n\
+\n\
+ full allow full printing\n\
+ low allow only low-resolution printing\n\
+ none disallow printing\n\
+\n\
+ modify-opt may be:\n\
+\n\
+ all allow full document modification\n\
+ annotate allow comment authoring and form operations\n\
+ form allow form field fill-in and signing\n\
+ assembly allow document assembly only\n\
+ none allow no modifications\n\
+\n\
+The default for each permission option is to be fully permissive.\n\
+\n\
+\n\
+Advanced Transformation Options\n\
+-------------------------------\n\
+\n\
+These transformation options control fine points of how qpdf creates\n\
+the output file. Mostly these are of use only to people who are very\n\
+familiar with the PDF file format or who are PDF developers.\n\
+\n\
+--stream-data=option controls transformation of stream data (below)\n\
+--normalize-content=[yn] enables or disables normalization of content streams\n\
+--suppress-recovery prevents qpdf from attempting to recover damaged files\n\
+--object-streams=mode controls handing of object streams\n\
+--ignore-xref-streams tells qpdf to ignore any cross-reference streams\n\
+--qdf turns on \"QDF mode\" (below)\n\
+\n\
+Values for stream data options:\n\
+\n\
+ compress recompress stream data when possible (default)\n\
+ preserve leave all stream data as is\n\
+ uncompress uncompress stream data when possible\n\
+\n\
+Values for object strea mode:\n\
+\n\
+ preserve preserve original object streams (default)\n\
+ disable don't write any object streams\n\
+ generate use object streams wherever possible\n\
+\n\
+In qdf mode, by default, content normalization is turned on, and the\n\
+stream data mode is set to uncompress.\n\
+\n\
+\n\
+Testing, Inspection, and Debugging Options\n\
+------------------------------------------\n\
+\n\
+These options can be useful for digging into PDF files or for use in\n\
+automated test suites for software that uses the qpdf library.\n\
+\n\
+--static-id generate static /ID: FOR TESTING ONLY!\n\
+--show-encryption quickly show encryption parameters\n\
+--check-linearization check file integrity and linearization status\n\
+--show-linearization check and show all linearization data\n\
+--show-xref show the contents of the cross-reference table\n\
+--show-object=obj[,gen] show the contents of the given object\n\
+ --raw-stream-data show raw stream data instead of object contents\n\
+ --filtered-stream-data show filtered stream data instead of object contents\n\
+--show-pages shows the object/generation number for each page\n\
+ --with-images also shows the object IDs for images on each page\n\
+--check check file structure + encryption, linearization\n\
+\n\
+The --raw-stream-data and --filtered-stream-data options are ignored\n\
+unless --show-object is given. Either of these options will cause the\n\
+stream data to be written to standard output.\n\
+\n\
+If --filtered-stream-data is given and --normalize-content=y is also\n\
+given, qpdf will attempt to normalize the stream data as if it is a\n\
+page content stream. This attempt will be made even if it is not a\n\
+page content stream, in which case it will produce unusuable results.\n\
+\n\
+\n";
+
+void usage(std::string const& msg)
+{
+ std::cerr
+ << std::endl
+ << whoami << ": " << msg << std::endl
+ << std::endl
+ << "Usage: " << whoami << " [options] infile outfile" << std::endl
+ << "For detailed help, run " << whoami << " --help" << std::endl
+ << std::endl;
+ exit(2);
+}
+
+static void show_encryption(QPDF& pdf)
+{
+ // Extract /P from /Encrypt
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
+ if (encrypt.isNull())
+ {
+ std::cout << "File is not encrypted" << std::endl;
+ }
+ else
+ {
+ QPDFObjectHandle P = encrypt.getKey("/P");
+ std::cout << "P = " << P.getIntValue() << std::endl;
+ std::string user_password = pdf.getUserPassword();
+ QPDF::trim_user_password(user_password);
+ std::cout << "User password = " << user_password << std::endl;
+ }
+}
+
+static void
+parse_encrypt_options(
+ int argc, char* argv[], int& cur_arg,
+ std::string& user_password, std::string& owner_password, int& keylen,
+ bool& r2_print, bool& r2_modify, bool& r2_extract, bool& r2_annotate,
+ bool& r3_accessibility, bool& r3_extract,
+ QPDFWriter::r3_print_e& r3_print, QPDFWriter::r3_modify_e& r3_modify)
+{
+ if (cur_arg + 3 >= argc)
+ {
+ usage("insufficient arguments to --encrypt");
+ }
+ user_password = argv[cur_arg++];
+ owner_password = argv[cur_arg++];
+ std::string len_str = argv[cur_arg++];
+ if (len_str == "40")
+ {
+ keylen = 40;
+ }
+ else if (len_str == "128")
+ {
+ keylen = 128;
+ }
+ else
+ {
+ usage("encryption key length must be 40 or 128");
+ }
+ while (1)
+ {
+ char* arg = argv[cur_arg];
+ if (arg == 0)
+ {
+ usage("insufficient arguments to --encrypt");
+ }
+ else if (strcmp(arg, "--") == 0)
+ {
+ return;
+ }
+ if (arg[0] == '-')
+ {
+ ++arg;
+ if (arg[0] == '-')
+ {
+ ++arg;
+ }
+ }
+ else
+ {
+ usage(std::string("invalid encryption parameter ") + arg);
+ }
+ ++cur_arg;
+ char* parameter = strchr(arg, '=');
+ if (parameter)
+ {
+ *parameter++ = 0;
+ }
+ if (strcmp(arg, "print") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--print must be given as --print=option");
+ }
+ std::string val = parameter;
+ if (keylen == 40)
+ {
+ if (val == "y")
+ {
+ r2_print = true;
+ }
+ else if (val == "n")
+ {
+ r2_print = false;
+ }
+ else
+ {
+ usage("invalid 40-bit -print parameter");
+ }
+ }
+ else
+ {
+ if (val == "full")
+ {
+ r3_print = QPDFWriter::r3p_full;
+ }
+ else if (val == "low")
+ {
+ r3_print = QPDFWriter::r3p_low;
+ }
+ else if (val == "none")
+ {
+ r3_print = QPDFWriter::r3p_none;
+ }
+ else
+ {
+ usage("invalid 128-bit -print parameter");
+ }
+ }
+ }
+ else if (strcmp(arg, "modify") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--modify must be given as --modify=option");
+ }
+ std::string val = parameter;
+ if (keylen == 40)
+ {
+ if (val == "y")
+ {
+ r2_modify = true;
+ }
+ else if (val == "n")
+ {
+ r2_modify = false;
+ }
+ else
+ {
+ usage("invalid 40-bit -modify parameter");
+ }
+ }
+ else
+ {
+ if (val == "all")
+ {
+ r3_modify = QPDFWriter::r3m_all;
+ }
+ else if (val == "annotate")
+ {
+ r3_modify = QPDFWriter::r3m_annotate;
+ }
+ else if (val == "form")
+ {
+ r3_modify = QPDFWriter::r3m_form;
+ }
+ else if (val == "assembly")
+ {
+ r3_modify = QPDFWriter::r3m_assembly;
+ }
+ else if (val == "none")
+ {
+ r3_modify = QPDFWriter::r3m_none;
+ }
+ else
+ {
+ usage("invalid 128-bit -modify parameter");
+ }
+ }
+ }
+ else if (strcmp(arg, "extract") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--extract must be given as --extract=option");
+ }
+ std::string val = parameter;
+ bool result = false;
+ if (val == "y")
+ {
+ result = true;
+ }
+ else if (val == "n")
+ {
+ result = false;
+ }
+ else
+ {
+ usage("invalid -extract parameter");
+ }
+ if (keylen == 40)
+ {
+ r2_extract = result;
+ }
+ else
+ {
+ r3_extract = result;
+ }
+ }
+ else if (strcmp(arg, "annotate") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--annotate must be given as --annotate=option");
+ }
+ std::string val = parameter;
+ bool result = false;
+ if (val == "y")
+ {
+ result = true;
+ }
+ else if (val == "n")
+ {
+ result = false;
+ }
+ else
+ {
+ usage("invalid -annotate parameter");
+ }
+ if (keylen == 40)
+ {
+ r2_annotate = result;
+ }
+ else
+ {
+ usage("-annotate invalid for 128-bit keys");
+ }
+ }
+ else if (strcmp(arg, "accessibility") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--accessibility must be given as"
+ " --accessibility=option");
+ }
+ std::string val = parameter;
+ bool result = false;
+ if (val == "y")
+ {
+ result = true;
+ }
+ else if (val == "n")
+ {
+ result = false;
+ }
+ else
+ {
+ usage("invalid -accessibility parameter");
+ }
+ if (keylen == 128)
+ {
+ r3_accessibility = result;
+ }
+ else
+ {
+ usage("-accessibility invalid for 40-bit keys");
+ }
+ }
+ else
+ {
+ usage(std::string("invalid encryption parameter --") + arg);
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ if ((whoami = strrchr(argv[0], '/')) == NULL)
+ {
+ whoami = argv[0];
+ }
+ else
+ {
+ ++whoami;
+ }
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
+ {
+ // make_dist looks for the line of code here that actually
+ // prints the version number, so read make_dist if you change
+ // anything other than the version number. Don't worry about
+ // the numbers. That's just a guide to 80 columns so that the
+ // help message looks right on an 80-column display.
+
+ // 1 2 3 4 5 6 7 8
+ // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
+ std::cout
+ << whoami << " version 2.0" << std::endl
+ << "Copyright (c) 2005-2008 Jay Berkenbilt"
+ << std::endl
+ << "This software may be distributed under the terms of version 2 of the"
+ << std::endl
+ << "Artistic License which may be found in the source distribution. It is"
+ << std::endl
+ << "provided \"as is\" without express or implied warranty."
+ << std::endl;
+ exit(0);
+ }
+
+ if ((argc == 2) && (strcmp(argv[1], "--help") == 0))
+ {
+ std::cout << help;
+ exit(0);
+ }
+
+ char const* password = "";
+ bool linearize = false;
+ bool decrypt = false;
+
+ bool encrypt = false;
+ std::string user_password;
+ std::string owner_password;
+ int keylen = 0;
+ bool r2_print = true;
+ bool r2_modify = true;
+ bool r2_extract = true;
+ bool r2_annotate = true;
+ bool r3_accessibility = true;
+ bool r3_extract = true;;
+ QPDFWriter::r3_print_e r3_print = QPDFWriter::r3p_full;
+ QPDFWriter::r3_modify_e r3_modify = QPDFWriter::r3m_all;
+
+ bool stream_data_set = false;
+ QPDFWriter::stream_data_e stream_data_mode = QPDFWriter::s_compress;
+ bool normalize_set = false;
+ bool normalize = false;
+ bool suppress_recovery = false;
+ bool object_stream_set = false;
+ QPDFWriter::object_stream_e object_stream_mode = QPDFWriter::o_preserve;
+ bool ignore_xref_streams = false;
+ bool qdf_mode = false;
+
+ bool static_id = false;
+ bool show_encryption = false;
+ bool check_linearization = false;
+ bool show_linearization = false;
+ bool show_xref = false;
+ int show_obj = 0;
+ int show_gen = 0;
+ bool show_raw_stream_data = false;
+ bool show_filtered_stream_data = false;
+ bool show_pages = false;
+ bool show_page_images = false;
+ bool check = false;
+
+ bool require_outfile = true;
+ char const* infilename = 0;
+ char const* outfilename = 0;
+
+ for (int i = 1; i < argc; ++i)
+ {
+ char const* arg = argv[i];
+ if ((arg[0] == '-') && (strcmp(arg, "-") != 0))
+ {
+ ++arg;
+ if (arg[0] == '-')
+ {
+ // Be lax about -arg vs --arg
+ ++arg;
+ }
+ char* parameter = strchr(arg, '=');
+ if (parameter)
+ {
+ *parameter++ = 0;
+ }
+
+ if (strcmp(arg, "password") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--password must be given as --password=pass");
+ }
+ password = parameter;
+ }
+ else if (strcmp(arg, "linearize") == 0)
+ {
+ linearize = true;
+ }
+ else if (strcmp(arg, "encrypt") == 0)
+ {
+ parse_encrypt_options(
+ argc, argv, ++i,
+ user_password, owner_password, keylen,
+ r2_print, r2_modify, r2_extract, r2_annotate,
+ r3_accessibility, r3_extract, r3_print, r3_modify);
+ encrypt = true;
+ }
+ else if (strcmp(arg, "decrypt") == 0)
+ {
+ decrypt = true;
+ }
+ else if (strcmp(arg, "stream-data") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--stream-data must be given as"
+ "--stream-data=option");
+ }
+ stream_data_set = true;
+ if (strcmp(parameter, "compress") == 0)
+ {
+ stream_data_mode = QPDFWriter::s_compress;
+ }
+ else if (strcmp(parameter, "preserve") == 0)
+ {
+ stream_data_mode = QPDFWriter::s_preserve;
+ }
+ else if (strcmp(parameter, "uncompress") == 0)
+ {
+ stream_data_mode = QPDFWriter::s_uncompress;
+ }
+ else
+ {
+ usage("invalid stream-data option");
+ }
+ }
+ else if (strcmp(arg, "normalize-content") == 0)
+ {
+ if ((parameter == 0) || (*parameter == '\0'))
+ {
+ usage("--normalize-content must be given as"
+ " --normalize-content=[yn]");
+ }
+ normalize_set = true;
+ normalize = (parameter[0] == 'y');
+ }
+ else if (strcmp(arg, "suppress-recovery") == 0)
+ {
+ suppress_recovery = true;
+ }
+ else if (strcmp(arg, "object-streams") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--object-streams must be given as"
+ " --object-streams=option");
+ }
+ object_stream_set = true;
+ if (strcmp(parameter, "disable") == 0)
+ {
+ object_stream_mode = QPDFWriter::o_disable;
+ }
+ else if (strcmp(parameter, "preserve") == 0)
+ {
+ object_stream_mode = QPDFWriter::o_preserve;
+ }
+ else if (strcmp(parameter, "generate") == 0)
+ {
+ object_stream_mode = QPDFWriter::o_generate;
+ }
+ else
+ {
+ usage("invalid object stream mode");
+ }
+ }
+ else if (strcmp(arg, "ignore-xref-streams") == 0)
+ {
+ ignore_xref_streams = true;
+ }
+ else if (strcmp(arg, "qdf") == 0)
+ {
+ qdf_mode = true;
+ }
+ else if (strcmp(arg, "static-id") == 0)
+ {
+ static_id = true;
+ }
+ else if (strcmp(arg, "show-encryption") == 0)
+ {
+ show_encryption = true;
+ require_outfile = false;
+ }
+ else if (strcmp(arg, "check-linearization") == 0)
+ {
+ check_linearization = true;
+ require_outfile = false;
+ }
+ else if (strcmp(arg, "show-linearization") == 0)
+ {
+ show_linearization = true;
+ require_outfile = false;
+ }
+ else if (strcmp(arg, "show-xref") == 0)
+ {
+ show_xref = true;
+ require_outfile = false;
+ }
+ else if (strcmp(arg, "show-object") == 0)
+ {
+ if (parameter == 0)
+ {
+ usage("--show-object must be given as"
+ " --show-object=obj[,gen]");
+ }
+ char* obj = parameter;
+ char* gen = obj;
+ if ((gen = strchr(obj, ',')) != 0)
+ {
+ *gen++ = 0;
+ show_gen = atoi(gen);
+ }
+ show_obj = atoi(obj);
+ require_outfile = false;
+ }
+ else if (strcmp(arg, "raw-stream-data") == 0)
+ {
+ show_raw_stream_data = true;
+ }
+ else if (strcmp(arg, "filtered-stream-data") == 0)
+ {
+ show_filtered_stream_data = true;
+ }
+ else if (strcmp(arg, "show-pages") == 0)
+ {
+ show_pages = true;
+ require_outfile = false;
+ }
+ else if (strcmp(arg, "with-images") == 0)
+ {
+ show_page_images = true;
+ }
+ else if (strcmp(arg, "check") == 0)
+ {
+ check = true;
+ require_outfile = false;
+ }
+ else
+ {
+ usage(std::string("unknown option --") + arg);
+ }
+ }
+ else if (infilename == 0)
+ {
+ infilename = arg;
+ }
+ else if (outfilename == 0)
+ {
+ outfilename = arg;
+ }
+ else
+ {
+ usage(std::string("unknown argument ") + arg);
+ }
+ }
+
+ if (infilename == 0)
+ {
+ usage("an input file name is required");
+ }
+ else if (require_outfile && (outfilename == 0))
+ {
+ usage("an output file name is required; use - for standard output");
+ }
+ else if ((! require_outfile) && (outfilename != 0))
+ {
+ usage("no output file may be given for this option");
+ }
+
+ try
+ {
+ QPDF pdf;
+ if (ignore_xref_streams)
+ {
+ pdf.setIgnoreXRefStreams(true);
+ }
+ if (suppress_recovery)
+ {
+ pdf.setAttemptRecovery(false);
+ }
+ pdf.processFile(infilename, password);
+ if (outfilename == 0)
+ {
+ if (show_encryption)
+ {
+ ::show_encryption(pdf);
+ }
+ if (check_linearization)
+ {
+ if (pdf.checkLinearization())
+ {
+ std::cout << infilename << ": no linearization errors"
+ << std::endl;
+ }
+ else
+ {
+ exit(2);
+ }
+ }
+ if (show_linearization)
+ {
+ pdf.showLinearizationData();
+ }
+ if (show_xref)
+ {
+ pdf.showXRefTable();
+ }
+ if (show_obj > 0)
+ {
+ QPDFObjectHandle obj = pdf.getObjectByID(show_obj, show_gen);
+ if (obj.isStream())
+ {
+ if (show_raw_stream_data || show_filtered_stream_data)
+ {
+ bool filter = show_filtered_stream_data;
+ if (filter &&
+ (! obj.pipeStreamData(0, true, false, false)))
+ {
+ QTC::TC("qpdf", "unable to filter");
+ std::cerr << "Unable to filter stream data."
+ << std::endl;
+ exit(2);
+ }
+ else
+ {
+ Pl_StdioFile out("stdout", stdout);
+ obj.pipeStreamData(&out, filter, normalize, false);
+ }
+ }
+ else
+ {
+ std::cout
+ << "Object is stream. Dictionary:" << std::endl
+ << obj.getDict().unparseResolved() << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << obj.unparseResolved() << std::endl;
+ }
+ }
+ if (show_pages)
+ {
+ std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
+ int pageno = 0;
+ for (std::vector<QPDFObjectHandle>::iterator iter =
+ pages.begin();
+ iter != pages.end(); ++iter)
+ {
+ QPDFObjectHandle& page = *iter;
+ ++pageno;
+
+ std::cout << "page " << pageno << ": "
+ << page.getObjectID() << " "
+ << page.getGeneration() << " R" << std::endl;
+ if (show_page_images)
+ {
+ std::map<std::string, QPDFObjectHandle> images =
+ page.getPageImages();
+ if (! images.empty())
+ {
+ std::cout << " images:" << std::endl;
+ for (std::map<std::string,
+ QPDFObjectHandle>::iterator
+ iter = images.begin();
+ iter != images.end(); ++iter)
+ {
+ std::string const& name = (*iter).first;
+ QPDFObjectHandle image = (*iter).second;
+ QPDFObjectHandle dict = image.getDict();
+ int width =
+ dict.getKey("/Width").getIntValue();
+ int height =
+ dict.getKey("/Height").getIntValue();
+ std::cout << " " << name << ": "
+ << image.unparse()
+ << ", " << width << " x " << height
+ << std::endl;
+ }
+ }
+ }
+
+ std::cout << " content:" << std::endl;
+ std::vector<QPDFObjectHandle> content =
+ page.getPageContents();
+ for (std::vector<QPDFObjectHandle>::iterator iter =
+ content.begin();
+ iter != content.end(); ++iter)
+ {
+ std::cout << " " << (*iter).unparse() << std::endl;
+ }
+ }
+ }
+ if (check)
+ {
+ bool okay = false;
+ std::cout << "checking " << infilename << std::endl;
+ try
+ {
+ ::show_encryption(pdf);
+ if (pdf.isLinearized())
+ {
+ std::cout << "File is linearized\n";
+ okay = pdf.checkLinearization();
+ // any errors are reported by checkLinearization().
+ }
+ else
+ {
+ std::cout << "File is not linearized\n";
+ // calling flattenScalarReferences causes full
+ // traversal of file, so any structural errors
+ // would be exposed.
+ pdf.flattenScalarReferences();
+ okay = true;
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ }
+ if (okay)
+ {
+ std::cout << "No errors found" << std::endl;
+ }
+ }
+ }
+ else
+ {
+ if (strcmp(outfilename, "-") == 0)
+ {
+ outfilename = 0;
+ }
+ QPDFWriter w(pdf, outfilename);
+ if (qdf_mode)
+ {
+ w.setQDFMode(true);
+ }
+ if (normalize_set)
+ {
+ w.setContentNormalization(normalize);
+ }
+ if (stream_data_set)
+ {
+ w.setStreamDataMode(stream_data_mode);
+ }
+ if (decrypt)
+ {
+ w.setPreserveEncryption(false);
+ }
+ if (static_id)
+ {
+ w.setStaticID(true);
+ }
+ if (encrypt)
+ {
+ if (keylen == 40)
+ {
+ w.setR2EncryptionParameters(
+ user_password.c_str(), owner_password.c_str(),
+ r2_print, r2_modify, r2_extract, r2_annotate);
+ }
+ else if (keylen == 128)
+ {
+ w.setR3EncryptionParameters(
+ user_password.c_str(), owner_password.c_str(),
+ r3_accessibility, r3_extract, r3_print, r3_modify);
+ }
+ else
+ {
+ throw QEXC::Internal("bad encryption keylen");
+ }
+ }
+ if (linearize)
+ {
+ w.setLinearization(true);
+ }
+ if (object_stream_set)
+ {
+ w.setObjectStreamMode(object_stream_mode);
+ }
+ w.write();
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
new file mode 100644
index 00000000..e6323600
--- /dev/null
+++ b/qpdf/qpdf.testcov
@@ -0,0 +1,117 @@
+ignored-scope: libtests
+QPDF lindict null found 0
+QPDF lindict searching after null 0
+QPDF err expected endobj 0
+QPDF err wrong objid/generation 0
+QPDF check objid 1
+QPDF check generation 1
+QPDF check obj 1
+QPDF hint table length indirect 0
+QPDF hint table length direct 0
+QPDF P absent in lindict 0
+QPDF P present in lindict 0
+QPDF expected n n obj 0
+QPDF lindict found newline 0
+QPDF /L mismatch 0
+QPDF err /T mismatch 0
+QPDF err /O mismatch 0
+QPDF opt direct pages resource 1
+QPDF opt inheritable keys 0
+QPDF opt no inheritable keys 0
+QPDF opt erase empty key ancestor 0
+QPDF opt resource inherited 0
+QPDF opt page resource hides ancestor 0
+QPDF opt key ancestors depth > 1 0
+QPDF opt loop detected 0
+QPDF categorize pagemode present 1
+QPDF categorize pagemode outlines 1
+QPDF warn /E mismatch 0
+QPDF lin outlines in part 1
+QPDF lin nshared_total > nshared_first_page 1
+QPDF lin part 8 empty 1
+QPDF lin check shared past first page 0
+QPDF opt flatten array scalar 0
+QPDF opt flatten dict scalar 0
+main QTest implicit 0
+main QTest indirect 1
+main QTest null 0
+main QTest bool 1
+main QTest int 0
+main QTest real 0
+main QTest name 0
+main QTest string 0
+main QTest array 0
+main QTest array indirect 1
+main QTest dictionary 0
+main QTest dictionary indirect 1
+main QTest stream 0
+QPDFWriter write to stdout 0
+QPDFWriter write to file 0
+QPDF lin write nshared_total > nshared_first_page 1
+QPDFWriter encrypted hint stream 0
+QPDF opt inherited scalar 0
+QPDF xref reused object 0
+QPDF xref gen > 0 1
+QPDF xref size mismatch 0
+QPDF not a pdf file 0
+QPDF can't find startxref 0
+QPDF invalid xref 0
+QPDF invalid xref entry 0
+QPDF missing trailer 0
+QPDF trailer lacks size 0
+QPDF trailer size not integer 0
+QPDF trailer prev not integer 0
+QPDF bad brace 0
+QPDF bad array close 0
+QPDF dictionary odd number of elements 0
+QPDF stream without length 0
+QPDF stream length not integer 0
+QPDF missing endstream 0
+QPDF bad dictionary close 0
+QPDF can't find xref 0
+QPDF_Tokenizer bad ) 0
+QPDF_Tokenizer bad > 0
+QPDF_Tokenizer bad ( 0
+QPDF_Tokenizer null in name 0
+QPDF_Tokenizer bad name 0
+QPDF_Stream invalid filter 0
+QPDF UseOutlines but no Outlines 0
+QPDFObjectHandle clone bool 0
+QPDFObjectHandle clone null 0
+QPDFObjectHandle clone integer 0
+QPDFObjectHandle clone real 0
+QPDFObjectHandle clone name 0
+QPDFObjectHandle clone string 0
+QPDFObjectHandle clone array 0
+QPDFObjectHandle clone dictionary 0
+QPDFObjectHandle makeDirect loop 0
+QPDFObjectHandle ERR clone stream 0
+QPDFTokenizer allow pound anywhere in name 0
+QPDF indirect last obj from xref 1
+QPDF default for xref stream field 0 0
+QPDF prev key in xref stream dictionary 0
+QPDF prev key in trailer dictionary 0
+QPDF found xref stream 0
+QPDF ignoring XRefStm in trailer 0
+QPDF xref deleted object 0
+QPDF_Stream PNG filter 0
+QPDF xref /Index is null 0
+QPDF xref /Index is array 1
+QPDFWriter copy Extends 0
+QPDFWriter encrypt object stream 0
+QPDFWriter uncompressing page dictionary 0
+QPDFWriter uncompressing root 0
+QPDFWriter compressing uncompressed stream 0
+QPDF exclude indirect length 0
+QPDFWriter generate >1 ostream 0
+QPDF exclude encryption dictionary 0
+QPDF loop detected traversing objects 0
+QPDF reconstructed xref table 0
+QPDF recovered in readObjectAtOffset 0
+QPDF recovered stream length 0
+QPDF found wrong endstream in recovery 0
+QPDFObjectHandle indirect to unknown 0
+QPDF_Stream pipeStreamData with null pipeline 0
+QPDFWriter not recompressing /FlateDecode 0
+QPDF piping xref stream from encrypted file 0
+unable to filter 0
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
new file mode 100644
index 00000000..d3aeded6
--- /dev/null
+++ b/qpdf/qtest/qpdf.test
@@ -0,0 +1,942 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+use File::Copy;
+use File::Basename;
+use Cwd;
+use Digest::MD5;
+
+chdir("qpdf") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+cleanup();
+
+my $td = new TestDriver('qpdf');
+
+my $compare_images = 1;
+if ((exists $ENV{'SKIP_TEST_COMPARE_IMAGES'}) &&
+ ($ENV{'SKIP_TEST_COMPARE_IMAGES'} eq '1'))
+{
+ $compare_images = 0;
+}
+
+my $have_acroread = 0;
+
+if ($compare_images)
+{
+ # check for acroread
+ my @path = split(':', $ENV{'PATH'});
+ foreach my $p (@path)
+ {
+ if (-x "$p/acroread")
+ {
+ $have_acroread = 1;
+ last;
+ }
+ }
+}
+
+# These variables are used to store the total number of tests in the
+# test suite. NOTE: qtest's requirement to indicate the number of
+# tests serves as a check that the test suite is operating properly.
+# Do not calculate these values as a side effect of running the tests.
+# That defeats the purpose. However, since this test suite consists
+# of several separate series of tests, many of which iterate over
+# static lists of things, we calculate the numbers as we go in terms
+# of static values.
+
+# This should be set to the number of times we called compare_pdfs.
+# This has to be kept separate because the number of test cases
+# compare_pdfs generates depends on the value of $compare_images.
+my $n_compare_pdfs = 0;
+
+# This should be set to the number of times we call acroread.
+my $n_acroread = 0;
+
+# Each section of tests should increment this number by the number of
+# tests they generate excluding calls to acroread or compare_pdfs,
+# which are tracked separately by $n_compare_pdfs and $n_acroread.
+my $n_tests = 0;
+
+# Call show_ntests after each block of test cases. In show_ntests,
+# you can turn on printing of the expected number of test cases. This
+# is useful for tracking down problems in the number of test cases.
+
+show_ntests();
+# ----------
+
+$n_compare_pdfs += 5;
+
+# Check compare_pdfs to make sure that it works properly. Each call
+# to compare_pdfs is worth three test cases.
+compare_pdfs("p1-a-p2-b.pdf", "p1-a-p2-b.pdf");
+compare_pdfs("p1-a.pdf", "p1-a.pdf");
+compare_pdfs("p1-a.pdf", "p1-b.pdf", 1);
+compare_pdfs("p1-a.pdf", "p1-a-p2-b.pdf", 1);
+compare_pdfs("p1-a-p2-a.pdf", "p1-a-p2-b.pdf", 1);
+flush_tiff_cache();
+
+show_ntests();
+# ----------
+$td->notify("--- Miscellaneous Tests ---");
+$n_tests += 3;
+
+foreach (my $i = 1; $i <= 3; ++$i)
+{
+ $td->runtest("misc tests",
+ {$td->COMMAND => "test_driver 5 misc-$i.pdf"},
+ {$td->FILE => "misc-$i.out", $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+}
+
+show_ntests();
+# ----------
+$td->notify("--- Error Condition Tests ---");
+# $n_tests incremented after initialization of badfiles below.
+
+my @badfiles = ("not a PDF file", # 1
+ "no startxref", # 2
+ "bad primary xref offset", # 3
+ "invalid xref syntax", # 4
+ "invalid xref entry", # 5
+ "free table inconsistency", # 6
+ "no trailer dictionary", # 7
+ "bad secondary xref", # 8
+ "no /Size in trailer", # 9
+ "/Size not integer", # 10
+ "/Prev not integer", # 11
+ "/Size inconsistency", # 12
+ "bad {", # 13
+ "bad }", # 14
+ "bad ]", # 15
+ "bad >>", # 16
+ "odd number of dictionary items", # 17
+ "bad )", # 18
+ "bad >", # 19
+ "invalid hexstring character", # 20
+ "invalid name token", # 21
+ "no /Length for stream dictionary", # 22
+ "/Length not integer", # 23
+ "expected endstream", # 24
+ "bad obj declaration (objid)", # 25
+ "bad obj declaration (generation)", # 26
+ "bad obj declaration (obj)", # 27
+ "expected endobj", # 28
+ "null in name", # 29
+ "invalid stream /Filter", # 30
+ "unknown stream /Filter", # 31
+ "obj/gen mismatch", # 32
+ );
+
+$n_tests += @badfiles;
+
+# Test 6 contains errors in the free table consistency, but we no
+# longer have any consistency check for this since it is not important
+# neither Acrobat nor other PDF viewers really care. Tests 12 and 28
+# have error conditions that used to be fatal but are now considered
+# non-fatal.
+my %badtest_overrides = (6 => 0, 12 => 0, 28 => 0, 31 => 0);
+for (my $i = 1; $i <= scalar(@badfiles); ++$i)
+{
+ my $status = $badtest_overrides{$i};
+ $status = 2 unless defined $status;
+ $td->runtest($badfiles[$i-1],
+ {$td->COMMAND => "test_driver 0 bad$i.pdf"},
+ {$td->FILE => "bad$i.out",
+ $td->EXIT_STATUS => $status},
+ $td->NORMALIZE_NEWLINES);
+}
+
+show_ntests();
+# ----------
+$td->notify("--- Recovery Tests ---");
+$n_tests += @badfiles + 2;
+
+# Recovery tests. These are mostly after-the-fact -- when recovery
+# was implemented, some degree of recovery was possible on many of the
+# files. Mostly the recovery does not actually repair the error,
+# though in some cases it may. Acrobat Reader would not be able to
+# recover any of these files any better.
+my %recover_failures = ();
+for (1, 7, 13..21, 24..27, 29..30)
+{
+ $recover_failures{$_} = 1;
+}
+for (my $i = 1; $i <= scalar(@badfiles); ++$i)
+{
+ my $status = 0;
+ if (exists $recover_failures{$i})
+ {
+ $status = 2;
+ }
+ $td->runtest("recover " . $badfiles[$i-1],
+ {$td->COMMAND => "test_driver 1 bad$i.pdf"},
+ {$td->FILE => "bad$i-recover.out",
+ $td->EXIT_STATUS => $status},
+ $td->NORMALIZE_NEWLINES);
+}
+
+# This heifer file was a real file that contained errors that Acrobat
+# Reader can recover. We can recover it too.
+$td->runtest("recover heifer file",
+ {$td->COMMAND => "qpdf --static-id -qdf heifer.pdf a.pdf"},
+ {$td->FILE => "heifer.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check output",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "heifer.qdf"});
+
+show_ntests();
+# ----------
+$td->notify("--- Basic Parsing Tests ---");
+# $n_tests incremented below after initialization of @goodfiles.
+
+my @goodfiles = ("implicit null", # 1
+ "direct null", # 2
+ "unresolved null", # 3
+ "indirect null", # 4
+ "indirect bool", # 5
+ "direct bool", # 6
+ "integer", # 7
+ "real, ASCIIHexDecode", # 8
+ "string", # 9
+ "array", # 10
+ "dictionary", # 11
+ "stream", # 12
+ "nesting, strings, names", # 13
+ "tokenizing pipeline", # 14
+ "name", # 15
+ "object-stream", # 16
+ "hybrid xref", # 17
+ "hybrid xref old mode", # 18
+ "xref with prev", # 19
+ "lots of compressible objects", # 20
+ );
+
+$n_tests += (9 * @goodfiles) + 6;
+
+my %goodtest_overrides = ('14' => 3);
+my %goodtest_flags =
+ ('18' => '-ignore-xref-streams',
+ '20' => '-object-streams=generate',
+ );
+for (my $i = 1; $i <= scalar(@goodfiles); ++$i)
+{
+ my $n = $goodtest_overrides{$i} || 1;
+ foreach my $lang (qw(C en_US en_US.UTF-8))
+ {
+ $td->runtest("$goodfiles[$i-1], ($lang)",
+ {$td->COMMAND => "test_driver $n good$i.pdf"},
+ {$td->FILE => "good$i.out",
+ $td->EXIT_STATUS => 0});
+ my $xflags = $goodtest_flags{$i} || '';
+ check_pdf("create qdf",
+ "qpdf --static-id -qdf $xflags good$i.pdf",
+ "good$i.qdf", 0);
+ }
+}
+
+check_pdf("no normalization",
+ "qpdf -qdf --static-id --normalize-content=n good7.pdf",
+ "good7-not-normalized.qdf",
+ 0);
+
+check_pdf("no qdf",
+ "qpdf --static-id good17.pdf",
+ "good17-not-qdf.pdf",
+ 0);
+
+check_pdf("no recompression",
+ "qpdf --static-id --stream-data=preserve good17.pdf",
+ "good17-not-recompressed.pdf",
+ 0);
+
+show_ntests();
+# ----------
+$td->notify("--- Object Stream Tests ---");
+$n_tests += 36 * 4;
+$n_compare_pdfs += 36;
+
+for (my $n = 16; $n <= 19; ++$n)
+{
+ my $in = "good$n.pdf";
+ foreach my $flags ('-object-streams=disable',
+ '-object-streams=preserve',
+ '-object-streams=generate')
+ {
+ foreach my $qdf ('-qdf', '', '-encrypt "" x 128 --')
+ {
+ # 4 tests + 1 compare_pdfs
+ $td->runtest("object stream mode",
+ {$td->COMMAND =>
+ "qpdf --static-id $flags $qdf $in a.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ compare_pdfs("good$n.pdf", "a.pdf");
+ $td->runtest("convert to qdf",
+ {$td->COMMAND =>
+ "qpdf --static-id -qdf -decrypt" .
+ " -object-streams=disable $in a.qdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("convert output to qdf",
+ {$td->COMMAND =>
+ "qpdf --static-id -qdf" .
+ " -object-streams=disable a.pdf b.qdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("compare files",
+ {$td->FILE => "a.qdf"},
+ {$td->FILE => "b.qdf"});
+ }
+ }
+ flush_tiff_cache();
+}
+
+show_ntests();
+# ----------
+$td->notify("--- Specific File Tests ---");
+$n_tests += 1;
+
+# Special PDF files that caused problems at some point
+
+# This file is a PDF 1.1 file with /# as a name and with
+# inconsistencies in its free table.
+$td->runtest("old and complex",
+ {$td->COMMAND => "qpdf --check old-and-complex.pdf"},
+ {$td->STRING => +("checking old-and-complex.pdf\n" .
+ "File is not encrypted\n" .
+ "File is not linearized\n" .
+ "No errors found\n"),
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+show_ntests();
+# ----------
+$td->notify("--- Mutability Tests ---");
+$n_tests += 4;
+
+$td->runtest("no normalization",
+ {$td->COMMAND => "test_driver 4 test4-1.pdf"},
+ {$td->FILE => "test4-1.qdf",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("object ordering",
+ {$td->COMMAND => "test_driver 4 test4-4.pdf"},
+ {$td->FILE => "test4-4.qdf",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("loop detected",
+ {$td->COMMAND => "test_driver 4 test4-2.pdf"},
+ {$td->FILE => "test4-2.out",
+ $td->EXIT_STATUS => 2},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("stream detected",
+ {$td->COMMAND => "test_driver 4 test4-3.pdf"},
+ {$td->FILE => "test4-3.out",
+ $td->EXIT_STATUS => 2},
+ $td->NORMALIZE_NEWLINES);
+
+show_ntests();
+# ----------
+$td->notify("--- Extraction Tests ---");
+$n_tests += 11;
+
+$td->runtest("show xref",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-xref"},
+ {$td->FILE => "show-xref.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("show pages",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-pages"},
+ {$td->FILE => "show-pages.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("show-pages-images",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-pages --with-images"},
+ {$td->FILE => "show-pages-images.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("show-page-1",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=5,0"},
+ {$td->FILE => "show-page-1.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("show-page-1-content-raw",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=7 --raw-stream-data"},
+ {$td->FILE => "show-page-1-content-raw.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("show-page-1-content-filtered",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=7 --filtered-stream-data"},
+ {$td->FILE => "show-page-1-content-filtered.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("show-page-1-content-normalized",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=7,0 --filtered-stream-data --normalize-content=y"},
+ {$td->FILE => "show-page-1-content-normalized.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("show-page-1-image",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=8 --raw-stream-data"},
+ {$td->FILE => "show-page-1-image.out",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("unfilterable stream data",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=8 --filtered-stream-data"},
+ {$td->FILE => "show-unfilterable.out",
+ $td->EXIT_STATUS => 2});
+
+$td->runtest("show-xref-by-id",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=12"},
+ {$td->FILE => "show-xref-by-id.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("show-xref-by-id-filtered",
+ {$td->COMMAND => "qpdf encrypted-with-images.pdf" .
+ " --show-object=12 --filtered-stream-data"},
+ {$td->FILE => "show-xref-by-id-filtered.out",
+ $td->EXIT_STATUS => 0});
+
+show_ntests();
+# ----------
+$td->notify("--- Linearization Tests ---");
+# $n_tests incremented after initialization of @linearized_files and
+# @to_linearize.
+
+# *'ed files were linearized with Pdlin.
+my @linearized_files =
+ ('lin0', # not linearized
+ 'lin1', # * outlines, page labels, pdlin
+ 'lin2', # * lin1 with null and newline
+ 'lin3', # same file saved with acrobat
+ 'lin4', # * lin1 with no /PageMode
+ 'lin5', # lin3 with embedded thumbnails
+ 'lin6', # * lin5 with pdlin
+ 'lin7', # lin5 with /PageMode /UseThumbs
+ 'lin8', # * lin7 with pdlin
+ 'lin9', # * shared objects, indirect null
+ 'badlin1', # parameter dictionary errors
+ );
+
+my @to_linearize =
+ ('lin-special', # lots of weird cases -- see file comments
+ 'delete-and-reuse', # deleted, reused objects
+ 'lin-delete-and-reuse', # linearized, then delete and reuse
+ 'object-stream', # contains object streams
+ 'hybrid-xref', # contains both xref tables and streams
+ @linearized_files, # we should be able to relinearize
+ );
+
+$n_tests += @linearized_files + 6;
+$n_tests += (3 * @to_linearize * 5) + 6;
+
+foreach my $base (@linearized_files)
+{
+ $td->runtest("dump linearization: $base",
+ {$td->COMMAND => "qpdf --show-linearization $base.pdf"},
+ {$td->FILE => "$base.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+}
+
+# Check normal modified and linearized modified files, making sure
+# that their qdf files are identical. The next two tests have the
+# same expected output files and different input files.
+check_pdf("modified",
+ "qpdf --static-id --qdf delete-and-reuse.pdf",
+ "delete-and-reuse.qdf",
+ 0);
+check_pdf("linearized and modified",
+ "qpdf --static-id --qdf lin-delete-and-reuse.pdf",
+ "delete-and-reuse.qdf", # not lin-delete-and-reuse.qdf
+ 0);
+
+$td->runtest("check linearized and modified",
+ {$td->COMMAND => "qpdf --check lin-delete-and-reuse.pdf"},
+ {$td->STRING => +("checking lin-delete-and-reuse.pdf\n" .
+ "File is not encrypted\n" .
+ "File is not linearized\n" .
+ "No errors found\n"),
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check multiple modifications",
+ {$td->COMMAND => "qpdf --check multiple-mods.pdf"},
+ {$td->STRING => +("checking multiple-mods.pdf\n" .
+ "File is not encrypted\n" .
+ "File is not linearized\n" .
+ "No errors found\n"),
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+foreach my $base (@to_linearize)
+{
+ foreach my $omode (qw(disable preserve generate))
+ {
+ my $oarg = "-object-streams=$omode";
+ $td->runtest("linearize $base ($omode)",
+ {$td->COMMAND =>
+ "qpdf -linearize $oarg --static-id $base.pdf a.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("check linearization",
+ {$td->COMMAND => "qpdf --check-linearization a.pdf"},
+ {$td->STRING => "a.pdf: no linearization errors\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+ # Relinearizing twice should produce identical results. We
+ # have to do it twice because, if objects changed ordering
+ # during the original linearization, the hint tables won't
+ # exactly match. This is because object identifiers are
+ # inserted into the hint table in their original order since
+ # we don't yet have renumbering information when we compute
+ # the table values.
+ $td->runtest("relinearize $base 1",
+ {$td->COMMAND =>
+ "qpdf -linearize --static-id a.pdf b.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("relinearize $base 2",
+ {$td->COMMAND =>
+ "qpdf -linearize --static-id b.pdf c.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("compare files ($omode)",
+ {$td->FILE => "b.pdf"},
+ {$td->FILE => "c.pdf"});
+ if (($base eq 'lin-special') || ($base eq 'object-stream'))
+ {
+ $td->runtest("check $base ($omode)",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "$base.$omode.exp"});
+ }
+ }
+}
+
+show_ntests();
+# ----------
+$td->notify("--- Encryption Tests ---");
+# $n_tests incremented below
+
+# The enc-file.pdf files were encrypted using Acrobat 5.0, not the
+# qpdf library. The files are decrypted using qpdf, then re-encrypted
+# using qpdf with specific flags. The /P value is checked. The
+# resulting files were saved and manually checked with Acrobat 5.0 to
+# ensure that the security settings were as intended.
+
+# Values: basename, password, encryption flags, /P Encrypt key.
+my @encrypted_files =
+ (['base', ''],
+ ['R3,V2', '',
+ '-accessibility=n -extract=n -print=full -modify=all', -532],
+ ['R3,V2,U=view', 'view',
+ '-accessibility=y -extract=n -print=none -modify=none', -3392],
+ ['R3,V2,O=master', 'master',
+ '-accessibility=n -extract=y -print=none -modify=annotate', -2576],
+ ['R3,V2,O=master', '',
+ '-accessibility=n -extract=n -print=none -modify=form', -2624],
+ ['R3,V2,U=view,O=master', 'view',
+ '-accessibility=n -extract=n -print=none -modify=assembly', -2880],
+ ['R3,V2,U=view,O=master', 'master',
+ '-accessibility=n -print=low', -2564],
+ ['R2,V1', '',
+ '-print=n -modify=n -extract=n -annotate=n', -64],
+ ['R2,V1,U=view', 'view',
+ '-print=y -modify=n -extract=n -annotate=n', -60],
+ ['R2,V1,O=master', 'master',
+ '-print=n -modify=y -extract=n -annotate=n', -56],
+ ['R2,V1,O=master', '',
+ '-print=n -modify=n -extract=y -annotate=n', -48],
+ ['R2,V1,U=view,O=master', 'view',
+ '-print=n -modify=n -extract=n -annotate=y', -32],
+ ['R2,V1,U=view,O=master', 'master',
+ '', -4],
+ ['long-password', 'asdf asdf asdf asdf asdf asdf qwer'],
+ ['long-password', 'asdf asdf asdf asdf asdf asdf qw']);
+
+$n_tests += 3 + (2 * (@encrypted_files)) + (6 * (@encrypted_files - 3)) + 8;
+
+$td->runtest("encrypted file",
+ {$td->COMMAND => "test_driver 2 U25A0.pdf"},
+ {$td->FILE => "encrypted1.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("preserve encryption",
+ {$td->COMMAND => "qpdf U25A0.pdf U25A0.enc"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+$td->runtest("recheck encrypted file",
+ {$td->COMMAND => "test_driver 2 U25A0.enc"},
+ {$td->FILE => "encrypted1.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+foreach my $d (@encrypted_files)
+{
+ my ($file, $pass, $xeflags, $P) = @$d;
+ # Test writing to stdout
+ $td->runtest("decrypt $file",
+ {$td->COMMAND =>
+ "qpdf --static-id -qdf" .
+ " --password=\"$pass\" enc-$file.pdf -" .
+ " > $file.enc"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ if ($file eq 'base')
+ {
+ $td->runtest("check ID",
+ {$td->COMMAND => "perl check-ID.pl $file.enc"},
+ {$td->STRING => "ID okay\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+ }
+ else
+ {
+ $td->runtest("check against base",
+ {$td->COMMAND => "./diff-encrypted base.enc $file.enc"},
+ {$td->STRING => "okay\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+ }
+ if ($file =~ m/^R(\d),V(\d)(?:,U=(\w+))?(?:,O=(\w+))?$/)
+ {
+ my $R = $1;
+ my $V = $2;
+ my $upass = $3 || "";
+ my $opass = $4 || "";
+ my $bits = (($V == 2) ? 128 : 40);
+
+ my $eflags = "-encrypt \"$upass\" \"$opass\" $bits $xeflags --";
+ $td->runtest("encrypt $file",
+ {$td->COMMAND =>
+ "qpdf --static-id -qdf $eflags $file.enc $file.enc2"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("check /P",
+ {$td->COMMAND =>
+ "qpdf --show-encryption --password=\"$pass\"" .
+ " $file.enc2"},
+ {$td->STRING => "P = $P\nUser password = $upass\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+ $td->runtest("decrypt again",
+ {$td->COMMAND =>
+ "qpdf --static-id -qdf --password=\"$pass\"" .
+ " $file.enc2 $file.enc3"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("compare",
+ {$td->FILE => "$file.enc"},
+ {$td->FILE => "$file.enc3"});
+ $td->runtest("preserve encryption",
+ {$td->COMMAND =>
+ "qpdf --static-id --password=\"$pass\"" .
+ " $file.enc2 $file.enc4"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ $td->runtest("check /P",
+ {$td->COMMAND =>
+ "qpdf --show-encryption --password=\"$pass\"" .
+ " $file.enc4"},
+ {$td->STRING => "P = $P\nUser password = $upass\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+ }
+}
+
+$td->runtest("non-encrypted",
+ {$td->COMMAND => "qpdf --show-encryption enc-base.pdf"},
+ {$td->STRING => "File is not encrypted\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->runtest("invalid password",
+ {$td->COMMAND => "qpdf -qdf --password=quack" .
+ " enc-R2,V1,U=view.pdf a.qdf"},
+ {$td->STRING => "enc-R2,V1,U=view.pdf: invalid password\n",
+ $td->EXIT_STATUS => 2},
+ $td->NORMALIZE_NEWLINES);
+
+# Test combinations of linearization and encryption. Note that we do
+# content checks on encrypted and linearized files in various
+# combinations below. Here we are just making sure that they are
+# linearized and/or encrypted as desired.
+
+$td->runtest("linearize encrypted file",
+ {$td->COMMAND => "qpdf --linearize U25A0.pdf a.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+$td->runtest("check encryption",
+ {$td->COMMAND => "qpdf --show-encryption a.pdf"},
+ {$td->STRING => "P = -60\nUser password = \n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check linearization",
+ {$td->COMMAND => "qpdf --check-linearization a.pdf"},
+ {$td->STRING => "a.pdf: no linearization errors\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("linearize and encrypt file",
+ {$td->COMMAND =>
+ "qpdf --linearize --encrypt user owner 128 --" .
+ " lin-special.pdf a.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+$td->runtest("check encryption",
+ {$td->COMMAND => "qpdf --show-encryption --password=owner a.pdf"},
+ {$td->STRING => "P = -4\nUser password = user\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check linearization",
+ {$td->COMMAND => "qpdf --check-linearization" .
+ " --password=user a.pdf"},
+ {$td->STRING => "a.pdf: no linearization errors\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+show_ntests();
+# ----------
+$td->notify("--- Content Preservation Tests ---");
+# $n_tests incremented below
+
+my @files = ("U25A0.pdf", # encrypted
+ "inline-images.pdf",
+ "lin-special.pdf",
+ "object-stream.pdf",
+ "hybrid-xref.pdf");
+my @flags = (["-qdf", # 1
+ "qdf"],
+ ["-qdf --normalize-content=n", # 2
+ "qdf not normalized"],
+ ["-qdf --stream-data=preserve", # 3
+ "qdf not uncompressed"],
+ ["-qdf --stream-data=preserve --normalize-content=n", # 4
+ "qdf not normalized or uncompressed"],
+ ["--stream-data=uncompress", # 5
+ "uncompresed"],
+ ["--normalize-content=y", # 6
+ "normalized"],
+ ["--stream-data=uncompress --normalize-content=y", # 7
+ "uncompressed and normalized"],
+ ["-decrypt", # 8
+ "decrypted"],
+ ["-linearize", # 9
+ "linearized"],
+ ["-encrypt \"\" owner 128 --", # 10
+ "encrypted"],
+ ["-linearize -encrypt \"\" o 128 --", # 11
+ "linearized and encrypted"],
+ ["", # 12
+ "no arguments"],
+ );
+
+$n_tests += (@files * @flags * 2 * 2);
+$n_compare_pdfs += (@files * @flags * 2);
+$n_acroread += (@files * @flags * 2);
+
+foreach my $file (@files)
+{
+ my $base = basename($file, '.pdf');
+
+ foreach my $o (qw(disable generate))
+ {
+ my $n = 0;
+ my $oflags = "--object-streams=$o";
+ my $odescrip = "os:" . substr($o, 0, 1);
+ foreach my $d (@flags)
+ {
+ my ($flags, $fdescrip) = @$d;
+ ++$n;
+ system("rm -f *.pnm");
+
+ $td->runtest("$file ($odescrip $fdescrip)",
+ {$td->COMMAND => "qpdf $flags $oflags $file a.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+
+ $td->runtest("check status",
+ {$td->COMMAND => "qpdf --check a.pdf"},
+ {$td->FILE => "$base.$n.check",
+ $td->EXIT_STATUS => 0});
+
+ compare_pdfs($file, "a.pdf");
+
+ if ($have_acroread)
+ {
+ # These tests require Adobe Reader > 7.x to work with
+ # encrypted files.
+ $td->runtest("check with Adobe Reader",
+ {$td->COMMAND =>
+ "acroread -toPostScript -pairs a.pdf 1.ps"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ }
+ }
+ flush_tiff_cache();
+ }
+}
+
+show_ntests();
+# ----------
+$td->notify("--- fix-qdf Tests ---");
+$n_tests += 6;
+
+foreach my $lang qw(C en_US en_US.UTF-8)
+{
+ for (my $n = 1; $n <= 2; ++$n)
+ {
+ $td->runtest("fix-qdf $n (LANG=$lang)",
+ {$td->COMMAND => "LANG=$lang fix-qdf fix$n.qdf"},
+ {$td->FILE => "fix$n.qdf.out",
+ $td->EXIT_STATUS => 0});
+ }
+}
+
+show_ntests();
+
+# ----------
+cleanup();
+
+# See comments at beginning about calculation of number of tests. We
+# do it strictly based on static values, not as a by-product of
+# running the test suite.
+$td->report(calc_ntests());
+
+sub calc_ntests
+{
+ my $result = $n_tests;
+ if ($have_acroread)
+ {
+ $result += $n_acroread;
+ }
+ if ($compare_images)
+ {
+ $result += 3 * ($n_compare_pdfs);
+ }
+ $result;
+}
+
+sub show_ntests
+{
+ if (0)
+ {
+ $td->emphasize("tests so far: ". calc_ntests());
+ }
+}
+
+sub check_pdf
+{
+ my ($description, $command, $output, $status) = @_;
+ unlink "a.pdf";
+ $td->runtest($description,
+ {$td->COMMAND => "$command a.pdf"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => $status});
+ $td->runtest("check output",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => $output});
+}
+
+sub flush_tiff_cache
+{
+ system("rm -rf tiff-cache");
+}
+
+sub compare_pdfs
+{
+ return unless $compare_images;
+
+ my ($f1, $f2, $exp) = @_;
+
+ $exp = 0 unless defined $exp;
+
+ system("rm -rf tif1 tif2");
+
+ mkdir "tiff-cache", 0777 unless -d "tiff-cache";
+
+ my $md5_1 = get_md5_checksum($f1);
+ my $md5_2 = get_md5_checksum($f2);
+
+ mkdir "tif1", 0777 or die;
+ mkdir "tif2", 0777 or die;
+
+ if (-f "tiff-cache/$md5_1.tif")
+ {
+ $td->runtest("get cached original file image",
+ {$td->COMMAND => "cp tiff-cache/$md5_1.tif tif1/a.tif"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ }
+ else
+ {
+ $td->runtest("convert original file to image",
+ {$td->COMMAND =>
+ "(cd tif1;" .
+ " gs -q -dNOPAUSE -sDEVICE=tiff12nc" .
+ " -sOutputFile=a.tif - < ../$f1)"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ copy("tif1/a.tif", "tiff-cache/$md5_1.tif");
+ }
+
+ if (-f "tiff-cache/$md5_2.tif")
+ {
+ $td->runtest("get cached new file image",
+ {$td->COMMAND => "cp tiff-cache/$md5_2.tif tif2/a.tif"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ }
+ else
+ {
+ $td->runtest("convert new file to image",
+ {$td->COMMAND =>
+ "(cd tif2;" .
+ " gs -q -dNOPAUSE -sDEVICE=tiff12nc" .
+ " -sOutputFile=a.tif - < ../$f2)"},
+ {$td->STRING => "",
+ $td->EXIT_STATUS => 0});
+ copy("tif2/a.tif", "tiff-cache/$md5_2.tif");
+ }
+
+ $td->runtest("compare images",
+ {$td->COMMAND => "tiffcmp -t tif1/a.tif tif2/a.tif"},
+ {$td->REGEXP => ".*",
+ $td->EXIT_STATUS => $exp});
+
+ system("rm -rf tif1 tif2");
+}
+
+sub get_md5_checksum
+{
+ my $file = shift;
+ open(F, "<$file") or fatal("can't open $file: $!");
+ binmode F;
+ my $digest = Digest::MD5->new->addfile(*F)->hexdigest;
+ close(F);
+ $digest;
+}
+
+sub cleanup
+{
+ system("rm -rf *.ps *.pnm a.pdf a.qdf b.pdf b.qdf c.pdf" .
+ " *.enc* tif1 tif2 tiff-cache");
+}
diff --git a/qpdf/qtest/qpdf/U25A0.1.check b/qpdf/qtest/qpdf/U25A0.1.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.1.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.10.check b/qpdf/qtest/qpdf/U25A0.10.check
new file mode 100644
index 00000000..0e0ed996
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.10.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.11.check b/qpdf/qtest/qpdf/U25A0.11.check
new file mode 100644
index 00000000..327d847a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.11.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.12.check b/qpdf/qtest/qpdf/U25A0.12.check
new file mode 100644
index 00000000..48b8e821
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.12.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -60
+User password =
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.2.check b/qpdf/qtest/qpdf/U25A0.2.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.2.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.3.check b/qpdf/qtest/qpdf/U25A0.3.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.3.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.4.check b/qpdf/qtest/qpdf/U25A0.4.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.4.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.5.check b/qpdf/qtest/qpdf/U25A0.5.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.5.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.6.check b/qpdf/qtest/qpdf/U25A0.6.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.6.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.7.check b/qpdf/qtest/qpdf/U25A0.7.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.7.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.8.check b/qpdf/qtest/qpdf/U25A0.8.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.8.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.9.check b/qpdf/qtest/qpdf/U25A0.9.check
new file mode 100644
index 00000000..547c43d5
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.9.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -60
+User password =
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/U25A0.pdf b/qpdf/qtest/qpdf/U25A0.pdf
new file mode 100644
index 00000000..f8b779d4
--- /dev/null
+++ b/qpdf/qtest/qpdf/U25A0.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/bad1-recover.out b/qpdf/qtest/qpdf/bad1-recover.out
new file mode 100644
index 00000000..1cd5b015
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad1-recover.out
@@ -0,0 +1 @@
+bad1.pdf: offset 0: not a PDF file
diff --git a/qpdf/qtest/qpdf/bad1.out b/qpdf/qtest/qpdf/bad1.out
new file mode 100644
index 00000000..1cd5b015
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad1.out
@@ -0,0 +1 @@
+bad1.pdf: offset 0: not a PDF file
diff --git a/qpdf/qtest/qpdf/bad1.pdf b/qpdf/qtest/qpdf/bad1.pdf
new file mode 100644
index 00000000..75891bc6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad1.pdf
@@ -0,0 +1 @@
+oops
diff --git a/qpdf/qtest/qpdf/bad10-recover.out b/qpdf/qtest/qpdf/bad10-recover.out
new file mode 100644
index 00000000..905ca597
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad10-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad10.pdf: offset 0: file is damaged
+WARNING: bad10.pdf: offset 712: /Size key in trailer dictionary is not an integer
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad10.out b/qpdf/qtest/qpdf/bad10.out
new file mode 100644
index 00000000..935f5b24
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad10.out
@@ -0,0 +1 @@
+bad10.pdf: offset 712: /Size key in trailer dictionary is not an integer
diff --git a/qpdf/qtest/qpdf/bad10.pdf b/qpdf/qtest/qpdf/bad10.pdf
new file mode 100644
index 00000000..1f2be0c8
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad10.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size (h)
+ /Root 1 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad11-recover.out b/qpdf/qtest/qpdf/bad11-recover.out
new file mode 100644
index 00000000..7dfac209
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad11-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad11.pdf: offset 0: file is damaged
+WARNING: bad11.pdf: offset 905: /Prev key in trailer dictionary is not an integer
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad11.out b/qpdf/qtest/qpdf/bad11.out
new file mode 100644
index 00000000..55705b73
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad11.out
@@ -0,0 +1 @@
+bad11.pdf: offset 905: /Prev key in trailer dictionary is not an integer
diff --git a/qpdf/qtest/qpdf/bad11.pdf b/qpdf/qtest/qpdf/bad11.pdf
new file mode 100644
index 00000000..4cf46e5a
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad11.pdf
@@ -0,0 +1,104 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
+
+4 0 obj
+<<
+ /Length 43
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Salad) Tj
+ET
+endstream
+endobj
+
+xref
+0 1
+0000000000 65535 f
+4 1
+0000000750 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Prev [542]
+>>
+startxref
+845
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad12-recover.out b/qpdf/qtest/qpdf/bad12-recover.out
new file mode 100644
index 00000000..97dfb642
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad12-recover.out
@@ -0,0 +1,7 @@
+WARNING: bad12.pdf: reported number of objects (9) inconsistent with actual number of objects (8)
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad12.out b/qpdf/qtest/qpdf/bad12.out
new file mode 100644
index 00000000..d07d74bd
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad12.out
@@ -0,0 +1,7 @@
+WARNING: bad12.pdf: reported number of objects (9) inconsistent with actual number of objects (8)
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 0 done
diff --git a/qpdf/qtest/qpdf/bad12.pdf b/qpdf/qtest/qpdf/bad12.pdf
new file mode 100644
index 00000000..0fc8028a
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad12.pdf
@@ -0,0 +1,122 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 7 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+7 0 obj
+<<
+ /Length 48
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Sandwiches) Tj
+ET
+endstream
+endobj
+
+xref
+0 1
+0000000004 65535 f
+3 2
+0000000750 00000 n
+0000000000 00001 f
+7 1
+0000000922 00000 n
+trailer <<
+ /Size 9
+ /Root 1 0 R
+ /Prev 542
+>>
+startxref
+1022
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad13-recover.out b/qpdf/qtest/qpdf/bad13-recover.out
new file mode 100644
index 00000000..5ea29917
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad13-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad13.pdf: offset 0: file is damaged
+WARNING: bad13.pdf: offset 753: unexpected brace token
+WARNING: Attempting to reconstruct cross-reference table
+bad13.pdf: offset 753: unexpected brace token
diff --git a/qpdf/qtest/qpdf/bad13.out b/qpdf/qtest/qpdf/bad13.out
new file mode 100644
index 00000000..12eedf08
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad13.out
@@ -0,0 +1 @@
+bad13.pdf: offset 753: unexpected brace token
diff --git a/qpdf/qtest/qpdf/bad13.pdf b/qpdf/qtest/qpdf/bad13.pdf
new file mode 100644
index 00000000..2fb59d2e
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad13.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something {
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad14-recover.out b/qpdf/qtest/qpdf/bad14-recover.out
new file mode 100644
index 00000000..26ee2ef6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad14-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad14.pdf: offset 0: file is damaged
+WARNING: bad14.pdf: offset 753: unexpected brace token
+WARNING: Attempting to reconstruct cross-reference table
+bad14.pdf: offset 753: unexpected brace token
diff --git a/qpdf/qtest/qpdf/bad14.out b/qpdf/qtest/qpdf/bad14.out
new file mode 100644
index 00000000..82c58c22
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad14.out
@@ -0,0 +1 @@
+bad14.pdf: offset 753: unexpected brace token
diff --git a/qpdf/qtest/qpdf/bad14.pdf b/qpdf/qtest/qpdf/bad14.pdf
new file mode 100644
index 00000000..551fdfdc
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad14.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something }
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad15-recover.out b/qpdf/qtest/qpdf/bad15-recover.out
new file mode 100644
index 00000000..2d6d0cf1
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad15-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad15.pdf: offset 0: file is damaged
+WARNING: bad15.pdf: offset 753: unexpected array close token
+WARNING: Attempting to reconstruct cross-reference table
+bad15.pdf: offset 753: unexpected array close token
diff --git a/qpdf/qtest/qpdf/bad15.out b/qpdf/qtest/qpdf/bad15.out
new file mode 100644
index 00000000..19ffbfcc
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad15.out
@@ -0,0 +1 @@
+bad15.pdf: offset 753: unexpected array close token
diff --git a/qpdf/qtest/qpdf/bad15.pdf b/qpdf/qtest/qpdf/bad15.pdf
new file mode 100644
index 00000000..5578e1d6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad15.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something ]
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad16-recover.out b/qpdf/qtest/qpdf/bad16-recover.out
new file mode 100644
index 00000000..22a49ee9
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad16-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad16.pdf: offset 0: file is damaged
+WARNING: bad16.pdf: offset 753: unexpected dictionary close token
+WARNING: Attempting to reconstruct cross-reference table
+bad16.pdf: offset 753: unexpected dictionary close token
diff --git a/qpdf/qtest/qpdf/bad16.out b/qpdf/qtest/qpdf/bad16.out
new file mode 100644
index 00000000..315f5203
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad16.out
@@ -0,0 +1 @@
+bad16.pdf: offset 753: unexpected dictionary close token
diff --git a/qpdf/qtest/qpdf/bad16.pdf b/qpdf/qtest/qpdf/bad16.pdf
new file mode 100644
index 00000000..b8bdb5f4
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad16.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something[>>
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad17-recover.out b/qpdf/qtest/qpdf/bad17-recover.out
new file mode 100644
index 00000000..bcaa948f
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad17-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad17.pdf: offset 0: file is damaged
+WARNING: bad17.pdf: offset 753: dictionary ending here has an odd number of elements
+WARNING: Attempting to reconstruct cross-reference table
+bad17.pdf: offset 753: dictionary ending here has an odd number of elements
diff --git a/qpdf/qtest/qpdf/bad17.out b/qpdf/qtest/qpdf/bad17.out
new file mode 100644
index 00000000..36c059d6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad17.out
@@ -0,0 +1 @@
+bad17.pdf: offset 753: dictionary ending here has an odd number of elements
diff --git a/qpdf/qtest/qpdf/bad17.pdf b/qpdf/qtest/qpdf/bad17.pdf
new file mode 100644
index 00000000..5afb00d2
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad17.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad18-recover.out b/qpdf/qtest/qpdf/bad18-recover.out
new file mode 100644
index 00000000..2a4d2a06
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad18-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad18.pdf: offset 0: file is damaged
+WARNING: bad18.pdf: offset 753: unexpected )
+WARNING: Attempting to reconstruct cross-reference table
+bad18.pdf: offset 753: unexpected )
diff --git a/qpdf/qtest/qpdf/bad18.out b/qpdf/qtest/qpdf/bad18.out
new file mode 100644
index 00000000..5e319d9b
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad18.out
@@ -0,0 +1 @@
+bad18.pdf: offset 753: unexpected )
diff --git a/qpdf/qtest/qpdf/bad18.pdf b/qpdf/qtest/qpdf/bad18.pdf
new file mode 100644
index 00000000..96cf7935
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad18.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something )
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad19-recover.out b/qpdf/qtest/qpdf/bad19-recover.out
new file mode 100644
index 00000000..4fa46af8
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad19-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad19.pdf: offset 0: file is damaged
+WARNING: bad19.pdf: offset 753: unexpected >
+WARNING: Attempting to reconstruct cross-reference table
+bad19.pdf: offset 753: unexpected >
diff --git a/qpdf/qtest/qpdf/bad19.out b/qpdf/qtest/qpdf/bad19.out
new file mode 100644
index 00000000..57ffd7d2
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad19.out
@@ -0,0 +1 @@
+bad19.pdf: offset 753: unexpected >
diff --git a/qpdf/qtest/qpdf/bad19.pdf b/qpdf/qtest/qpdf/bad19.pdf
new file mode 100644
index 00000000..f95036f0
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad19.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something >
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad2-recover.out b/qpdf/qtest/qpdf/bad2-recover.out
new file mode 100644
index 00000000..142f10ff
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad2-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad2.pdf: offset 0: file is damaged
+WARNING: bad2.pdf: can't find startxref
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad2.out b/qpdf/qtest/qpdf/bad2.out
new file mode 100644
index 00000000..9179b774
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad2.out
@@ -0,0 +1 @@
+bad2.pdf: can't find startxref
diff --git a/qpdf/qtest/qpdf/bad2.pdf b/qpdf/qtest/qpdf/bad2.pdf
new file mode 100644
index 00000000..aa63b0b2
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad2.pdf
@@ -0,0 +1,76 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+farbage 542
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad20-recover.out b/qpdf/qtest/qpdf/bad20-recover.out
new file mode 100644
index 00000000..95fc3ca6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad20-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad20.pdf: offset 0: file is damaged
+WARNING: bad20.pdf: offset 753: invalid character (q) in hexstring
+WARNING: Attempting to reconstruct cross-reference table
+bad20.pdf: offset 753: invalid character (q) in hexstring
diff --git a/qpdf/qtest/qpdf/bad20.out b/qpdf/qtest/qpdf/bad20.out
new file mode 100644
index 00000000..f70b938a
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad20.out
@@ -0,0 +1 @@
+bad20.pdf: offset 753: invalid character (q) in hexstring
diff --git a/qpdf/qtest/qpdf/bad20.pdf b/qpdf/qtest/qpdf/bad20.pdf
new file mode 100644
index 00000000..e42cfe08
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad20.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Something <abqd>
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad21-recover.out b/qpdf/qtest/qpdf/bad21-recover.out
new file mode 100644
index 00000000..7423fe4f
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad21-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad21.pdf: offset 0: file is damaged
+WARNING: bad21.pdf: offset 742: invalid name token
+WARNING: Attempting to reconstruct cross-reference table
+bad21.pdf: offset 742: invalid name token
diff --git a/qpdf/qtest/qpdf/bad21.out b/qpdf/qtest/qpdf/bad21.out
new file mode 100644
index 00000000..fb71b5ac
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad21.out
@@ -0,0 +1 @@
+bad21.pdf: offset 742: invalid name token
diff --git a/qpdf/qtest/qpdf/bad21.pdf b/qpdf/qtest/qpdf/bad21.pdf
new file mode 100644
index 00000000..4be5f0ef
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad21.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Som#ething 1
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad22-recover.out b/qpdf/qtest/qpdf/bad22-recover.out
new file mode 100644
index 00000000..823e8b96
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad22-recover.out
@@ -0,0 +1,21 @@
+WARNING: bad22.pdf: offset 341: attempting to recover stream length
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Qength 44 >>
+Raw stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+Uncompressed stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+End of stream data
+unparse: 4 0 R
+unparseResolved: 4 0 R
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad22.out b/qpdf/qtest/qpdf/bad22.out
new file mode 100644
index 00000000..40d92a45
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad22.out
@@ -0,0 +1 @@
+bad22.pdf: offset 317: stream dictionary lacks /Length key
diff --git a/qpdf/qtest/qpdf/bad22.pdf b/qpdf/qtest/qpdf/bad22.pdf
new file mode 100644
index 00000000..b0d42ac7
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad22.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Qength 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad23-recover.out b/qpdf/qtest/qpdf/bad23-recover.out
new file mode 100644
index 00000000..981766cd
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad23-recover.out
@@ -0,0 +1,21 @@
+WARNING: bad23.pdf: offset 341: attempting to recover stream length
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Length () >>
+Raw stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+Uncompressed stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+End of stream data
+unparse: 4 0 R
+unparseResolved: 4 0 R
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad23.out b/qpdf/qtest/qpdf/bad23.out
new file mode 100644
index 00000000..5cef84f9
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad23.out
@@ -0,0 +1 @@
+bad23.pdf: offset 317: /Length key in stream dictionary is not an integer
diff --git a/qpdf/qtest/qpdf/bad23.pdf b/qpdf/qtest/qpdf/bad23.pdf
new file mode 100644
index 00000000..0baead97
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad23.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length ()
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad24-recover.out b/qpdf/qtest/qpdf/bad24-recover.out
new file mode 100644
index 00000000..5e643eff
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad24-recover.out
@@ -0,0 +1,2 @@
+WARNING: bad24.pdf: offset 341: attempting to recover stream length
+bad24.pdf: offset 341: unable to recover stream data
diff --git a/qpdf/qtest/qpdf/bad24.out b/qpdf/qtest/qpdf/bad24.out
new file mode 100644
index 00000000..76baa51a
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad24.out
@@ -0,0 +1 @@
+bad24.pdf: offset 385: expected endstream
diff --git a/qpdf/qtest/qpdf/bad24.pdf b/qpdf/qtest/qpdf/bad24.pdf
new file mode 100644
index 00000000..7af8c7d6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad24.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+enxstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad25-recover.out b/qpdf/qtest/qpdf/bad25-recover.out
new file mode 100644
index 00000000..f8a18758
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad25-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad25.pdf: offset 0: file is damaged
+WARNING: bad25.pdf: offset 307: expected n n obj
+WARNING: Attempting to reconstruct cross-reference table
+bad25.pdf: offset 307: expected n n obj
diff --git a/qpdf/qtest/qpdf/bad25.out b/qpdf/qtest/qpdf/bad25.out
new file mode 100644
index 00000000..11e3899a
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad25.out
@@ -0,0 +1 @@
+bad25.pdf: offset 307: expected n n obj
diff --git a/qpdf/qtest/qpdf/bad25.pdf b/qpdf/qtest/qpdf/bad25.pdf
new file mode 100644
index 00000000..a51974d3
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad25.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+x 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad26-recover.out b/qpdf/qtest/qpdf/bad26-recover.out
new file mode 100644
index 00000000..64b6f610
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad26-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad26.pdf: offset 0: file is damaged
+WARNING: bad26.pdf: offset 307: expected n n obj
+WARNING: Attempting to reconstruct cross-reference table
+bad26.pdf: offset 307: expected n n obj
diff --git a/qpdf/qtest/qpdf/bad26.out b/qpdf/qtest/qpdf/bad26.out
new file mode 100644
index 00000000..2b1b01e2
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad26.out
@@ -0,0 +1 @@
+bad26.pdf: offset 307: expected n n obj
diff --git a/qpdf/qtest/qpdf/bad26.pdf b/qpdf/qtest/qpdf/bad26.pdf
new file mode 100644
index 00000000..4a7e3b21
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad26.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 x obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad27-recover.out b/qpdf/qtest/qpdf/bad27-recover.out
new file mode 100644
index 00000000..be980b95
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad27-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad27.pdf: offset 0: file is damaged
+WARNING: bad27.pdf: offset 307: expected n n obj
+WARNING: Attempting to reconstruct cross-reference table
+bad27.pdf: offset 307: expected n n obj
diff --git a/qpdf/qtest/qpdf/bad27.out b/qpdf/qtest/qpdf/bad27.out
new file mode 100644
index 00000000..a0c47a7c
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad27.out
@@ -0,0 +1 @@
+bad27.pdf: offset 307: expected n n obj
diff --git a/qpdf/qtest/qpdf/bad27.pdf b/qpdf/qtest/qpdf/bad27.pdf
new file mode 100644
index 00000000..032b2125
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad27.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 xbj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad28-recover.out b/qpdf/qtest/qpdf/bad28-recover.out
new file mode 100644
index 00000000..3bf944d5
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad28-recover.out
@@ -0,0 +1,21 @@
+WARNING: bad28.pdf: offset 395: expected endobj
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Length 44 >>
+Raw stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+Uncompressed stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+End of stream data
+unparse: 4 0 R
+unparseResolved: 4 0 R
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad28.out b/qpdf/qtest/qpdf/bad28.out
new file mode 100644
index 00000000..a0809eb9
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad28.out
@@ -0,0 +1,21 @@
+WARNING: bad28.pdf: offset 395: expected endobj
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Length 44 >>
+Raw stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+Uncompressed stream data:
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+
+End of stream data
+unparse: 4 0 R
+unparseResolved: 4 0 R
+test 0 done
diff --git a/qpdf/qtest/qpdf/bad28.pdf b/qpdf/qtest/qpdf/bad28.pdf
new file mode 100644
index 00000000..c77a2069
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad28.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+enwobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad29-recover.out b/qpdf/qtest/qpdf/bad29-recover.out
new file mode 100644
index 00000000..bc6e38d5
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad29-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad29.pdf: offset 0: file is damaged
+WARNING: bad29.pdf: offset 742: null character not allowed in name token
+WARNING: Attempting to reconstruct cross-reference table
+bad29.pdf: offset 742: null character not allowed in name token
diff --git a/qpdf/qtest/qpdf/bad29.out b/qpdf/qtest/qpdf/bad29.out
new file mode 100644
index 00000000..9f279743
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad29.out
@@ -0,0 +1 @@
+bad29.pdf: offset 742: null character not allowed in name token
diff --git a/qpdf/qtest/qpdf/bad29.pdf b/qpdf/qtest/qpdf/bad29.pdf
new file mode 100644
index 00000000..a45151e2
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad29.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Som#00ething 1
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad3-recover.out b/qpdf/qtest/qpdf/bad3-recover.out
new file mode 100644
index 00000000..d205398a
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad3-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad3.pdf: offset 0: file is damaged
+WARNING: bad3.pdf: offset 542: xref not found
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad3.out b/qpdf/qtest/qpdf/bad3.out
new file mode 100644
index 00000000..22ee8fbd
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad3.out
@@ -0,0 +1 @@
+bad3.pdf: offset 542: xref not found
diff --git a/qpdf/qtest/qpdf/bad3.pdf b/qpdf/qtest/qpdf/bad3.pdf
new file mode 100644
index 00000000..3e078f37
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad3.pdf
@@ -0,0 +1,76 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+noxref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref 542
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad30-recover.out b/qpdf/qtest/qpdf/bad30-recover.out
new file mode 100644
index 00000000..95d194d4
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad30-recover.out
@@ -0,0 +1,6 @@
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Filter (FlateDecode) /Length 123 >>
+Raw stream data:
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+Uncompressed stream data:
+bad30.pdf: offset 629: invalid filter object type for this stream
diff --git a/qpdf/qtest/qpdf/bad30.out b/qpdf/qtest/qpdf/bad30.out
new file mode 100644
index 00000000..95d194d4
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad30.out
@@ -0,0 +1,6 @@
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Filter (FlateDecode) /Length 123 >>
+Raw stream data:
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+Uncompressed stream data:
+bad30.pdf: offset 629: invalid filter object type for this stream
diff --git a/qpdf/qtest/qpdf/bad30.pdf b/qpdf/qtest/qpdf/bad30.pdf
new file mode 100644
index 00000000..05c52764
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad30.pdf
@@ -0,0 +1,93 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj
+<<
+ % Comment
+ /Length
+ 123
+ /Filter (FlateDecode)
+>>
+stream
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+endstream
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+0000000556 00000 n
+trailer <<
+ /Size 8
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+771
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad31-recover.out b/qpdf/qtest/qpdf/bad31-recover.out
new file mode 100644
index 00000000..313e2083
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad31-recover.out
@@ -0,0 +1,9 @@
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Filter [ /Oink /Moo /FlateDecode ] /Length 123 >>
+Raw stream data:
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+Uncompressed stream data:
+Stream data is not filterable.
+unparse: 7 0 R
+unparseResolved: 7 0 R
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad31.out b/qpdf/qtest/qpdf/bad31.out
new file mode 100644
index 00000000..2ad01536
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad31.out
@@ -0,0 +1,9 @@
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Filter [ /Oink /Moo /FlateDecode ] /Length 123 >>
+Raw stream data:
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+Uncompressed stream data:
+Stream data is not filterable.
+unparse: 7 0 R
+unparseResolved: 7 0 R
+test 0 done
diff --git a/qpdf/qtest/qpdf/bad31.pdf b/qpdf/qtest/qpdf/bad31.pdf
new file mode 100644
index 00000000..b3c986c8
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad31.pdf
@@ -0,0 +1,93 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj
+<<
+ % Comment
+ /Length
+ 123
+ /Filter [/Oink /Moo /FlateDecode]
+>>
+stream
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+endstream
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+0000000556 00000 n
+trailer <<
+ /Size 8
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+783
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad32-recover.out b/qpdf/qtest/qpdf/bad32-recover.out
new file mode 100644
index 00000000..d0fe873b
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad32-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad32.pdf: offset 0: file is damaged
+WARNING: bad32.pdf: offset 307: expected 4 0 obj
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is indirect
+/QTest is null
+unparse: 4 0 R
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad32.out b/qpdf/qtest/qpdf/bad32.out
new file mode 100644
index 00000000..3212ea02
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad32.out
@@ -0,0 +1 @@
+bad32.pdf: offset 307: expected 4 0 obj
diff --git a/qpdf/qtest/qpdf/bad32.pdf b/qpdf/qtest/qpdf/bad32.pdf
new file mode 100644
index 00000000..25819933
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad32.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+9 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 4 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad4-recover.out b/qpdf/qtest/qpdf/bad4-recover.out
new file mode 100644
index 00000000..f7c56522
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad4-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad4.pdf: offset 0: file is damaged
+WARNING: bad4.pdf: offset 547: xref syntax invalid
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad4.out b/qpdf/qtest/qpdf/bad4.out
new file mode 100644
index 00000000..c29db5f4
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad4.out
@@ -0,0 +1 @@
+bad4.pdf: offset 547: xref syntax invalid
diff --git a/qpdf/qtest/qpdf/bad4.pdf b/qpdf/qtest/qpdf/bad4.pdf
new file mode 100644
index 00000000..ed833b92
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad4.pdf
@@ -0,0 +1,77 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+x0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad5-recover.out b/qpdf/qtest/qpdf/bad5-recover.out
new file mode 100644
index 00000000..44f76aed
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad5-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad5.pdf: offset 0: file is damaged
+WARNING: bad5.pdf: offset 591: invalid xref entry (obj=2)
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad5.out b/qpdf/qtest/qpdf/bad5.out
new file mode 100644
index 00000000..5a9d8a13
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad5.out
@@ -0,0 +1 @@
+bad5.pdf: offset 591: invalid xref entry (obj=2)
diff --git a/qpdf/qtest/qpdf/bad5.pdf b/qpdf/qtest/qpdf/bad5.pdf
new file mode 100644
index 00000000..d6b0871f
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad5.pdf
@@ -0,0 +1,77 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+000x000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad6-recover.out b/qpdf/qtest/qpdf/bad6-recover.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad6-recover.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad6.out b/qpdf/qtest/qpdf/bad6.out
new file mode 100644
index 00000000..26b50cb6
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad6.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 0 done
diff --git a/qpdf/qtest/qpdf/bad6.pdf b/qpdf/qtest/qpdf/bad6.pdf
new file mode 100644
index 00000000..50238b21
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad6.pdf
@@ -0,0 +1,122 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 7 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+7 0 obj
+<<
+ /Length 48
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Sandwiches) Tj
+ET
+endstream
+endobj
+
+xref
+0 1
+0000000006 65535 f
+3 2
+0000000750 00000 n
+0000000000 00000 f
+7 1
+0000000922 00000 n
+trailer <<
+ /Size 8
+ /Root 1 0 R
+ /Prev 542
+>>
+startxref
+1022
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad7-recover.out b/qpdf/qtest/qpdf/bad7-recover.out
new file mode 100644
index 00000000..56b99f9d
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad7-recover.out
@@ -0,0 +1,4 @@
+WARNING: bad7.pdf: offset 0: file is damaged
+WARNING: bad7.pdf: offset 698: expected trailer dictionary
+WARNING: Attempting to reconstruct cross-reference table
+bad7.pdf: unable to find trailer dictionary while recovering damanged file
diff --git a/qpdf/qtest/qpdf/bad7.out b/qpdf/qtest/qpdf/bad7.out
new file mode 100644
index 00000000..aac77151
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad7.out
@@ -0,0 +1 @@
+bad7.pdf: offset 698: expected trailer dictionary
diff --git a/qpdf/qtest/qpdf/bad7.pdf b/qpdf/qtest/qpdf/bad7.pdf
new file mode 100644
index 00000000..f44c1e66
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad7.pdf
@@ -0,0 +1,77 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer 3 <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad8-recover.out b/qpdf/qtest/qpdf/bad8-recover.out
new file mode 100644
index 00000000..e9144d42
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad8-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad8.pdf: offset 0: file is damaged
+WARNING: bad8.pdf: offset 543: xref not found
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad8.out b/qpdf/qtest/qpdf/bad8.out
new file mode 100644
index 00000000..a3338ed4
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad8.out
@@ -0,0 +1 @@
+bad8.pdf: offset 543: xref not found
diff --git a/qpdf/qtest/qpdf/bad8.pdf b/qpdf/qtest/qpdf/bad8.pdf
new file mode 100644
index 00000000..9f424af1
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad8.pdf
@@ -0,0 +1,104 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000128 00000 n
+0000000300 00000 n
+0000000389 00000 n
+0000000424 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+542
+%%EOF
+
+4 0 obj
+<<
+ /Length 43
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Salad) Tj
+ET
+endstream
+endobj
+
+xref
+0 1
+0000000000 65535 f
+4 1
+0000000750 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /Prev 543
+>>
+startxref
+845
+%%EOF
diff --git a/qpdf/qtest/qpdf/bad9-recover.out b/qpdf/qtest/qpdf/bad9-recover.out
new file mode 100644
index 00000000..424b47cf
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad9-recover.out
@@ -0,0 +1,9 @@
+WARNING: bad9.pdf: offset 0: file is damaged
+WARNING: bad9.pdf: offset 712: trailer dictionary lacks /Size key
+WARNING: Attempting to reconstruct cross-reference table
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/bad9.out b/qpdf/qtest/qpdf/bad9.out
new file mode 100644
index 00000000..6799ccd9
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad9.out
@@ -0,0 +1 @@
+bad9.pdf: offset 712: trailer dictionary lacks /Size key
diff --git a/qpdf/qtest/qpdf/bad9.pdf b/qpdf/qtest/qpdf/bad9.pdf
new file mode 100644
index 00000000..a52b15fa
--- /dev/null
+++ b/qpdf/qtest/qpdf/bad9.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Siqe 7
+ /Root 1 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/badlin1.out b/qpdf/qtest/qpdf/badlin1.out
new file mode 100644
index 00000000..8ad4bfd5
--- /dev/null
+++ b/qpdf/qtest/qpdf/badlin1.out
@@ -0,0 +1,380 @@
+ERROR: first page object (/O) mismatch
+ERROR: space before first xref item (/T) mismatch (computed = 11777; file = 11771
+WARNING: end of first page section (/E) mismatch: /E = 1827; computed = 3889..3891
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 62: in hint table but not computed list
+badlin1.pdf: linearization data:
+
+file_size: 13103
+first_page_object: 63
+first_page_end: 1827
+npages: 30
+xref_zero_offset: 11770
+first_page: 0
+H_offset: 1211
+H_length: 203
+
+Page Offsets Hint Table
+
+min_nobjects: 2
+first_page_offset: 1414
+nbits_delta_nobjects: 4
+min_page_length: 259
+nbits_delta_page_length: 12
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 12
+nbits_nshared_objects: 2
+nbits_shared_identifier: 2
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 16
+ length: 2477
+ content_offset: 0
+ content_length: 2218
+ nshared_objects: 2
+ identifier 0: 0
+ numerator 0: 0
+ identifier 1: 0
+ numerator 1: 0
+Page 1:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 2:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 3:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 4:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 5:
+ nobjects: 2
+ length: 261
+ content_offset: 0
+ content_length: 2
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 6:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 7:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 8:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 9:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 10:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 11:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 12:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 13:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 14:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 15:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 16:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 17:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 18:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 19:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 20:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 21:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 22:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 23:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 24:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 25:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 26:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 27:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 28:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 29:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 0
+nshared_first_page: 16
+nshared_total: 16
+nbits_nobjects: 0
+min_group_length: 34
+nbits_delta_group_length: 9
+Shared Object 0:
+ group length: 157
+Shared Object 1:
+ group length: 105
+Shared Object 2:
+ group length: 117
+Shared Object 3:
+ group length: 34
+Shared Object 4:
+ group length: 82
+Shared Object 5:
+ group length: 191
+Shared Object 6:
+ group length: 144
+Shared Object 7:
+ group length: 168
+Shared Object 8:
+ group length: 291
+Shared Object 9:
+ group length: 165
+Shared Object 10:
+ group length: 162
+Shared Object 11:
+ group length: 182
+Shared Object 12:
+ group length: 201
+Shared Object 13:
+ group length: 150
+Shared Object 14:
+ group length: 164
+Shared Object 15:
+ group length: 164
+
+Outlines Hint Table
+
+first_object: 66
+first_object_offset: 1827
+nobjects: 12
+group_length: 2064
diff --git a/qpdf/qtest/qpdf/badlin1.pdf b/qpdf/qtest/qpdf/badlin1.pdf
new file mode 100644
index 00000000..8539ac4b
--- /dev/null
+++ b/qpdf/qtest/qpdf/badlin1.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/check-ID.pl b/qpdf/qtest/qpdf/check-ID.pl
new file mode 100644
index 00000000..963b48fe
--- /dev/null
+++ b/qpdf/qtest/qpdf/check-ID.pl
@@ -0,0 +1,20 @@
+use strict;
+$^W=1;
+
+my $okay = 0;
+my $id = '31415926535897932384626433832795';
+while (<>)
+{
+ if ((m,/ID ?\[<([[:xdigit:]]{32})><$id>\],) && ($1 ne $id))
+ {
+ $okay = 1;
+ }
+}
+if ($okay)
+{
+ print "ID okay\n";
+}
+else
+{
+ print "ID bad\n";
+}
diff --git a/qpdf/qtest/qpdf/delete-and-reuse.pdf b/qpdf/qtest/qpdf/delete-and-reuse.pdf
new file mode 100644
index 00000000..53a89ae5
--- /dev/null
+++ b/qpdf/qtest/qpdf/delete-and-reuse.pdf
@@ -0,0 +1,1573 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels 107 0 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+95 0 obj
+<<
+ /Type /Outlines
+ /First 96 0 R
+ /Last 97 0 R
+ /Count 6
+>>
+endobj
+
+96 0 obj
+<<
+ /Type /Outline
+ /Title (Isís 1 -> 5: /XYZ null null null)
+ /Parent 95 0 R
+ /Count 4
+ /Next 97 0 R
+ /First 98 0 R
+ /Last 99 0 R
+ /Dest [ 8 0 R /XYZ null null null ]
+>>
+endobj
+
+97 0 obj
+<<
+ /Type /Outline
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Parent 95 0 R
+ /Prev 96 0 R
+ /Dest [ 18 0 R /XYZ 66 756 3 ]
+>>
+endobj
+
+98 0 obj
+<<
+ /Type /Outline
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Parent 96 0 R
+ /Next 99 0 R
+ /First 100 0 R
+ /Last 101 0 R
+ /Count -3
+ /Dest [ 14 0 R /Fit ]
+>>
+endobj
+
+99 0 obj
+<<
+ /Type /Outline
+ % /Title (Sandy (Sandy [Greek]) 1.2 -> 13: /FitH 792)
+ /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
+ /Parent 96 0 R
+ /Prev 98 0 R
+ /First 105 0 R
+ /Last 106 0 R
+ /Count 2
+ /Dest [ 16 0 R /FitH 792 ]
+>>
+endobj
+
+100 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Parent 98 0 R
+ /Next 101 0 R
+ /First 102 0 R
+ /Last 103 0 R
+ /Count -2
+ /Dest [ 15 0 R /FitV 100 ]
+>>
+endobj
+
+101 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Parent 98 0 R
+ /Prev 100 0 R
+ /First 104 0 R
+ /Last 104 0 R
+ /Count 1
+ /Dest [ 15 0 R /XYZ null null null ]
+>>
+endobj
+
+102 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Parent 100 0 R
+ /Next 103 0 R
+ /Dest [ 21 0 R /XYZ null null null ]
+>>
+endobj
+
+103 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Parent 100 0 R
+ /Prev 102 0 R
+ /Dest [ 22 0 R /XYZ null null null ]
+>>
+endobj
+
+104 0 obj
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Parent 101 0 R
+ /Dest [ 25 0 R /XYZ null null null ]
+>>
+endobj
+
+105 0 obj
+<<
+ /Type /Outline
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Parent 99 0 R
+ /Next 106 0 R
+ /Dest [ 4 0 R /FitR 66 714 180 770 ]
+>>
+endobj
+
+106 0 obj
+<<
+ /Type /Outline
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Parent 99 0 R
+ /Prev 105 0 R
+ /Dest [ 3 0 R /XYZ null null null ]
+>>
+endobj
+
+107 0 obj
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /r /St 1 >>
+ 7 << /P () >>
+ 9 << /S /r /St 6 >>
+ 11 << /P () >>
+ 12 << /S /D /St 2 >>
+ 15 << /S /D /St 6 >>
+ 19 << /P () >>
+ 20 << /S /D /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endobj
+
+xref
+0 108
+0000000000 65535 f
+0000000025 00000 n
+0000000145 00000 n
+0000000541 00000 n
+0000000746 00000 n
+0000000951 00000 n
+0000001156 00000 n
+0000001361 00000 n
+0000001566 00000 n
+0000001771 00000 n
+0000001976 00000 n
+0000002182 00000 n
+0000002389 00000 n
+0000002596 00000 n
+0000002803 00000 n
+0000003010 00000 n
+0000003217 00000 n
+0000003424 00000 n
+0000003631 00000 n
+0000003838 00000 n
+0000004045 00000 n
+0000004252 00000 n
+0000004459 00000 n
+0000004666 00000 n
+0000004873 00000 n
+0000005080 00000 n
+0000005287 00000 n
+0000005494 00000 n
+0000005701 00000 n
+0000005908 00000 n
+0000006115 00000 n
+0000006322 00000 n
+0000006529 00000 n
+0000006748 00000 n
+0000006851 00000 n
+0000006871 00000 n
+0000006990 00000 n
+0000007049 00000 n
+0000007152 00000 n
+0000007195 00000 n
+0000007298 00000 n
+0000007341 00000 n
+0000007444 00000 n
+0000007487 00000 n
+0000007590 00000 n
+0000007633 00000 n
+0000007736 00000 n
+0000007779 00000 n
+0000007882 00000 n
+0000007925 00000 n
+0000008028 00000 n
+0000008071 00000 n
+0000008174 00000 n
+0000008218 00000 n
+0000008321 00000 n
+0000008365 00000 n
+0000008469 00000 n
+0000008513 00000 n
+0000008617 00000 n
+0000008661 00000 n
+0000008765 00000 n
+0000008809 00000 n
+0000008913 00000 n
+0000008957 00000 n
+0000009061 00000 n
+0000009105 00000 n
+0000009209 00000 n
+0000009253 00000 n
+0000009357 00000 n
+0000009401 00000 n
+0000009505 00000 n
+0000009549 00000 n
+0000009653 00000 n
+0000009697 00000 n
+0000009801 00000 n
+0000009845 00000 n
+0000009949 00000 n
+0000009993 00000 n
+0000010097 00000 n
+0000010141 00000 n
+0000010245 00000 n
+0000010289 00000 n
+0000010393 00000 n
+0000010437 00000 n
+0000010541 00000 n
+0000010585 00000 n
+0000010689 00000 n
+0000010733 00000 n
+0000010837 00000 n
+0000010881 00000 n
+0000010985 00000 n
+0000011029 00000 n
+0000011133 00000 n
+0000011177 00000 n
+0000011281 00000 n
+0000011301 00000 n
+0000011388 00000 n
+0000011584 00000 n
+0000011730 00000 n
+0000011905 00000 n
+0000012258 00000 n
+0000012449 00000 n
+0000012659 00000 n
+0000012828 00000 n
+0000012997 00000 n
+0000013150 00000 n
+0000013319 00000 n
+0000013484 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 108
+>>
+startxref
+13801
+%%EOF
+
+% 1. Delete page labels
+xref
+0 1
+0000000107 65535 f
+107 1
+0000000000 00001 f
+trailer << /Root 1 0 R /Size 108 /Prev 13801 >>
+startxref
+16059
+%%EOF
+
+% 2. Delete outlines, reuse page labels.
+
+107 1 obj
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /D /St 1 >>
+ 7 << /P () >>
+ 9 << /S /R /St 6 >>
+ 11 << /P () >>
+ 12 << /S /r /St 2 >>
+ 15 << /S /r /St 6 >>
+ 19 << /P () >>
+ 20 << /S /R /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endobj
+
+% Reuse object 1 with the same generation number. Leave outlines
+% there pointing to a deleted object.
+1 0 obj
+<<
+ /PageLabels 107 1 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+xref
+0 2
+0000000095 65535 f
+0000016648 00000 n
+95 13
+0000000096 00001 f
+0000000097 00001 f
+0000000098 00001 f
+0000000099 00001 f
+0000000100 00001 f
+0000000101 00001 f
+0000000102 00001 f
+0000000103 00001 f
+0000000104 00001 f
+0000000105 00001 f
+0000000106 00001 f
+0000000000 00001 f
+0000016227 00001 n
+trailer << /Size 108 /Prev 16059 /Root 1 0 R >>
+startxref
+16768
+%%EOF
diff --git a/qpdf/qtest/qpdf/delete-and-reuse.qdf b/qpdf/qtest/qpdf/delete-and-reuse.qdf
new file mode 100644
index 00000000..14fbbdb5
--- /dev/null
+++ b/qpdf/qtest/qpdf/delete-and-reuse.qdf
@@ -0,0 +1,1408 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels 2 0 R
+ /PageMode /UseOutlines
+ /Pages 3 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Nums [
+ 0
+ <<
+ /P ()
+ >>
+ 2
+ <<
+ /S /D
+ /St 1
+ >>
+ 7
+ <<
+ /P ()
+ >>
+ 9
+ <<
+ /S /R
+ /St 6
+ >>
+ 11
+ <<
+ /P ()
+ >>
+ 12
+ <<
+ /S /r
+ /St 2
+ >>
+ 15
+ <<
+ /S /r
+ /St 6
+ >>
+ 19
+ <<
+ /P ()
+ >>
+ 20
+ <<
+ /S /R
+ /St 12
+ >>
+ 22
+ <<
+ /S /D
+ /St 16059
+ >>
+ 23
+ <<
+ /S /r
+ /St 50
+ >>
+ 29
+ <<
+ /S /r
+ /St 54
+ >>
+ ]
+>>
+endobj
+
+3 0 obj
+<<
+ /Count 30
+ /Kids [
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ 33 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+4 0 obj
+<<
+ /Contents 34 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+5 0 obj
+<<
+ /Contents 38 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+6 0 obj
+<<
+ /Contents 40 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+7 0 obj
+<<
+ /Contents 42 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+8 0 obj
+<<
+ /Contents 44 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+9 0 obj
+<<
+ /Contents 46 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+10 0 obj
+<<
+ /Contents 48 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+11 0 obj
+<<
+ /Contents 50 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+12 0 obj
+<<
+ /Contents 52 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+13 0 obj
+<<
+ /Contents 54 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+14 0 obj
+<<
+ /Contents 56 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+15 0 obj
+<<
+ /Contents 58 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+16 0 obj
+<<
+ /Contents 60 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+17 0 obj
+<<
+ /Contents 62 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+18 0 obj
+<<
+ /Contents 64 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+19 0 obj
+<<
+ /Contents 66 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+20 0 obj
+<<
+ /Contents 68 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+21 0 obj
+<<
+ /Contents 70 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+22 0 obj
+<<
+ /Contents 72 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+23 0 obj
+<<
+ /Contents 74 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+24 0 obj
+<<
+ /Contents 76 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+25 0 obj
+<<
+ /Contents 78 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+26 0 obj
+<<
+ /Contents 80 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+27 0 obj
+<<
+ /Contents 82 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+28 0 obj
+<<
+ /Contents 84 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+29 0 obj
+<<
+ /Contents 86 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+30 0 obj
+<<
+ /Contents 88 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+31 0 obj
+<<
+ /Contents 90 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+32 0 obj
+<<
+ /Contents 92 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+33 0 obj
+<<
+ /Contents 94 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 36 0 R
+ >>
+ /ProcSet 37 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+34 0 obj
+<<
+ /Length 35 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+35 0 obj
+46
+endobj
+
+36 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+37 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+38 0 obj
+<<
+ /Length 39 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+39 0 obj
+46
+endobj
+
+%% Contents for page 3
+40 0 obj
+<<
+ /Length 41 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+41 0 obj
+46
+endobj
+
+%% Contents for page 4
+42 0 obj
+<<
+ /Length 43 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+43 0 obj
+46
+endobj
+
+%% Contents for page 5
+44 0 obj
+<<
+ /Length 45 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+45 0 obj
+46
+endobj
+
+%% Contents for page 6
+46 0 obj
+<<
+ /Length 47 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+47 0 obj
+46
+endobj
+
+%% Contents for page 7
+48 0 obj
+<<
+ /Length 49 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+49 0 obj
+46
+endobj
+
+%% Contents for page 8
+50 0 obj
+<<
+ /Length 51 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+51 0 obj
+46
+endobj
+
+%% Contents for page 9
+52 0 obj
+<<
+ /Length 53 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+53 0 obj
+46
+endobj
+
+%% Contents for page 10
+54 0 obj
+<<
+ /Length 55 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+55 0 obj
+46
+endobj
+
+%% Contents for page 11
+56 0 obj
+<<
+ /Length 57 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+57 0 obj
+47
+endobj
+
+%% Contents for page 12
+58 0 obj
+<<
+ /Length 59 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+59 0 obj
+47
+endobj
+
+%% Contents for page 13
+60 0 obj
+<<
+ /Length 61 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+61 0 obj
+47
+endobj
+
+%% Contents for page 14
+62 0 obj
+<<
+ /Length 63 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+63 0 obj
+47
+endobj
+
+%% Contents for page 15
+64 0 obj
+<<
+ /Length 65 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+65 0 obj
+47
+endobj
+
+%% Contents for page 16
+66 0 obj
+<<
+ /Length 67 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+67 0 obj
+47
+endobj
+
+%% Contents for page 17
+68 0 obj
+<<
+ /Length 69 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+69 0 obj
+47
+endobj
+
+%% Contents for page 18
+70 0 obj
+<<
+ /Length 71 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+71 0 obj
+47
+endobj
+
+%% Contents for page 19
+72 0 obj
+<<
+ /Length 73 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+73 0 obj
+47
+endobj
+
+%% Contents for page 20
+74 0 obj
+<<
+ /Length 75 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+75 0 obj
+47
+endobj
+
+%% Contents for page 21
+76 0 obj
+<<
+ /Length 77 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+77 0 obj
+47
+endobj
+
+%% Contents for page 22
+78 0 obj
+<<
+ /Length 79 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+79 0 obj
+47
+endobj
+
+%% Contents for page 23
+80 0 obj
+<<
+ /Length 81 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+81 0 obj
+47
+endobj
+
+%% Contents for page 24
+82 0 obj
+<<
+ /Length 83 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+83 0 obj
+47
+endobj
+
+%% Contents for page 25
+84 0 obj
+<<
+ /Length 85 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+85 0 obj
+47
+endobj
+
+%% Contents for page 26
+86 0 obj
+<<
+ /Length 87 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+87 0 obj
+47
+endobj
+
+%% Contents for page 27
+88 0 obj
+<<
+ /Length 89 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+89 0 obj
+47
+endobj
+
+%% Contents for page 28
+90 0 obj
+<<
+ /Length 91 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+91 0 obj
+47
+endobj
+
+%% Contents for page 29
+92 0 obj
+<<
+ /Length 93 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+93 0 obj
+47
+endobj
+
+%% Contents for page 30
+94 0 obj
+<<
+ /Length 95 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+95 0 obj
+47
+endobj
+
+xref
+0 96
+0000000000 65535 f
+0000000025 00000 n
+0000000124 00000 n
+0000000655 00000 n
+0000001052 00000 n
+0000001257 00000 n
+0000001462 00000 n
+0000001667 00000 n
+0000001872 00000 n
+0000002077 00000 n
+0000002282 00000 n
+0000002488 00000 n
+0000002694 00000 n
+0000002901 00000 n
+0000003108 00000 n
+0000003315 00000 n
+0000003522 00000 n
+0000003729 00000 n
+0000003936 00000 n
+0000004143 00000 n
+0000004350 00000 n
+0000004557 00000 n
+0000004764 00000 n
+0000004971 00000 n
+0000005178 00000 n
+0000005385 00000 n
+0000005592 00000 n
+0000005799 00000 n
+0000006006 00000 n
+0000006213 00000 n
+0000006420 00000 n
+0000006627 00000 n
+0000006834 00000 n
+0000007041 00000 n
+0000007260 00000 n
+0000007363 00000 n
+0000007383 00000 n
+0000007502 00000 n
+0000007561 00000 n
+0000007664 00000 n
+0000007707 00000 n
+0000007810 00000 n
+0000007853 00000 n
+0000007956 00000 n
+0000007999 00000 n
+0000008102 00000 n
+0000008145 00000 n
+0000008248 00000 n
+0000008291 00000 n
+0000008394 00000 n
+0000008437 00000 n
+0000008540 00000 n
+0000008583 00000 n
+0000008686 00000 n
+0000008730 00000 n
+0000008833 00000 n
+0000008877 00000 n
+0000008981 00000 n
+0000009025 00000 n
+0000009129 00000 n
+0000009173 00000 n
+0000009277 00000 n
+0000009321 00000 n
+0000009425 00000 n
+0000009469 00000 n
+0000009573 00000 n
+0000009617 00000 n
+0000009721 00000 n
+0000009765 00000 n
+0000009869 00000 n
+0000009913 00000 n
+0000010017 00000 n
+0000010061 00000 n
+0000010165 00000 n
+0000010209 00000 n
+0000010313 00000 n
+0000010357 00000 n
+0000010461 00000 n
+0000010505 00000 n
+0000010609 00000 n
+0000010653 00000 n
+0000010757 00000 n
+0000010801 00000 n
+0000010905 00000 n
+0000010949 00000 n
+0000011053 00000 n
+0000011097 00000 n
+0000011201 00000 n
+0000011245 00000 n
+0000011349 00000 n
+0000011393 00000 n
+0000011497 00000 n
+0000011541 00000 n
+0000011645 00000 n
+0000011689 00000 n
+0000011793 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 96
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+11813
+%%EOF
diff --git a/qpdf/qtest/qpdf/diff-encrypted b/qpdf/qtest/qpdf/diff-encrypted
new file mode 100755
index 00000000..64c0b2a8
--- /dev/null
+++ b/qpdf/qtest/qpdf/diff-encrypted
@@ -0,0 +1,7 @@
+#!/bin/sh
+lines=$(expr + $(diff $1 $2 | egrep '^[<>]' | egrep -v 'Date' | wc -l))
+if [ "$lines" == "0" ]; then
+ echo okay
+else
+ diff -a -U 0 $1 $2
+fi
diff --git a/qpdf/qtest/qpdf/enc-R2,V1,O=master.pdf b/qpdf/qtest/qpdf/enc-R2,V1,O=master.pdf
new file mode 100644
index 00000000..bac7eaec
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R2,V1,O=master.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R2,V1,U=view,O=master.pdf b/qpdf/qtest/qpdf/enc-R2,V1,U=view,O=master.pdf
new file mode 100644
index 00000000..d5492134
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R2,V1,U=view,O=master.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R2,V1,U=view.pdf b/qpdf/qtest/qpdf/enc-R2,V1,U=view.pdf
new file mode 100644
index 00000000..d99bf6f8
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R2,V1,U=view.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R2,V1.pdf b/qpdf/qtest/qpdf/enc-R2,V1.pdf
new file mode 100644
index 00000000..dec9e6d7
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R2,V1.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R3,V2,O=master.pdf b/qpdf/qtest/qpdf/enc-R3,V2,O=master.pdf
new file mode 100644
index 00000000..88585663
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R3,V2,O=master.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R3,V2,U=view,O=master.pdf b/qpdf/qtest/qpdf/enc-R3,V2,U=view,O=master.pdf
new file mode 100644
index 00000000..9b95ae36
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R3,V2,U=view,O=master.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R3,V2,U=view.pdf b/qpdf/qtest/qpdf/enc-R3,V2,U=view.pdf
new file mode 100644
index 00000000..a4efba7a
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R3,V2,U=view.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-R3,V2.pdf b/qpdf/qtest/qpdf/enc-R3,V2.pdf
new file mode 100644
index 00000000..80727887
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-R3,V2.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-base.pdf b/qpdf/qtest/qpdf/enc-base.pdf
new file mode 100644
index 00000000..bac51307
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-base.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/enc-long-password.pdf b/qpdf/qtest/qpdf/enc-long-password.pdf
new file mode 100755
index 00000000..ef064fe9
--- /dev/null
+++ b/qpdf/qtest/qpdf/enc-long-password.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/encrypted-with-images.pdf b/qpdf/qtest/qpdf/encrypted-with-images.pdf
new file mode 100644
index 00000000..dbceb445
--- /dev/null
+++ b/qpdf/qtest/qpdf/encrypted-with-images.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/encrypted1.out b/qpdf/qtest/qpdf/encrypted1.out
new file mode 100644
index 00000000..f3946c2f
--- /dev/null
+++ b/qpdf/qtest/qpdf/encrypted1.out
@@ -0,0 +1,578 @@
+D:20000914005716
+Acrobat Distiller 4.05 for Windows
+(hs[¨.<7µ¸"\205\020º~?ö¥zßù\220\024\203Þ#W\230\214\nBªH)
+(ó*Øý¢¬:F\027\21177\nov\007\031 I\235­\205\n\225ñw¹\b\233n Ê)
+1 g
+/GS1 gs
+1 i
+178.226 60.781 344.491 -11.279 re
+f
+BT
+/F4 1 Tf
+9.999 0 0 9.999 178.2259 51.9016 Tm
+0 g
+0.003 Tc
+0 Tw
+[(T)7(h)-1(e)-249(U)5(ni)5(code)-249(St)5(andar)8(d)-253(3)-1(.0,)-251(C)10(opyr)8(i)5(ght)-247(©)-221(1991-2000,)-251(U)5(n)-1(i)5(c)3(ode,)-251(I)0(nc.)-251(A)2(l)5(l)-247(r)8(i)5(ght)5(s)-244(r)8(es)8(er)8(ved)]TJ
+ET
+1 g
+72.035 60.781 15.119 -11.279 re
+f
+BT
+9.999 0 0 9.999 72.0347 51.9016 Tm
+0 g
+0.004 Tc
+(542)Tj
+ET
+1 g
+490.8 769.802 31.197 -15.959 re
+f
+BT
+/F5 1 Tf
+13.9985 0 0 13.9985 490.7998 756.9629 Tm
+0 g
+0.0057 Tc
+[(25F)8.1(F)]TJ
+ET
+1 g
+242.541 769.802 108.831 -15.959 re
+f
+BT
+13.9985 0 0 13.9985 242.5405 756.9629 Tm
+0 g
+0.0027 Tc
+[(Geom)12.8(etric)-247.6(Shapes)]TJ
+ET
+1 g
+72.035 769.802 31.317 -15.959 re
+f
+BT
+13.9985 0 0 13.9985 72.0347 756.9629 Tm
+0 g
+0.0057 Tc
+[(25A)7.7(0)]TJ
+ET
+0 G
+2 J 1 j 1.49 w 10 M []0 d
+202.104 727.685 m
+202.104 79.259 l
+391.928 727.685 m
+391.928 79.259 l
+202.104 712.807 m
+391.928 712.807 l
+202.104 79.259 m
+391.928 79.259 l
+S
+BT
+/F6 1 Tf
+9.999 0 0 9.999 209.0633 719.286 Tm
+-0.004 Tc
+[(25A)-1389(25B)-1377(25C)-1346(25D)-1370(25E)-1413(25F)]TJ
+ET
+1 g
+360.371 396.033 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 396.033 31.557 -39.597 re
+f
+1 g
+360.371 356.436 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 356.436 31.557 -39.597 re
+f
+1 g
+360.371 316.84 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 316.84 31.557 -39.597 re
+f
+1 g
+360.371 277.243 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 277.243 31.557 -39.597 re
+f
+1 g
+360.371 237.646 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 237.646 31.557 -39.597 re
+f
+1 g
+360.371 198.049 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 198.049 31.557 -39.597 re
+f
+1 g
+360.371 158.453 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 158.453 31.557 -39.597 re
+f
+1 g
+360.371 118.856 31.557 -39.597 re
+f
+/Cs9 cs 0 /P1 scn
+360.371 118.856 31.557 -39.597 re
+f
+0.248 w
+202.104 712.807 m
+202.104 79.259 l
+233.781 712.807 m
+233.781 79.259 l
+265.339 712.807 m
+265.339 79.259 l
+297.016 712.807 m
+297.016 79.259 l
+328.693 712.807 m
+328.693 79.259 l
+360.371 712.807 m
+360.371 79.259 l
+391.928 712.807 m
+391.928 79.259 l
+202.104 712.807 m
+391.928 712.807 l
+202.104 673.21 m
+391.928 673.21 l
+202.104 633.613 m
+391.928 633.613 l
+202.104 594.016 m
+391.928 594.016 l
+202.104 554.42 m
+391.928 554.42 l
+202.104 514.823 m
+391.928 514.823 l
+202.104 475.226 m
+391.928 475.226 l
+202.104 435.63 m
+391.928 435.63 l
+202.104 396.033 m
+391.928 396.033 l
+202.104 356.436 m
+391.928 356.436 l
+202.104 316.84 m
+391.928 316.84 l
+202.104 277.243 m
+391.928 277.243 l
+202.104 237.646 m
+391.928 237.646 l
+202.104 198.049 m
+391.928 198.049 l
+202.104 158.453 m
+391.928 158.453 l
+202.104 118.856 m
+391.928 118.856 l
+202.104 79.259 m
+391.928 79.259 l
+S
+BT
+/F7 1 Tf
+21.998 0 0 21.998 209.6633 687.6086 Tm
+0 g
+0 Tc
+()Tj
+0 -1.8 TD
+()Tj
+T*
+()Tj
+T*
+()Tj
+T*
+()Tj
+T*
+()Tj
+T*
+()Tj
+T*
+()Tj
+T*
+( )Tj
+T*
+(\012)Tj
+/F9 1 Tf
+0.2673 -1.8 TD
+()Tj
+T*
+()Tj
+/F7 1 Tf
+-0.3436 -1.8 TD
+( )Tj
+T*
+( )Tj
+0.2018 -1.8 TD
+(\015)Tj
+T*
+()Tj
+1.2491 27.0002 TD
+()Tj
+0 -1.8 TD
+()Tj
+0.06 -1.8 TD
+()Tj
+T*
+()Tj
+0.2127 -1.8 TD
+()Tj
+T*
+()Tj
+-0.1636 -1.8 TD
+()Tj
+T*
+()Tj
+0.1855 -1.8 TD
+()Tj
+T*
+()Tj
+-0.1418 -1.8 TD
+()Tj
+T*
+()Tj
+-0.0927 -1.8 TD
+()Tj
+T*
+()Tj
+0.2127 -1.8 TD
+()Tj
+T*
+()Tj
+1.2764 27.0002 TD
+()Tj
+0 -1.8 TD
+( )Tj
+0.1855 -1.8 TD
+(!)Tj
+T*
+(")Tj
+-0.1418 -1.8 TD
+(#)Tj
+T*
+($)Tj
+-0.0927 -1.8 TD
+(%)Tj
+T*
+(&)Tj
+T*
+(')Tj
+T*
+(\()Tj
+0.0927 -1.8 TD
+(\))Tj
+-0.0927 -1.8 TD
+(*)Tj
+T*
+(+)Tj
+T*
+(,)Tj
+T*
+(-)Tj
+T*
+(.)Tj
+1.44 27.0002 TD
+(/)Tj
+0 -1.8 TD
+(0)Tj
+T*
+(1)Tj
+T*
+(2)Tj
+T*
+(3)Tj
+T*
+(4)Tj
+T*
+(5)Tj
+T*
+(6)Tj
+0.2018 -1.8 TD
+(7)Tj
+-0.2018 -1.8 TD
+(8)Tj
+T*
+(9)Tj
+T*
+(:)Tj
+T*
+(;)Tj
+T*
+(<)Tj
+T*
+(=)Tj
+T*
+(>)Tj
+1.44 27.0002 TD
+(?)Tj
+0 -1.8 TD
+(@)Tj
+T*
+(A)Tj
+T*
+(B)Tj
+T*
+(C)Tj
+T*
+(D)Tj
+0.2018 -1.8 TD
+(E)Tj
+-0.2018 -1.8 TD
+(F)Tj
+T*
+(G)Tj
+T*
+(H)Tj
+T*
+(I)Tj
+T*
+(J)Tj
+T*
+(K)Tj
+T*
+(L)Tj
+T*
+(M)Tj
+T*
+(N)Tj
+1.4346 27.0002 TD
+(O)Tj
+0 -1.8 TD
+(P)Tj
+T*
+(Q)Tj
+T*
+(R)Tj
+T*
+(S)Tj
+T*
+(T)Tj
+T*
+(U)Tj
+T*
+(V)Tj
+/F11 1 Tf
+5.9995 0 0 5.9995 212.183 675.2496 Tm
+0.004 Tc
+[(25A)11(0)]TJ
+0 -6.6 TD
+[(25A)11(1)]TJ
+T*
+[(25A)11(2)]TJ
+T*
+[(25A)11(3)]TJ
+T*
+[(25A)11(4)]TJ
+T*
+[(25A)11(5)]TJ
+T*
+[(25A)11(6)]TJ
+T*
+[(25A)11(7)]TJ
+T*
+[(25A)11(8)]TJ
+T*
+[(25A)11(9)]TJ
+-0.04 -6.6 TD
+[(25A)11(A)]TJ
+T*
+[(25A)11(B)]TJ
+-0.04 -6.6 TD
+[(25A)11(C)]TJ
+T*
+[(25A)11(D)]TJ
+0.04 -6.6 TD
+[(25A)11(E)]TJ
+0.02 -6.6 TD
+[(25A)11(F)]TJ
+5.28 99 TD
+[(25B)11(0)]TJ
+0 -6.6 TD
+[(25B)11(1)]TJ
+T*
+[(25B)11(2)]TJ
+T*
+[(25B)11(3)]TJ
+T*
+[(25B)11(4)]TJ
+T*
+[(25B)11(5)]TJ
+T*
+[(25B)11(6)]TJ
+T*
+[(25B)11(7)]TJ
+T*
+[(25B)11(8)]TJ
+T*
+[(25B)11(9)]TJ
+-0.04 -6.6 TD
+[(25B)11(A)]TJ
+T*
+[(25B)11(B)]TJ
+-0.04 -6.6 TD
+[(25B)11(C)]TJ
+T*
+[(25B)11(D)]TJ
+0.04 -6.6 TD
+[(25B)11(E)]TJ
+0.02 -6.6 TD
+[(25B)11(F)]TJ
+5.26 99 TD
+0.0053 Tc
+(25C0)Tj
+0 -6.6 TD
+(25C1)Tj
+T*
+(25C2)Tj
+T*
+(25C3)Tj
+T*
+(25C4)Tj
+T*
+(25C5)Tj
+T*
+(25C6)Tj
+T*
+(25C7)Tj
+T*
+(25C8)Tj
+T*
+(25C9)Tj
+-0.04 -6.6 TD
+(25CA)Tj
+T*
+(25CB)Tj
+-0.02 -6.6 TD
+(25CC)Tj
+T*
+(25CD)Tj
+0.02 -6.6 TD
+(25CE)Tj
+0.02 -6.6 TD
+(25CF)Tj
+5.3 99 TD
+(25D0)Tj
+0 -6.6 TD
+(25D1)Tj
+T*
+(25D2)Tj
+T*
+(25D3)Tj
+T*
+(25D4)Tj
+T*
+(25D5)Tj
+T*
+(25D6)Tj
+T*
+(25D7)Tj
+T*
+(25D8)Tj
+T*
+(25D9)Tj
+-0.04 -6.6 TD
+(25DA)Tj
+T*
+(25DB)Tj
+-0.02 -6.6 TD
+(25DC)Tj
+T*
+(25DD)Tj
+0.02 -6.6 TD
+(25DE)Tj
+0.02 -6.6 TD
+(25DF)Tj
+5.34 99 TD
+0.004 Tc
+[(25E)11(0)]TJ
+0 -6.6 TD
+[(25E)11(1)]TJ
+T*
+[(25E)11(2)]TJ
+T*
+[(25E)11(3)]TJ
+T*
+[(25E)11(4)]TJ
+T*
+[(25E)11(5)]TJ
+T*
+[(25E)11(6)]TJ
+T*
+[(25E)11(7)]TJ
+T*
+[(25E)11(8)]TJ
+T*
+[(25E)11(9)]TJ
+-0.04 -6.6 TD
+[(25E)11(A)]TJ
+T*
+[(25E)11(B)]TJ
+-0.04 -6.6 TD
+[(25E)11(C)]TJ
+T*
+[(25E)11(D)]TJ
+0.04 -6.6 TD
+[(25E)11(E)]TJ
+0.02 -6.6 TD
+[(25E)11(F)]TJ
+5.3 99 TD
+0.0023 Tc
+(25F0)Tj
+0 -6.6 TD
+(25F1)Tj
+T*
+(25F2)Tj
+T*
+(25F3)Tj
+T*
+(25F4)Tj
+T*
+(25F5)Tj
+T*
+(25F6)Tj
+T*
+(25F7)Tj
+/F6 1 Tf
+9.999 0 0 9.999 191.4248 687.6086 Tm
+0 Tc
+(0)Tj
+0 -3.9601 TD
+(1)Tj
+T*
+(2)Tj
+T*
+(3)Tj
+T*
+(4)Tj
+T*
+(5)Tj
+T*
+(6)Tj
+T*
+(7)Tj
+T*
+(8)Tj
+T*
+(9)Tj
+-0.06 -3.9601 TD
+(A)Tj
+T*
+(B)Tj
+-0.024 -3.9601 TD
+(C)Tj
+T*
+(D)Tj
+0.024 -3.9601 TD
+(E)Tj
+0.024 -3.9601 TD
+(F)Tj
+ET
+1.49 w
+202.104 727.685 m
+202.104 79.259 l
+391.928 727.685 m
+391.928 79.259 l
+202.104 712.807 m
+391.928 712.807 l
+202.104 79.259 m
+391.928 79.259 l
+S
+test 2 done
diff --git a/qpdf/qtest/qpdf/fix1.qdf b/qpdf/qtest/qpdf/fix1.qdf
new file mode 100644
index 00000000..091372fc
--- /dev/null
+++ b/qpdf/qtest/qpdf/fix1.qdf
@@ -0,0 +1,111 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents [ 4 0 R 8 0 R ]
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato Soup) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 648 Td
+ (and Salad) Tj
+ET
+endstream
+endobj
+
+9 0 obj
+0
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/fix1.qdf.out b/qpdf/qtest/qpdf/fix1.qdf.out
new file mode 100644
index 00000000..d436bce7
--- /dev/null
+++ b/qpdf/qtest/qpdf/fix1.qdf.out
@@ -0,0 +1,113 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents [ 4 0 R 8 0 R ]
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato Soup) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+49
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 648 Td
+ (and Salad) Tj
+ET
+endstream
+endobj
+
+9 0 obj
+47
+endobj
+
+xref
+0 10
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000386 00000 n
+0000000490 00000 n
+0000000509 00000 n
+0000000627 00000 n
+0000000662 00000 n
+0000000764 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 10
+>>
+startxref
+783
+%%EOF
diff --git a/qpdf/qtest/qpdf/fix2.qdf b/qpdf/qtest/qpdf/fix2.qdf
new file mode 100644
index 00000000..c368523e
--- /dev/null
+++ b/qpdf/qtest/qpdf/fix2.qdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/fix2.qdf.out b/qpdf/qtest/qpdf/fix2.qdf.out
new file mode 100644
index 00000000..ccccaa9e
--- /dev/null
+++ b/qpdf/qtest/qpdf/fix2.qdf.out
Binary files differ
diff --git a/qpdf/qtest/qpdf/good1.out b/qpdf/qtest/qpdf/good1.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good1.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good1.pdf b/qpdf/qtest/qpdf/good1.pdf
new file mode 100644
index 00000000..55b7a764
--- /dev/null
+++ b/qpdf/qtest/qpdf/good1.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good1.qdf b/qpdf/qtest/qpdf/good1.qdf
new file mode 100644
index 00000000..976ed2b2
--- /dev/null
+++ b/qpdf/qtest/qpdf/good1.qdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good10.out b/qpdf/qtest/qpdf/good10.out
new file mode 100644
index 00000000..3c0bed95
--- /dev/null
+++ b/qpdf/qtest/qpdf/good10.out
@@ -0,0 +1,8 @@
+/QTest is direct
+/QTest is an array with 3 items
+ item 0 is direct
+ item 1 is direct
+ item 2 is indirect
+unparse: [ 1 (2) 8 0 R ]
+unparseResolved: [ 1 (2) 8 0 R ]
+test 1 done
diff --git a/qpdf/qtest/qpdf/good10.pdf b/qpdf/qtest/qpdf/good10.pdf
new file mode 100644
index 00000000..13a88101
--- /dev/null
+++ b/qpdf/qtest/qpdf/good10.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest [1 (2) 8 0 R]
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good10.qdf b/qpdf/qtest/qpdf/good10.qdf
new file mode 100644
index 00000000..c2e7a50c
--- /dev/null
+++ b/qpdf/qtest/qpdf/good10.qdf
@@ -0,0 +1,100 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest [
+ 1
+ (2)
+ null
+ ]
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good11.out b/qpdf/qtest/qpdf/good11.out
new file mode 100644
index 00000000..676a0343
--- /dev/null
+++ b/qpdf/qtest/qpdf/good11.out
@@ -0,0 +1,6 @@
+/QTest is direct
+/QTest is a dictionary
+ /a is direct
+unparse: << /a (a) /b 8 0 R >>
+unparseResolved: << /a (a) /b 8 0 R >>
+test 1 done
diff --git a/qpdf/qtest/qpdf/good11.pdf b/qpdf/qtest/qpdf/good11.pdf
new file mode 100644
index 00000000..4e18be7b
--- /dev/null
+++ b/qpdf/qtest/qpdf/good11.pdf
@@ -0,0 +1,81 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest << /a(a)
+ /b 8 0 R >>
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good11.qdf b/qpdf/qtest/qpdf/good11.qdf
new file mode 100644
index 00000000..3d673b04
--- /dev/null
+++ b/qpdf/qtest/qpdf/good11.qdf
@@ -0,0 +1,98 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest <<
+ /a (a)
+ >>
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good12.out b/qpdf/qtest/qpdf/good12.out
new file mode 100644
index 00000000..b75d27b1
--- /dev/null
+++ b/qpdf/qtest/qpdf/good12.out
@@ -0,0 +1,13 @@
+/QTest is indirect
+/QTest is a stream. Dictionary: << /Filter /FlateDecode /Length 123 >>
+Raw stream data:
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+Uncompressed stream data:
+This stream is not very interesting, but it is long enough that
+compressing shrinks it somewhat. Or maybe not. But it doesn't really
+matter that much.
+
+End of stream data
+unparse: 7 0 R
+unparseResolved: 7 0 R
+test 1 done
diff --git a/qpdf/qtest/qpdf/good12.pdf b/qpdf/qtest/qpdf/good12.pdf
new file mode 100644
index 00000000..8d91aef8
--- /dev/null
+++ b/qpdf/qtest/qpdf/good12.pdf
@@ -0,0 +1,93 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj
+<<
+ % Comment
+ /Length
+ 123
+ /Filter /FlateDecode
+>>
+stream
+xœ%11 û¼b;tà4| wXIDì Øå÷8G·«Í>rQ¨uŠ OÒ êEŒ:©IWìÃPlíµII)Ãr´p4~;§ÎAs/òÒ…jcúú¾÷Žs§åözû»žT.?®uŽæ§<Ž¼…Ð*6ä
+endstream
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+0000000556 00000 n
+trailer <<
+ /Size 8
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+770
+%%EOF
diff --git a/qpdf/qtest/qpdf/good12.qdf b/qpdf/qtest/qpdf/good12.qdf
new file mode 100644
index 00000000..107f3d04
--- /dev/null
+++ b/qpdf/qtest/qpdf/good12.qdf
@@ -0,0 +1,113 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 4 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Length 3 0 R
+>>
+stream
+This stream is not very interesting, but it is long enough that
+compressing shrinks it somewhat. Or maybe not. But it doesn't really
+matter that much.
+endstream
+endobj
+
+3 0 obj
+153
+endobj
+
+4 0 obj
+<<
+ /Count 1
+ /Kids [
+ 5 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+5 0 obj
+<<
+ /Contents 6 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 8 0 R
+ >>
+ /ProcSet 9 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+6 0 obj
+<<
+ /Length 7 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+7 0 obj
+44
+endobj
+
+8 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+9 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 10
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000287 00000 n
+0000000307 00000 n
+0000000389 00000 n
+0000000604 00000 n
+0000000703 00000 n
+0000000722 00000 n
+0000000840 00000 n
+trailer <<
+ /QTest 2 0 R
+ /Root 1 0 R
+ /Size 10
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+875
+%%EOF
diff --git a/qpdf/qtest/qpdf/good13.out b/qpdf/qtest/qpdf/good13.out
new file mode 100644
index 00000000..a75f68c5
--- /dev/null
+++ b/qpdf/qtest/qpdf/good13.out
@@ -0,0 +1,9 @@
+/QTest is indirect
+/QTest is a dictionary
+ /hex strings is direct
+ /indirect is indirect
+ /nesting is direct
+ /strings is direct
+unparse: 7 0 R
+unparseResolved: << /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) ($¢) () (\(\)) (\() (\)) (a\f\b\t\r\nb) <410042> (a\nb) (a b) ] >>
+test 1 done
diff --git a/qpdf/qtest/qpdf/good13.pdf b/qpdf/qtest/qpdf/good13.pdf
new file mode 100644
index 00000000..516774c5
--- /dev/null
+++ b/qpdf/qtest/qpdf/good13.pdf
@@ -0,0 +1,101 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj
+<<
+ /strings [(one) ($\242) () (()) (\() (\)) (a\f\b\t\r\nb) (A\000B) (a
+b) (a \
+b)]
+ /hex#20strings [<506F7461746f> <010 203 0004056> <41
+42>]
+ /indirect 8 0 R
+ /n#65sting <<
+ /a [1 2 << /x (y) >> [(z)]]
+ /b <</a [1 2] / (legal)>>
+ >>
+>>
+endobj
+
+8 0 obj
+(hello)
+endobj
+
+xref
+0 9
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+0000000556 00000 n
+0000000822 00000 n
+trailer <<
+ /Size 9
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+846
+%%EOF
diff --git a/qpdf/qtest/qpdf/good13.qdf b/qpdf/qtest/qpdf/good13.qdf
new file mode 100644
index 00000000..c2f50c0f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good13.qdf
@@ -0,0 +1,139 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 3 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /hex#20strings [
+ (Potato)
+ <01020300040560>
+ (AB)
+ ]
+ /indirect (hello)
+ /nesting <<
+ /a [
+ 1
+ 2
+ <<
+ /x (y)
+ >>
+ [
+ (z)
+ ]
+ ]
+ /b <<
+ / (legal)
+ /a [
+ 1
+ 2
+ ]
+ >>
+ >>
+ /strings [
+ (one)
+ ($¢)
+ ()
+ (\(\))
+ (\()
+ (\))
+ (a\f\b\t\r\nb)
+ <410042>
+ (a\nb)
+ (a b)
+ ]
+>>
+endobj
+
+3 0 obj
+<<
+ /Count 1
+ /Kids [
+ 4 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+4 0 obj
+<<
+ /Contents 5 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 7 0 R
+ >>
+ /ProcSet 8 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+5 0 obj
+<<
+ /Length 6 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+6 0 obj
+44
+endobj
+
+7 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+8 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 9
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000495 00000 n
+0000000577 00000 n
+0000000792 00000 n
+0000000891 00000 n
+0000000910 00000 n
+0000001028 00000 n
+trailer <<
+ /QTest 2 0 R
+ /Root 1 0 R
+ /Size 9
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+1063
+%%EOF
diff --git a/qpdf/qtest/qpdf/good14.out b/qpdf/qtest/qpdf/good14.out
new file mode 100644
index 00000000..c8e5fc9b
--- /dev/null
+++ b/qpdf/qtest/qpdf/good14.out
@@ -0,0 +1,39 @@
+-- stream 0 --
+A %here is a comment
+B % here is another with CR
+A B
+
+one
+two
+three lines
+(string with \r\nCRNL)
+ and another
+ indentation
+(\001B%DEF)<01>
+<8a8b>
+(ab)
+<8c>(Ý) ) >
+<610062> (MOO)
+-- stream 1 --
+This stream does end with a newline.
+// tests:
+// bad tokens preserved
+// comments
+// indentation
+// CR/NL inside string literal -- changed to \r or \n, newline follows
+// whitespace in hexstring (removed)
+// strings normalized
+// newlines normalized
+// names normalized
+// trailing space (preserved)
+// final newline added
+
+/bad#name
+
+/good name
+/bad#00name
+-- stream 2 --
+(This stream ends with a \001 bad token
+-- stream 3 --
+<AB X
+test 3 done
diff --git a/qpdf/qtest/qpdf/good14.pdf b/qpdf/qtest/qpdf/good14.pdf
new file mode 100644
index 00000000..a6cd4bee
--- /dev/null
+++ b/qpdf/qtest/qpdf/good14.pdf
@@ -0,0 +1,142 @@
+%PDF-1.3 -*- coding: no-conversion -*-
+%¿›þ¢
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj
+<< /Length 9 0 R >>
+stream
+A %here is a comment
+B % here is another with CR
+A B
+one two three lines
+(string with
+CRNL) and another
+ indentation
+(B%DEF)()
+<8A
+8B><61 62><8c><DD> ) >
+(a\000b) <4D4F4F>endstream endobj
+
+8 0 obj
+<< /Length 385 >>
+stream
+This stream does end with a newline.
+// tests:
+// bad tokens preserved
+// comments
+// indentation
+// CR/NL inside string literal -- changed to \r or \n, newline follows
+// whitespace in hexstring (removed)
+// strings normalized
+// newlines normalized
+// names normalized
+// trailing space (preserved)
+// final newline added
+
+/bad#name
+
+/g#6f#6Fd name
+/bad#00name
+endstream
+endobj
+
+9 0 obj
+181
+endobj
+
+10 0 obj
+<< /Length 40 >>
+stream
+(This stream ends with a \001 bad token
+endstream
+endobj
+
+11 0 obj
+<< /Length 5 >>
+stream
+<AB X
+endstream
+endobj
+
+xref
+0 12
+0000000000 65535 f
+0000000045 00000 n
+0000000099 00000 n
+0000000171 00000 n
+0000000343 00000 n
+0000000439 00000 n
+0000000474 00000 n
+0000000592 00000 n
+0000000827 00000 n
+0000001263 00000 n
+0000001283 00000 n
+0000001374 00000 n
+trailer <<
+ /Size 12
+ /Root 1 0 R
+ /QStreams [ 7 0 R 8 0 R 10 0 R 11 0 R ]
+>>
+startxref
+1430
+%%EOF
diff --git a/qpdf/qtest/qpdf/good14.qdf b/qpdf/qtest/qpdf/good14.qdf
new file mode 100644
index 00000000..07ac0240
--- /dev/null
+++ b/qpdf/qtest/qpdf/good14.qdf
@@ -0,0 +1,189 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 10 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Length 3 0 R
+>>
+stream
+A %here is a comment
+B % here is another with CR
+A B
+one two three lines
+(string with
+CRNL) and another
+ indentation
+(B%DEF)()
+<8A
+8B><61 62><8c><DD> ) >
+(a\000b) <4D4F4F>
+endstream
+endobj
+
+%QDF: ignore_newline
+3 0 obj
+181
+endobj
+
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+This stream does end with a newline.
+// tests:
+// bad tokens preserved
+// comments
+// indentation
+// CR/NL inside string literal -- changed to \r or \n, newline follows
+// whitespace in hexstring (removed)
+// strings normalized
+// newlines normalized
+// names normalized
+// trailing space (preserved)
+// final newline added
+
+/bad#name
+
+/g#6f#6Fd name
+/bad#00name
+endstream
+endobj
+
+5 0 obj
+385
+endobj
+
+6 0 obj
+<<
+ /Length 7 0 R
+>>
+stream
+(This stream ends with a \001 bad token
+endstream
+endobj
+
+7 0 obj
+40
+endobj
+
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+<AB X
+endstream
+endobj
+
+%QDF: ignore_newline
+9 0 obj
+5
+endobj
+
+10 0 obj
+<<
+ /Count 1
+ /Kids [
+ 11 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+11 0 obj
+<<
+ /Contents 12 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 10 0 R
+ /Resources <<
+ /Font <<
+ /F1 14 0 R
+ >>
+ /ProcSet 15 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+12 0 obj
+<<
+ /Length 13 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+13 0 obj
+44
+endobj
+
+14 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+15 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 16
+0000000000 65535 f
+0000000025 00000 n
+0000000080 00000 n
+0000000338 00000 n
+0000000358 00000 n
+0000000798 00000 n
+0000000818 00000 n
+0000000913 00000 n
+0000000932 00000 n
+0000001014 00000 n
+0000001032 00000 n
+0000001116 00000 n
+0000001336 00000 n
+0000001437 00000 n
+0000001457 00000 n
+0000001576 00000 n
+trailer <<
+ /QStreams [
+ 2 0 R
+ 4 0 R
+ 6 0 R
+ 8 0 R
+ ]
+ /Root 1 0 R
+ /Size 16
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+1612
+%%EOF
diff --git a/qpdf/qtest/qpdf/good15.out b/qpdf/qtest/qpdf/good15.out
new file mode 100644
index 00000000..884ea6ed
--- /dev/null
+++ b/qpdf/qtest/qpdf/good15.out
@@ -0,0 +1,5 @@
+/QTest is direct
+/QTest is a name with value /oink
+unparse: /oink
+unparseResolved: /oink
+test 1 done
diff --git a/qpdf/qtest/qpdf/good15.pdf b/qpdf/qtest/qpdf/good15.pdf
new file mode 100644
index 00000000..5981765a
--- /dev/null
+++ b/qpdf/qtest/qpdf/good15.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+
+BT
+/F1 24 Tf 72 720 Td
+ (Potato) Tj ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest /oink
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good15.qdf b/qpdf/qtest/qpdf/good15.qdf
new file mode 100644
index 00000000..c60469c1
--- /dev/null
+++ b/qpdf/qtest/qpdf/good15.qdf
@@ -0,0 +1,97 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+
+BT
+/F1 24 Tf
+72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+43
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000474 00000 n
+0000000493 00000 n
+0000000611 00000 n
+trailer <<
+ /QTest /oink
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+646
+%%EOF
diff --git a/qpdf/qtest/qpdf/good16.out b/qpdf/qtest/qpdf/good16.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good16.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good16.pdf b/qpdf/qtest/qpdf/good16.pdf
new file mode 100644
index 00000000..1a468202
--- /dev/null
+++ b/qpdf/qtest/qpdf/good16.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good16.qdf b/qpdf/qtest/qpdf/good16.qdf
new file mode 100644
index 00000000..b98326ae
--- /dev/null
+++ b/qpdf/qtest/qpdf/good16.qdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good17-not-qdf.pdf b/qpdf/qtest/qpdf/good17-not-qdf.pdf
new file mode 100644
index 00000000..53eadd79
--- /dev/null
+++ b/qpdf/qtest/qpdf/good17-not-qdf.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good17-not-recompressed.pdf b/qpdf/qtest/qpdf/good17-not-recompressed.pdf
new file mode 100644
index 00000000..b6e3a530
--- /dev/null
+++ b/qpdf/qtest/qpdf/good17-not-recompressed.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good17.out b/qpdf/qtest/qpdf/good17.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good17.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good17.pdf b/qpdf/qtest/qpdf/good17.pdf
new file mode 100644
index 00000000..f0c66b35
--- /dev/null
+++ b/qpdf/qtest/qpdf/good17.pdf
@@ -0,0 +1,1550 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels 107 0 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+xref
+0 111
+0000000095 65535 f
+0000000025 00000 n
+0000000145 00000 n
+0000000541 00000 n
+0000000746 00000 n
+0000000951 00000 n
+0000001156 00000 n
+0000001361 00000 n
+0000001566 00000 n
+0000001771 00000 n
+0000001976 00000 n
+0000002182 00000 n
+0000002389 00000 n
+0000002596 00000 n
+0000002803 00000 n
+0000003010 00000 n
+0000003217 00000 n
+0000003424 00000 n
+0000003631 00000 n
+0000003838 00000 n
+0000004045 00000 n
+0000004252 00000 n
+0000004459 00000 n
+0000004666 00000 n
+0000004873 00000 n
+0000005080 00000 n
+0000005287 00000 n
+0000005494 00000 n
+0000005701 00000 n
+0000005908 00000 n
+0000006115 00000 n
+0000006322 00000 n
+0000006529 00000 n
+0000006748 00000 n
+0000006851 00000 n
+0000006871 00000 n
+0000006990 00000 n
+0000007049 00000 n
+0000007152 00000 n
+0000007195 00000 n
+0000007298 00000 n
+0000007341 00000 n
+0000007444 00000 n
+0000007487 00000 n
+0000007590 00000 n
+0000007633 00000 n
+0000007736 00000 n
+0000007779 00000 n
+0000007882 00000 n
+0000007925 00000 n
+0000008028 00000 n
+0000008071 00000 n
+0000008174 00000 n
+0000008218 00000 n
+0000008321 00000 n
+0000008365 00000 n
+0000008469 00000 n
+0000008513 00000 n
+0000008617 00000 n
+0000008661 00000 n
+0000008765 00000 n
+0000008809 00000 n
+0000008913 00000 n
+0000008957 00000 n
+0000009061 00000 n
+0000009105 00000 n
+0000009209 00000 n
+0000009253 00000 n
+0000009357 00000 n
+0000009401 00000 n
+0000009505 00000 n
+0000009549 00000 n
+0000009653 00000 n
+0000009697 00000 n
+0000009801 00000 n
+0000009845 00000 n
+0000009949 00000 n
+0000009993 00000 n
+0000010097 00000 n
+0000010141 00000 n
+0000010245 00000 n
+0000010289 00000 n
+0000010393 00000 n
+0000010437 00000 n
+0000010541 00000 n
+0000010585 00000 n
+0000010689 00000 n
+0000010733 00000 n
+0000010837 00000 n
+0000010881 00000 n
+0000010985 00000 n
+0000011029 00000 n
+0000011133 00000 n
+0000011177 00000 n
+0000011281 00000 n
+0000000096 65535 f
+0000000097 65535 f
+0000000098 65535 f
+0000000099 65535 f
+0000000100 65535 f
+0000000101 65535 f
+0000000102 65535 f
+0000000103 65535 f
+0000000104 65535 f
+0000000105 65535 f
+0000000106 65535 f
+0000000107 65535 f
+0000000108 65535 f
+0000000109 65535 f
+0000000110 65535 f
+0000000000 65535 f
+trailer <<
+ /Root 1 0 R
+ /Size 111
+>>
+startxref
+11301
+%%EOF
+
+108 0 obj
+<<
+ /Type /ObjStm
+ /N 10
+ /First 81
+ /Length 1806
+>>
+stream
+95 0
+96 75
+97 260
+98 394
+99 557
+100 899
+101 1078
+102 1276
+103 1433
+104 1590
+% 95
+<<
+ /Type /Outlines
+ /First 96 0 R
+ /Last 97 0 R
+ /Count 6
+>>
+% 96
+<<
+ /Type /Outline
+ /Title (Isís 1 -> 5: /XYZ null null null)
+ /Parent 95 0 R
+ /Count 4
+ /Next 97 0 R
+ /First 98 0 R
+ /Last 99 0 R
+ /Dest [ 8 0 R /XYZ null null null ]
+>>
+% 97
+<<
+ /Type /Outline
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Parent 95 0 R
+ /Prev 96 0 R
+ /Dest [ 18 0 R /XYZ 66 756 3 ]
+>>
+% 98
+<<
+ /Type /Outline
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Parent 96 0 R
+ /Next 99 0 R
+ /First 100 0 R
+ /Last 101 0 R
+ /Count -3
+ /Dest [ 14 0 R /Fit ]
+>>
+% 99
+<<
+ /Type /Outline
+ % /Title (Sandy (Sandy [Greek]) 1.2 -> 13: /FitH 792)
+ /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
+ /Parent 96 0 R
+ /Prev 98 0 R
+ /First 105 0 R
+ /Last 106 0 R
+ /Count 2
+ /Dest [ 16 0 R /FitH 792 ]
+>>
+% 100
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Parent 98 0 R
+ /Next 101 0 R
+ /First 102 0 R
+ /Last 103 0 R
+ /Count -2
+ /Dest [ 15 0 R /FitV 100 ]
+>>
+% 101
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Parent 98 0 R
+ /Prev 100 0 R
+ /First 104 0 R
+ /Last 104 0 R
+ /Count 1
+ /Dest [ 15 0 R /XYZ null null null ]
+>>
+% 102
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Parent 100 0 R
+ /Next 103 0 R
+ /Dest [ 21 0 R /XYZ null null null ]
+>>
+% 103
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Parent 100 0 R
+ /Prev 102 0 R
+ /Dest [ 22 0 R /XYZ null null null ]
+>>
+% 104
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Parent 101 0 R
+ /Dest [ 25 0 R /XYZ null null null ]
+>>
+endstream
+endobj
+
+110 0 obj
+<<
+ /Type /ObjStm
+ /N 3
+ /First 28
+ /Length 636
+ /Extends 108 0 R
+>>
+stream
+105 0
+106 157
+107 310
+% 105
+<<
+ /Type /Outline
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Parent 99 0 R
+ /Next 106 0 R
+ /Dest [ 4 0 R /FitR 66 714 180 770 ]
+>>
+% 106
+<<
+ /Type /Outline
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Parent 99 0 R
+ /Prev 105 0 R
+ /Dest [ 3 0 R /XYZ null null null ]
+>>
+% 107
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /r /St 1 >>
+ 7 << /P () >>
+ 9 << /S /r /St 6 >>
+ 11 << /P () >>
+ 12 << /S /D /St 2 >>
+ 15 << /S /D /St 6 >>
+ 19 << /P () >>
+ 20 << /S /D /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endstream
+endobj
+
+109 0 obj
+<<
+ /Type /XRef
+ /Size 111
+ /Index [0 111]
+ /W [1 2 1]
+ /Length 444
+ /Root 1 0 R
+>>
+stream
+
+$
+endstream
+endobj
+
+xref
+0 0
+trailer <<
+ /Size 111
+ /Root 1 0 R
+ /Prev 11301
+ /XRefStm 16238
+>>
+
+startxref
+16808
+%%EOF
diff --git a/qpdf/qtest/qpdf/good17.qdf b/qpdf/qtest/qpdf/good17.qdf
new file mode 100644
index 00000000..ddd3a5ce
--- /dev/null
+++ b/qpdf/qtest/qpdf/good17.qdf
@@ -0,0 +1,1523 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Outlines 3 0 R
+ /PageLabels 16 0 R
+ /PageMode /UseOutlines
+ /Pages 17 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /ObjStm
+ /Length 2179
+ /N 10
+ /First 102
+>>
+stream
+3 0
+4 100
+5 335
+6 520
+7 718
+8 1044
+9 1262
+10 1508
+11 1715
+12 1922
+%% Object stream: object 3, index 0
+<<
+ /Count 6
+ /First 4 0 R
+ /Last 5 0 R
+ /Type /Outlines
+>>
+%% Object stream: object 4, index 1
+<<
+ /Count 4
+ /Dest [
+ 18 0 R
+ /XYZ
+ null
+ null
+ null
+ ]
+ /First 6 0 R
+ /Last 7 0 R
+ /Next 5 0 R
+ /Parent 3 0 R
+ /Title (Isís 1 -> 5: /XYZ null null null)
+ /Type /Outline
+>>
+%% Object stream: object 5, index 2
+<<
+ /Dest [
+ 19 0 R
+ /XYZ
+ 66
+ 756
+ 3
+ ]
+ /Parent 3 0 R
+ /Prev 4 0 R
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Type /Outline
+>>
+%% Object stream: object 6, index 3
+<<
+ /Count -3
+ /Dest [
+ 20 0 R
+ /Fit
+ ]
+ /First 8 0 R
+ /Last 9 0 R
+ /Next 7 0 R
+ /Parent 4 0 R
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Type /Outline
+>>
+%% Object stream: object 7, index 4
+<<
+ /Count 2
+ /Dest [
+ 21 0 R
+ /FitH
+ 792
+ ]
+ /First 14 0 R
+ /Last 15 0 R
+ /Parent 4 0 R
+ /Prev 6 0 R
+ /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
+ /Type /Outline
+>>
+%% Object stream: object 8, index 5
+<<
+ /Count -2
+ /Dest [
+ 22 0 R
+ /FitV
+ 100
+ ]
+ /First 10 0 R
+ /Last 11 0 R
+ /Next 9 0 R
+ /Parent 6 0 R
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Type /Outline
+>>
+%% Object stream: object 9, index 6
+<<
+ /Count 1
+ /Dest [
+ 22 0 R
+ /XYZ
+ null
+ null
+ null
+ ]
+ /First 12 0 R
+ /Last 12 0 R
+ /Parent 6 0 R
+ /Prev 8 0 R
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Type /Outline
+>>
+%% Object stream: object 10, index 7
+<<
+ /Dest [
+ 23 0 R
+ /XYZ
+ null
+ null
+ null
+ ]
+ /Next 11 0 R
+ /Parent 8 0 R
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Type /Outline
+>>
+%% Object stream: object 11, index 8
+<<
+ /Dest [
+ 24 0 R
+ /XYZ
+ null
+ null
+ null
+ ]
+ /Parent 8 0 R
+ /Prev 10 0 R
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Type /Outline
+>>
+%% Object stream: object 12, index 9
+<<
+ /Dest [
+ 25 0 R
+ /XYZ
+ null
+ null
+ null
+ ]
+ /Parent 9 0 R
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Type /Outline
+>>
+endstream
+endobj
+
+13 0 obj
+<<
+ /Type /ObjStm
+ /Length 989
+ /N 3
+ /First 56
+ /Extends 2 0 R
+>>
+stream
+14 0
+15 213
+16 418
+%% Object stream: object 14, index 0
+<<
+ /Dest [
+ 26 0 R
+ /FitR
+ 66
+ 714
+ 180
+ 770
+ ]
+ /Next 15 0 R
+ /Parent 7 0 R
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Type /Outline
+>>
+%% Object stream: object 15, index 1
+<<
+ /Dest [
+ 27 0 R
+ /XYZ
+ null
+ null
+ null
+ ]
+ /Parent 7 0 R
+ /Prev 14 0 R
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Type /Outline
+>>
+%% Object stream: object 16, index 2
+<<
+ /Nums [
+ 0
+ <<
+ /P ()
+ >>
+ 2
+ <<
+ /S /r
+ /St 1
+ >>
+ 7
+ <<
+ /P ()
+ >>
+ 9
+ <<
+ /S /r
+ /St 6
+ >>
+ 11
+ <<
+ /P ()
+ >>
+ 12
+ <<
+ /S /D
+ /St 2
+ >>
+ 15
+ <<
+ /S /D
+ /St 6
+ >>
+ 19
+ <<
+ /P ()
+ >>
+ 20
+ <<
+ /S /D
+ /St 12
+ >>
+ 22
+ <<
+ /S /D
+ /St 16059
+ >>
+ 23
+ <<
+ /S /r
+ /St 50
+ >>
+ 29
+ <<
+ /S /r
+ /St 54
+ >>
+ ]
+>>
+endstream
+endobj
+
+17 0 obj
+<<
+ /Count 30
+ /Kids [
+ 27 0 R
+ 26 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 18 0 R
+ 31 0 R
+ 32 0 R
+ 33 0 R
+ 34 0 R
+ 35 0 R
+ 20 0 R
+ 22 0 R
+ 21 0 R
+ 36 0 R
+ 19 0 R
+ 37 0 R
+ 38 0 R
+ 23 0 R
+ 24 0 R
+ 39 0 R
+ 40 0 R
+ 25 0 R
+ 41 0 R
+ 42 0 R
+ 43 0 R
+ 44 0 R
+ 45 0 R
+ 46 0 R
+ 47 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 6
+18 0 obj
+<<
+ /Contents 48 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+19 0 obj
+<<
+ /Contents 52 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+20 0 obj
+<<
+ /Contents 54 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+21 0 obj
+<<
+ /Contents 56 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+22 0 obj
+<<
+ /Contents 58 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+23 0 obj
+<<
+ /Contents 60 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+24 0 obj
+<<
+ /Contents 62 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 64 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+26 0 obj
+<<
+ /Contents 66 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 1
+27 0 obj
+<<
+ /Contents 68 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+28 0 obj
+<<
+ /Contents 70 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+29 0 obj
+<<
+ /Contents 72 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+30 0 obj
+<<
+ /Contents 74 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+31 0 obj
+<<
+ /Contents 76 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+32 0 obj
+<<
+ /Contents 78 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+33 0 obj
+<<
+ /Contents 80 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+34 0 obj
+<<
+ /Contents 82 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+35 0 obj
+<<
+ /Contents 84 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+36 0 obj
+<<
+ /Contents 86 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+37 0 obj
+<<
+ /Contents 88 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+38 0 obj
+<<
+ /Contents 90 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+39 0 obj
+<<
+ /Contents 92 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+40 0 obj
+<<
+ /Contents 94 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+41 0 obj
+<<
+ /Contents 96 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+42 0 obj
+<<
+ /Contents 98 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+43 0 obj
+<<
+ /Contents 100 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+44 0 obj
+<<
+ /Contents 102 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+45 0 obj
+<<
+ /Contents 104 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+46 0 obj
+<<
+ /Contents 106 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+47 0 obj
+<<
+ /Contents 108 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 17 0 R
+ /Resources <<
+ /Font <<
+ /F1 50 0 R
+ >>
+ /ProcSet 51 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 6
+48 0 obj
+<<
+ /Length 49 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+49 0 obj
+46
+endobj
+
+50 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+51 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 16
+52 0 obj
+<<
+ /Length 53 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+53 0 obj
+47
+endobj
+
+%% Contents for page 12
+54 0 obj
+<<
+ /Length 55 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+55 0 obj
+47
+endobj
+
+%% Contents for page 14
+56 0 obj
+<<
+ /Length 57 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+57 0 obj
+47
+endobj
+
+%% Contents for page 13
+58 0 obj
+<<
+ /Length 59 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+59 0 obj
+47
+endobj
+
+%% Contents for page 19
+60 0 obj
+<<
+ /Length 61 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+61 0 obj
+47
+endobj
+
+%% Contents for page 20
+62 0 obj
+<<
+ /Length 63 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+63 0 obj
+47
+endobj
+
+%% Contents for page 23
+64 0 obj
+<<
+ /Length 65 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+65 0 obj
+47
+endobj
+
+%% Contents for page 2
+66 0 obj
+<<
+ /Length 67 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+67 0 obj
+46
+endobj
+
+%% Contents for page 1
+68 0 obj
+<<
+ /Length 69 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+69 0 obj
+46
+endobj
+
+%% Contents for page 3
+70 0 obj
+<<
+ /Length 71 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+71 0 obj
+46
+endobj
+
+%% Contents for page 4
+72 0 obj
+<<
+ /Length 73 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+73 0 obj
+46
+endobj
+
+%% Contents for page 5
+74 0 obj
+<<
+ /Length 75 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+75 0 obj
+46
+endobj
+
+%% Contents for page 7
+76 0 obj
+<<
+ /Length 77 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+77 0 obj
+46
+endobj
+
+%% Contents for page 8
+78 0 obj
+<<
+ /Length 79 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+79 0 obj
+46
+endobj
+
+%% Contents for page 9
+80 0 obj
+<<
+ /Length 81 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+81 0 obj
+46
+endobj
+
+%% Contents for page 10
+82 0 obj
+<<
+ /Length 83 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+83 0 obj
+46
+endobj
+
+%% Contents for page 11
+84 0 obj
+<<
+ /Length 85 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+85 0 obj
+47
+endobj
+
+%% Contents for page 15
+86 0 obj
+<<
+ /Length 87 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+87 0 obj
+47
+endobj
+
+%% Contents for page 17
+88 0 obj
+<<
+ /Length 89 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+89 0 obj
+47
+endobj
+
+%% Contents for page 18
+90 0 obj
+<<
+ /Length 91 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+91 0 obj
+47
+endobj
+
+%% Contents for page 21
+92 0 obj
+<<
+ /Length 93 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+93 0 obj
+47
+endobj
+
+%% Contents for page 22
+94 0 obj
+<<
+ /Length 95 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+95 0 obj
+47
+endobj
+
+%% Contents for page 24
+96 0 obj
+<<
+ /Length 97 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+97 0 obj
+47
+endobj
+
+%% Contents for page 25
+98 0 obj
+<<
+ /Length 99 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+99 0 obj
+47
+endobj
+
+%% Contents for page 26
+100 0 obj
+<<
+ /Length 101 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+101 0 obj
+47
+endobj
+
+%% Contents for page 27
+102 0 obj
+<<
+ /Length 103 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+103 0 obj
+47
+endobj
+
+%% Contents for page 28
+104 0 obj
+<<
+ /Length 105 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+105 0 obj
+47
+endobj
+
+%% Contents for page 29
+106 0 obj
+<<
+ /Length 107 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+107 0 obj
+47
+endobj
+
+%% Contents for page 30
+108 0 obj
+<<
+ /Length 109 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+109 0 obj
+47
+endobj
+
+110 0 obj
+<<
+ /Type /XRef
+ /Length 444
+ /W [ 1 2 1 ]
+ /Root 1 0 R
+ /Size 111
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+stream
+
+endstream
+endobj
+
+startxref
+14730
+%%EOF
diff --git a/qpdf/qtest/qpdf/good18.out b/qpdf/qtest/qpdf/good18.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good18.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good18.pdf b/qpdf/qtest/qpdf/good18.pdf
new file mode 100644
index 00000000..7563574f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good18.pdf
@@ -0,0 +1,1538 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels 107 0 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+xref
+0 110
+0000000095 65535 f
+0000000025 00000 n
+0000000145 00000 n
+0000000541 00000 n
+0000000746 00000 n
+0000000951 00000 n
+0000001156 00000 n
+0000001361 00000 n
+0000001566 00000 n
+0000001771 00000 n
+0000001976 00000 n
+0000002182 00000 n
+0000002389 00000 n
+0000002596 00000 n
+0000002803 00000 n
+0000003010 00000 n
+0000003217 00000 n
+0000003424 00000 n
+0000003631 00000 n
+0000003838 00000 n
+0000004045 00000 n
+0000004252 00000 n
+0000004459 00000 n
+0000004666 00000 n
+0000004873 00000 n
+0000005080 00000 n
+0000005287 00000 n
+0000005494 00000 n
+0000005701 00000 n
+0000005908 00000 n
+0000006115 00000 n
+0000006322 00000 n
+0000006529 00000 n
+0000006748 00000 n
+0000006851 00000 n
+0000006871 00000 n
+0000006990 00000 n
+0000007049 00000 n
+0000007152 00000 n
+0000007195 00000 n
+0000007298 00000 n
+0000007341 00000 n
+0000007444 00000 n
+0000007487 00000 n
+0000007590 00000 n
+0000007633 00000 n
+0000007736 00000 n
+0000007779 00000 n
+0000007882 00000 n
+0000007925 00000 n
+0000008028 00000 n
+0000008071 00000 n
+0000008174 00000 n
+0000008218 00000 n
+0000008321 00000 n
+0000008365 00000 n
+0000008469 00000 n
+0000008513 00000 n
+0000008617 00000 n
+0000008661 00000 n
+0000008765 00000 n
+0000008809 00000 n
+0000008913 00000 n
+0000008957 00000 n
+0000009061 00000 n
+0000009105 00000 n
+0000009209 00000 n
+0000009253 00000 n
+0000009357 00000 n
+0000009401 00000 n
+0000009505 00000 n
+0000009549 00000 n
+0000009653 00000 n
+0000009697 00000 n
+0000009801 00000 n
+0000009845 00000 n
+0000009949 00000 n
+0000009993 00000 n
+0000010097 00000 n
+0000010141 00000 n
+0000010245 00000 n
+0000010289 00000 n
+0000010393 00000 n
+0000010437 00000 n
+0000010541 00000 n
+0000010585 00000 n
+0000010689 00000 n
+0000010733 00000 n
+0000010837 00000 n
+0000010881 00000 n
+0000010985 00000 n
+0000011029 00000 n
+0000011133 00000 n
+0000011177 00000 n
+0000011281 00000 n
+0000000096 65535 f
+0000000097 65535 f
+0000000098 65535 f
+0000000099 65535 f
+0000000100 65535 f
+0000000101 65535 f
+0000000102 65535 f
+0000000103 65535 f
+0000000104 65535 f
+0000000105 65535 f
+0000000106 65535 f
+0000000107 65535 f
+0000000108 65535 f
+0000000109 65535 f
+0000000000 65535 f
+trailer <<
+ /Root 1 0 R
+ /Size 110
+>>
+startxref
+11301
+%%EOF
+
+108 0 obj
+<<
+ /Type /ObjStm
+ /N 13
+ /First 107
+ /Length 2445
+>>
+stream
+95 0
+96 74
+97 259
+98 393
+99 556
+100 898
+101 1077
+102 1275
+103 1432
+104 1589
+105 1730
+106 1887
+107 2040
+%95
+<<
+ /Type /Outlines
+ /First 96 0 R
+ /Last 97 0 R
+ /Count 6
+>>
+%96
+<<
+ /Type /Outline
+ /Title (Isís 1 -> 5: /XYZ null null null)
+ /Parent 95 0 R
+ /Count 4
+ /Next 97 0 R
+ /First 98 0 R
+ /Last 99 0 R
+ /Dest [ 8 0 R /XYZ null null null ]
+>>
+% 97
+<<
+ /Type /Outline
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Parent 95 0 R
+ /Prev 96 0 R
+ /Dest [ 18 0 R /XYZ 66 756 3 ]
+>>
+% 98
+<<
+ /Type /Outline
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Parent 96 0 R
+ /Next 99 0 R
+ /First 100 0 R
+ /Last 101 0 R
+ /Count -3
+ /Dest [ 14 0 R /Fit ]
+>>
+% 99
+<<
+ /Type /Outline
+ % /Title (Sandy (Sandy [Greek]) 1.2 -> 13: /FitH 792)
+ /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
+ /Parent 96 0 R
+ /Prev 98 0 R
+ /First 105 0 R
+ /Last 106 0 R
+ /Count 2
+ /Dest [ 16 0 R /FitH 792 ]
+>>
+% 100
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Parent 98 0 R
+ /Next 101 0 R
+ /First 102 0 R
+ /Last 103 0 R
+ /Count -2
+ /Dest [ 15 0 R /FitV 100 ]
+>>
+% 101
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Parent 98 0 R
+ /Prev 100 0 R
+ /First 104 0 R
+ /Last 104 0 R
+ /Count 1
+ /Dest [ 15 0 R /XYZ null null null ]
+>>
+% 102
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Parent 100 0 R
+ /Next 103 0 R
+ /Dest [ 21 0 R /XYZ null null null ]
+>>
+% 103
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Parent 100 0 R
+ /Prev 102 0 R
+ /Dest [ 22 0 R /XYZ null null null ]
+>>
+% 104
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Parent 101 0 R
+ /Dest [ 25 0 R /XYZ null null null ]
+>>
+% 105
+<<
+ /Type /Outline
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Parent 99 0 R
+ /Next 106 0 R
+ /Dest [ 4 0 R /FitR 66 714 180 770 ]
+>>
+% 106
+<<
+ /Type /Outline
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Parent 99 0 R
+ /Prev 105 0 R
+ /Dest [ 3 0 R /XYZ null null null ]
+>>
+% 107
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /r /St 1 >>
+ 7 << /P () >>
+ 9 << /S /r /St 6 >>
+ 11 << /P () >>
+ 12 << /S /D /St 2 >>
+ 15 << /S /D /St 6 >>
+ 19 << /P () >>
+ 20 << /S /D /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endstream
+endobj
+
+109 0 obj
+<<
+ /Type /XRef
+ /Size 110
+ /Index [0 110]
+ /W [1 2 1]
+ /Length 110
+ /Root 1 0 R
+ /Filter /FlateDecode
+ /DecodeParms << /Columns 4 /Predictor 12 >>
+>>
+stream
+xœcb
+ ÁÔbŒX$‰s â<Œ`8Â%B‚4m·Abé BÄ-±¬abŒÚpY‹Î"IŒQ. b1fÀX $ˆ1ÒA‘¦0^‰qÉ%þ›ÎþÂÄÀùŠ
+endstream
+endobj
+
+xref
+0 0
+trailer <<
+ /Size 110
+ /Root 1 0 R
+ /Prev 11301
+ /XRefStm 16113
+>>
+
+startxref
+16418
+%%EOF
diff --git a/qpdf/qtest/qpdf/good18.qdf b/qpdf/qtest/qpdf/good18.qdf
new file mode 100644
index 00000000..58e17b82
--- /dev/null
+++ b/qpdf/qtest/qpdf/good18.qdf
@@ -0,0 +1,1343 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageMode /UseOutlines
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+xref
+0 95
+0000000000 65535 f
+0000000025 00000 n
+0000000104 00000 n
+0000000500 00000 n
+0000000705 00000 n
+0000000910 00000 n
+0000001115 00000 n
+0000001320 00000 n
+0000001525 00000 n
+0000001730 00000 n
+0000001935 00000 n
+0000002141 00000 n
+0000002348 00000 n
+0000002555 00000 n
+0000002762 00000 n
+0000002969 00000 n
+0000003176 00000 n
+0000003383 00000 n
+0000003590 00000 n
+0000003797 00000 n
+0000004004 00000 n
+0000004211 00000 n
+0000004418 00000 n
+0000004625 00000 n
+0000004832 00000 n
+0000005039 00000 n
+0000005246 00000 n
+0000005453 00000 n
+0000005660 00000 n
+0000005867 00000 n
+0000006074 00000 n
+0000006281 00000 n
+0000006488 00000 n
+0000006707 00000 n
+0000006810 00000 n
+0000006830 00000 n
+0000006949 00000 n
+0000007008 00000 n
+0000007111 00000 n
+0000007154 00000 n
+0000007257 00000 n
+0000007300 00000 n
+0000007403 00000 n
+0000007446 00000 n
+0000007549 00000 n
+0000007592 00000 n
+0000007695 00000 n
+0000007738 00000 n
+0000007841 00000 n
+0000007884 00000 n
+0000007987 00000 n
+0000008030 00000 n
+0000008133 00000 n
+0000008177 00000 n
+0000008280 00000 n
+0000008324 00000 n
+0000008428 00000 n
+0000008472 00000 n
+0000008576 00000 n
+0000008620 00000 n
+0000008724 00000 n
+0000008768 00000 n
+0000008872 00000 n
+0000008916 00000 n
+0000009020 00000 n
+0000009064 00000 n
+0000009168 00000 n
+0000009212 00000 n
+0000009316 00000 n
+0000009360 00000 n
+0000009464 00000 n
+0000009508 00000 n
+0000009612 00000 n
+0000009656 00000 n
+0000009760 00000 n
+0000009804 00000 n
+0000009908 00000 n
+0000009952 00000 n
+0000010056 00000 n
+0000010100 00000 n
+0000010204 00000 n
+0000010248 00000 n
+0000010352 00000 n
+0000010396 00000 n
+0000010500 00000 n
+0000010544 00000 n
+0000010648 00000 n
+0000010692 00000 n
+0000010796 00000 n
+0000010840 00000 n
+0000010944 00000 n
+0000010988 00000 n
+0000011092 00000 n
+0000011136 00000 n
+0000011240 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 95
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+11260
+%%EOF
diff --git a/qpdf/qtest/qpdf/good19.out b/qpdf/qtest/qpdf/good19.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good19.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good19.pdf b/qpdf/qtest/qpdf/good19.pdf
new file mode 100644
index 00000000..3ffc2db0
--- /dev/null
+++ b/qpdf/qtest/qpdf/good19.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good19.qdf b/qpdf/qtest/qpdf/good19.qdf
new file mode 100644
index 00000000..1716fc75
--- /dev/null
+++ b/qpdf/qtest/qpdf/good19.qdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/good2.out b/qpdf/qtest/qpdf/good2.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good2.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good2.pdf b/qpdf/qtest/qpdf/good2.pdf
new file mode 100644
index 00000000..535f369c
--- /dev/null
+++ b/qpdf/qtest/qpdf/good2.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest null
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good2.qdf b/qpdf/qtest/qpdf/good2.qdf
new file mode 100644
index 00000000..976ed2b2
--- /dev/null
+++ b/qpdf/qtest/qpdf/good2.qdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good20.out b/qpdf/qtest/qpdf/good20.out
new file mode 100644
index 00000000..1d31025f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good20.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is direct
+/QTest is null
+unparse: null
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good20.pdf b/qpdf/qtest/qpdf/good20.pdf
new file mode 100644
index 00000000..91c3f2b3
--- /dev/null
+++ b/qpdf/qtest/qpdf/good20.pdf
@@ -0,0 +1,901 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+ /OtherStuff [
+ 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R
+ 15 0 R 16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R
+ 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R
+ 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R 38 0 R
+ 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R
+ 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R
+ 55 0 R 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R
+ 63 0 R 64 0 R 65 0 R 66 0 R 67 0 R 68 0 R 69 0 R 70 0 R
+ 71 0 R 72 0 R 73 0 R 74 0 R 75 0 R 76 0 R 77 0 R 78 0 R
+ 79 0 R 80 0 R 81 0 R 82 0 R 83 0 R 84 0 R 85 0 R 86 0 R
+ 87 0 R 88 0 R 89 0 R 90 0 R 91 0 R 92 0 R 93 0 R 94 0 R
+ 95 0 R 96 0 R 97 0 R 98 0 R 99 0 R 100 0 R 101 0 R 102 0 R
+ 103 0 R 104 0 R 105 0 R 106 0 R 107 0 R 108 0 R 109 0 R 110 0 R
+ 111 0 R 112 0 R 113 0 R 114 0 R 115 0 R 116 0 R 117 0 R 118 0 R
+ 119 0 R 120 0 R 121 0 R 122 0 R 123 0 R 124 0 R 125 0 R 126 0 R
+ 127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R 133 0 R 134 0 R
+ 135 0 R 136 0 R 137 0 R 138 0 R 139 0 R 140 0 R 141 0 R 142 0 R
+ 143 0 R 144 0 R 145 0 R 146 0 R 147 0 R 148 0 R 149 0 R 150 0 R
+ 151 0 R 152 0 R 153 0 R 154 0 R 155 0 R 156 0 R 157 0 R 158 0 R
+ 159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R 165 0 R 166 0 R
+ ]
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj
+[/Object-7]
+endobj
+
+8 0 obj
+[/Object-8]
+endobj
+
+9 0 obj
+[/Object-9]
+endobj
+
+10 0 obj
+[/Object-10]
+endobj
+
+11 0 obj
+[/Object-11]
+endobj
+
+12 0 obj
+[/Object-12]
+endobj
+
+13 0 obj
+[/Object-13]
+endobj
+
+14 0 obj
+[/Object-14]
+endobj
+
+15 0 obj
+[/Object-15]
+endobj
+
+16 0 obj
+[/Object-16]
+endobj
+
+17 0 obj
+[/Object-17]
+endobj
+
+18 0 obj
+[/Object-18]
+endobj
+
+19 0 obj
+[/Object-19]
+endobj
+
+20 0 obj
+[/Object-20]
+endobj
+
+21 0 obj
+[/Object-21]
+endobj
+
+22 0 obj
+[/Object-22]
+endobj
+
+23 0 obj
+[/Object-23]
+endobj
+
+24 0 obj
+[/Object-24]
+endobj
+
+25 0 obj
+[/Object-25]
+endobj
+
+26 0 obj
+[/Object-26]
+endobj
+
+27 0 obj
+[/Object-27]
+endobj
+
+28 0 obj
+[/Object-28]
+endobj
+
+29 0 obj
+[/Object-29]
+endobj
+
+30 0 obj
+[/Object-30]
+endobj
+
+31 0 obj
+[/Object-31]
+endobj
+
+32 0 obj
+[/Object-32]
+endobj
+
+33 0 obj
+[/Object-33]
+endobj
+
+34 0 obj
+[/Object-34]
+endobj
+
+35 0 obj
+[/Object-35]
+endobj
+
+36 0 obj
+[/Object-36]
+endobj
+
+37 0 obj
+[/Object-37]
+endobj
+
+38 0 obj
+[/Object-38]
+endobj
+
+39 0 obj
+[/Object-39]
+endobj
+
+40 0 obj
+[/Object-40]
+endobj
+
+41 0 obj
+[/Object-41]
+endobj
+
+42 0 obj
+[/Object-42]
+endobj
+
+43 0 obj
+[/Object-43]
+endobj
+
+44 0 obj
+[/Object-44]
+endobj
+
+45 0 obj
+[/Object-45]
+endobj
+
+46 0 obj
+[/Object-46]
+endobj
+
+47 0 obj
+[/Object-47]
+endobj
+
+48 0 obj
+[/Object-48]
+endobj
+
+49 0 obj
+[/Object-49]
+endobj
+
+50 0 obj
+[/Object-50]
+endobj
+
+51 0 obj
+[/Object-51]
+endobj
+
+52 0 obj
+[/Object-52]
+endobj
+
+53 0 obj
+[/Object-53]
+endobj
+
+54 0 obj
+[/Object-54]
+endobj
+
+55 0 obj
+[/Object-55]
+endobj
+
+56 0 obj
+[/Object-56]
+endobj
+
+57 0 obj
+[/Object-57]
+endobj
+
+58 0 obj
+[/Object-58]
+endobj
+
+59 0 obj
+[/Object-59]
+endobj
+
+60 0 obj
+[/Object-60]
+endobj
+
+61 0 obj
+[/Object-61]
+endobj
+
+62 0 obj
+[/Object-62]
+endobj
+
+63 0 obj
+[/Object-63]
+endobj
+
+64 0 obj
+[/Object-64]
+endobj
+
+65 0 obj
+[/Object-65]
+endobj
+
+66 0 obj
+[/Object-66]
+endobj
+
+67 0 obj
+[/Object-67]
+endobj
+
+68 0 obj
+[/Object-68]
+endobj
+
+69 0 obj
+[/Object-69]
+endobj
+
+70 0 obj
+[/Object-70]
+endobj
+
+71 0 obj
+[/Object-71]
+endobj
+
+72 0 obj
+[/Object-72]
+endobj
+
+73 0 obj
+[/Object-73]
+endobj
+
+74 0 obj
+[/Object-74]
+endobj
+
+75 0 obj
+[/Object-75]
+endobj
+
+76 0 obj
+[/Object-76]
+endobj
+
+77 0 obj
+[/Object-77]
+endobj
+
+78 0 obj
+[/Object-78]
+endobj
+
+79 0 obj
+[/Object-79]
+endobj
+
+80 0 obj
+[/Object-80]
+endobj
+
+81 0 obj
+[/Object-81]
+endobj
+
+82 0 obj
+[/Object-82]
+endobj
+
+83 0 obj
+[/Object-83]
+endobj
+
+84 0 obj
+[/Object-84]
+endobj
+
+85 0 obj
+[/Object-85]
+endobj
+
+86 0 obj
+[/Object-86]
+endobj
+
+87 0 obj
+[/Object-87]
+endobj
+
+88 0 obj
+[/Object-88]
+endobj
+
+89 0 obj
+[/Object-89]
+endobj
+
+90 0 obj
+[/Object-90]
+endobj
+
+91 0 obj
+[/Object-91]
+endobj
+
+92 0 obj
+[/Object-92]
+endobj
+
+93 0 obj
+[/Object-93]
+endobj
+
+94 0 obj
+[/Object-94]
+endobj
+
+95 0 obj
+[/Object-95]
+endobj
+
+96 0 obj
+[/Object-96]
+endobj
+
+97 0 obj
+[/Object-97]
+endobj
+
+98 0 obj
+[/Object-98]
+endobj
+
+99 0 obj
+[/Object-99]
+endobj
+
+100 0 obj
+[/Object-100]
+endobj
+
+101 0 obj
+[/Object-101]
+endobj
+
+102 0 obj
+[/Object-102]
+endobj
+
+103 0 obj
+[/Object-103]
+endobj
+
+104 0 obj
+[/Object-104]
+endobj
+
+105 0 obj
+[/Object-105]
+endobj
+
+106 0 obj
+[/Object-106]
+endobj
+
+107 0 obj
+[/Object-107]
+endobj
+
+108 0 obj
+[/Object-108]
+endobj
+
+109 0 obj
+[/Object-109]
+endobj
+
+110 0 obj
+[/Object-110]
+endobj
+
+111 0 obj
+[/Object-111]
+endobj
+
+112 0 obj
+[/Object-112]
+endobj
+
+113 0 obj
+[/Object-113]
+endobj
+
+114 0 obj
+[/Object-114]
+endobj
+
+115 0 obj
+[/Object-115]
+endobj
+
+116 0 obj
+[/Object-116]
+endobj
+
+117 0 obj
+[/Object-117]
+endobj
+
+118 0 obj
+[/Object-118]
+endobj
+
+119 0 obj
+[/Object-119]
+endobj
+
+120 0 obj
+[/Object-120]
+endobj
+
+121 0 obj
+[/Object-121]
+endobj
+
+122 0 obj
+[/Object-122]
+endobj
+
+123 0 obj
+[/Object-123]
+endobj
+
+124 0 obj
+[/Object-124]
+endobj
+
+125 0 obj
+[/Object-125]
+endobj
+
+126 0 obj
+[/Object-126]
+endobj
+
+127 0 obj
+[/Object-127]
+endobj
+
+128 0 obj
+[/Object-128]
+endobj
+
+129 0 obj
+[/Object-129]
+endobj
+
+130 0 obj
+[/Object-130]
+endobj
+
+131 0 obj
+[/Object-131]
+endobj
+
+132 0 obj
+[/Object-132]
+endobj
+
+133 0 obj
+[/Object-133]
+endobj
+
+134 0 obj
+[/Object-134]
+endobj
+
+135 0 obj
+[/Object-135]
+endobj
+
+136 0 obj
+[/Object-136]
+endobj
+
+137 0 obj
+[/Object-137]
+endobj
+
+138 0 obj
+[/Object-138]
+endobj
+
+139 0 obj
+[/Object-139]
+endobj
+
+140 0 obj
+[/Object-140]
+endobj
+
+141 0 obj
+[/Object-141]
+endobj
+
+142 0 obj
+[/Object-142]
+endobj
+
+143 0 obj
+[/Object-143]
+endobj
+
+144 0 obj
+[/Object-144]
+endobj
+
+145 0 obj
+[/Object-145]
+endobj
+
+146 0 obj
+[/Object-146]
+endobj
+
+147 0 obj
+[/Object-147]
+endobj
+
+148 0 obj
+[/Object-148]
+endobj
+
+149 0 obj
+[/Object-149]
+endobj
+
+150 0 obj
+[/Object-150]
+endobj
+
+151 0 obj
+[/Object-151]
+endobj
+
+152 0 obj
+[/Object-152]
+endobj
+
+153 0 obj
+[/Object-153]
+endobj
+
+154 0 obj
+[/Object-154]
+endobj
+
+155 0 obj
+[/Object-155]
+endobj
+
+156 0 obj
+[/Object-156]
+endobj
+
+157 0 obj
+[/Object-157]
+endobj
+
+158 0 obj
+[/Object-158]
+endobj
+
+159 0 obj
+[/Object-159]
+endobj
+
+160 0 obj
+[/Object-160]
+endobj
+
+161 0 obj
+[/Object-161]
+endobj
+
+162 0 obj
+[/Object-162]
+endobj
+
+163 0 obj
+[/Object-163]
+endobj
+
+164 0 obj
+[/Object-164]
+endobj
+
+165 0 obj
+[/Object-165]
+endobj
+
+166 0 obj
+[/Object-166]
+endobj
+
+xref
+0 167
+0000006875 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000001687 00000 n
+0000001783 00000 n
+0000001818 00000 n
+0000001936 00000 n
+0000001964 00000 n
+0000001992 00000 n
+0000002020 00000 n
+0000002050 00000 n
+0000002080 00000 n
+0000002110 00000 n
+0000002140 00000 n
+0000002170 00000 n
+0000002200 00000 n
+0000002230 00000 n
+0000002260 00000 n
+0000002290 00000 n
+0000002320 00000 n
+0000002350 00000 n
+0000002380 00000 n
+0000002410 00000 n
+0000002440 00000 n
+0000002470 00000 n
+0000002500 00000 n
+0000002530 00000 n
+0000002560 00000 n
+0000002590 00000 n
+0000002620 00000 n
+0000002650 00000 n
+0000002680 00000 n
+0000002710 00000 n
+0000002740 00000 n
+0000002770 00000 n
+0000002800 00000 n
+0000002830 00000 n
+0000002860 00000 n
+0000002890 00000 n
+0000002920 00000 n
+0000002950 00000 n
+0000002980 00000 n
+0000003010 00000 n
+0000003040 00000 n
+0000003070 00000 n
+0000003100 00000 n
+0000003130 00000 n
+0000003160 00000 n
+0000003190 00000 n
+0000003220 00000 n
+0000003250 00000 n
+0000003280 00000 n
+0000003310 00000 n
+0000003340 00000 n
+0000003370 00000 n
+0000003400 00000 n
+0000003430 00000 n
+0000003460 00000 n
+0000003490 00000 n
+0000003520 00000 n
+0000003550 00000 n
+0000003580 00000 n
+0000003610 00000 n
+0000003640 00000 n
+0000003670 00000 n
+0000003700 00000 n
+0000003730 00000 n
+0000003760 00000 n
+0000003790 00000 n
+0000003820 00000 n
+0000003850 00000 n
+0000003880 00000 n
+0000003910 00000 n
+0000003940 00000 n
+0000003970 00000 n
+0000004000 00000 n
+0000004030 00000 n
+0000004060 00000 n
+0000004090 00000 n
+0000004120 00000 n
+0000004150 00000 n
+0000004180 00000 n
+0000004210 00000 n
+0000004240 00000 n
+0000004270 00000 n
+0000004300 00000 n
+0000004330 00000 n
+0000004360 00000 n
+0000004390 00000 n
+0000004420 00000 n
+0000004450 00000 n
+0000004480 00000 n
+0000004510 00000 n
+0000004540 00000 n
+0000004570 00000 n
+0000004600 00000 n
+0000004630 00000 n
+0000004660 00000 n
+0000004690 00000 n
+0000004720 00000 n
+0000004752 00000 n
+0000004784 00000 n
+0000004816 00000 n
+0000004848 00000 n
+0000004880 00000 n
+0000004912 00000 n
+0000004944 00000 n
+0000004976 00000 n
+0000005008 00000 n
+0000005040 00000 n
+0000005072 00000 n
+0000005104 00000 n
+0000005136 00000 n
+0000005168 00000 n
+0000005200 00000 n
+0000005232 00000 n
+0000005264 00000 n
+0000005296 00000 n
+0000005328 00000 n
+0000005360 00000 n
+0000005392 00000 n
+0000005424 00000 n
+0000005456 00000 n
+0000005488 00000 n
+0000005520 00000 n
+0000005552 00000 n
+0000005584 00000 n
+0000005616 00000 n
+0000005648 00000 n
+0000005680 00000 n
+0000005712 00000 n
+0000005744 00000 n
+0000005776 00000 n
+0000005808 00000 n
+0000005840 00000 n
+0000005872 00000 n
+0000005904 00000 n
+0000005936 00000 n
+0000005968 00000 n
+0000006000 00000 n
+0000006032 00000 n
+0000006064 00000 n
+0000006096 00000 n
+0000006128 00000 n
+0000006160 00000 n
+0000006192 00000 n
+0000006224 00000 n
+0000006256 00000 n
+0000006288 00000 n
+0000006320 00000 n
+0000006352 00000 n
+0000006384 00000 n
+0000006416 00000 n
+0000006448 00000 n
+0000006480 00000 n
+0000006512 00000 n
+0000006544 00000 n
+0000006576 00000 n
+0000006608 00000 n
+0000006640 00000 n
+0000006672 00000 n
+0000006704 00000 n
+0000006736 00000 n
+0000006768 00000 n
+0000006800 00000 n
+0000006832 00000 n
+trailer <<
+ /Size 167
+ /Root 1 0 R
+>>
+startxref
+6864
+%%EOF
diff --git a/qpdf/qtest/qpdf/good20.qdf b/qpdf/qtest/qpdf/good20.qdf
new file mode 100644
index 00000000..f4c8cad9
--- /dev/null
+++ b/qpdf/qtest/qpdf/good20.qdf
@@ -0,0 +1,1075 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Type /ObjStm
+ /Length 7271
+ /N 83
+ /First 686
+>>
+stream
+2 0
+3 74
+4 166
+5 2236
+6 2288
+7 2340
+8 2392
+9 2445
+10 2499
+11 2553
+12 2608
+13 2663
+14 2718
+15 2773
+16 2828
+17 2883
+18 2938
+19 2993
+20 3048
+21 3103
+22 3158
+23 3213
+24 3268
+25 3323
+26 3378
+27 3433
+28 3488
+29 3543
+30 3598
+31 3653
+32 3708
+33 3763
+34 3818
+35 3873
+36 3928
+37 3983
+38 4038
+39 4093
+40 4148
+41 4203
+42 4258
+43 4313
+44 4368
+45 4423
+46 4478
+47 4533
+48 4588
+49 4643
+50 4698
+51 4753
+52 4808
+53 4863
+54 4918
+55 4973
+56 5028
+57 5083
+58 5138
+59 5193
+60 5248
+61 5303
+62 5358
+63 5413
+64 5468
+65 5523
+66 5578
+67 5633
+68 5688
+69 5743
+70 5798
+71 5853
+72 5908
+73 5963
+74 6018
+75 6073
+76 6128
+77 6183
+78 6238
+79 6293
+80 6348
+81 6403
+82 6458
+83 6513
+84 6568
+%% Object stream: object 2, index 0
+<<
+ /Pages 3 0 R
+ /Type /Catalog
+>>
+%% Object stream: object 3, index 1
+<<
+ /Count 1
+ /Kids [
+ 4 0 R
+ ]
+ /Type /Pages
+>>
+%% Object stream: object 4, index 2
+%% Page 1
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /OtherStuff [
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ 33 0 R
+ 34 0 R
+ 35 0 R
+ 36 0 R
+ 37 0 R
+ 38 0 R
+ 39 0 R
+ 40 0 R
+ 41 0 R
+ 42 0 R
+ 43 0 R
+ 44 0 R
+ 45 0 R
+ 46 0 R
+ 47 0 R
+ 48 0 R
+ 49 0 R
+ 50 0 R
+ 51 0 R
+ 52 0 R
+ 53 0 R
+ 54 0 R
+ 55 0 R
+ 56 0 R
+ 57 0 R
+ 58 0 R
+ 59 0 R
+ 60 0 R
+ 61 0 R
+ 62 0 R
+ 63 0 R
+ 64 0 R
+ 65 0 R
+ 66 0 R
+ 67 0 R
+ 68 0 R
+ 69 0 R
+ 70 0 R
+ 71 0 R
+ 72 0 R
+ 73 0 R
+ 74 0 R
+ 75 0 R
+ 76 0 R
+ 77 0 R
+ 78 0 R
+ 79 0 R
+ 80 0 R
+ 81 0 R
+ 82 0 R
+ 83 0 R
+ 84 0 R
+ 90 0 R
+ 91 0 R
+ 92 0 R
+ 93 0 R
+ 94 0 R
+ 95 0 R
+ 96 0 R
+ 97 0 R
+ 98 0 R
+ 99 0 R
+ 100 0 R
+ 101 0 R
+ 102 0 R
+ 103 0 R
+ 104 0 R
+ 105 0 R
+ 106 0 R
+ 107 0 R
+ 108 0 R
+ 109 0 R
+ 110 0 R
+ 111 0 R
+ 112 0 R
+ 113 0 R
+ 114 0 R
+ 115 0 R
+ 116 0 R
+ 117 0 R
+ 118 0 R
+ 119 0 R
+ 120 0 R
+ 121 0 R
+ 122 0 R
+ 123 0 R
+ 124 0 R
+ 125 0 R
+ 126 0 R
+ 127 0 R
+ 128 0 R
+ 129 0 R
+ 130 0 R
+ 131 0 R
+ 132 0 R
+ 133 0 R
+ 134 0 R
+ 135 0 R
+ 136 0 R
+ 137 0 R
+ 138 0 R
+ 139 0 R
+ 140 0 R
+ 141 0 R
+ 142 0 R
+ 143 0 R
+ 144 0 R
+ 145 0 R
+ 146 0 R
+ 147 0 R
+ 148 0 R
+ 149 0 R
+ 150 0 R
+ 151 0 R
+ 152 0 R
+ 153 0 R
+ 154 0 R
+ 155 0 R
+ 156 0 R
+ 157 0 R
+ 158 0 R
+ 159 0 R
+ 160 0 R
+ 161 0 R
+ 162 0 R
+ 163 0 R
+ 164 0 R
+ 165 0 R
+ 166 0 R
+ 167 0 R
+ 168 0 R
+ 169 0 R
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 89 0 R
+ >>
+ /ProcSet 88 0 R
+ >>
+ /Type /Page
+>>
+%% Object stream: object 5, index 3
+[
+ /Object-7
+]
+%% Object stream: object 6, index 4
+[
+ /Object-8
+]
+%% Object stream: object 7, index 5
+[
+ /Object-9
+]
+%% Object stream: object 8, index 6
+[
+ /Object-10
+]
+%% Object stream: object 9, index 7
+[
+ /Object-11
+]
+%% Object stream: object 10, index 8
+[
+ /Object-12
+]
+%% Object stream: object 11, index 9
+[
+ /Object-13
+]
+%% Object stream: object 12, index 10
+[
+ /Object-14
+]
+%% Object stream: object 13, index 11
+[
+ /Object-15
+]
+%% Object stream: object 14, index 12
+[
+ /Object-16
+]
+%% Object stream: object 15, index 13
+[
+ /Object-17
+]
+%% Object stream: object 16, index 14
+[
+ /Object-18
+]
+%% Object stream: object 17, index 15
+[
+ /Object-19
+]
+%% Object stream: object 18, index 16
+[
+ /Object-20
+]
+%% Object stream: object 19, index 17
+[
+ /Object-21
+]
+%% Object stream: object 20, index 18
+[
+ /Object-22
+]
+%% Object stream: object 21, index 19
+[
+ /Object-23
+]
+%% Object stream: object 22, index 20
+[
+ /Object-24
+]
+%% Object stream: object 23, index 21
+[
+ /Object-25
+]
+%% Object stream: object 24, index 22
+[
+ /Object-26
+]
+%% Object stream: object 25, index 23
+[
+ /Object-27
+]
+%% Object stream: object 26, index 24
+[
+ /Object-28
+]
+%% Object stream: object 27, index 25
+[
+ /Object-29
+]
+%% Object stream: object 28, index 26
+[
+ /Object-30
+]
+%% Object stream: object 29, index 27
+[
+ /Object-31
+]
+%% Object stream: object 30, index 28
+[
+ /Object-32
+]
+%% Object stream: object 31, index 29
+[
+ /Object-33
+]
+%% Object stream: object 32, index 30
+[
+ /Object-34
+]
+%% Object stream: object 33, index 31
+[
+ /Object-35
+]
+%% Object stream: object 34, index 32
+[
+ /Object-36
+]
+%% Object stream: object 35, index 33
+[
+ /Object-37
+]
+%% Object stream: object 36, index 34
+[
+ /Object-38
+]
+%% Object stream: object 37, index 35
+[
+ /Object-39
+]
+%% Object stream: object 38, index 36
+[
+ /Object-40
+]
+%% Object stream: object 39, index 37
+[
+ /Object-41
+]
+%% Object stream: object 40, index 38
+[
+ /Object-42
+]
+%% Object stream: object 41, index 39
+[
+ /Object-43
+]
+%% Object stream: object 42, index 40
+[
+ /Object-44
+]
+%% Object stream: object 43, index 41
+[
+ /Object-45
+]
+%% Object stream: object 44, index 42
+[
+ /Object-46
+]
+%% Object stream: object 45, index 43
+[
+ /Object-47
+]
+%% Object stream: object 46, index 44
+[
+ /Object-48
+]
+%% Object stream: object 47, index 45
+[
+ /Object-49
+]
+%% Object stream: object 48, index 46
+[
+ /Object-50
+]
+%% Object stream: object 49, index 47
+[
+ /Object-51
+]
+%% Object stream: object 50, index 48
+[
+ /Object-52
+]
+%% Object stream: object 51, index 49
+[
+ /Object-53
+]
+%% Object stream: object 52, index 50
+[
+ /Object-54
+]
+%% Object stream: object 53, index 51
+[
+ /Object-55
+]
+%% Object stream: object 54, index 52
+[
+ /Object-56
+]
+%% Object stream: object 55, index 53
+[
+ /Object-57
+]
+%% Object stream: object 56, index 54
+[
+ /Object-58
+]
+%% Object stream: object 57, index 55
+[
+ /Object-59
+]
+%% Object stream: object 58, index 56
+[
+ /Object-60
+]
+%% Object stream: object 59, index 57
+[
+ /Object-61
+]
+%% Object stream: object 60, index 58
+[
+ /Object-62
+]
+%% Object stream: object 61, index 59
+[
+ /Object-63
+]
+%% Object stream: object 62, index 60
+[
+ /Object-64
+]
+%% Object stream: object 63, index 61
+[
+ /Object-65
+]
+%% Object stream: object 64, index 62
+[
+ /Object-66
+]
+%% Object stream: object 65, index 63
+[
+ /Object-67
+]
+%% Object stream: object 66, index 64
+[
+ /Object-68
+]
+%% Object stream: object 67, index 65
+[
+ /Object-69
+]
+%% Object stream: object 68, index 66
+[
+ /Object-70
+]
+%% Object stream: object 69, index 67
+[
+ /Object-71
+]
+%% Object stream: object 70, index 68
+[
+ /Object-72
+]
+%% Object stream: object 71, index 69
+[
+ /Object-73
+]
+%% Object stream: object 72, index 70
+[
+ /Object-74
+]
+%% Object stream: object 73, index 71
+[
+ /Object-75
+]
+%% Object stream: object 74, index 72
+[
+ /Object-76
+]
+%% Object stream: object 75, index 73
+[
+ /Object-77
+]
+%% Object stream: object 76, index 74
+[
+ /Object-78
+]
+%% Object stream: object 77, index 75
+[
+ /Object-79
+]
+%% Object stream: object 78, index 76
+[
+ /Object-80
+]
+%% Object stream: object 79, index 77
+[
+ /Object-81
+]
+%% Object stream: object 80, index 78
+[
+ /Object-82
+]
+%% Object stream: object 81, index 79
+[
+ /Object-83
+]
+%% Object stream: object 82, index 80
+[
+ /Object-84
+]
+%% Object stream: object 83, index 81
+[
+ /Object-85
+]
+%% Object stream: object 84, index 82
+[
+ /Object-86
+]
+endstream
+endobj
+
+%% Contents for page 1
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+44
+endobj
+
+87 0 obj
+<<
+ /Type /ObjStm
+ /Length 5430
+ /N 82
+ /First 743
+>>
+stream
+88 0
+89 56
+90 195
+91 249
+92 303
+93 357
+94 411
+95 465
+96 519
+97 573
+98 628
+99 683
+100 739
+101 795
+102 851
+103 907
+104 964
+105 1021
+106 1078
+107 1135
+108 1192
+109 1249
+110 1306
+111 1363
+112 1420
+113 1477
+114 1534
+115 1591
+116 1648
+117 1705
+118 1762
+119 1819
+120 1876
+121 1933
+122 1990
+123 2047
+124 2104
+125 2161
+126 2218
+127 2275
+128 2332
+129 2389
+130 2446
+131 2503
+132 2560
+133 2617
+134 2674
+135 2731
+136 2788
+137 2845
+138 2902
+139 2959
+140 3016
+141 3073
+142 3130
+143 3187
+144 3244
+145 3301
+146 3358
+147 3415
+148 3472
+149 3529
+150 3586
+151 3643
+152 3700
+153 3757
+154 3814
+155 3871
+156 3928
+157 3985
+158 4042
+159 4099
+160 4156
+161 4213
+162 4270
+163 4327
+164 4384
+165 4441
+166 4498
+167 4555
+168 4612
+169 4669
+%% Object stream: object 88, index 0
+[
+ /PDF
+ /Text
+]
+%% Object stream: object 89, index 1
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+%% Object stream: object 90, index 2
+[
+ /Object-87
+]
+%% Object stream: object 91, index 3
+[
+ /Object-88
+]
+%% Object stream: object 92, index 4
+[
+ /Object-89
+]
+%% Object stream: object 93, index 5
+[
+ /Object-90
+]
+%% Object stream: object 94, index 6
+[
+ /Object-91
+]
+%% Object stream: object 95, index 7
+[
+ /Object-92
+]
+%% Object stream: object 96, index 8
+[
+ /Object-93
+]
+%% Object stream: object 97, index 9
+[
+ /Object-94
+]
+%% Object stream: object 98, index 10
+[
+ /Object-95
+]
+%% Object stream: object 99, index 11
+[
+ /Object-96
+]
+%% Object stream: object 100, index 12
+[
+ /Object-97
+]
+%% Object stream: object 101, index 13
+[
+ /Object-98
+]
+%% Object stream: object 102, index 14
+[
+ /Object-99
+]
+%% Object stream: object 103, index 15
+[
+ /Object-100
+]
+%% Object stream: object 104, index 16
+[
+ /Object-101
+]
+%% Object stream: object 105, index 17
+[
+ /Object-102
+]
+%% Object stream: object 106, index 18
+[
+ /Object-103
+]
+%% Object stream: object 107, index 19
+[
+ /Object-104
+]
+%% Object stream: object 108, index 20
+[
+ /Object-105
+]
+%% Object stream: object 109, index 21
+[
+ /Object-106
+]
+%% Object stream: object 110, index 22
+[
+ /Object-107
+]
+%% Object stream: object 111, index 23
+[
+ /Object-108
+]
+%% Object stream: object 112, index 24
+[
+ /Object-109
+]
+%% Object stream: object 113, index 25
+[
+ /Object-110
+]
+%% Object stream: object 114, index 26
+[
+ /Object-111
+]
+%% Object stream: object 115, index 27
+[
+ /Object-112
+]
+%% Object stream: object 116, index 28
+[
+ /Object-113
+]
+%% Object stream: object 117, index 29
+[
+ /Object-114
+]
+%% Object stream: object 118, index 30
+[
+ /Object-115
+]
+%% Object stream: object 119, index 31
+[
+ /Object-116
+]
+%% Object stream: object 120, index 32
+[
+ /Object-117
+]
+%% Object stream: object 121, index 33
+[
+ /Object-118
+]
+%% Object stream: object 122, index 34
+[
+ /Object-119
+]
+%% Object stream: object 123, index 35
+[
+ /Object-120
+]
+%% Object stream: object 124, index 36
+[
+ /Object-121
+]
+%% Object stream: object 125, index 37
+[
+ /Object-122
+]
+%% Object stream: object 126, index 38
+[
+ /Object-123
+]
+%% Object stream: object 127, index 39
+[
+ /Object-124
+]
+%% Object stream: object 128, index 40
+[
+ /Object-125
+]
+%% Object stream: object 129, index 41
+[
+ /Object-126
+]
+%% Object stream: object 130, index 42
+[
+ /Object-127
+]
+%% Object stream: object 131, index 43
+[
+ /Object-128
+]
+%% Object stream: object 132, index 44
+[
+ /Object-129
+]
+%% Object stream: object 133, index 45
+[
+ /Object-130
+]
+%% Object stream: object 134, index 46
+[
+ /Object-131
+]
+%% Object stream: object 135, index 47
+[
+ /Object-132
+]
+%% Object stream: object 136, index 48
+[
+ /Object-133
+]
+%% Object stream: object 137, index 49
+[
+ /Object-134
+]
+%% Object stream: object 138, index 50
+[
+ /Object-135
+]
+%% Object stream: object 139, index 51
+[
+ /Object-136
+]
+%% Object stream: object 140, index 52
+[
+ /Object-137
+]
+%% Object stream: object 141, index 53
+[
+ /Object-138
+]
+%% Object stream: object 142, index 54
+[
+ /Object-139
+]
+%% Object stream: object 143, index 55
+[
+ /Object-140
+]
+%% Object stream: object 144, index 56
+[
+ /Object-141
+]
+%% Object stream: object 145, index 57
+[
+ /Object-142
+]
+%% Object stream: object 146, index 58
+[
+ /Object-143
+]
+%% Object stream: object 147, index 59
+[
+ /Object-144
+]
+%% Object stream: object 148, index 60
+[
+ /Object-145
+]
+%% Object stream: object 149, index 61
+[
+ /Object-146
+]
+%% Object stream: object 150, index 62
+[
+ /Object-147
+]
+%% Object stream: object 151, index 63
+[
+ /Object-148
+]
+%% Object stream: object 152, index 64
+[
+ /Object-149
+]
+%% Object stream: object 153, index 65
+[
+ /Object-150
+]
+%% Object stream: object 154, index 66
+[
+ /Object-151
+]
+%% Object stream: object 155, index 67
+[
+ /Object-152
+]
+%% Object stream: object 156, index 68
+[
+ /Object-153
+]
+%% Object stream: object 157, index 69
+[
+ /Object-154
+]
+%% Object stream: object 158, index 70
+[
+ /Object-155
+]
+%% Object stream: object 159, index 71
+[
+ /Object-156
+]
+%% Object stream: object 160, index 72
+[
+ /Object-157
+]
+%% Object stream: object 161, index 73
+[
+ /Object-158
+]
+%% Object stream: object 162, index 74
+[
+ /Object-159
+]
+%% Object stream: object 163, index 75
+[
+ /Object-160
+]
+%% Object stream: object 164, index 76
+[
+ /Object-161
+]
+%% Object stream: object 165, index 77
+[
+ /Object-162
+]
+%% Object stream: object 166, index 78
+[
+ /Object-163
+]
+%% Object stream: object 167, index 79
+[
+ /Object-164
+]
+%% Object stream: object 168, index 80
+[
+ /Object-165
+]
+%% Object stream: object 169, index 81
+[
+ /Object-166
+]
+endstream
+endobj
+
+170 0 obj
+<<
+ /Type /XRef
+ /Length 684
+ /W [ 1 2 1 ]
+ /Root 2 0 R
+ /Size 171
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+stream
+
+
+
+endstream
+endobj
+
+startxref
+13053
+%%EOF
diff --git a/qpdf/qtest/qpdf/good3.out b/qpdf/qtest/qpdf/good3.out
new file mode 100644
index 00000000..7982e109
--- /dev/null
+++ b/qpdf/qtest/qpdf/good3.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is indirect
+/QTest is null
+unparse: 7 0 R
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good3.pdf b/qpdf/qtest/qpdf/good3.pdf
new file mode 100644
index 00000000..068e7968
--- /dev/null
+++ b/qpdf/qtest/qpdf/good3.pdf
@@ -0,0 +1,80 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good3.qdf b/qpdf/qtest/qpdf/good3.qdf
new file mode 100644
index 00000000..976ed2b2
--- /dev/null
+++ b/qpdf/qtest/qpdf/good3.qdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good4.out b/qpdf/qtest/qpdf/good4.out
new file mode 100644
index 00000000..7982e109
--- /dev/null
+++ b/qpdf/qtest/qpdf/good4.out
@@ -0,0 +1,6 @@
+/QTest is implicit
+/QTest is indirect
+/QTest is null
+unparse: 7 0 R
+unparseResolved: null
+test 1 done
diff --git a/qpdf/qtest/qpdf/good4.pdf b/qpdf/qtest/qpdf/good4.pdf
new file mode 100644
index 00000000..326d542d
--- /dev/null
+++ b/qpdf/qtest/qpdf/good4.pdf
@@ -0,0 +1,83 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj null endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+0000000556 00000 n
+trailer <<
+ /Size 8
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+577
+%%EOF
diff --git a/qpdf/qtest/qpdf/good4.qdf b/qpdf/qtest/qpdf/good4.qdf
new file mode 100644
index 00000000..976ed2b2
--- /dev/null
+++ b/qpdf/qtest/qpdf/good4.qdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good5.out b/qpdf/qtest/qpdf/good5.out
new file mode 100644
index 00000000..ff2e3fdf
--- /dev/null
+++ b/qpdf/qtest/qpdf/good5.out
@@ -0,0 +1,5 @@
+/QTest is indirect
+/QTest is Boolean with value true
+unparse: 7 0 R
+unparseResolved: true
+test 1 done
diff --git a/qpdf/qtest/qpdf/good5.pdf b/qpdf/qtest/qpdf/good5.pdf
new file mode 100644
index 00000000..0d9b55dd
--- /dev/null
+++ b/qpdf/qtest/qpdf/good5.pdf
@@ -0,0 +1,83 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+7 0 obj true endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+0000000556 00000 n
+trailer <<
+ /Size 8
+ /Root 1 0 R
+ /QTest 7 0 R
+>>
+startxref
+577
+%%EOF
diff --git a/qpdf/qtest/qpdf/good5.qdf b/qpdf/qtest/qpdf/good5.qdf
new file mode 100644
index 00000000..3ace3aa8
--- /dev/null
+++ b/qpdf/qtest/qpdf/good5.qdf
@@ -0,0 +1,96 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest true
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good6.out b/qpdf/qtest/qpdf/good6.out
new file mode 100644
index 00000000..17b498d1
--- /dev/null
+++ b/qpdf/qtest/qpdf/good6.out
@@ -0,0 +1,5 @@
+/QTest is direct
+/QTest is Boolean with value false
+unparse: false
+unparseResolved: false
+test 1 done
diff --git a/qpdf/qtest/qpdf/good6.pdf b/qpdf/qtest/qpdf/good6.pdf
new file mode 100644
index 00000000..790f700a
--- /dev/null
+++ b/qpdf/qtest/qpdf/good6.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest false
+>>
+startxref 556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good6.qdf b/qpdf/qtest/qpdf/good6.qdf
new file mode 100644
index 00000000..1602336f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good6.qdf
@@ -0,0 +1,96 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest false
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good7-not-normalized.qdf b/qpdf/qtest/qpdf/good7-not-normalized.qdf
new file mode 100644
index 00000000..5c6e9caf
--- /dev/null
+++ b/qpdf/qtest/qpdf/good7-not-normalized.qdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+
+BT
+/F1 24 Tf 72 720 Td
+ (Potato) Tj ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest 16059
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good7.out b/qpdf/qtest/qpdf/good7.out
new file mode 100644
index 00000000..ab14fba0
--- /dev/null
+++ b/qpdf/qtest/qpdf/good7.out
@@ -0,0 +1,5 @@
+/QTest is direct
+/QTest is an integer with value 16059
+unparse: 16059
+unparseResolved: 16059
+test 1 done
diff --git a/qpdf/qtest/qpdf/good7.pdf b/qpdf/qtest/qpdf/good7.pdf
new file mode 100644
index 00000000..e5f2298e
--- /dev/null
+++ b/qpdf/qtest/qpdf/good7.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+
+BT
+/F1 24 Tf 72 720 Td
+ (Potato) Tj ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 16059
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good7.qdf b/qpdf/qtest/qpdf/good7.qdf
new file mode 100644
index 00000000..c338e80c
--- /dev/null
+++ b/qpdf/qtest/qpdf/good7.qdf
@@ -0,0 +1,97 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+
+BT
+/F1 24 Tf
+72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+43
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000474 00000 n
+0000000493 00000 n
+0000000611 00000 n
+trailer <<
+ /QTest 16059
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+646
+%%EOF
diff --git a/qpdf/qtest/qpdf/good8.out b/qpdf/qtest/qpdf/good8.out
new file mode 100644
index 00000000..5087db3f
--- /dev/null
+++ b/qpdf/qtest/qpdf/good8.out
@@ -0,0 +1,5 @@
+/QTest is direct
+/QTest is a real number with value 3.14159
+unparse: 3.14159
+unparseResolved: 3.14159
+test 1 done
diff --git a/qpdf/qtest/qpdf/good8.pdf b/qpdf/qtest/qpdf/good8.pdf
new file mode 100644
index 00000000..f766dba8
--- /dev/null
+++ b/qpdf/qtest/qpdf/good8.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 132
+ /Filter /ASCIIHexDecode
+>>
+stream
+42 54 0a 20 20 2f 46 31 20 32 34 20 54 66 0a 20
+20 37 32 20 37 32 30 20 54 64 0a 20 20 28 50 6f
+74 61 74 6F 29 20 54 6A 0A 45 540a>
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000518 00000 n
+0000000553 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest 3.14159
+>>
+startxref
+671
+%%EOF
diff --git a/qpdf/qtest/qpdf/good8.qdf b/qpdf/qtest/qpdf/good8.qdf
new file mode 100644
index 00000000..19c75991
--- /dev/null
+++ b/qpdf/qtest/qpdf/good8.qdf
@@ -0,0 +1,96 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest 3.14159
+ /Root 1 0 R
+ /Size 8
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/good9.out b/qpdf/qtest/qpdf/good9.out
new file mode 100644
index 00000000..75c40bc9
--- /dev/null
+++ b/qpdf/qtest/qpdf/good9.out
@@ -0,0 +1,5 @@
+/QTest is direct
+/QTest is a string with value ¡Hola!
+unparse: (¡Hola!)
+unparseResolved: (¡Hola!)
+test 1 done
diff --git a/qpdf/qtest/qpdf/good9.pdf b/qpdf/qtest/qpdf/good9.pdf
new file mode 100644
index 00000000..881392e0
--- /dev/null
+++ b/qpdf/qtest/qpdf/good9.pdf
@@ -0,0 +1,81 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+ /QTest (\241Hola!)
+ /Z ('žyÔãjø׸B^Q\n‹9”\rD|kã¢JZm:½l™\\)
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/good9.qdf b/qpdf/qtest/qpdf/good9.qdf
new file mode 100644
index 00000000..c9c3d69b
--- /dev/null
+++ b/qpdf/qtest/qpdf/good9.qdf
@@ -0,0 +1,97 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+trailer <<
+ /QTest (¡Hola!)
+ /Root 1 0 R
+ /Size 8
+ /Z ('\236yÔ\005\037ãjø׸B^Q\n\2139\224\rD|kã¢JZm:½l\231\002\\)
+ /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
+>>
+startxref
+647
+%%EOF
diff --git a/qpdf/qtest/qpdf/heifer.out b/qpdf/qtest/qpdf/heifer.out
new file mode 100644
index 00000000..5a9bb975
--- /dev/null
+++ b/qpdf/qtest/qpdf/heifer.out
@@ -0,0 +1,4 @@
+WARNING: heifer.pdf: offset 0: file is damaged
+WARNING: heifer.pdf: offset 92741: xref not found
+WARNING: Attempting to reconstruct cross-reference table
+WARNING: heifer.pdf: offset 51: attempting to recover stream length
diff --git a/qpdf/qtest/qpdf/heifer.pdf b/qpdf/qtest/qpdf/heifer.pdf
new file mode 100644
index 00000000..a3c62422
--- /dev/null
+++ b/qpdf/qtest/qpdf/heifer.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/heifer.qdf b/qpdf/qtest/qpdf/heifer.qdf
new file mode 100644
index 00000000..0e20c934
--- /dev/null
+++ b/qpdf/qtest/qpdf/heifer.qdf
@@ -0,0 +1,1349 @@
+%PDF-1.2
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Metadata 3 0 R
+ /Pages 5 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /CreationDate (D:20020815124312-04'00')
+ /Creator (Acrobat 4.0 Import Plug-in for Windows)
+ /ModDate (D:20020815124312-04'00')
+ /Producer (Acrobat Distiller 5.0.5 \(Windows\))
+ /Title (geese_w-anchors.pdf)
+>>
+endobj
+
+3 0 obj
+<<
+ /Subtype /XML
+ /Type /Metadata
+ /Length 4 0 R
+>>
+stream
+<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d' bytes='992'?><rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'><rdf:Description about='' xmlns='http://ns.adobe.com/pdf/1.3/' xmlns:pdf='http://ns.adobe.com/pdf/1.3/' pdf:CreationDate='2002-08-15T16:43:12Z' pdf:ModDate='2002-08-15T16:43:12Z' pdf:Producer='Acrobat Distiller 5.0.5 (Windows)' pdf:Creator='Acrobat 4.0 Import Plug-in for Windows' pdf:Title='geese_w-anchors.pdf'/>
+<rdf:Description about='' xmlns='http://ns.adobe.com/xap/1.0/' xmlns:xap='http://ns.adobe.com/xap/1.0/' xap:CreateDate='2002-08-15T16:43:12Z' xap:ModifyDate='2002-08-15T16:43:12Z' xap:MetadataDate='2002-08-15T16:43:12Z'><xap:Title><rdf:Alt><rdf:li xml:lang='x-default'>geese_w-anchors.pdf</rdf:li></rdf:Alt></xap:Title></rdf:Description>
+<rdf:Description about='' xmlns='http://purl.org/dc/elements/1.1/' xmlns:dc='http://purl.org/dc/elements/1.1/' dc:title='geese_w-anchors.pdf'/>
+</rdf:RDF><?xpacket end='r'?>
+endstream
+endobj
+
+4 0 obj
+993
+endobj
+
+5 0 obj
+<<
+ /Count 1
+ /Kids [
+ 6 0 R
+ ]
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+6 0 obj
+<<
+ /Contents 7 0 R
+ /Parent 5 0 R
+ /Resources 9 0 R
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+7 0 obj
+<<
+ /Length 8 0 R
+>>
+stream
+q
+/RelativeColorimetric ri
+1 g
+/GS1 gs
+1 i
+0 792 m
+0 792 l
+f
+q
+3.617 790.98 608.383 -787.92 re
+W n
+q
+610.995 0 0 789.113 3.0369 2.5269 cm
+/Im1 Do
+Q
+Q
+BT
+/F1 1 Tf
+16 0 0 16 112.495 255.964 Tm
+/Cs5 cs 0.78 0.275 0.157 sc
+0 Tc
+0 Tw
+<01>Tj
+/F2 1 Tf
+14 0 0 14 164.401 206.964 Tm
+0 0 0 sc
+0.0003 Tc
+[<01>-219.7<02>0<03040506>-24.7<070406>-24.7(\b)0.1<07090a06>-24.7<0b0c0d06>-24.7<0e0a0a0f06>-24.7<0203090a0f06>-24.7<030f06>-24.7<1007111206>-24.7<0f0c130a06>-24.7<0e1006>]TJ
+6.7492 -2.889 TD
+[<140c1006>-24.7<050b030d06>-24.7<0203040506>-24.7<070406>]TJ
+-11.7937 -2.4191 TD
+[<0e12030f0206>-24.7<10071106>-24.7<15071006>-24.7<0c0d06>-24.7<030506>-24.7<0e12030f020d06>-24.7<0b07160a06>-24.7<0c0f1706>-24.7<0f071112030d0b130a0f0506>-24.7<05>0.1<0706>-24.7<0c06>-24.7<040c1303081006>-24.7<03>0.1<0f06>-24.7<0f0a0a1718>]TJ
+/F3 1 Tf
+9.75 0 0 9.75 101.201 106.951 Tm
+0 Tc
+0.028 Tw
+[(Heifer International is a nonpr)30(ofit that alleviates hunger)125(, poverty and envir)30(onmental degradation )]TJ
+-1.5183 -1.3026 TD
+[(thr)30(ough gifts of food- and income-pr)30(oducing farm animals and training. These animals pr)29.9(ovide a sour)30(ce)]TJ
+-0.7968 -1.3026 TD
+[(of pr)30(otein, such as eggs and milk, for childr)30(en and generate income for families thr)30(ough the sale of animal )]TJ
+0.5957 -1.3026 TD
+[(pr)30(oducts. Since 1944, Heifer has helped over 4 million families in 125 countries become self-r)29.9(eliant. Each )]TJ
+1.2818 -1.3026 TD
+[(family Òpasses on the giftÓ by giving one or mor)30(e of its animalÕ)140(s of)10(fspring to another family in need.)]TJ
+/F4 1 Tf
+8.1749 -2.1231 TD
+0.031 Tw
+[(T)80(o)0( learn mor)30(e about Heifer, visit http://www)79.9(.heifer)125(.or)30(g)]TJ
+/F5 1 Tf
+16 0 0 16 48.2658 742 Tm
+/Cs5 cs 0.275 0.275 0.471 sc
+0.0002 Tc
+0 Tw
+( 666)Tj
+1.9556 -1.875 TD
+( 444)Tj
+12 0 0 12 140.128 286.264 Tm
+-0.0003 Tc
+()Tj
+-2.1762 -2.5478 TD
+( wwwwwwwwwwwwwwwwwwwwwwwwwwwww )Tj
+-4.6179 -1.9108 TD
+( wwwwwwwwwwwwwwwwwwwwwwwwwwwwwww wwwwwwwwwwwwwwwwwwwwwwwwwwwww )Tj
+7.1656 -3.6623 TD
+( 333)Tj
+0.0531 -3.4502 TD
+( 555)Tj
+/F4 1 Tf
+9.75 0 0 9.75 117.723 24.2689 Tm
+/Cs5 cs 0 0 0 sc
+0 Tc
+0.031 Tw
+(To learn more about the gift you've been given, visit http://www.heifer.org/gift )Tj
+ET
+q
+375 0 0 375 121 317 cm
+/Im2 Do
+Q
+Q
+endstream
+endobj
+
+8 0 obj
+2338
+endobj
+
+9 0 obj
+<<
+ /ColorSpace <<
+ /Cs5 10 0 R
+ >>
+ /ExtGState <<
+ /GS1 11 0 R
+ >>
+ /Font <<
+ /F1 12 0 R
+ /F2 13 0 R
+ /F3 14 0 R
+ /F4 15 0 R
+ /F5 16 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ /ImageC
+ ]
+ /XObject <<
+ /Im1 17 0 R
+ /Im2 19 0 R
+ >>
+>>
+endobj
+
+10 0 obj
+[
+ /CalRGB
+ <<
+ /Gamma [
+ 2.22222
+ 2.22222
+ 2.22222
+ ]
+ /Matrix [
+ 0.4124
+ 0.2126
+ 0.0193
+ 0.3576
+ 0.7152
+ 0.1192
+ 0.1805
+ 0.0722
+ 0.9505
+ ]
+ /WhitePoint [
+ 0.9505
+ 1
+ 1.089
+ ]
+ >>
+]
+endobj
+
+11 0 obj
+<<
+ /SA false
+ /SM 0.02
+ /TR /Identity
+ /Type /ExtGState
+>>
+endobj
+
+12 0 obj
+<<
+ /BaseFont /KPPLPG+Times-Bold+2
+ /Encoding 21 0 R
+ /FirstChar 1
+ /FontDescriptor 22 0 R
+ /LastChar 1
+ /Subtype /Type1
+ /Type /Font
+ /Widths [
+ 250
+ ]
+>>
+endobj
+
+13 0 obj
+<<
+ /BaseFont /KPPMKC+Palatino-Roman+2
+ /Encoding 23 0 R
+ /FirstChar 1
+ /FontDescriptor 24 0 R
+ /LastChar 24
+ /Subtype /Type1
+ /Type /Font
+ /Widths [
+ 778
+ 556
+ 291
+ 333
+ 326
+ 250
+ 546
+ 291
+ 565
+ 479
+ 582
+ 500
+ 424
+ 553
+ 582
+ 556
+ 603
+ 395
+ 883
+ 946
+ 234
+ 601
+ 611
+ 250
+ ]
+>>
+endobj
+
+14 0 obj
+<<
+ /BaseFont /ItcEras-Book
+ /Encoding /MacRomanEncoding
+ /FirstChar 32
+ /FontDescriptor 25 0 R
+ /LastChar 213
+ /Subtype /Type1
+ /Type /Font
+ /Widths [
+ 282
+ 214
+ 333
+ 565
+ 565
+ 830
+ 669
+ 195
+ 283
+ 283
+ 518
+ 565
+ 282
+ 243
+ 282
+ 401
+ 565
+ 565
+ 565
+ 565
+ 565
+ 565
+ 565
+ 565
+ 565
+ 565
+ 282
+ 282
+ 565
+ 565
+ 565
+ 453
+ 768
+ 582
+ 569
+ 616
+ 720
+ 536
+ 512
+ 733
+ 710
+ 219
+ 358
+ 520
+ 447
+ 820
+ 732
+ 788
+ 512
+ 788
+ 526
+ 457
+ 475
+ 695
+ 620
+ 926
+ 553
+ 497
+ 551
+ 285
+ 282
+ 285
+ 565
+ 500
+ 268
+ 511
+ 570
+ 461
+ 583
+ 514
+ 271
+ 595
+ 584
+ 205
+ 230
+ 440
+ 205
+ 840
+ 584
+ 572
+ 577
+ 574
+ 329
+ 376
+ 292
+ 579
+ 468
+ 816
+ 445
+ 464
+ 424
+ 287
+ 282
+ 287
+ 565
+ 0
+ 582
+ 582
+ 616
+ 536
+ 732
+ 788
+ 695
+ 511
+ 511
+ 511
+ 511
+ 511
+ 511
+ 461
+ 514
+ 514
+ 514
+ 514
+ 205
+ 205
+ 205
+ 205
+ 584
+ 572
+ 572
+ 572
+ 572
+ 572
+ 579
+ 579
+ 579
+ 579
+ 518
+ 430
+ 565
+ 565
+ 518
+ 565
+ 504
+ 545
+ 768
+ 768
+ 830
+ 268
+ 334
+ 0
+ 795
+ 788
+ 0
+ 565
+ 0
+ 0
+ 565
+ 579
+ 0
+ 0
+ 0
+ 0
+ 0
+ 360
+ 360
+ 0
+ 820
+ 572
+ 453
+ 214
+ 565
+ 0
+ 565
+ 0
+ 0
+ 398
+ 398
+ 1000
+ 282
+ 582
+ 582
+ 788
+ 1020
+ 934
+ 500
+ 1000
+ 333
+ 333
+ 195
+ 195
+ ]
+>>
+endobj
+
+15 0 obj
+<<
+ /BaseFont /ItcEras-Demi
+ /Encoding /WinAnsiEncoding
+ /FirstChar 32
+ /FontDescriptor 26 0 R
+ /LastChar 121
+ /Subtype /Type1
+ /Type /Font
+ /Widths [
+ 316
+ 316
+ 389
+ 633
+ 633
+ 883
+ 728
+ 212
+ 351
+ 351
+ 568
+ 633
+ 316
+ 261
+ 316
+ 412
+ 633
+ 633
+ 633
+ 633
+ 633
+ 633
+ 633
+ 633
+ 633
+ 633
+ 316
+ 316
+ 633
+ 633
+ 633
+ 494
+ 824
+ 695
+ 651
+ 649
+ 752
+ 616
+ 574
+ 759
+ 778
+ 296
+ 448
+ 666
+ 531
+ 880
+ 792
+ 835
+ 587
+ 835
+ 630
+ 525
+ 555
+ 752
+ 695
+ 1073
+ 628
+ 584
+ 619
+ 351
+ 316
+ 351
+ 633
+ 500
+ 339
+ 568
+ 621
+ 489
+ 635
+ 561
+ 352
+ 639
+ 644
+ 272
+ 312
+ 550
+ 272
+ 896
+ 644
+ 618
+ 626
+ 629
+ 389
+ 446
+ 373
+ 629
+ 543
+ 874
+ 560
+ 543
+ ]
+>>
+endobj
+
+16 0 obj
+<<
+ /BaseFont /Courier
+ /Encoding /WinAnsiEncoding
+ /FirstChar 0
+ /FontDescriptor 27 0 R
+ /LastChar 255
+ /Subtype /Type1
+ /Type /Font
+ /Widths [
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ 600
+ ]
+>>
+endobj
+
+17 0 obj
+<<
+ /BitsPerComponent 8
+ /ColorSpace 10 0 R
+ /Filter /DCTDecode
+ /Height 790
+ /Intent /RelativeColorimetric
+ /Subtype /Image
+ /Type /XObject
+ /Width 611
+ /Length 18 0 R
+>>
+stream
+ÿØÿî
+
+
+
+     ÿÀ
+ 
+ 
+„”EF¤´VÓU(òãóÄÔäôeu…•¥µÅÕåõfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêú
+&6E'dtU7ò£³Ã()Óã󄔤´ÄÔäôeu…•¥µÅÕåõFVfv†–¦¶ÆÖæöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ
+Ó~¸«±Wb®Å]Š»v*ìUØ«±Wb®ÅVÆüÐ7µìz⫱Wb®Å]Š´@"‡¡Å[Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUÝñWbª²É,\¤^. R>F•ÈD¥_$‡aWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZR§pkŠ·Š»v*ìUØ«±Wb®Å]Š¸N*ÕWøâ­â®Å]Š»v*ìUØ«±WöÅ]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*î¹UØHWaWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZU
+Žƒov*ìUØ«±Wb®Å]Š»v*ìUØ«»ÿ
+÷Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅV’=öÅWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®®*ê UØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ÐP #¾*Þ*ìUتÐ
+…Oߊ¶­U„W±ëŠ®$ Î*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å\qWb®Å]Š»v*±Wb®Å]Š»v*ìUØ«±Wb®Å]‚•£…Zb¢•4®Ã]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*Õßov*êo\UØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb«YAÁê1W"ñ@µ­;œUv*ìUØ«±V»ôÛov*ìUØ«±Wb®Å]Š»v*ìUØ«±U¡TTŽýqUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»q½™»
+Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®®ôÅ]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»Býv­‹QÈËND
+Ç‘N
+¡GAŠ·Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZR{Šb­øŠŸ£Ü`VÚ´ØT⮩ñuö­â®ÅV…¡&§|UÌái^øªá°Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*´- ð8ªìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š¸Šâ®Å]Š¨ÃwÏ*DáÚá(²Ô CôiZ¹$8׶*·zÓµ:â­†´íŠ·Š»v* pn$WŒT/§%wb~ÖÝ€ÅUñWb®Å]Š»Zå
+»v*ìUJxRdàßf Ÿ£|‰¡Tb+²JìUØ«±Wb®Å]Š´¦¢´¦*Þ*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZÞ¿«ov*ìUØ«±Wb®Å]Š»pÅ]Š»v*ìUØ«±Wb®ô×Ôõ;ÓÑ×_Š»v*ìUØ««Š»pÅ]Š»v*ìU¡ZœU¼UØ«±Wb®Å]Š»v*ìUØ«±Wb­mŠ-¨ÜËn!tS*¬Ÿê·ÃúÎS’e²"ѹsªáºn<qUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZn]±VñWb®Å]Š»v*ìUØ«±Wb®Å]Š»q
+ӹ銮Å]Š»ZXLUΤ©
+¹*¶Ä*ì*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅTæ…&…¢UQ‡MËn(’(Ö8Å
+=†*¿v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±WtÅZ
+ÔnLU±^ø«±Wb®Å]Š»v*ìUØ«±Wb®ÅZV®*Þ*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUdlç—%¥ zÔxâ«ñWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±W\UØ«±Wb®Å]Š»v*ìUت×jPPší¶*à
+»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*±}Q^T;íAM¾óŠ¯Å]Š»[U);žƒåŠ®Å]Š¸€zâ®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±WbªIsÊñ+ƒ"}¤î>Œˆ’ªáV•Tt­â®Å]Š»v*ÖÜý銷Š»v*ê
+×¾*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb«A¨þ¸ªìUØ«ºâ®Å]Š»k¿Ïov*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«\¾*b­â®Å]Š­å¹;wÅWb®ëÓv*ìUØ«±Wb®Å]Š»v*¤ÑBÎ%( §Ùjn1U\UØ«±Wb®Å]Š»ukßv*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ÓØWov*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*×*-N*Þ*ìUØ«±W UØ«±Wb®Å]Š¸â®Å]Š»v*ìUØ«±Wb®Å]ŠµÆ;õÅ[Å]Š»v*ìUØ«±Wb«JÕ­)ø⫱Wb®Å]Š»Zî‹ND
+|N*»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«‰ ®*ìUØ«±Wb®Å]Š»Y$jåkÑ,U~õöÅ]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb«TMMA; Uv*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØªÞ Ë—zR¾ØªìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]ŠµŠ·Š»u:ûâ®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«Jj:SÛov*ìUتÊý5ü0*ü*ìUØ«±Wb®Å]Š»v*ìUØ«±U‹êónTáû$uúr*¿$®Å]Š»v*±Ä„¯Eý¯U~*ìUØ«±Wb®ÅZ&¾ìU¼UØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUg3êq§ÃJ×_Š»v*ìUØ«±Wb®Å]Š»v*ìU¥$ö¦*Þ*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«F½¶Å[Å]Š¸ì1Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*â*)Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±V'~Ø«x«±Wb®ÅV»*)cÐnqW+ƒÐ⫱Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUت›»+ [‘¡§aâqULUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUhêkóÅWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUتÖPÊAèqUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUتÕUU
+µcAÜâ­ŠÆ*Þ*ìUØ«±Wb®5튻v*ìUØ«±Wb®Å]Š»v*Õ
+…OË^1Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«¶Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb­
+šŸ¼â«À¦*ìUØ«¨+^ø«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÀªõŸPpcïZÖ™WÉ«±Wb®Å\kÛv*ìUØ«±Wb®Å]Š»v*ኻv*ìUhåÈ’vì1UØ«±WuÅ]Š»hˆŠb­â®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±¥RœÊ8zb¿ä?Éï•IUrÕSne‡8oʽ~ŒUSv*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»»
+»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±V‰s¶*µ%‰‰U`Jý LU}:{b®Å]Š»v*ìUØ«±Wb®ñÅ]Š»v*ìUØ«±W`]…]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZ«x«©½qWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*Õ~*SéÅ[ÅZ•÷Å[Å]Š»h×ov*ìUÀÓv*ìUØ«±Wb®‚˜«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«Kã㊶MqWb®Å]Š»v*ìUØ«{b®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š´¼»â­â®¨8«±Wb®Å]Š»i–«LU¼UØ«±Wb®Å]Š»w¶*ìUØ«±Wb®¸«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»P–Ýžd“Õ‘D{úh@V?åm_ÇWÅ]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®éŠ»v*ìUØ«±Wb®Å]Š»k~^ÝñW¸Å[Å]Š»v*ìUØ«±Wb®Å]Š»v*§ ˜ÇûàïP¦£ñÅU1Wb« j\?B;øâ«ñU[«{»t¸ùÅ'Ùa÷bªØ«±Wb­2ÕiŠ·óÅ]Š»v*ìUØ«±Wb®Å]Š´9TøvÅ[Å]Š»iZ¸«Jªµ ¥w8ªìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ë¸Å]Š»v*ìU ÛÓ¦*Þ*ìUØ«±Wb®Å]Nþ«±Wb®Å]Š»v*ìUØ«±Wb®ÅVs_áׄÒü(v*êb®Å]Š»v*ìUªÕj7ðÅ[Å]Š»v*ìUØ«±Wb®Å]Š¬Ž4"…QÑFÃ_Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±V늷Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±WSv*ìUKêð¾×¯.ƒ¯Ž
+ µ\(v*ìUØ«±WQ\UØ«±Wb®Å]Š»v*ìUØ«±WtÅ]Š»v*ìUØ«€¦*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±V›¦Ý{b­!$EqŠ®Å]Š»v*ìU®#•i¿Ž*Þ*ìUØ«±Wb®Å]Óv*ìUÕü1Wb®ÅVSÐ׶Þ##Äš_Q’ mإث±Wb®Å]Š»v*ìUØ«½†*ìUÛ×ÛÃv*ìUØ«±Wb­(aÔ×ovø«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±U¤Fô§Q㊮Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«Ž*ìUØ«±Wb®Å]Š»u\UØ«±Wb®Å]Š¡­l ·yÞ GÖ$õdÛ•’jÓ#›DÓ$Ó±K±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ««^˜«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]ŠµŠ¬šOJ%â_€-Áw&ƒ ÅTìîâÚ9š'€È+éK@ãçBqTF*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®˜«C
+»v*ìUØ«±Wb®Å]Š»h×·ÑŠ·Š»i¹Sn¸«x«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb«O.@·sŠ®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUÛ×ÛÇv*Öü©M¼qVñWb®Å]\UØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUkóÛˆ}ëኮÅ]Š»v*ìUØ«\‡*W U¼UØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb«Qh V´ïŠ®Å]Ói]OLU¼UØ«‡LUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUت’ÛB.à(õ™eÿ
+V©5
+nqU\UØ«±Wb®Å]Š»v*ìUØ«±V«ñRŸN*Þ*ìUØ«±Wb®Å]Š­ä¼¸÷ëLUv*ìUØ«±Wb®Å]Š»v*ìUÞø«±Wb®Å]Š»j›â­â®Å]Š»u1Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUتÞ•­6ûñUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»i–´ö5Å[ÅZ:×ßov*ìUØ«±Wb®Å]Š»v*ìUØ«±Wbª~´~=øý9M*dìUØ«±Wb®ÅZ ­{ô®*Þ*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š´Â½éŠ·Š»v*ìUØ«±Wb®8ªÉK
+Õ“jÕ|†*­Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»i–¸«x«±Wb®Å]Š»v*Ð5®*Þ*ìUØ«±Wb®Å]Š»v*ìUØ«MŠ·Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*µùÓá¥{W[”'ï;xAüqULUØ«±Wb®ÅV…´®çÜ⫱Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»ZW ¥M~“Š®Å]Š»qÅ]Š»v*ìUØ«±Wb®Å\1Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*íñWb®Å]Š»v*ìU¡ZoŠ·Š»v*ìU¦åQNð+xUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]€v%\M0«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅV¨"µ5ÅWb®Å]Š»v*ìUjÖŸ+튮Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«Ž*ìUØ«±Wb®Å]Š»v*ìUتÄpÕ¥vÛpGëÀ«ð«±Wb®Å]Š»v*ìUØ«±WLUØ«±T£ÍêÍÇ£V/t#+‰fQ½²Æ늻v*ìUØ«±Wb­
+‘ҾتüUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±U6ç¨èG\U~*ìUØ«±Wb®Å]Š»v*ìUØ«A·#Ãov*ìUØ«±Wb®Å]Š»v*ìUØ«±W€š^j6×\B%…¹FI½ÔÐþ#mH¥l*Öõ銷Š»v*ìUØ«±Wb®Å]Š»v*ÐêqVñWbª~¤}kþ}26´©’Wb®Å]Š­
+h
+Rm[
+»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅVÐ-®É+±V¹)¨ð늷Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š´H§"M*ÈeY¡ISì¸ +àqÕS$®Å]Š»v*ìUØ«±Wb®Å]Š»v*Ñ uŠ»v*ìUØ«±Wb®Å]Š»v*ìUØ«±VºñVñWb®Å]Š»v*ìUتÖ`´¯}±UØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUÛâ®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*Ó("‡¦D‹W
+ƒov*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ««½1WUØ«±Wb®v*µ:†]ÁÅWb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Šº›×v*ìUØ«±Wb­0¯zb­â®Å]Š»pÅ]Š»q­6늻v*ìUØ«¼1WSv*¥,Ü:¡=¶ÅUªµÅ[Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUm7&¿F*»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìU®ÿ
+b«ñWb®Å]Š»v*´¡êø«jO~¸«xªÖ*)SJì1UØ«±Wb®Å]Š»k½qV߉ë×Û]Š©Ì…£*¦‡mþœU1
+ì*Ñ4ë튷Š»v*ìUØ«½ñWb®Å]Š»v*ìUØ«±Wb®Å]Š»¦ø«±Wb­{b­â®Å]Š©Ë,Q'9*Ô
+± ©4Ž*¨1Wb®Å]Š»v*ìUØ«±Wb®Å]Š»v*ìUØ«±Wb®ÅZŠ­~ø©O|U½¸íÓÛov*ìUØ«F´ÛowËv*ìU¥Å[Å]Š»v*ìUÛLUØ«±Wb®Å
+3ú\WÔåNKNë]ºv®¯?m|7ÀUyÂUØUØ«±Wb®Å]Š»Rç)”©Œ„¢JŠáN¹ª¹%v*ìU¦åÛov*ìUØ«±Wb®Å]Š»v*ìU§ãO‹¦*Þ*ìUØ«±Wb®ÅPšèÿ
+´9o_£ov*ìUØ«±Wb®Å\ißv*ìUØ«Mʆ{b¨~Wû§í×õeR®_k'ÿÙ
+endstream
+endobj
+
+18 0 obj
+18458
+endobj
+
+19 0 obj
+<<
+ /BitsPerComponent 8
+ /ColorSpace 10 0 R
+ /Filter /DCTDecode
+ /Height 375
+ /Intent /RelativeColorimetric
+ /Subtype /Image
+ /Type /XObject
+ /Width 375
+ /Length 20 0 R
+>>
+stream
+ÿØÿî
+
+
+
+     ÿÀ
+ 
+ 
+„”EF¤´VÓU(òãóÄÔäôeu…•¥µÅÕåõfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêú
+&6E'dtU7ò£³Ã()Óã󄔤´ÄÔäôeu…•¥µÅÕåõFVfv†–¦¶ÆÖæöGWgw‡—§·Ç×ç÷8HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ
+⮥:ý'll}†*Õ?Ìâ­Ðtû±Zu1M:”¡ÔéOŠiªn6öÅ ë㊸÷Ëu+×æ6Å]M«Š´Gá×犺‡éÅiÀ}Ø«TÅZ¦ÞÕÅ]LU¯£j›ä•Ô5é×hß犼çóÇ^ú§–­¼¿Ïטæ4‘m¡e{†Û¨+E§zæ.§%F›°BËÓ¥¿±Ó–+ìÚÊÙ’ÞÞÙg>«D–bÌ#
+ÔýŸçæ;ÛÑÊ1Ú«¹•~Ofÿ
+¥-Wzb*<3y ‡A®ß1z úæ{ˆ°Œ)k‰¯O–*ò†ü´ó|×ú¢Ã“M%ÉšId0·Ãj¼[í?!˜RÁ##¾Í#­ÿ
+xíÕzÍÛ‹cÍ–üÓë…•­åX¨$d!APÕ>X¨?I¦^ÆCgùëTú¶¥oÕÍÖžn.m”éó-TÇÄŠ kcêÆY¸°vaÓ~Ù…9üÚˆ€eGŸõ¼¶î Ò,.¡×Ä1êPAwë´ºlWwj©YŠ=&Œ´–åw?|]J•oƒøý(…~¿Çâžý§ÞCr­wPÞzƯsÂÎîZ 4¼Y¸×ß}†fã&€l≺䊧ÜrÅlW·õÅ[ú~œ
+¡{
++ÅfÐs·š æÛ”…“<fØn`jâ ›st׶Ým…[Á ’Jm­åžó~0%xP‘¨;UœQsRo“µn@Ýèß–—úÿ
+<Çíd"AßÏÜ‚_Ë+gIïü»vå­Ã@ñܨŽ4Z+/îÀ1=i¸¨jó'&q ô…BÙW“åÖí!M#\ÓÎú8‰ý'oé˜/d%¿» Ç„|h¿<ž#FˆZ$2z‚+PG†^†Í?ϦpwnØQK-@åzq¹“¯AÊürêÌôaÚ÷æ1Ó5›:­¿Ñ„jÂêCÞ£§"
+òŸËN£|Äͪ”e@98´ñ"ÉKWó[Puc°ŒŸÛäì)^&•aöNTu“îf4ÐïO¼›çÍrúk{ˆÁèˆ.­ãa
+²KÁá‘É`†ä¾49vŸQ)Ê‹^|" ÊÏ\Ìq\iÓ ÅZ#3¨ ´tæ£öy
+­~cZ]áMÎ*×O–+N¯öáZw…0+ºáW~ª×¶wÏïÅZ­6=±R4ë߶ÍOÑ…Z4¯Ï­ð´ÕvÛéÅÑ ö¥2Ó”ãUšõ©Å\Tb@Uâ{žUåÛ¦U“·FØêËý:s#¬Ž÷qN]nE.ŒŽJÄ|J6¥A4ðÈ”i°JŽjTòU·—é$(>¶ü½KÙT#ª8¥Û¯á˜xtâõr5¯oáîýl‡„Ø%µÊ¤ð–v•
+™‹³ gâm©™"$¹¸†É,bòÛê×RÀ eFøþÒ0ä§î9— X¶’)Güü2h¥§ ððÅ/;˜—JD²@…>¬T@Ÿ½ÐÝdF4<~ÆaÇS¸ÛÞÑ,§zø1“ç-Yõ¸5Y¢Ô«L#RK~a‚2ƒÄŠ
+þ¼®YdM¬%BüÃ-‡ó)EäßZ´AlÄU‰Èm¯Úå»æéóˆ£ÇãÜ‘—Ÿãñæ²Ïó6O_ý2M¬Ž´(Ä2! <7<¿ÙwÁù“|¶üsXe?Äט<É \êq¼ÚÖa¶õÝÔ„™äp /' G““pèMK&Hšµ9H69ï_¬ý©.§hÚ”÷ó^¬Q]G5­Æ›w"ˆfy%b“C$z'Ó®àД;zoŠDŸÁl‰ë}…é‘jºwI§A<aø€#ˆú5Ø;ÔôUù÷ï™`ðÐIÉ4Œ~hycÕXý;¾&¾¤ž’ü
+Ž*ôcô 1È&Ñ QÊOvjP04Ünù+eKd¹¶‰¡I¥HZáŠ[¬¬Èê§*r?,lU±$îWÅ<RK,1¸imø‰£iyÖœ¾|q°•¬E«4R8GºŠˆ± n *>ý*,‡ñ~;ÓÓñÜ«nTKvõP­:ž~<¢Zoßa‚?QIä\ÝÛZÁ$ÓIÂ(©Ì€XÕP
+Ô““$ ì„O0h¦Ù.í!VBþ”ß‚ŒW‰Mêj½› L€C7<¶±ú‚éÆc é° Ng Oøde’"ì„  ¤·ÿ
+À/2Tôû;â òbd5¶,°=ÒÑÝÍ$±È¿e£JEàB~9oeœº*´Ð¤‘Ç$Š’IËÓV!Kzc“Ò¾ ×&ÂÔþ½aÍã7Púˆž¤‹ê%Uí^›bŽ!Þ²çTÓmnb·º¸H¤™]âg4Ž‘z‡á~•®6¦@snMKK’^À±°%]¥J0SŸšïB)ŠñŽö†±¤µ´×+{[ÁžiUÁ û,i¸­6Æ׈7§¦Í*CÔo4‘¬©oÓeæ¯Uñ¦*$_êú^šœï®£‡nJ¥ªì¨*‹V51S0ïh“ÔA¨A!²ãßü‚9bòG‰õ‰æBDWk#/:ª#·÷oÁ»7ß„ G[˜´9îšÒ+ÔúȨ¿$äV•àX
+Ò£@Ù ´\[1@²ÆLˆdŽŽ§’-y:ïÐxâ¶J?éô÷Å(}Bò )o.‰X ^L@©>}ÉÀdÒËcÓõÉ'’dŠ @„ÉqÅcwegÅ @µø›âÈ‚6F9qH›=V{m z‘ZÆYã*© ‘Ûaʼϼ¹¢¹PÜ—2Q¡L¥g.ü#u2*4Ž¤ÐÐR¾ÃvŨ—ÙÞA4'‘ -y+nÊ<0¦$§Všåµ[ggXíšô£Þ¬Cªõ¥·|æÛ
+8+M¤ããã„gžÌü3d ¼Ãç&ÕæHîµ G+‚)8¯ _Œòb@«ø׶øÏ<ååA#æúþ>K-üѨÚNaU)o]ášgy *‚{m•ñʹ–FI…Çæ½wnðê#×øÜq<
+Ÿål2G,ÿ
+=xÊbãû°›2³NMü2³–c«t1’”ë~hF½[[{ˆ Å9Jü“Ó†#ñUªÝwí¾Gy,eR¶“E<cQ)VVžè
+Ÿ]¢‹Ôø£ »ÕQSʧ Ä T­ZVÆÚwFf}žn;ÐÔlŸùTæc2Øžh”»¿¾´×, Q.£€XÉN)N'ö{Ž¹‘“^x>DS‰ƒAy<N#´¯íè–\Zz6?^Êb2ˆy­6•¾5¨4ðù£1t™ %ÅWN_h€qÐú­oæíBÒá·…L
+ª2ì¯É*€Õ@5ßÜæ|5¼?ÃÑÔ˜ñ]íº÷[¿¿1‹ô’xãæœJŽŽ%,´j>œ2í ;EˆÒØú¯îRYíÙ‘ÖÓÓ••Ü€U£’¡ÔŠu*~ŒF¶#ø~ÖRÓžðŠ{ëgÒmôùaybF˜ Ü3siñ.ËBv²_}%–#få¿I.Zá  xzqC"ÆÑFµcð­ü›—ûxN»þÃÀŸx´Lhp¥¤P·DŽ&fHØ°Šž˜‘ˆø»õÂ5¸ÿ
+~ mÁÉn>`
+GcHÈuK
+ÎËÇê·!!–¡h~!ܵrÈkqÙéðe,RîÝ«‹Ëid[‚-®¼y(b¦N+Ö§†Z¼w±ø€Ã†Drn×QŠÌÑ<¶ò´ÆG‘PÇÅQŠþÂ6jq’OͶù(Â`ýÚJœãŽÙ­ã‹˜(=Gv“ˆ#jß<6+æˆN¹uW±½žÖ脺»¹2¢¢‰$$hOIYƒ=g¶OÆ„ üÓ 9¸óî·jZÅÚè×>´s\³ÂÊñÄÄm²¯ù Õc”i³ò¹a¹3 ,ÊV¶÷#e½‘ 7oC(–#ÃÔ£*ªï²¨¦cž{9x€:Z]¤ÛÞ…¹½H^3<ËêK-
+7éQÛõäá´o½œ÷“.Ñ`™®žç„ „1 ®seßèúpÂföXÊ-®ÀF
+'+°
+þ#·^øm—0•j×·CÌÜ%g{{[(ÞÞ¢‚G’B‘OåP«ý¹Uú›#Jÿ
+!'©VF£SðÃG½Ÿ‚;‘I¦L$xítÁeæYaˆrQ±`iñSÛôøgù¿j.=RŽ&º:0$`úóq„Ü·°Ûcà×ðý¨È´0q+š8ªzƒ€Œ+)3öOуÃ%Ÿ‚@úBYëÆÝæ¾’ï$b¤T¯*ü<)Œ5¿ Qé^`’"RÍe %fˆ(jÐ)f ŽØ<4ør€CÏo²ÞÜé-œÁŽ)Ib€°Þ€°¦ô­0d1‰˜þM&˜}@æÒÖÜN(.%XcBÊ+Åå¦ÄòèÙ!YÈó¥=GËQ2êz…¢HÅ yØÆÅd?b9u¾Õìzáá˜ävYD]«.—,¶"hR%ƒÓõcI¾%ô8×’€½ïÁÊ1­ù,L¾umëË
+**À÷úpÑèÄbp?SVÓki9¶—÷¬ÜžÚ_OÔIaçASUâÜX{d Z#‚q4/Ésk©…<= "¢+-?ÝlÌÔ*ßÈÄŽMçÂÿ
+À…â#VÂpÇâ'’EÌðÇ™óü}¨ÿ
+Õ~~=pVìøöCëZšÃ®é¬-âr-d Ry#«Ž<@<výžUñÊÎÒgÜ>*^{ßÉ«)MµìNìǯ6h‰
+=ÈK+Ù^,Ö³™–DwXàk¥˜€6 8mÓî˶·_‹ ÏÞ…Ô¼¥i:ÜO0E"’<¬$Uè{rcZq¯^žøÕ2–ó(M#Ê w1‰X­âážCNM]ö¯!ôãv±À
+ilâ”<Ò\͇GŒJ –)((LÄ:îzm¾_ÊE§ù "’æÑgŒž&[ɨjGÂß÷n?NPÁÐ/·ò½•„Ô])eµ˜°õÙ„ñ©~›•ùk¶ F÷gF<‚2×Ë6r#Ëk*]Bü„ dxÅ
+@Ä4ÿ
+ü[.݀ɜ‘™ŒrKN“e$×M×½D|Ùäh@£ò‹à‹#r^ûwn‚ÉÄ`6I]£Gæ}:Þk3uss`ò3ÚÈÅm®cVQÁĵ47qð2õ^ØŒµÉ—$Q*Ó&­wjSR[?^Uá,±•‰f@A<㣞ü
+øâs2ü½Š–íiÉw¦I!†â#¸q$è$šUÇðòt4#í0ëÜo¼û™ÇŠÝKHÐuq!Ô£Žà:ݬb 8“º°‘J“]Îÿ
+Ú¾9
+-¶)³6œ²‚–à)ƒ É¡­7ø°€Pgt—±˜Â[ÙC;Üʤ¯ÅØ×
+íË&#¹E¢-¬î?zd•ž¦Š*E6§l”Açh4żçæhôMBÚ(¸´âfÕâe’o«
+~¯úJ(¦æEjž±J·FË8Å¢Ó¸ò{e·½›î"Ræß­UÃ@ìÃ~­·0.í”H)6¿Yµ.ÝP4ê”T°+@”tßí}9Xr =ÞŒó%­ßøS†PìÖñ¤ˆÌœc•%ø ê „ýôÊuTq”éèe,bà"½Cl7÷횧d·â-Ä¡¨5»S¸«_2%®¢²ÊÍn×-Å&åÀ-*+ÉOW;ïÔf_Û<Î3ê»f¼Ú¦Š$µŽãP*þŒGx¸nÊÈ8—ïû9e’2”Aˆ-ÛÍæ:Ék ‰ÈZ2‡Ž­B´‘I¡Û½7ÀÕ¢6¶y ä¿Vš6Hs4¬`õVJ•ëÓ$2lìxUžîÝ%lH`6©®Äáñ86·M; oåš³úvòª—‹aEVˆ•r;6Ƙ™ß0±ŽÜ÷PKc®ÏªÙÝú¶wpÒK7 ¦s§/zõÈ™uê‘
+%[S‡KÕ>«ªÚÆ‘êö©‘H3|>›²rMzøtœˆ8¯qÍtÐCªZÖþÂ5¼‘8HÜy¨?²Uä¥_o ‰ÞËÃK´»1Y™êåoQ#hä—KʨÅ4¢
+0ÿ
+{W “TBem£Þ²úqDJò,[¸íÐ{a'f ÚÓÊws02(UUûLEzצ]O90–@o(:3s‘xžÃ-ŽŠG™`s„Â-Z Ø×~´9|4q rÌ‹‹G³ŒÕWmë°¡lpD0–BUÒÊÝ:-Ë,‰’¯£Ú€ŸC“¤.TŒŸ†;!µXÕi¶Ûví„+„q”'[ôÓu®ÇîÆÖœa¨öü0q'… ó2jÞ¼P¾ŠÖ4ŒÑ…¬ÜØìõ­)N™ƒ¬É G s4¸ÁÃÔœÅ<ìO¨Îß¼šB¼¤”…¥¶
+’C|ªq°ˆÆ…]Øݽâ!AfÒ1»—Òô Up´ŽH,ìO£søå93Œ{–x0™šPòø‚ÇR³Ó4Ç h‘·©!DP‘URß¾aèòŸÌF7·_}9Z¼CÀ”Œhô÷_OØÈì,õK{«énõ'½‚æa%•©Š(ÖÚ €zJè9IV«rc\è#É.†R
+eíJt¹-˜L“ÕZ=Ìžc0ɧZ\ÜÚ.шGK fr‘°ÿ
+†RhHʼn„zΩ<émkhÓÞ?ºEgrHÜðZ±³ã=Û/"þcjDÑi†Ö ¡¹]N"/^áEYv>1 g
+ºåÇæD#›§Ž"
+:R™°Ðå90ƒÕ×ë± Yˆè˜ZØÞ[ZÚ¤ºŒ—ˆ³ÜÈ ™EÙ
+‘]ý²')™ØÖì„
+žeˆjžù«Ï‚Tg·»ð\ìÆR†þô—L‹ÌVúµ‘Ô `·uzL@T5¤htø€ý³V4&Gú~EÚËY â—ܶóø—¡Zù¾&¢N„?íØ ææ9âyº éHä·Y†×VÒ.Y`S=¸$Õ]àWÅv#2#!vÕÂG6$R¡Å
+aøÔ}¡™\$IÇ9@ÈÖÑ4>»ÊŠf…Ô<2‚ ~"Gü.l4úfˆÙúÖäÉnc­·«Fxä=96ü_v*ú&Þæ壆ÛQ25ÄqEº©ýýË2 Vk•`¾¶ýþØñlÕ
+qž.{KùÃî“MŠhÃzÔE,oQ%IߨUwÛc±ä7s0ÂPžãöþ;óFÑDÞŸ¨c?HÍ\r=‘¶mÎûÖ™`6çû”3õr^Rò/îÕ¹)RHmÇ-úøclkdâãHÓ¡
+n'™íʱ““±
+ †8ʽE–Ic'Ò1ù#KóMÕµõÐX/í¨¢êÙé$°T–·—o°NàõSÓ©Ã’Cd㘉LXׯ⹞×I±|b¶Í.¬òGÆ8ÏÖþ¤Ì 7g1òñ¦h'‹ÔD‰'­n~Úôå3
+JŠ¸£~6Á§_–‰yW™­¾¦.`ž6šK9ŠUÌÓÅhÙfP QuyµážêýJžfI
+LAñ5b|3X}E¼L®l zá«m,&HÅš°ªÑW§‡AL°Àsè‹kË–Ú„×*‘£’É'/js 7Å‘Ç)PI4-èšLW—EŒÇpT¼ªÅkÕŒj«øo™’Î1ÃŽh†#9T±5]@Áaq ±hʳ@ÒЖfZòPzwø¸ýžs”Ô唥)Œž‹œóáü[1‚ÃDÕ´M-5kHncU‚ê k…ˆæj® ×âZõ΋KY0ÀžçžÔñcË0;ÊatðËP8ɘòä®ëLËq€! ßæ2h´é˧}²j—ùÎÝ[Ë—É¡x¦¯P8¸ G‡ÂÇNû"wž—Še­ z úí„ ¶“×åAì´©
+]•Gòª÷ÊòLÆ$lá#V¯q®yÞ*A5Ì—'hÞúÞs><#WûóQ©×dþOØìph·õ
+ü~@G9"?§%!vÍq–éŽ.ð™Al"‚9bv9¢v³… êBò
+ðšôÈHÞÍë~„ÆHk"ðã0_Ò
+J’j
+råEÜV› ˆc-öéÏö¡ÒîÞ7)qš(÷P¬€Ü
+NÝó:yÍYupÅÅ m{äo.,–­q¯êvñ„2CMRÃPB«_å'1óqä1²ça†æ‡Ÿ_ÇÉŽ_yâ8g–a£\ÚÉ!ä÷)u#õþ`¼{.aËC0(ßãÞçGYÈ„ÛÉ~lÕ&ÔÖîÏG’òÌFê÷QE)ØuFçå\–‹NqOˆnÃ[š91ð³güÀº· žÒXŸù&FZ{ü@fÔç=Σòñ+¢üÆihQâè
+Ôí\„‹9Ê÷y÷æó ?0éó
++ÈŸÚ|[n?EFb
+% "¥ßŠÒ£Ç
+Ênü¡¤G¥Ád. ×Ò’M,gg&Œñðª
+:sCh&Ydôô‹Æ’K¦:rN(Y¸‹o—\Œ“mÈåÞõ¿'F”-X…I®]‘kÁO¨ƒ[¢×rzõÍŽ˜©ÄS» `o 4¨EžW©<•!O~ŽùwáŒÎÉæÄ“Eä-A!?¿™­âF$+zbhµø{í•jeQaŽ<Wîyg‘5Xôÿ
+
+úw’¼Ë}Ä­™¶‰·Ý7§·ücÞO¼ ‡2@ezåž™
+Ô®$º›©T>”cäXý'ËYŸry¦ùc@Ó”}ZÊ>u¯«"ú²u¯ÛjŸ»ìLËWözÍÜŽ¿^[[n‘Ç’í_çr¦U(Hžt!“Fâʦ¤A§# ™›«õ­~Öç©=ðãÂ!É–\ç"]28|/^Ûá©#2CQM,"W‘ƒŸ…V«CâzÔS#6 Ò`GôÀ® J~-ѧ¾¸Ÿó8±µ) ‚dã,k"ÿ
+ °Í)ì-´»$’Þ+‰®d)ih-4<èèU€¡QNÃ0õPÉÃ’¢mw“_—‘´±Á£g[‚¼ˆ&êAÔÿ
+2%—XÛˆæUãŸ*·Y·'sZåå¦FÃüè³K¯ËÛÕ’6’8æ·–E]¾–¬I§‡ã˜ú¥žwî|Í­ëwú|±½ ,öàM ”êÀ´-Ghªÿ
+ÀÑFyD“àIvR–¼›cšÏ¹Úä[)¶ÖãHÖxAweW¸‚µn+±ö@ïO|¾3¡cŸV…š<º2í1c–Þ+ˆþ(åEpÕ$:•Ø¨?Ç6p1:¬»H‚ŠÔ-ÄÖÄ
+FY½Šÿ
+r86·¢K§hú¼WW‰g±S,/VVB>!ЀÒֆ£.Œ€—sÄ`x‚O®d±kÔÆK^¡é\“[}Ø)KƒûdK0W,m^…ù{oMÖ"ŸXº“n„ª* ?ðUÈvÎGfyé¯NÀÓl²ÜBóÍ qþ8R=Hž6’‚Œƒ(-Ö£‘ú0MØŽì3È[s&òEÈK¹ã5âåŠlJ×íü¿^SÑ ° 1²ºš ¶µp£@~
+«ý€[u¯à‰ ÒÎ ‹ejËÅI5¨µœÈp›ªôï…Ñ54׹ŵÇs¾ß,mid°E"ñuä­+áã4ƒHk™u@¶*ОLÌ´
+?•A\«'z[1ˆ]È¥pó8
+ÅGįµj|i_»&%êdcéL0md*yÕK¨mÏ%í×'-âÓR DìJªUÙ9JœÔПòzý†2Žn|°”Ö9®§Uao(ÿ
+±'…~¾KÇGƒÕ€Ôü³kn±£°$ôÀca¹v
+¶¨y*•?h¹êrØ‚ãÎc§>ôbªªÐ¹©Éµk©¶v*Ùâ:¾ e±‹ÖŸ OBÄþ¬E!t>º™Ã´*Í"%(¦†œ€©ú2$ŽöB'¹(·TXêÌIZ*<Gq•DŽ®Dè‹‚ä£!UdRh*SÜ|²ØËf©Ác¦éöµ’ÞI\–iiÉÏ#R9éíÓ"1Ħ2Ë)lJ3~½~ycRqVi·^ر+d¯iN§·Ó†
+òú t,ÌMO€ÓÛrÎ02Ù†yËLk¿(뺡·/tÖí"[(Á#âÍSZé©®Ù“2­Ü““„pñ>ò¶QGi¨?Ö==)SU˜¬lÜ•yñ÷sÆ&1Èv²Rë»K;˜ÄR\ýv퇹·BÌ®Ƥ1
+dÝ*S¸d쎌1ȇԚl‘ÛúêÕÁ\4cP+µ7¦gÂB‚r@îœ
+Q÷åÍ$—÷‹a¨Ð‚Eõ@õ<Z•÷Êe1äã‡VË©éÓúÀ&ŸÝÆäªÔƒRÔ¦BsæʧH但 ^R…”9$@ 9'¯ûx8øB>)-ŸSŠ5UDnRT¤a~/pTe±Êaàyìë[œz·`цÑn*?ÊÂ<ØÊu´^Gù×ç-5¸t=?ÓKñ, ÈÍY® X€vŒu^§¶bç<Rò ¸òxpï‘Ý1ü·òg˜,¯^×(å’Í ²€sõKKÀI<ŠÀù$`ê*qƵ‰#ÍèRJñ”;“öO_‹u5ÞŸÇ/œ©œ" D%¬=»õ…ú¨wÐj{o€Ä™Ñ` —éLRHþÊ°¨è_ºÃI~Þ8U¦u®ì1¦*/s
+þدb;a¥¢–^ycËz3ßiVwS; Í,ÁÈûAøsåþUr³Œ6 ɿ˶‚XcÒ>¨!Ÿ”‚¾Ñ_ˆZTäY çŸV-ç« h¾aòÏ–¬áßjwpÅumëÉÇêsH"n|˜·9 ¢R‡©í”Oxƒ“$¸ '¦Ì?ÔÌÇÜÎH§‰¹ •NU5ï„–M†,›‘)ÎÇÓcìi÷aä¼ÞÍ¢ÇtåÌoQFZ¿´¨ouÈã#‡šrÄC+°¼[ÀŽKOµË°ãÊ.¿Óíµ )¬nÓ½Êä^‡Ø
+uÂQåÿ
+¨Ó1!ŠÕ”|4÷ï„@جw·MËãŠòèI?ü2$‚Û+ˆK?3ï™ä zá{s‘ªÀ=Ó¬
+†”¨ËYÕ&zd®Ñ†ˆI ¥.ý:m–@ØhÉ*ZÞ…mªÇM,°</Ê9à*eøÕÇï·lÆ&ŒyN>HkO)ZÛ78ï®ü\Âv÷ýÞU=OãàÝ-Q—Aøø¢¤Ñ¾?U&c7Bò¨pÂN9c½ÁÝ„sVÄlÕ¶­u¸{y*Œ¨¬¯Zü*ÈçÛÃ#ŽUåœ%Èx…ôÄýaÝÄ+fùÐ~9x'¹¦B#“Ó|‚ñþlkþmÕ9Í ŽÑtf%ýÏ ä"¤´‘¼|W—Ù OqƇ«tÌرÜÍeGw,Ƭ6À°‹Q°¤.½,PØ—d.Šñ×á!‚—™YwÊ5·é2N!‘^5en[Šœk·\¼rq¥Í.ÖêЬë@…‚ȧ¥OJe9O¶ì£Hh5ØØ* T¹¯Â6 tܶà 2ƒ²g€ó¦Œ–ÒIHËu%C•4*Ö»w¦ SÃ!܈6ÊHev «»šÐíA–Šä×Å%3v’8Z¡UWb=÷üp‰)… ,[óƒó=|ƒåÅ’Î8®¼Á}ÉtûI”øïgF á}«Ò¹ ζ Š¹äùfo6y¾(í¼Ò׬5ËÉÞâ}I£ŠIMÜ,D"úkð§Ù
+¯¦ÛKs{m·¨^XÃP
+á‹,›sNmíæñļ”PH =ÆÛå±ÜyHW4r+q©È
+n2MGšá¶(q>ØY:»ï‹XÒ¢Ò§¯†øiTýgfâ´þ<4´çykðŸpR„¶íþj
+ì7®G<€ °D’“"N’ú¢FŽ^A¹õz%)ðïQ]ó
+Û—µS(±º"DfRŒ´äNÍã¹ÜÕ™p‘¡nà Ù8YyPŠ/‰©í—´¸H• `I¨ #¨ÅP—·7@ð¶E’J€:÷Û!"G&Pˆ?R'V3]HSö"…=v!’=ÊdEP=KPDfk‰HEE$©LrHD3Ç ß¢3I€Y@Q˜bǃ Žù!šrNËüþÔ òîxšsmõ«Ëh…Š(ef›r*X7¥ö{åY¶ €Ø¾n±ÐëÙêAnæµ¼B¶$ñu'Ó!ÌŸ gý–¥)MÍ3 ä«o†8’>Ç þ]~^êy÷A½—O[8,&yŒ€íRÑh[vbý=²µœ„A¹9Y´s„x¤(ì{ä𹳎OSÓe‘DËZ±—ÙŒnGC^½FdjÚc-ÈN­ž49
+Ž+AÆ‘kšö¥¤È­ážÑ€ýè‘Ñ×ýe*Êà³.IÃz°åáà H(x¼ág;zsÅ<>˜'ˆ«Fá÷ÞÇc”þr$î qÑ6#⩳grüm$´kÎðH”#w‰‚· þÚì?¸jŽßÙæÖp7ü|{ü–j—êlÚŠ¤Ô`æ¼xµ ]þÏÄ´ÛÇ1óæ¾_Ùøè݃ûÿ
+)YZ´5¡¡PîžÇ›¸`¤v¢¯_£®BÒ&‚õYX†'tað²©?«"gMƒzè¡šcÎUdü@ÛÚ²@Ú$@ä¨e†1Á8 u~vcÂJâürd,]€­)ã჈6F
+0ÂnÙYܬ#â¤s#¿¯YO‡Þ‰¸u‚XЄZqO–HÔC\A‘Ý€ùËT–;gaP[“ü (5ëšÍTŒ;]4DE¯ŸZ†Gõ¡rñNªÀÊ‘µeðß1N{oi3µÖ¦·ˆ!S,Rî®4 µNeÃ!Åž Jqo«T5AZ–g4©ß‰Ù‘´K/ôÅ´J’´©€MûÓ,YÆJ‚êðÇ$—çpÕ&€²¢Ð<9{uÁ|Êx.‡à®·šõ¡Yš­FbK„ô îú2
+ÒÉ$EØ°°Ä%÷Õ™"N¬Â­ìI"Z]æMVÞ)ŽK^,£íG\£4€‹~Ÿâ·Z\¤7Í+3p¸£:Tå
+­A߈¦jˆ¢ ¶» žÙ,o ôÜ"žQº·F«# ÁËñÊ3ô´dŽã’Y.´Úm¤¶W³!g(–wD„c>2ÆùèÔ½|2¨úbc_ÙÖ›MJ@þ/¢oc­¬6ýt’•·—â^lÃìþÏ_¿%‹!€ç·F¼¸„/z­Ö§kª1ÑýZ¥äRÁpÑõ ":3¨ÿ
+¨^Á*ž=OL€•¦Ú±Vˆ¿óµ¥–‘u{¦Ç3•bi¥Þ!3U£~A° xµ“èsjÍ3gsÓñÜòë:Ç_­•ÝÚ\NªÍr3¼®ÁÁÚDõ6PÍñmÏb0ñîá r?Ђ›Ë·©—QÈ–÷ñÞé÷1ÜKÆŽ8U®³òYxší⢇%Æ:w~6l»5düyWédÏ=o¢‰M ±!¶ãÇÀ›"©ºüÆN&š¨Ùü{‘¶“ €Í2qH jÄÅqÊŒ/öäüQt=;¨ÝÎñ}hÄÑ¢±ã+´…˜?åðd7+ünâˆm–Í\\Þˆ"eŒI(U*€Ž5Ú¤tíMÿ
+ "µ÷ßlV˃‡«O«¢ºÄ3±ë^(
+4u}¸î9ì;W,¶§bÑCX…¼h¨ãmèjŸ†_”Òbä×cT&5©åàTíÓlËA …¦£(¸ê~_H©¾ÅFçl˜™¶<"“øoYÂËrÒ¼ƒd†Üì‡r8·FznÌÛ ‚÷9#3Ì°ƒ£Ôl­b`%’€²DˆÅûîU R0è;ùÌGñÕ²P2a~{ó¼M‘9p»VÙiê4‰´qÒ„W—Ú=†ä3,j8ÇË5 g]žÛœJ#–5õ,i V‹ûÉ$5–›Ö¼jUEÇɪ™ü~”.£­\¤vÖÒH%ô‘þ«4}B$P^¥›âŸËßµf¸²™ëº{ù_z¶^dŽB¤ú¬öPrR±H¦Fø¿¼R÷oÇ ãÛxe$ îÿ
+Lp‡ ϱ¨“Ç­s
+Wד¹åõ=OÕc’õ¸,Ρݨȭ1€÷'6xò­ÕdÄE×à&pjŠÀµU¤¹
+îßñÔ&w:”µq*±õ-ýx¨ˆ»»s¶B1îdg¸—Ÿè‰V{£=œrz‹ »2ò£?ÂôR­ñ!
+9=ðr5ÕœÏn¶¿†þ}<”_XÒ¤{·+4Ö‰Qˆ$d_SšŒÛâjüþüDÊrÈ“cñæ†[ÐìÃ
+FG cÓ4f>´eÉøCxþËc(‰.íÜì^âÒ5‘FC
+-P™t7øszí¿›d½ŽÎòæCÝÂVxã4ÙË"ñöQ‡¾P3Hÿ
+õcÛ+ÚFƒ9“ñx”ºýÍõÚÞM|fÔÈa¶ä V%ZTä
+šü]T‘ó̱
+ñ“âTúr‰ÄÇbíqe?±ŸéºÉú±ôçQ‹ÉEvó*­öiý‡3A”÷(ŸÓ¢£õ=PEPŠ_:xåÜ{5p£­|À‹9BÅhŒî(¿êü¾ü¶9Mµœa7¶¹¶¹‹Õ{–³£˜ácü…M¾&õ¯\²Ä†å;
+K¥jwµRœJÅ° x ÂŶ ú¸Q:¬’[i¯}HËë´ŸPLJÇP6äi”Ç7‘BÝ¥j¶–íXïlåŠð©FõWá‘)WcVÚ0
+«1Ù^ù<ãêu&9?æìÉpò„¶ÑL÷׉é…I#‰]qÈzôfÚ£‡ÃßqÓ,ã³³ƒâäêZF¥êYÃ$V¶–ñÛê+S' Ê~ê;o晥äyo÷åQÉ*ß™åûYb?ªŠÒ¼Ÿqc ³Þ¹º¶pÍÅ u©™@>¥;#/%45ärg7ÑØèôƒ,O ·îü~‹ ò¦‹oi«ÝX»™8;\Þ‘I¹‰E D<OJuÌ\ùL $–MÁ)Âdø¬­›\G åå¹úÍÂ*P$w2P èÁ‹§ÀíE?cö²Þ"wp#‚rwú|öR6:]ž–¶·—r¥ŒóÒÄÇ-£,LŒ$¸ôè¼ØwûL²\{Ý5$j¯õ$BúâKÓ,¯–­ žš•bãÓ ²3’/®ëZ÷ÌŽTŒkaðC$ÖrBó—¥¹‘£cFUÜqê8©ù“ØbAl…wþ>ÄM„m5èo­?ïU¥¢P¬¼¾©àÊWí$€–FNNP¯/Å÷üR»§ƒôµÕ½¿5pªÐ½}P­Ä
+©×¬¯½ º’#uoî0™w±t:ô@ŠF¡<V@Kí¾Ù.&²¨5ûg’²‘)û'Õ&6 ÃÄ”T¨d9•gá“™c_õ(Ë·†&H¸õW¶Š«>íEtˆcÖ‚ŒNøÝnž{Tj•`ån"†ª‹‡n,h~!Б„LÕ$e(Ô|ÒÒCp³\+Ç´”ªð
+h ø@&„m2$ógµraúÿ
+²\–vCÉ |GõÌ)@DC³2AâaóƒjZ½åØî,œ²D„31²F¢ ø¸’932èS¯Ëœ’B®—¢\ÜGmœž‘úÀ“êà3‡3G4 #„E>×½{`”€Ü¸i4&Òêw± v ‰ôýE¥@u:‚8«ï‘"ù·C`i¨o¦’%$¶‘Q¬{Ö6Eõû°¯ñrûüððµd—AÉÅÜ–qýy¡y^EyVÒJs§ ŒcOŠƒÛ}¶ ÙŒr|¿‹Ll%µý5 µÄ
+cšèAw0šHùN ˜Ñ·§.b8õ¦@­ÈÇ–òM©Þßh—<n´$ßžÛV¦¿ \ÇíÚÊTŠ´ó*In$u …hà©Û•GA€SëMRÝÀ’4RÃfãÜx•Â
+SË=g‘_ãqB Ä‘¾û‚>Œ´M®“ko1Ag˜}aÃ0Y;±'cU_€WöFù/DPýhàâ;°ÏÌO<Ø·”5ä¼æ§êßU´`x¼·2 -+·ÚjtÛ
+pš†’­i"~öæÞh¤ pä«ÉgnÕD_…™·~^9W¾ßw㣚5˜Á»ßmûû뿇©<ïÉ-ŸPkø.ši&´™Ø}IYUÚ'”0©~ª¡{ÐV£/úH¢y l‘#-»Ëà ˜¿Öî-"õŠ £ˆE{8hùxùðeåðu£6Oà?C#T$k¯ãξ il+ou[¹‘cÉ7¨„ñ
+Êåù?1BHMŸöO|»‰®P1;Ž_»ÿ
+ÍžƒÙHo‹–ß,ÅœeaË„£.Ewž<É©è:×=8ຽŸê–ðrÜ“”“Æ­èÿ
+ö5ªÊgo¨|7?&ˆÛ¨WÐáÕ¥/ ­œ÷r»^+Jeh`Š¢8P'ØYïBWâ¼Oc3¹¾öF@r;þ/ÓÜÈnõ“q,³Gõk…„LtÐìepTúHçí*58(]Ë|Mñu³†5M/ªïnôîXPÚ´ŸVI#pHhV¨fýÒ·.5ø£¡¡;ýœ«‹~nÇÀ< KééîC[Á©;#Ã|²ªG¶—1óTä¡„|Uh¼Õ»uíYY "ößîüBéóÜ1ƒQaéZ°ø£Õ•ÃR7›à'àáÈr@rnLjqQÝ««[Yf‚Ùî. Šä%‹oR¿Hùqv…HíZa‰<Ó<1½×.eõ†½šú8a‰£[‡VôbhX;Y&fAì?kgˆ÷1rË+g—Q‘âŠ;8ˆ’K˜ÉÔñ )ŒqUAðQM;npËíF1é»
+n’09šs þ•sJ­L ç¡;%—z=ŒVÒK-¡¬AY „ËëÈÄQ"¡ä£ÛÛ$$mªP5·ö¡'&Ú
+©37&B®ÒÈ$cýã1û'ímû8RK7ò½ýÃhr;×ÑI}(ÛØ(g5# nY…ž#ÛhrŸ÷[Ïn¯"¿šâ~k'ïe”:ÐenTåÔûü³4
+ÙÔÊ\D”•5]>ÛP€HÓz·S¢Ã:¨¬êÓ*vâõÈe‰!ÈÑÎ"@oišõÛ‡ÓÆ“)’8}QÅŠ™(~Q¸ü Õ¾ì†,`&Yõr1àîæ{Ò]&Öõež-âŠêEÖöŠL·˜j4j*wNdmJ¯¾_"9žN<éVòÞîH™%mKÌüd –…×cSÑä+FÄmgt,M*ØEÎ14Ï$ˆ¡¤íÇ`€À§
+áEî¾óKžeXªÆ+t+è¡^T/ȨÏþWÑ‘ŸçKbòo˜ol{m6Y`”1Y`^(Ò)¡ Hcuú>ÖFY  Ìx2J6#"m¼‘«Ý^ÁdºuÌw×l‘#Éo"D íê–§ã]ÿ
+j>ž\þÄÁ.ô3§ýrë¤C©þí`VnD/"jÃÇè
+e?— äú^Ÿ ooeq?ïÔ²úJU¤Šwû1C§CN'¾ûÔrpƒ'#b>óä?gÚõ=?BXøZ[Fc1¨A͸pEjGë½wîÇ5'%î^¬F10ûÐ6±ÃëÂí5èø¢’Bc‰š|#w~õ­>]ò©d÷·ÀJ÷`~l±–ÏQºiîuycÇkUhôˆå„LjXÿ
+–õ8ñGø‚Óâ4Èä‰nö·5ßøûz/oü½¬Ûiš}£/—]ø]ªƒÈÝÌ@wøOîÏÆ¿ü¾TʳiüH’O«ñø·aÙÚóŽB<ã"íof»¶·
+ÑßcR
+Ç“2qc_‡5uGw¨'éåÞÝÙÝ5Ì/)Â\,VÑŸ³·zðÚ
+¿
+õ¯Jû×]I1¥Ã ŒgÄ/âÅ|ͦ=ï›5 ëq-œJ’µ‰s*´L:4küì3'«]^¨ƒž@¢á°¾Ô¥kĽ‚Ù§¶”ˆÂ˜èbz™Â/'AÌ«©nÔÂhtp±ÊäAý›'G™Ý.N”–ñ5#W¸<š9¤’Ð’²$cÒçÑ[†Å¨)O‹*ËŠ÷¿Áe@œ•[^ÆÒýbÜÞ[ͨ³Itä%²,Qeô¾)DBAöQ¨y~Öù3†¶ø¢2 sÛ¯»™v®ùŽÚêTÞÕáL%–í/“%‘Ãñn¿f¹)ãƒ3=ãÉ2»¼&ñÌ‘²ªÃ$\•Fsâ=HH‚ðgëºî(B#oÇéc–¶ÁY§y‡R‹LÒ¹[±µŠd‘¤dk‡H!u|
+ËÇ“x Ÿ 4KPI
+´£–èQ¾zäg1
+T÷3FÑ<Ð3̶ÄUC8eåÈŸM½>.A}MÀ©Ë8{œc.þÿ
+ˆæŒúªñÍ+qતüMF¦Íµ2Q‘‚6-щoºi¤yÇórB+ ½ìDòA%ÃC4³*dx¸d–Œe >ôÊ2i°÷ü}ÎÇlä_¼~¦_cùðéÍ­ÝEíŒq¬õ7ô®Ú:ˆ^9hˆ7ç!gªŽTí˜ß“ŸW.¯#|QÛ‹nø}ÿ
+ñ­y¯ 0D†D^üøƒÉ.†Ìi‚9-=)¤…ÀŽxµys ëo€u—j ¶­2Ã+æÔc\ÿ
+
+ÌjÍñTmö²GnmÊãVÓ4âòa4Ó†25¼K$1!4‘]—â ÝiN¸8IäÛÇÃÕõÒp¢­´D}npy—ñäò(yT÷ÁÄjšFHñ“~ÿ
+ þÍ"§ìlJQXK!âæ–5ŒGs5ÁswÂIfœ*‰!
+þ—ãô|?T §ÂZÑ⻸æ¦_ï^¼!N/ÆF‘¢^NŒ?hrñoÍgˆŠþqûº*ÇúCM[«tÏ«›pnæ’YŒ±’褥THÿ
+<6®ƾ®lLAøø£ÞÛU†Â‚ØÜÉn¬Þ” eGn%L@ºý¦ø#¯JTÓ¾åLjÄÔ€âýß‹Dˆ®Vi⾬fÖæ!FÇJŒ­1Ç’+vçñý•"'—Ûøü{™O„
+'»ûUî &š+xÙȾ¬/Ì †.7Y@¯×âÜt$œ
+âãÓbÞPÌ™^?°i€K`O͉1÷õüròKc°ÓI–hµ&¥ ÂÇ5ôH(³¼¬"×íûýåœGŠ«fóà¡îý¯~ÿ
+endstream
+endobj
+
+20 0 obj
+45194
+endobj
+
+21 0 obj
+<<
+ /Differences [
+ 1
+ /g3
+ ]
+ /Type /Encoding
+>>
+endobj
+
+22 0 obj
+<<
+ /Ascent 0
+ /CapHeight 0
+ /CharSet (/g3)
+ /Descent 0
+ /Flags 4
+ /FontBBox [
+ 0
+ 0
+ 0
+ 0
+ ]
+ /FontFile3 28 0 R
+ /FontName /KPPLPG+Times-Bold+2
+ /ItalicAngle 0
+ /StemV 0
+ /Type /FontDescriptor
+>>
+endobj
+
+23 0 obj
+<<
+ /Differences [
+ 1
+ /g36
+ /g74
+ /g76
+ /g73
+ /g87
+ /g3
+ /g82
+ /g79
+ /g89
+ /g72
+ /g75
+ /g68
+ /g86
+ /g69
+ /g81
+ /g92
+ /g88
+ /g85
+ /g80
+ /g48
+ /g77
+ /g83
+ /g71
+ /g17
+ ]
+ /Type /Encoding
+>>
+endobj
+
+24 0 obj
+<<
+ /Ascent 0
+ /CapHeight 0
+ /CharSet (/g80/g71/g75/g73/g87/g48/g69/g81/g83/g74/g77/g17/g92/g36/g72/g3/g89/g85/g68/g79/g88/g82/g76/g86)
+ /Descent 0
+ /Flags 4
+ /FontBBox [
+ -32
+ -277
+ 923
+ 777
+ ]
+ /FontFile3 30 0 R
+ /FontName /KPPMKC+Palatino-Roman+2
+ /ItalicAngle 0
+ /StemV 0
+ /Type /FontDescriptor
+>>
+endobj
+
+25 0 obj
+<<
+ /Ascent 667
+ /CapHeight 667
+ /Descent -219
+ /Flags 32
+ /FontBBox [
+ -177
+ -250
+ 1141
+ 880
+ ]
+ /FontName /ItcEras-Book
+ /ItalicAngle -2
+ /StemH 44
+ /StemV 60
+ /Type /FontDescriptor
+ /XHeight 494
+>>
+endobj
+
+26 0 obj
+<<
+ /Ascent 667
+ /CapHeight 667
+ /Descent -224
+ /Flags 262176
+ /FontBBox [
+ -169
+ -250
+ 1247
+ 909
+ ]
+ /FontName /ItcEras-Demi
+ /ItalicAngle -2.5
+ /StemH 98
+ /StemV 140
+ /Type /FontDescriptor
+ /XHeight 497
+>>
+endobj
+
+27 0 obj
+<<
+ /Ascent 629
+ /CapHeight 562
+ /Descent -157
+ /Flags 35
+ /FontBBox [
+ -28
+ -250
+ 628
+ 805
+ ]
+ /FontFile3 32 0 R
+ /FontName /Courier
+ /ItalicAngle 0
+ /StemH 51
+ /StemV 51
+ /Type /FontDescriptor
+ /XHeight 426
+>>
+endobj
+
+28 0 obj
+<<
+ /Subtype /Type1C
+ /Length 29 0 R
+>>
+stream
+
+endstream
+endobj
+
+%QDF: ignore_newline
+29 0 obj
+85
+endobj
+
+30 0 obj
+<<
+ /Subtype /Type1C
+ /Length 31 0 R
+>>
+stream
+
+ "%(+.0369<?BEHXg80g71g75g73g87g48g69g81g83g74g77g17g92g36g72g3g89g85g68g79g88g82g76g86Palatino-Roman+2
+ˆŠªfŽsŒƒŽŒ†‡‘‡‘‰ŠªŠµŠ¶·÷ê÷~üx«D…Ž€Ÿ Àœ²–£™¬ ·¥Â÷=÷ôûúŠ6Š\„Št‰z‡…‡…†ˆƒˆ‚ˆt‰dŠlÕ»‹¡¦¹Š‰ÍªdŒsƒŽƒŒ…‡‘‡‘‰ŠªŠµŠ¶·÷vŒâŒ¹’Œ¢œ’“Ž•¢²ŒªŠZhŠusnŒŒi{cmG],û;ûòûNøt¼pÄnÌŠomŠlkkŒŒil±Š¢‰”‰¾Ûƒ²° {žž…‡žŸ‡¡¤ Ž‘›œ‘¡™¨¡Ó¾‘”–•š˜Ÿ–¢“¥”¤§¨¯„®|ª|§v¤oœ›ok”guu‡„ww„}ƒ‚„FIìŠ×´‹½Å›Œ‹ŽŠŒŠŒŽŠ‰‹‰ˆˆŠ‰‡o}XB‚o³¢Š‰Ž‰Ž‰ˆŒ†uŒdŽR‹SUûm}Šc‰D‰r‡b›…÷ø¤§”ª¤¤…~  ~œx—q—q‘keU~^rgfqgy\vxŽ’yy’{”}–‚”…‰‰–›÷K“¦›¡¤œÛ÷'Ž¬¯Š‰³§Œhy‹‰†‡ŒˆˆŽ‰ŠŽˆ“‰—Š›‘Š¹ŠàƯ¥”š”™™™Ÿ–– ¡‘¤¦£„~Ÿ~˜y‘u|iX9v‰X†;µ©Œ¡¥Š‰«§VŒƒ†ˆ‡Ž‰’‰•ŠšŠ¨µáÏŠ³‰š†¤„ ›šy™s––uqqrr†p2=Š²£Œ—‰ŒŠŠŒŠ‰Œ‰ˆ‡‰ˆ…l|\I‚o° Š‰‘Žˆ‡Ž‡Œ€ŒxŒlŒoqQŠ3Š\‡Šz‰€‡…‰†ˆ‰‡‰‰ˆ…Š„\oɸ¦‹îÙø$Š‰Žˆˆ‡Œ†Œ…kŒPŒPŒQSûAŠ3Š\‡Šz‰€‡…‰†ˆ‰‡‰‰ˆ…Š„\oŸ§°ÏÀŠ‰´§gŒwŒˆŒ†Š‡ŽˆˆŒ‰ŽŠ‡“‰—›’Š¹ŠÝÙŸœ„š‡‰›šˆ›¢žŽ‘ž‘›’¡–¡—Ÿ˜žšž›—”’“”•”™“—”›’›’š‘žŸ¯„ª~©}§v¤mžžlh”bgp‡‚y„hnTX¾•‹“Œ”Œ‹ŠŠŒ‰‰Œ‰‰ˆŠ‰‡€…y„t„t…v†xˆ‰x‰…oÇŠöûœŒ—‘˜•˜š™˜™œ•’”Žž¤¤„~¤£Ÿw˜q˜p’mhe„j}l|lxts||sp„mts•uu•w™z÷PÁø#øAz™x–w’“vvŽuifƒ{ccyovzqyrƒmjtw”x”y—|›€œ€¡‚©ƒhrry{~ƒl…{…‚„“ƒ‘ƒƒ¦‚y~o{cy|ƒ~‡~†‰}}q“rštšt£x«}}¨²„¸»•Ÿ¶·Ÿ¬¦¡®Ÿ®—­¬¤†¡‚Ÿƒž}šx•”wpf!‰gp|ƒƒ†‘†’‰’“’‘“™˜ œªŠ£¨¥–¤œ£žž˜£—¢’£¤œ‡„žå’“˜˜ž‡”Œk\‰NŠûytŸž¤•«©¥s¡ s–kbb€ovyyur‚ovw‘–z|•}œ‚¡„ †¢¢¯•¨žž÷fü1˜‡•†“…“…‘ƒ€‘€Ž|Œvr„t}s{svxo}nlƒi—¢pr£}¨­œŽž’–Ž‘ŽŽ˜•¥’‘’Ž‘ŒŒ™©‹»«ŠŠ“Œû Úù3€€†~||~–€–˜†šš‰˜‘––––˜šš†˜€–•€~‘||~†€€-þG£¡–žž—ž›œ¡› ™¥”¨™²‘Ëá‰÷”Œ®ŒÊŒ¸Œ±­œŒ™Œ”ŒŽ‹ŽŠŽŠŒ‰‰Œ‰ˆ‡Šˆ†kyXEƒo•™‹˜Š“ŠˆŽˆ‰Œˆ„Œ}ŒvŠhvƒû¦~ŠoŠa‰aˆl†y‡x„|‚‚€‚€…‡„‚‰†„ŒŒ€‘iŠ‹ŽŠÞꀅ}{|‘}–€~—™†›š™‘––˜—™›š…š€––€}‘{z}…€€Á¿û¥ˆ“•Š–  ”ž•›™˜šœšªžµ÷÷œ¾÷­Ô°°™¡”’”˜œŒ¨‰onŠnljŒeŒn¬ˆŸˆˆ‘†‡…‡Š‡Š†‡{|drKpMz_tqQ¨{°y¹kצ~®~³‡š‡–Œ“‘“Žž­§‰gfŠedcŒco¢ˆšˆ’‡‘ˆ’ƒ‘™mž`¢RØûUše—k•n~f{hzh€r{ƒ‚‚‚‚„‡†ƒ€‰‚ƒŒ††Œ†Ž‡Ž‡†…~s@•…•‡”‰÷¨÷ Ž§´Š‰Â¬mvŒŽƒ†Ž‡ˆŽŠ”œ•¡¾÷÷±Åû)‘„Š†Š‡ˆˆ‰‰…ˆƒ‰„Št‰gŠj÷2ž¯ˆ¾ˆ¬qz„„Ž„“…–€ t½iÛûcø~ja mI~mûû¨f<v]…uƒ~††…‡…‡…‰Š…{Šqj±®«Š÷øÉ÷ û»ûŠ÷÷»tø<ànzsw…„xwˆwmo’™pp˜v¡|¨z¦„²Šº÷1­‰¯®ŽžŒ Ž¢Œ˜Œ–”¯„«}¨~§u¢nœšmj”gmo†€qxƒw€w~x~|‚}{€vm€m‡jf‰Y–cžgŸg¦p®y{­³¶Ÿ¡Ÿž‘š’•›•¡™®‚“û£÷Ï¥¢©˜°¬¨s Ÿt–eX‡‹…ƒ‰|oŠ`yŒj‹ZqŒzŒ‚ŒÖ´¢¦Ê÷À†»÷§Í“»ï¨Ê®“‘–’“’‘™ŸŒ¨‰XlŠ€}lŒ[Šn®ŠŸˆ“‡‰‡…ŒˆŠ†Š……vn{dqH|gˆ„Zû…˜€¥{²}¬P÷)}ª…¡•Ž‘’Ÿ®ŒŒ¨‰ZfŠprdŒUnŸŠ—ŠŠŠ‘ˆ†Ž†‘’|îû}´.€”u˜j¾Š ÷$Ž´¼Š‰Ä§`ŽpŽŽ‡Œ‡‰ˆŠŽŠ‘‰‹˜ŸˆÅ‹² ½µ”ª ž›¡–¤›—‡„••…”“{ŸŽ­±¶†’€|}~}ˆ†~€‡„ƒ†…‚z~z~z|z¶Œ©ŒŸ‹ŠŠŒŠ‰Œ‰ˆ‡‰ˆ…l|\I‚o° Š‰’Žˆ‡‡€ŒxŠloqQ‰Š]Š4Šz‰€ˆ„Š†‰ˆˆ‰‡Š‡‰…ŠŠŠvŠfŠo²³‹µ‹‰÷ø”œ”™‘™œž¦¡…€žž˜|“z’zsla†a„a`€m‚x‚†€ƒ€€‚€|ƒx„z‡vug–p¡vu¡ª²ž›Ž‘——’³§Í½‰5«¥Œž¡¡Š‰¦§kŽ‚Œ„Œˆ…‰‰ˆ‘Š—›÷&䩇¥ƒ}¥yŸr™™ql’fquˆ„wpiybpƒ‹€}ŒŠ€„¥„–’š”žŠŒ÷aû“vrvxv~€tv„uux’™~|—…Ÿ£ž“›’˜‘’’‘˜” ”©”¨”¯“µ’Œûûg÷*Ž­²Š‰·§Œiy‹‰ƒˆŒˆŠŽˆŠŽ‡“‰—›‘Š¹Šà÷‘Œ×´Œ½Å›Œ‹ŽŠŒŠŒŽŠ‰‹‰ˆˆŠ‰‡n}XB‚o´¢Š‰Ž‰Ž‰ˆŒ†uŒdŽR‹SUû^Š/Š^‡Šz‰€‡…Š†ˆ‰‡‰‰‡†Š„Zo½¶«‹ðø ¨…‡ˆŠŒˆŽ‰Ž‰“‰—›‰’‹¢Š²ŠÏΟŒ®À«ŒŸŒ•Œ‹ŽŽŠŽŠŒ‰‰Œ‰ˆ‡Šˆ†lyXEƒo•™‹˜Š“ŠˆŽˆ‰Œˆ„Œ}ŒuŠjuƒbmŠoŠnŠƒŠƒ‰†ˆ…‡„„‚€~‚‚„€}„|†„{|‰{ux•|z”˜†›†›ˆ§³êŸŒ¯ÂŒ§Œ Œ•Œ‹ŽŽŠŽŠŒ‰‰Œ‰ˆ‡Šˆ†kyXEƒo•™‹˜Š“ŠˆŽˆ‰Œˆ„Œ}ŒuŠjuƒ7‹ŠŠ€‹€€tŽvzy“~•€—|›€„ƒš¢ˆ¥ ›Ž™˜™™“’Ž‘‘‘¥¨£Ÿž›ŠjŠmŠq¤£Œ£ «Š‰µ§Œgz‹‰‹·Â÷”w—w›xx {¥~~¤¬…±º¸–¡³µ¢©©¡²£´•¶»ÍuÃ`¶·aS GAPt]]\]tPBb’fšhŠö÷±¨¤¬™³¨¥ƒ|£¡{Ÿqše›f’^WN~\rmoql{emp•žrpxª~´~´„´³Ç—¸¤©ûgñù3€€†~||~–€–˜†šš‰˜‘––•–‘˜šš†˜€–•~‘|z†€€}û¤‰‡†Œ‚ŽnZ5Š3Š\‡Šx‰€‡„‰Šˆ‡‡‰‰ˆ…Š„\oƶ¥©²Š‰½§Œiy‹‰…ˆŒˆˆŽ‰‰Žˆ“‰—›’Š¹‰à䯌ÁŽÑ€“auV~L„‰o´ Šˆ=¶ËŠ}‰}ˆ}Š‰‹ˆ‰ˆŒŠŒŠˆ™ˆ¥†„¸±†§È»›¬¯±¬±·‰¡‡ž‚››—|’z’o”b•;Ÿ{‘€ƒ‘€‘…’†”‡•ˆ–˜ ” œœ›¢”¨žˆ†™—†—…”„”†‘„…Ž…Ž„„Ž„{t¥Ž°Œ°¯z“u’p‘psŽvjk„}nnvy~u|u…sq{Žz‘|’|“––™ƒ„˜†¥„´‚µ‚¥ƒ˜…˜†”ƒ’’~Ž€}n€rvyzvp‚ju}ŒŒŒŽƒ‘ƒ’ƒ’…”‡–ˆ•ˆ–‰–‰–ŠšžnŠaŠo~|šøì½÷ŽøŠ
+endstream
+endobj
+
+%QDF: ignore_newline
+31 0 obj
+5820
+endobj
+
+32 0 obj
+<<
+ /Subtype /Type1C
+ /Length 33 0 R
+>>
+stream
+
+(
+x
+Ñ  N © ä  J œ   > Š 士Ý/l¹]©Ãß";½hÆ!hÛ V®#™ë0™þKÒg¢ìN”Â(=£ò(–:QªãVl˜Ïð  € Ô ç! !@!a!•!¶!Î!ñ""M"š#Y#Á#Û#ô$$h${$¨$½$Ü%%^%„%·%Ù%ì&I&¼&ú'w'Ó( (Û(ù)1)­*K+
+÷ ødw÷‚÷(ÈÐ÷íøÐ=ü·à¹û«i¦kanmmm©m²³§§¬÷¬÷¸‹w÷;÷¢`øIøÐ- ¢û¸¼û,÷¸+¢û¸½÷ À÷7Áÿ
+Öû
+È­5÷÷RÁ÷¦Áø–÷RÁûN÷PUûPûQU÷QûPÁ÷Pû÷Ž÷I÷=÷ò÷ ,AûŽÌ÷qÂ÷÷Ôø_÷qÂûÔT÷ ÷~÷ø¹ªo©cekpjm¨nµ«®£­û#ùàçø0øŒù<\ üý˺vÂøzÂ÷Â÷§Áø„÷¾¹‡ãdÌÆh_§Hwwˆ†y8rg0€9‡lˆ^~+Ÿûa÷@÷M’÷léU‡‚&zû!û
+3pÖ£…¹„½½÷¦÷÷·²td ¦X‘NŒN‹Âø¥w÷­ÂøÂû?ø¥û{XT÷D¯ü_ûDT‹ÂøoÁíÁ÷¤Áør÷UDû¢÷?÷õẼÚ¨ƒ©~£Ìh?§NALpWYDÁÎÓ¨Ä×Ï[;|‡}†}j<DqwûtûDPÂ÷lÂ÷lÁøÁxÀèøl÷.ð=©i“𲧲¨Ù¬‚¤€ŸµsU¯HHPtiV_˜¡Ç­Ìá²VXYcM ˆT›訨‰„§®‚»mTIJ\.QO[}\¯}sÈÒ…¡èéöÀ÷‹ÂöÂ÷Ç»÷ãÂøxÂ-öéÂ-÷÷;ûûýZ÷¦ ûT÷ø ûÇûiÂ÷‘Â÷:Â÷Â÷ Áøˆ÷?éHáû]\yf÷X÷·ÂûîûŲ‚±ÊÀ‹šîÁLKCNU!MN T€TwÈÍxÎ÷?¸÷Î~Â÷‚Â÷UÃìÁ÷¡ÑRÀôøø~ø£ÄDGN{iX8SP4û*ûU÷NâôóÖÕïèLÜû5\\enŒ÷ºæÜ·ø ²¾™¸Œ‰‹ Œ ø•–‹Š’ôRüUiK(RY¬¼v…™§ˆ¢¾¦Æ³Ì··yg¢–y’rt vø™ÂðÁ÷µÆø‹ø–Åü&ûÁÝ÷µûXü™È~Ã÷pÃ÷fÃóÁdÂ÷ŠÁgÁòø€÷0äN®g™ì®·©ÞÎcèû#>Q#M§a»ròuFc16Ð;÷ò÷Ò×èìC÷ LWaCi3–çî蓨׻\Qòû¤9=pP\+šåí뜵ØÌbE~Ä÷IÃ÷ŒÂ÷ Á÷­ÁøŽ÷ÚÔ{âQ¿©j[›[û@7-0Å1÷ Æ˦À¬û7BL0rƒnj‡j„…„WRα²”²÷
+¨é÷
+÷õc¸ûû÷^ø6íÂû[T¹Åü™Ë÷÷ô÷
+ûôÈÃø™‹Âøb¡÷rû^÷`÷÷fûc÷PÔØøÍÂKûD÷‰Ô÷1÷mËÂûPTÉûûBû÷BÖÂû`TÍ÷1ûmèûFû‰JT÷rÂ-÷(÷]÷%û]7T‹Âøb®÷ZºÂ¸÷WøÓø™ÂûWTÐû"û„û$÷„ÑÂûZTÏ÷Eû»û;ûT÷ÂÂû÷;÷A÷»‹ÂøbÂ÷Á÷ÃÂø¢÷mTû6ûÏøøe¿ü/û^Á÷'÷®üücU*ÂùÂ÷ÉÂø~*Âûù÷ÂûIý}û"ùßçø/ø‹ûüùË]wøýË*ÂùÂ÷‚Â÷¹*ù}ûIT÷ýûTøy÷ïø%ø‰øz¹,Ö`¸eíXj.[T.D]֦ѻÃÃÅPÎ^Öqû¾‹øìøìû¾üìXøÐw÷t÷?ø÷Õ?÷,öûÂ`Â÷2Ã÷ÃÅÃ÷ÂÁ|ø¼Â9÷…¦‰§|¦²vY©6GFwsQ™UšªÓ¦Ï­¬ˆy¨¥{’hjl’_Z’[û8V4P¼JÄEñ×жÀÂ|7Š÷*¼OYH\:N`´±¦›¡Ÿ™¥°Áº·µ…„µÂ`Â÷åÂ÷ÂöÁ÷èÂ|¼øÀ÷m÷*ûÛ%!RMrz÷ŸûTÞ|ü™8T÷¼Ð{˜µJ÷¼÷ß÷ ÷T%:C6</Á÷ôáÎà÷¿-:Á÷ñÃÓÂ÷çÂø¨ÎuÂur=Q:û0`÷ÌäÓÝ÷ÄÀ}g¶FÂ÷CT[ª][œQûAFû0û(÷4÷èÒ¬¹ÆÂ`Â÷åÂ÷¾Â÷ëÁ|øÛÂ;øÐûRT÷û_ÉZG›Uû/'û¼ûØû÷&Ò̩Ų|?†÷r¼!FB'ûPãâçÐÝï|÷­&FÁ÷<Â÷ÃÊÄ÷óÆø¬¾zÀ_==y\\^‘£eg¢mÁÀ“ø.÷H÷û5û!/ûû
+Ðû÷CÜÞ¦¯ÌJ÷jûñÆ“ÆÎ÷÷ª&r‹Â÷ØÂ÷Â÷`Ãø›øùjB“cfûŠ8y‡|‹uxW!TõûØ!TøÂûl÷Ø÷lÂûl¿¹Œ²÷±Â……¯ûVÁ÷CÂ÷µÂa®Â÷ûÁìøÉøÂûÜQ±iH¬;û-;û,*Õ ÷2ÍÖ£¼´û.Xmû GI—V€U¿àyÞ÷ÙÃ÷ìø,ÜRû5=J'%?ÏÜæßÉë÷ ¯+T‹Â÷åÂ÷Â÷Á÷¢ÁøÚÂ9÷’ÊvÖûEIf^X÷šûTàü™8T÷pÂ8÷Ž¶ºÈ·ÌÝšYTû|9T‹Â÷ØÂì÷÷šÒTÂèð÷áø§÷Dû÷ˆü§ÂèûAøûcT÷,ûØûDTûUÁøšÂì÷÷ÇÒhÂèðøø§÷Dûèæü¹øXûÍT÷–ü|‹r‡}<xOˆi‚`\’’iƒV€»¸‡¼¦­–¢Ȩ¥»Ý‹Â÷ØÂ÷Â÷Á÷÷lûA÷hôøËÂ-dºbº`³BÏø÷/÷ëÂûlT¹ûDûøûTàü™8T÷÷Oĵô³jÝ<¼MTT‹Âø™Â÷¤Âø‰ÂûBøÐûuT÷>ü™ûCT‹Â÷ØÂ`ÃÎÂ÷2Â÷2ÂÜøìÂW÷š¼¶¼d£–yyŽwXdhgo°}i­X_momoܸ T¿üõÂX¼÷¥¨Ÿ£­¸ÍŽ?ûÅöÂW÷š•®Ì––‰…”¬t‹fdû±‹Â÷×ÃaÂ÷Á÷¢ÁØøÔÂ9÷”¸°„·m¤œvl˜[FHm]XØÊûSÞû×8T÷pÂ8¸÷“¹µÏ¯È¶Ã~Fû“9TÂ÷ñ¿ÂøÂø¾÷mãR÷"ûTû!û4û#ûí+÷0÷,ëí÷TŠ';BûûLçÜèÔÞ÷÷5­ûUûVÂ÷Â÷äÂaÂïÁ÷éÂìøº÷q°ƒ°|ªÜÞcA±>5Og\gìÑûTÞüš8T÷¶Âû-÷dcªÂbæì÷ìí÷ÜTŠû6I9.=ÒôæÌÝ÷
+ÂûV÷]°ó÷
+Á\ÁaÁ÷lÁ[Án¾ÒÉø}÷c¯r¦p ûk÷9tƒ”–ª¯ŸÊ÷:1Á÷%ûKhhŠmnyolk u¡wäŸylƒXjPhžl¤x÷iû7¨uŽ|€†ujÔûRåUû%÷\¥¨Œ ¦‘¬Ÿ¹¨z¨tžÑ‹{—„’É垌ȣX‡|€_Gáû/÷
+|—z›¡±¶£¥÷4û Éœ~Ÿyt÷!¼÷å¼Þ¼÷ã»ø¬÷-HΪ³š½¾½}¼k°ÎÎkªJI«d[šYWVzleIÎkjÐIf]\aW›W«eGHªmÏÍaû†¬¿¼œ©³ÌIe÷$:I5/?ÕêÞÌàóíÏ95øÐw÷ê÷ïøÐ,¡û¸¾÷Õ÷‹w÷*÷î` ø„÷Õ@÷+öûû@÷+õû©øàøCø˜ÙûL÷$÷L÷$z»û†ûT÷†ûTû/»ûM÷$÷M÷$z»û†ûT÷†ûT©ø÷9÷˜ø=ÙûM÷$÷M÷$z»û‡ûT÷‡ûT©ø÷?÷˜øC÷rû‡÷Tz[÷Mû$ûMû$œ[‹Â÷ØÂë÷8ÂõÁ÷“ÑUÁÚìøyø¦÷Eû÷Eü¦ÂÚ øÜûTÚÜûØ#Tƒøüq]xr\z„w‹uuS!TõûØ!T÷žÂ!÷ØõÂ!½À˜­Ó¡¢‡†Ÿ‹Â÷ØÂ÷€–÷À÷¤ÁìøæÂ"øÏû%Tæü˜!TÜ…øûìqn‘o1c[EA TöûØ!T÷Â!÷ØõÂ!·¾ŽµÝ¢¡†† ÷qÂÝøGø™÷qÂüGTø
+Â÷#w÷¥ÂøMø
+Âû÷#Tû#ûT÷ü:Âø:÷MÂ÷Â÷#w÷¥ÂøM÷MÂû÷÷Âû÷#Tû#ûT÷ûûT÷û}Â÷}÷o÷ ÷€÷ø
+÷©ªo©cekpjm¨nµ«®£­ùSµ÷Բбø’ùSµû&!n2Rui__3»û÷@oüF²ùíÐýí±ùí÷÷þ÷ ÷üøt÷½ï;Ü'';:''Û:ïïÛÜïû÷Ž÷M÷>÷÷÷,@ûŽËû÷è÷îøK÷+@ûÌF÷+@ûË÷Õ÷‹wé÷î`øLøÐ+ @ûÌF÷+@ûË©øßøCø—÷rû†÷Tz[÷Mû$ûMû$œ[Ñ÷Tû†÷Tz[÷Lû$ûLû$œ[÷ ¨÷Ò÷Ò÷pøÛ¹ªo©celpjm§nµ«®£­ûdªo©cekpjm¨nµ«®£­ûeªp©cekpjm¨nµ«­£­Â÷ Á÷Âw÷/Á¦Á~ÁðÀÀ Á÷"ÀÝ`-
+÷‡½÷¯w÷¨½ø7÷‡½.÷¯û$uYé˜ût.Y÷­Âø`Âø—é÷†üATø
+ûO~ÂaÃ÷×Â÷Â÷¢ÂxøÑÃ8øûTÞû&¸3g$ûIaºÈ÷°ûTÞü¶Â÷Yt ¬w¼¿Ù£Ë°x@øÍ‹w÷c·m©÷·÷
+ü~Â9÷…¦‰§|¦²vY©6GFwsQ™UšªÓ¦Ï­¬ˆy¨¥{’hjl’_Z’[û8V4P¾JÄEñ×жÀÂ~7Š÷*¾OYH\:N`´±¦›¡Ÿ™¥°Áº·µ…„µÂ`Â÷2Ã÷ÃÒ÷ÅÿàÊÞžÁ~€ø¼Â9÷…¦‰§|¦²vY©6GFwsQ™UšªÓ¦Ï­¬ˆy¨¥{’hjl’_Z’[û8V4P¾€JÄEñ×жÀÂ~€7Š÷*¾€OYH\:N`´±¦›¡Ÿ™¥°Áº·µ…„µ€x÷Ò÷8ûL÷6ûÂ`Â÷2Ã÷ÃÅÃ÷ÂÁ|øOøû÷&i>÷´'÷ ü~Â9÷…¦‰§|¦²vY©6GFwsQ™UšªÓ¦Ï­¬ˆy¨¥{’hjl’_Z’[û8V4P¼JÄEñ×жÀÂ|7Š÷*¼OYH\:N`´±¦›¡Ÿ™¥°Áº·µ…„µÂ`Â÷2Ã÷óÆ×ÆÅÃÝÆ×Æ¥Ás@ÀøøÜÁ`¶UU``UU¶`ÁÁ¶¶ÁPvzzvvzœ  œœ  œzvs@÷qüÜÂ9÷…¦‰§|¦²vY©6GFwsQ™UšªÓ¦Ï­¬ˆy¨¥{’hjl’_Z’[û8V4P³@JÄEñ×жÀÂs@7Š÷*³@OYH\:N`´±¦›¡Ÿ™¥°Áº·µ…„µÂ`Â÷2Ã÷ÃÒ¾¿}wÅÃ÷ÂÁ{€øxùY•q‚ocgptœt}€trœoXWeGu¾€šž½¯¡¢zz¤{€y¥¨z¬{€É»¼ÅžÏýÂ9÷…¦‰§|¦²vY©6GFwsQ™UšªÓ¦Ï­¬ˆy¨¥{’hjl’_Z’[û8V4P»€JÄEñ×жÀÂ{€7Š÷*»€OYH\:N`´±¦›¡Ÿ™¥°Áº·µ…„µûJ¸÷À÷ñÃÓÂÿ
+Ðû÷CÜÞ¦¯ÌJ÷jûñÆ“ÆÎ÷÷ª&rÁ÷<Â÷Ã÷-ÎÊÄ÷óÆøøû(÷3;û)û3´y÷(÷÷&ûâüKzÀ_==y\\^‘£eg¢mÁÀ“ø.÷H÷û5û!/ûû
+Ðû÷CÜÞ¦¯ÌJ÷jûñÆ“ÆÎ÷÷ª&rÁ÷<Â÷ÃÒ÷ÊÄÈàÊÞÆÆø¬¾zÀ_==y\\^‘£eg¢mÁÀ“ø.÷H÷û5û!/ûû
+Ðû÷CÜÞ¦¯ÌJ÷jûñÆ“ÆÎ÷÷ª&rP÷‘÷8ûL÷6ûÁ÷<Â÷ÃÊÄ÷óÆø^øû÷&i>÷´'äüKzÀ_==y\\^‘£eg¢mÁÀ“ø.÷H÷û5û!/ûû
+Ðû÷CÜÞ¦¯ÌJ÷jûñÆ“ÆÎ÷÷ª&r‹Â÷ØÂ÷ªÂøVøâj×ûžû%—l÷ëü~ÂûAøûcT÷,ûØûDT‹Â÷ØÂ÷:Î÷ªÂønøû(÷3;û)û3´y÷(÷÷&ûÕü~ÂûAøûcT÷,ûØûDT‹Â÷ØÂß÷÷8à¨ÂvÞèôøøš÷8ûL÷6û÷êüšÂèûAøûcT÷,ûØûDT‹Â÷ØÂ÷ªÂøMøû÷&i>÷´'×ü~ÂûAøûcT÷,ûØûDT‹Â÷×ÃaÂÒ¾¿}w÷Á÷¢Á×ø‡ùY•q‚ocgptœtÛtrœoXWeGu¾€šž½¯¡¢zz¤×y¥¨z¬×É»¼ÅžØýÂ9÷”·°„·m¤œvl˜[FHm]X×ÊûSÞû×8T÷pÂ8·÷“¹µÏ¯È¶Ã~Fû“9TÂ÷ñ¿ÂøÂøgøâj×ûžû%—lø
+û¥ãR÷"ûTû!û4û#ûí+÷0÷,ëí÷TŠ';BûûLçÜèÔÞ÷÷5­ûUÂ÷ñÂ÷-οÂøÂøøû(÷3;û)û3´y÷(÷÷&ûôû¥ãR÷"ûTû!û4û#ûí+÷0÷,ëí÷TŠ';BûûLçÜèÔÞ÷÷5­ûUÂ÷ñÂÒ÷¿ÂÕàÊÞâÂø¾÷mãR÷"ûTû!û4û#ûí+÷0÷,ëí÷TŠ';BûûLçÜèÔÞ÷÷5­ûU4÷Â÷8ûL÷6ûÂ÷ñ¿ÂøÂø^øû÷&i>÷´'öû¥ãR÷"ûTû!û4û#ûí+÷0÷,ëí÷TŠ';BûûLçÜèÔÞ÷÷5­ûUÂ÷ñÂÒ¾¿}w¿ÂøÂîø‡ùY•q‚ocgptœtötrœoXWeGu¾€šž½¯¡¢zz¤îy¥¨z¬îÉ»¼ÅžÂü,ãR÷"ûTû!û4û#ûí+÷0÷,ëí÷TŠ';BûûLçÜèÔÞ÷÷5­ûUÂ÷ñ¶ÍèÂ\Á÷¯ÁlÂôøùaŸû%ûû)÷bw÷*û0Ûê÷@ûûÞP FF/ˆ]¨|•€É㘶ìÂÂzpµPÁ÷2Uc¦^U˜SûCV5r’pžzÀ[ØÕ…ò·‡¿’¦e„{…AûƒfLTž°[ÆTû>¸t¼¼uÛê÷ÚÄáÁaÂ÷ØÂ÷Á÷¢Áxø^øâj×ûžû%—lø"ü~Â9øûTÞ¸û‡YcW_Kpn‘švm¡„¯¯÷©ûTÞûb—b®psª²‚³²¿‘Ô×xHÁaÂ÷ØÂ÷:Î÷Á÷¢Á|øvøû(÷3;û)û3´y÷(÷÷&û÷ü~Â9øûTÞ¼û‡YcW_Kpn‘švm¡„¯¯÷©ûTÞûb—b®psª²‚³²¿‘Ô×|HÁaÂ÷ØÂß÷÷Á”àÊÞ©Áyø'øš÷8ûL÷6ûyø!üšÂ9ø{ûT¹Þû‡YcW_Kpn‘švm¡„¯¯÷©ûTÞûb—b®psª²‚³²¿‘Ô×yHÁaÂ÷ØÂ÷Á÷¢ÁxøUøû÷&i>÷´'÷ü~Â9øûTÞ¸û‡YcW_Kpn‘švm¡„¯¯÷©ûTÞûb—b®psª²‚³²¿‘Ô×xHûVÂøšÂ ÷Sû&÷’æ÷Gèøgøâj×ûžû%—lø.ûÂûGTÃû:û¿û-÷¿ËÂûSTÎ÷Lûõ*û9ØûT÷’Â6÷¸øšûVÂøšÂß÷ ÷Sû&÷’ûàÊÞŠ÷Gæø0øš÷8ûL÷6ûñø-ûÂûGTÃû:û¿û-÷¿ËÂûSTÎ÷Lûõ*û9éûT÷’Â6÷¸øš‹Â÷ØÂÃÍ÷Á÷­Âø†ùaŸû%ûû)÷bw÷*û0Û÷/ü~÷'T/û£÷Ú÷ܾüû$Áä÷•ûØûÛWÂ÷5ÂÂÂ÷4ÂâÃøÁœ÷`Ûû¨ã.÷'Úب¸ÈsºdVHpG'9Åòm÷vŸÂû”–Š––’‹“Œ’÷¦ŸÂû±ê£ÓÌëÑÐqc±CÁ÷UUV®ZVCû--û pQwTÑz~ŒŒ~W}™øИû+™÷â ûE‹÷€’ð‹ü¯}™øИû+™÷â ûE‹÷€’ð‹ü¯ Â
+Â øì
+endstream
+endobj
+
+%QDF: ignore_newline
+33 0 obj
+19922
+endobj
+
+xref
+0 34
+0000000000 65535 f
+0000000025 00000 n
+0000000097 00000 n
+0000000331 00000 n
+0000001413 00000 n
+0000001433 00000 n
+0000001561 00000 n
+0000001673 00000 n
+0000004066 00000 n
+0000004087 00000 n
+0000004374 00000 n
+0000004670 00000 n
+0000004751 00000 n
+0000004936 00000 n
+0000005310 00000 n
+0000006925 00000 n
+0000007829 00000 n
+0000010054 00000 n
+0000028727 00000 n
+0000028750 00000 n
+0000074159 00000 n
+0000074182 00000 n
+0000074258 00000 n
+0000074496 00000 n
+0000074779 00000 n
+0000075122 00000 n
+0000075364 00000 n
+0000075613 00000 n
+0000075867 00000 n
+0000076050 00000 n
+0000076070 00000 n
+0000081988 00000 n
+0000082010 00000 n
+0000102030 00000 n
+trailer <<
+ /Info 2 0 R
+ /Root 1 0 R
+ /Size 34
+ /ID [<66be986488f3991cf47a7d3b19e355e5><31415926535897932384626433832795>]
+>>
+startxref
+102053
+%%EOF
diff --git a/qpdf/qtest/qpdf/hybrid-xref.1.check b/qpdf/qtest/qpdf/hybrid-xref.1.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.1.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.10.check b/qpdf/qtest/qpdf/hybrid-xref.10.check
new file mode 100644
index 00000000..0e0ed996
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.10.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.11.check b/qpdf/qtest/qpdf/hybrid-xref.11.check
new file mode 100644
index 00000000..327d847a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.11.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.12.check b/qpdf/qtest/qpdf/hybrid-xref.12.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.12.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.2.check b/qpdf/qtest/qpdf/hybrid-xref.2.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.2.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.3.check b/qpdf/qtest/qpdf/hybrid-xref.3.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.3.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.4.check b/qpdf/qtest/qpdf/hybrid-xref.4.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.4.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.5.check b/qpdf/qtest/qpdf/hybrid-xref.5.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.5.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.6.check b/qpdf/qtest/qpdf/hybrid-xref.6.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.6.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.7.check b/qpdf/qtest/qpdf/hybrid-xref.7.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.7.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.8.check b/qpdf/qtest/qpdf/hybrid-xref.8.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.8.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.9.check b/qpdf/qtest/qpdf/hybrid-xref.9.check
new file mode 100644
index 00000000..37ea00cf
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.9.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/hybrid-xref.pdf b/qpdf/qtest/qpdf/hybrid-xref.pdf
new file mode 100644
index 00000000..3ad97078
--- /dev/null
+++ b/qpdf/qtest/qpdf/hybrid-xref.pdf
@@ -0,0 +1,1538 @@
+%PDF-1.5
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /PageLabels 107 0 R
+ /Pages 2 0 R
+ /Type /Catalog
+ /PageMode /UseOutlines
+ /Outlines 95 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 30
+ /Kids [
+ 3 0 R
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ 20 0 R
+ 21 0 R
+ 22 0 R
+ 23 0 R
+ 24 0 R
+ 25 0 R
+ 26 0 R
+ 27 0 R
+ 28 0 R
+ 29 0 R
+ 30 0 R
+ 31 0 R
+ 32 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+5 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+6 0 obj
+<<
+ /Contents 41 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+7 0 obj
+<<
+ /Contents 43 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+8 0 obj
+<<
+ /Contents 45 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+9 0 obj
+<<
+ /Contents 47 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+10 0 obj
+<<
+ /Contents 49 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+11 0 obj
+<<
+ /Contents 51 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+12 0 obj
+<<
+ /Contents 53 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 11
+13 0 obj
+<<
+ /Contents 55 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+14 0 obj
+<<
+ /Contents 57 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+15 0 obj
+<<
+ /Contents 59 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+16 0 obj
+<<
+ /Contents 61 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+17 0 obj
+<<
+ /Contents 63 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 16
+18 0 obj
+<<
+ /Contents 65 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+19 0 obj
+<<
+ /Contents 67 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+20 0 obj
+<<
+ /Contents 69 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+21 0 obj
+<<
+ /Contents 71 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+22 0 obj
+<<
+ /Contents 73 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 21
+23 0 obj
+<<
+ /Contents 75 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 22
+24 0 obj
+<<
+ /Contents 77 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 23
+25 0 obj
+<<
+ /Contents 79 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 24
+26 0 obj
+<<
+ /Contents 81 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 25
+27 0 obj
+<<
+ /Contents 83 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 26
+28 0 obj
+<<
+ /Contents 85 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 27
+29 0 obj
+<<
+ /Contents 87 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 28
+30 0 obj
+<<
+ /Contents 89 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 29
+31 0 obj
+<<
+ /Contents 91 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 30
+32 0 obj
+<<
+ /Contents 93 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 35 0 R
+ >>
+ /ProcSet 36 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 0) Tj
+ET
+endstream
+endobj
+
+34 0 obj
+46
+endobj
+
+35 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+36 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+38 0 obj
+46
+endobj
+
+%% Contents for page 3
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+40 0 obj
+46
+endobj
+
+%% Contents for page 4
+41 0 obj
+<<
+ /Length 42 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+42 0 obj
+46
+endobj
+
+%% Contents for page 5
+43 0 obj
+<<
+ /Length 44 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+44 0 obj
+46
+endobj
+
+%% Contents for page 6
+45 0 obj
+<<
+ /Length 46 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+46 0 obj
+46
+endobj
+
+%% Contents for page 7
+47 0 obj
+<<
+ /Length 48 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 6) Tj
+ET
+endstream
+endobj
+
+48 0 obj
+46
+endobj
+
+%% Contents for page 8
+49 0 obj
+<<
+ /Length 50 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 7) Tj
+ET
+endstream
+endobj
+
+50 0 obj
+46
+endobj
+
+%% Contents for page 9
+51 0 obj
+<<
+ /Length 52 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 8) Tj
+ET
+endstream
+endobj
+
+52 0 obj
+46
+endobj
+
+%% Contents for page 10
+53 0 obj
+<<
+ /Length 54 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 9) Tj
+ET
+endstream
+endobj
+
+54 0 obj
+46
+endobj
+
+%% Contents for page 11
+55 0 obj
+<<
+ /Length 56 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 10) Tj
+ET
+endstream
+endobj
+
+56 0 obj
+47
+endobj
+
+%% Contents for page 12
+57 0 obj
+<<
+ /Length 58 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 11) Tj
+ET
+endstream
+endobj
+
+58 0 obj
+47
+endobj
+
+%% Contents for page 13
+59 0 obj
+<<
+ /Length 60 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 12) Tj
+ET
+endstream
+endobj
+
+60 0 obj
+47
+endobj
+
+%% Contents for page 14
+61 0 obj
+<<
+ /Length 62 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 13) Tj
+ET
+endstream
+endobj
+
+62 0 obj
+47
+endobj
+
+%% Contents for page 15
+63 0 obj
+<<
+ /Length 64 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 14) Tj
+ET
+endstream
+endobj
+
+64 0 obj
+47
+endobj
+
+%% Contents for page 16
+65 0 obj
+<<
+ /Length 66 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 15) Tj
+ET
+endstream
+endobj
+
+66 0 obj
+47
+endobj
+
+%% Contents for page 17
+67 0 obj
+<<
+ /Length 68 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 16) Tj
+ET
+endstream
+endobj
+
+68 0 obj
+47
+endobj
+
+%% Contents for page 18
+69 0 obj
+<<
+ /Length 70 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 17) Tj
+ET
+endstream
+endobj
+
+70 0 obj
+47
+endobj
+
+%% Contents for page 19
+71 0 obj
+<<
+ /Length 72 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 18) Tj
+ET
+endstream
+endobj
+
+72 0 obj
+47
+endobj
+
+%% Contents for page 20
+73 0 obj
+<<
+ /Length 74 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 19) Tj
+ET
+endstream
+endobj
+
+74 0 obj
+47
+endobj
+
+%% Contents for page 21
+75 0 obj
+<<
+ /Length 76 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 20) Tj
+ET
+endstream
+endobj
+
+76 0 obj
+47
+endobj
+
+%% Contents for page 22
+77 0 obj
+<<
+ /Length 78 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 21) Tj
+ET
+endstream
+endobj
+
+78 0 obj
+47
+endobj
+
+%% Contents for page 23
+79 0 obj
+<<
+ /Length 80 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 22) Tj
+ET
+endstream
+endobj
+
+80 0 obj
+47
+endobj
+
+%% Contents for page 24
+81 0 obj
+<<
+ /Length 82 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 23) Tj
+ET
+endstream
+endobj
+
+82 0 obj
+47
+endobj
+
+%% Contents for page 25
+83 0 obj
+<<
+ /Length 84 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 24) Tj
+ET
+endstream
+endobj
+
+84 0 obj
+47
+endobj
+
+%% Contents for page 26
+85 0 obj
+<<
+ /Length 86 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 25) Tj
+ET
+endstream
+endobj
+
+86 0 obj
+47
+endobj
+
+%% Contents for page 27
+87 0 obj
+<<
+ /Length 88 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 26) Tj
+ET
+endstream
+endobj
+
+88 0 obj
+47
+endobj
+
+%% Contents for page 28
+89 0 obj
+<<
+ /Length 90 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 27) Tj
+ET
+endstream
+endobj
+
+90 0 obj
+47
+endobj
+
+%% Contents for page 29
+91 0 obj
+<<
+ /Length 92 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 28) Tj
+ET
+endstream
+endobj
+
+92 0 obj
+47
+endobj
+
+%% Contents for page 30
+93 0 obj
+<<
+ /Length 94 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 29) Tj
+ET
+endstream
+endobj
+
+94 0 obj
+47
+endobj
+
+xref
+0 110
+0000000095 65535 f
+0000000025 00000 n
+0000000145 00000 n
+0000000541 00000 n
+0000000746 00000 n
+0000000951 00000 n
+0000001156 00000 n
+0000001361 00000 n
+0000001566 00000 n
+0000001771 00000 n
+0000001976 00000 n
+0000002182 00000 n
+0000002389 00000 n
+0000002596 00000 n
+0000002803 00000 n
+0000003010 00000 n
+0000003217 00000 n
+0000003424 00000 n
+0000003631 00000 n
+0000003838 00000 n
+0000004045 00000 n
+0000004252 00000 n
+0000004459 00000 n
+0000004666 00000 n
+0000004873 00000 n
+0000005080 00000 n
+0000005287 00000 n
+0000005494 00000 n
+0000005701 00000 n
+0000005908 00000 n
+0000006115 00000 n
+0000006322 00000 n
+0000006529 00000 n
+0000006748 00000 n
+0000006851 00000 n
+0000006871 00000 n
+0000006990 00000 n
+0000007049 00000 n
+0000007152 00000 n
+0000007195 00000 n
+0000007298 00000 n
+0000007341 00000 n
+0000007444 00000 n
+0000007487 00000 n
+0000007590 00000 n
+0000007633 00000 n
+0000007736 00000 n
+0000007779 00000 n
+0000007882 00000 n
+0000007925 00000 n
+0000008028 00000 n
+0000008071 00000 n
+0000008174 00000 n
+0000008218 00000 n
+0000008321 00000 n
+0000008365 00000 n
+0000008469 00000 n
+0000008513 00000 n
+0000008617 00000 n
+0000008661 00000 n
+0000008765 00000 n
+0000008809 00000 n
+0000008913 00000 n
+0000008957 00000 n
+0000009061 00000 n
+0000009105 00000 n
+0000009209 00000 n
+0000009253 00000 n
+0000009357 00000 n
+0000009401 00000 n
+0000009505 00000 n
+0000009549 00000 n
+0000009653 00000 n
+0000009697 00000 n
+0000009801 00000 n
+0000009845 00000 n
+0000009949 00000 n
+0000009993 00000 n
+0000010097 00000 n
+0000010141 00000 n
+0000010245 00000 n
+0000010289 00000 n
+0000010393 00000 n
+0000010437 00000 n
+0000010541 00000 n
+0000010585 00000 n
+0000010689 00000 n
+0000010733 00000 n
+0000010837 00000 n
+0000010881 00000 n
+0000010985 00000 n
+0000011029 00000 n
+0000011133 00000 n
+0000011177 00000 n
+0000011281 00000 n
+0000000096 65535 f
+0000000097 65535 f
+0000000098 65535 f
+0000000099 65535 f
+0000000100 65535 f
+0000000101 65535 f
+0000000102 65535 f
+0000000103 65535 f
+0000000104 65535 f
+0000000105 65535 f
+0000000106 65535 f
+0000000107 65535 f
+0000000108 65535 f
+0000000109 65535 f
+0000000000 65535 f
+trailer <<
+ /Root 1 0 R
+ /Size 110
+>>
+startxref
+11301
+%%EOF
+
+108 0 obj
+<<
+ /Type /ObjStm
+ /N 13
+ /First 107
+ /Length 2445
+>>
+stream
+95 0
+96 74
+97 259
+98 393
+99 556
+100 898
+101 1077
+102 1275
+103 1432
+104 1589
+105 1730
+106 1887
+107 2040
+%95
+<<
+ /Type /Outlines
+ /First 96 0 R
+ /Last 97 0 R
+ /Count 6
+>>
+%96
+<<
+ /Type /Outline
+ /Title (Isís 1 -> 5: /XYZ null null null)
+ /Parent 95 0 R
+ /Count 4
+ /Next 97 0 R
+ /First 98 0 R
+ /Last 99 0 R
+ /Dest [ 8 0 R /XYZ null null null ]
+>>
+% 97
+<<
+ /Type /Outline
+ /Title (Trepak 2 -> 15: /XYZ 66 756 3)
+ /Parent 95 0 R
+ /Prev 96 0 R
+ /Dest [ 18 0 R /XYZ 66 756 3 ]
+>>
+% 98
+<<
+ /Type /Outline
+ /Title (Amanda 1.1 -> 11: /Fit)
+ /Parent 96 0 R
+ /Next 99 0 R
+ /First 100 0 R
+ /Last 101 0 R
+ /Count -3
+ /Dest [ 14 0 R /Fit ]
+>>
+% 99
+<<
+ /Type /Outline
+ % /Title (Sandy (Sandy [Greek]) 1.2 -> 13: /FitH 792)
+ /Title <feff00530061006e00640079002000f703a303b103bd03b403b900f700200031002e00320020002d003e002000310033003a0020002f00460069007400480020003700390032>
+ /Parent 96 0 R
+ /Prev 98 0 R
+ /First 105 0 R
+ /Last 106 0 R
+ /Count 2
+ /Dest [ 16 0 R /FitH 792 ]
+>>
+% 100
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1 -> 12: /FitV 100)
+ /Parent 98 0 R
+ /Next 101 0 R
+ /First 102 0 R
+ /Last 103 0 R
+ /Count -2
+ /Dest [ 15 0 R /FitV 100 ]
+>>
+% 101
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2 -> 12: /XYZ null null null)
+ /Parent 98 0 R
+ /Prev 100 0 R
+ /First 104 0 R
+ /Last 104 0 R
+ /Count 1
+ /Dest [ 15 0 R /XYZ null null null ]
+>>
+% 102
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.1 -> 18: /XYZ null null null)
+ /Parent 100 0 R
+ /Next 103 0 R
+ /Dest [ 21 0 R /XYZ null null null ]
+>>
+% 103
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.1.2 -> 19: /XYZ null null null)
+ /Parent 100 0 R
+ /Prev 102 0 R
+ /Dest [ 22 0 R /XYZ null null null ]
+>>
+% 104
+<<
+ /Type /Outline
+ /Title (Isosicle 1.1.2.1 -> 22: /XYZ null null null)
+ /Parent 101 0 R
+ /Dest [ 25 0 R /XYZ null null null ]
+>>
+% 105
+<<
+ /Type /Outline
+ /Title (Trepsichord 1.2.1 -> 1: /FitR 66 714 180 770)
+ /Parent 99 0 R
+ /Next 106 0 R
+ /Dest [ 4 0 R /FitR 66 714 180 770 ]
+>>
+% 106
+<<
+ /Type /Outline
+ /Title (Trepsicle 1.2.2 -> 0: /XYZ null null null)
+ /Parent 99 0 R
+ /Prev 105 0 R
+ /Dest [ 3 0 R /XYZ null null null ]
+>>
+% 107
+ << /Nums [
+ 0 << /P () >>
+ 2 << /S /r /St 1 >>
+ 7 << /P () >>
+ 9 << /S /r /St 6 >>
+ 11 << /P () >>
+ 12 << /S /D /St 2 >>
+ 15 << /S /D /St 6 >>
+ 19 << /P () >>
+ 20 << /S /D /St 12 >>
+ 22 << /S /D /St 16059 >>
+ 23 << /S /r /St 50 >>
+ 29 << /S /r /St 54 >>
+ ] >>
+endstream
+endobj
+
+109 0 obj
+<<
+ /Type /XRef
+ /Size 110
+ /Index [0 110]
+ /W [1 2 1]
+ /Length 440
+ /Root 1 0 R
+>>
+stream
+
+$
+
+endstream
+endobj
+
+xref
+0 0
+trailer <<
+ /Size 110
+ /Root 1 0 R
+ /Prev 11301
+ /XRefStm 16113
+>>
+
+startxref
+16679
+%%EOF
diff --git a/qpdf/qtest/qpdf/inline-images.1.check b/qpdf/qtest/qpdf/inline-images.1.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.1.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.10.check b/qpdf/qtest/qpdf/inline-images.10.check
new file mode 100644
index 00000000..0e0ed996
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.10.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.11.check b/qpdf/qtest/qpdf/inline-images.11.check
new file mode 100644
index 00000000..327d847a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.11.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.12.check b/qpdf/qtest/qpdf/inline-images.12.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.12.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.2.check b/qpdf/qtest/qpdf/inline-images.2.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.2.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.3.check b/qpdf/qtest/qpdf/inline-images.3.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.3.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.4.check b/qpdf/qtest/qpdf/inline-images.4.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.4.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.5.check b/qpdf/qtest/qpdf/inline-images.5.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.5.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.6.check b/qpdf/qtest/qpdf/inline-images.6.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.6.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.7.check b/qpdf/qtest/qpdf/inline-images.7.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.7.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.8.check b/qpdf/qtest/qpdf/inline-images.8.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.8.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.9.check b/qpdf/qtest/qpdf/inline-images.9.check
new file mode 100644
index 00000000..37ea00cf
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.9.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/inline-images.pdf b/qpdf/qtest/qpdf/inline-images.pdf
new file mode 100644
index 00000000..e9c59e2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/inline-images.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin-delete-and-reuse.pdf b/qpdf/qtest/qpdf/lin-delete-and-reuse.pdf
new file mode 100644
index 00000000..a7b20ae2
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-delete-and-reuse.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin-special.1.check b/qpdf/qtest/qpdf/lin-special.1.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.1.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.10.check b/qpdf/qtest/qpdf/lin-special.10.check
new file mode 100644
index 00000000..0e0ed996
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.10.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.11.check b/qpdf/qtest/qpdf/lin-special.11.check
new file mode 100644
index 00000000..327d847a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.11.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.12.check b/qpdf/qtest/qpdf/lin-special.12.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.12.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.2.check b/qpdf/qtest/qpdf/lin-special.2.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.2.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.3.check b/qpdf/qtest/qpdf/lin-special.3.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.3.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.4.check b/qpdf/qtest/qpdf/lin-special.4.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.4.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.5.check b/qpdf/qtest/qpdf/lin-special.5.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.5.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.6.check b/qpdf/qtest/qpdf/lin-special.6.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.6.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.7.check b/qpdf/qtest/qpdf/lin-special.7.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.7.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.8.check b/qpdf/qtest/qpdf/lin-special.8.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.8.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.9.check b/qpdf/qtest/qpdf/lin-special.9.check
new file mode 100644
index 00000000..37ea00cf
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.9.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/lin-special.disable.exp b/qpdf/qtest/qpdf/lin-special.disable.exp
new file mode 100644
index 00000000..4c2173d3
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.disable.exp
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin-special.generate.exp b/qpdf/qtest/qpdf/lin-special.generate.exp
new file mode 100644
index 00000000..a150957c
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.generate.exp
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin-special.pdf b/qpdf/qtest/qpdf/lin-special.pdf
new file mode 100644
index 00000000..6dcff293
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.pdf
@@ -0,0 +1,354 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+%
+% This file exercises several special conditions in the linearization
+% and optimization code including various cases of shared resources,
+% inherited page attributes, indirect null objects (resolution of
+% which is a qpdf feature), null dictionary keys, and indirect scalar
+% objects.
+%
+% The page tree is
+%
+% (A)--- page 1
+% |
+% +---- page 2
+% |
+% +---(B)--- page 3
+% |
+% +---- page 4
+% |
+% +---- page 5
+%
+% Node (A) defines /MediaBox (direct) and /Resources (indirect)
+% Node (B) overrides /MediaBox
+% Page 1 overrides /Resources
+% Page 4 overrides /Resources
+% Page 5 overrides /MediaBox
+%
+% Page 5 provides the case of two levels of shadowing on a resource.
+%
+% The /MediaBox defined in node (B) is shared between pages 3 and 4
+% but not page 1. The /MediaBox defined in node (A) is shared between
+% pages 1 and 2 only.
+%
+% The document catalog has two non-standard keys /Moo and /Quack each
+% of which contains (directly or indirectly) an indirect null object.
+%
+% The /Moo object, which is a dictionary, is shared between the
+% document level and page 3 where it appears as a resource.
+%
+
+1 0 obj
+<<
+ /Moo 2 0 R
+ /Pages 3 0 R
+ /Quack 26 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Null1 27 0 R
+ /Null2 null
+ /One 1
+ /Two 28 0 R
+>>
+endobj
+
+3 0 obj
+<<
+ /Count 5
+ /Kids [
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ ]
+ /MediaBox [
+ 0
+ 0
+ 576
+ 792
+ ]
+ /Resources 7 0 R
+ /Quack 16059
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+4 0 obj
+<<
+ /Contents 8 0 R
+ /Parent 3 0 R
+ /Resources 10 0 R
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+5 0 obj
+<<
+ /Contents 11 0 R
+ /Parent 3 0 R
+ /Type /Page
+>>
+endobj
+
+6 0 obj
+<<
+ /Count 3
+ /Kids [
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ ]
+ /MediaBox [
+ 0
+ 0
+ 576
+ 396
+ ]
+ /Parent 3 0 R
+ /Type /Pages
+>>
+endobj
+
+7 0 obj
+<<
+ /Font <<
+ /F1 16 0 R
+ >>
+ /ProcSet 17 0 R
+>>
+endobj
+
+%% Contents for page 1
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+9 0 obj
+46
+endobj
+
+10 0 obj
+<<
+ /Font <<
+ /F1 18 0 R
+ >>
+ /ProcSet 17 0 R
+>>
+endobj
+
+%% Contents for page 2
+11 0 obj
+<<
+ /Length 12 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 322 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+12 0 obj
+46
+endobj
+
+%% Page 3
+13 0 obj
+<<
+ /Contents 19 0 R
+ /Moo 2 0 R
+ /Parent 6 0 R
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+14 0 obj
+<<
+ /Contents 21 0 R
+ /Parent 6 0 R
+ /Resources <<
+ /Font <<
+ /F1 23 0 R
+ >>
+ /ProcSet 17 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+15 0 obj
+<<
+ /Contents 24 0 R
+ /MediaBox [
+ 0
+ 0
+ 306
+ 396
+ ]
+ /Parent 6 0 R
+ /Type /Page
+>>
+endobj
+
+16 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+17 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+18 0 obj
+<<
+ /BaseFont /Courier-Oblique
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+%% Contents for page 3
+19 0 obj
+<<
+ /Length 20 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 322 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+20 0 obj
+46
+endobj
+
+%% Contents for page 4
+21 0 obj
+<<
+ /Length 22 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 322 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+22 0 obj
+46
+endobj
+
+23 0 obj
+<<
+ /BaseFont /Times-Bold
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+%% Contents for page 5
+24 0 obj
+<<
+ /Length 25 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 322 Td
+ (Potato 5) Tj
+ET
+endstream
+endobj
+
+25 0 obj
+46
+endobj
+
+26 0 obj
+null
+endobj
+
+27 0 obj
+null
+endobj
+
+28 0 obj
+2
+endobj
+
+xref
+0 29
+0000000000 65535 f
+0000001161 00000 n
+0000001244 00000 n
+0000001319 00000 n
+0000001501 00000 n
+0000001601 00000 n
+0000001672 00000 n
+0000001829 00000 n
+0000001923 00000 n
+0000002024 00000 n
+0000002043 00000 n
+0000002138 00000 n
+0000002241 00000 n
+0000002271 00000 n
+0000002366 00000 n
+0000002526 00000 n
+0000002644 00000 n
+0000002763 00000 n
+0000002799 00000 n
+0000002947 00000 n
+0000003050 00000 n
+0000003093 00000 n
+0000003196 00000 n
+0000003216 00000 n
+0000003359 00000 n
+0000003462 00000 n
+0000003482 00000 n
+0000003504 00000 n
+0000003526 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 29
+ /ID [<ce9551b56c5a7e3b5b0ba6fa0d281296><a74aa55a69070b600e39f9ed1ed6c4df>]
+>>
+startxref
+3545
+%%EOF
diff --git a/qpdf/qtest/qpdf/lin-special.preserve.exp b/qpdf/qtest/qpdf/lin-special.preserve.exp
new file mode 100644
index 00000000..4c2173d3
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin-special.preserve.exp
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin0.out b/qpdf/qtest/qpdf/lin0.out
new file mode 100644
index 00000000..a6e32e44
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin0.out
@@ -0,0 +1 @@
+lin0.pdf is not linearized
diff --git a/qpdf/qtest/qpdf/lin0.pdf b/qpdf/qtest/qpdf/lin0.pdf
new file mode 100644
index 00000000..a7e01f91
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin0.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+1 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+556
+%%EOF
diff --git a/qpdf/qtest/qpdf/lin1.out b/qpdf/qtest/qpdf/lin1.out
new file mode 100644
index 00000000..d97842bc
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin1.out
@@ -0,0 +1,378 @@
+WARNING: end of first page section (/E) mismatch: /E = 1827; computed = 3889..3891
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 62: in hint table but not computed list
+lin1.pdf: linearization data:
+
+file_size: 13103
+first_page_object: 62
+first_page_end: 1827
+npages: 30
+xref_zero_offset: 11776
+first_page: 0
+H_offset: 1211
+H_length: 203
+
+Page Offsets Hint Table
+
+min_nobjects: 2
+first_page_offset: 1414
+nbits_delta_nobjects: 4
+min_page_length: 259
+nbits_delta_page_length: 12
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 12
+nbits_nshared_objects: 2
+nbits_shared_identifier: 2
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 16
+ length: 2477
+ content_offset: 0
+ content_length: 2218
+ nshared_objects: 2
+ identifier 0: 0
+ numerator 0: 0
+ identifier 1: 0
+ numerator 1: 0
+Page 1:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 2:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 3:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 4:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 5:
+ nobjects: 2
+ length: 261
+ content_offset: 0
+ content_length: 2
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 6:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 7:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 8:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 9:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 10:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 11:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 12:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 13:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 14:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 15:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 16:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 17:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 18:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 19:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 20:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 21:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 22:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 23:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 24:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 25:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 26:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 27:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 28:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 29:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 0
+nshared_first_page: 16
+nshared_total: 16
+nbits_nobjects: 0
+min_group_length: 34
+nbits_delta_group_length: 9
+Shared Object 0:
+ group length: 157
+Shared Object 1:
+ group length: 105
+Shared Object 2:
+ group length: 117
+Shared Object 3:
+ group length: 34
+Shared Object 4:
+ group length: 82
+Shared Object 5:
+ group length: 191
+Shared Object 6:
+ group length: 144
+Shared Object 7:
+ group length: 168
+Shared Object 8:
+ group length: 291
+Shared Object 9:
+ group length: 165
+Shared Object 10:
+ group length: 162
+Shared Object 11:
+ group length: 182
+Shared Object 12:
+ group length: 201
+Shared Object 13:
+ group length: 150
+Shared Object 14:
+ group length: 164
+Shared Object 15:
+ group length: 164
+
+Outlines Hint Table
+
+first_object: 66
+first_object_offset: 1827
+nobjects: 12
+group_length: 2064
diff --git a/qpdf/qtest/qpdf/lin1.pdf b/qpdf/qtest/qpdf/lin1.pdf
new file mode 100644
index 00000000..aac12916
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin1.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin2.out b/qpdf/qtest/qpdf/lin2.out
new file mode 100644
index 00000000..4be08814
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin2.out
@@ -0,0 +1,378 @@
+WARNING: end of first page section (/E) mismatch: /E = 1827; computed = 3889..3891
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 62: in hint table but not computed list
+lin2.pdf: linearization data:
+
+file_size: 13103
+first_page_object: 62
+first_page_end: 1827
+npages: 30
+xref_zero_offset: 11776
+first_page: 0
+H_offset: 1211
+H_length: 203
+
+Page Offsets Hint Table
+
+min_nobjects: 2
+first_page_offset: 1414
+nbits_delta_nobjects: 4
+min_page_length: 259
+nbits_delta_page_length: 12
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 12
+nbits_nshared_objects: 2
+nbits_shared_identifier: 2
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 16
+ length: 2477
+ content_offset: 0
+ content_length: 2218
+ nshared_objects: 2
+ identifier 0: 0
+ numerator 0: 0
+ identifier 1: 0
+ numerator 1: 0
+Page 1:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 2:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 3:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 4:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 5:
+ nobjects: 2
+ length: 261
+ content_offset: 0
+ content_length: 2
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 6:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 7:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 8:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 9:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 10:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 11:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 12:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 13:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 14:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 15:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 16:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 17:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 18:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 19:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 20:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 21:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 22:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 23:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 24:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 25:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 26:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 27:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 28:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 29:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 0
+nshared_first_page: 16
+nshared_total: 16
+nbits_nobjects: 0
+min_group_length: 34
+nbits_delta_group_length: 9
+Shared Object 0:
+ group length: 157
+Shared Object 1:
+ group length: 105
+Shared Object 2:
+ group length: 117
+Shared Object 3:
+ group length: 34
+Shared Object 4:
+ group length: 82
+Shared Object 5:
+ group length: 191
+Shared Object 6:
+ group length: 144
+Shared Object 7:
+ group length: 168
+Shared Object 8:
+ group length: 291
+Shared Object 9:
+ group length: 165
+Shared Object 10:
+ group length: 162
+Shared Object 11:
+ group length: 182
+Shared Object 12:
+ group length: 201
+Shared Object 13:
+ group length: 150
+Shared Object 14:
+ group length: 164
+Shared Object 15:
+ group length: 164
+
+Outlines Hint Table
+
+first_object: 66
+first_object_offset: 1827
+nobjects: 12
+group_length: 2064
diff --git a/qpdf/qtest/qpdf/lin2.pdf b/qpdf/qtest/qpdf/lin2.pdf
new file mode 100644
index 00000000..40cb0027
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin2.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin3.out b/qpdf/qtest/qpdf/lin3.out
new file mode 100644
index 00000000..468cfa59
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin3.out
@@ -0,0 +1,318 @@
+WARNING: end of first page section (/E) mismatch: /E = 3978; computed = 3785..3786
+WARNING: page 1: shared object 107: in computed list but not hint table
+WARNING: page 1: shared object 109: in computed list but not hint table
+WARNING: page 2: shared object 107: in computed list but not hint table
+WARNING: page 2: shared object 109: in computed list but not hint table
+WARNING: page 3: shared object 107: in computed list but not hint table
+WARNING: page 3: shared object 109: in computed list but not hint table
+WARNING: page 4: shared object 107: in computed list but not hint table
+WARNING: page 4: shared object 109: in computed list but not hint table
+WARNING: page 5: shared object 107: in computed list but not hint table
+WARNING: page 5: shared object 109: in computed list but not hint table
+WARNING: page 6: shared object 107: in computed list but not hint table
+WARNING: page 6: shared object 109: in computed list but not hint table
+WARNING: page 7: shared object 107: in computed list but not hint table
+WARNING: page 7: shared object 109: in computed list but not hint table
+WARNING: page 8: shared object 107: in computed list but not hint table
+WARNING: page 8: shared object 109: in computed list but not hint table
+WARNING: page 9: shared object 107: in computed list but not hint table
+WARNING: page 9: shared object 109: in computed list but not hint table
+WARNING: page 10: shared object 107: in computed list but not hint table
+WARNING: page 10: shared object 109: in computed list but not hint table
+WARNING: page 11: shared object 107: in computed list but not hint table
+WARNING: page 11: shared object 109: in computed list but not hint table
+WARNING: page 12: shared object 107: in computed list but not hint table
+WARNING: page 12: shared object 109: in computed list but not hint table
+WARNING: page 13: shared object 107: in computed list but not hint table
+WARNING: page 13: shared object 109: in computed list but not hint table
+WARNING: page 14: shared object 107: in computed list but not hint table
+WARNING: page 14: shared object 109: in computed list but not hint table
+WARNING: page 15: shared object 107: in computed list but not hint table
+WARNING: page 15: shared object 109: in computed list but not hint table
+WARNING: page 16: shared object 107: in computed list but not hint table
+WARNING: page 16: shared object 109: in computed list but not hint table
+WARNING: page 17: shared object 107: in computed list but not hint table
+WARNING: page 17: shared object 109: in computed list but not hint table
+WARNING: page 18: shared object 107: in computed list but not hint table
+WARNING: page 18: shared object 109: in computed list but not hint table
+WARNING: page 19: shared object 107: in computed list but not hint table
+WARNING: page 19: shared object 109: in computed list but not hint table
+WARNING: page 20: shared object 107: in computed list but not hint table
+WARNING: page 20: shared object 109: in computed list but not hint table
+WARNING: page 21: shared object 107: in computed list but not hint table
+WARNING: page 21: shared object 109: in computed list but not hint table
+WARNING: page 22: shared object 107: in computed list but not hint table
+WARNING: page 22: shared object 109: in computed list but not hint table
+WARNING: page 23: shared object 107: in computed list but not hint table
+WARNING: page 23: shared object 109: in computed list but not hint table
+WARNING: page 24: shared object 107: in computed list but not hint table
+WARNING: page 24: shared object 109: in computed list but not hint table
+WARNING: page 25: shared object 107: in computed list but not hint table
+WARNING: page 25: shared object 109: in computed list but not hint table
+WARNING: page 26: shared object 107: in computed list but not hint table
+WARNING: page 26: shared object 109: in computed list but not hint table
+WARNING: page 27: shared object 107: in computed list but not hint table
+WARNING: page 27: shared object 109: in computed list but not hint table
+WARNING: page 28: shared object 107: in computed list but not hint table
+WARNING: page 28: shared object 109: in computed list but not hint table
+WARNING: page 29: shared object 107: in computed list but not hint table
+WARNING: page 29: shared object 109: in computed list but not hint table
+WARNING: incorrect offset in outlines table: hint table = 1627; computed = 1547
+WARNING: incorrect length in outlines table: hint table = 1988; computed = 1936
+lin3.pdf: linearization data:
+
+file_size: 16937
+first_page_object: 93
+first_page_end: 3978
+npages: 30
+xref_zero_offset: 14999
+first_page: 0
+H_offset: 1142
+H_length: 210
+
+Page Offsets Hint Table
+
+min_nobjects: 3
+first_page_offset: 1352
+nbits_delta_nobjects: 5
+min_page_length: 339
+nbits_delta_page_length: 12
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 12
+nbits_nshared_objects: 0
+nbits_shared_identifier: 5
+nbits_shared_numerator: 0
+shared_denominator: 8
+Page 0:
+ nobjects: 17
+ length: 2434
+ content_offset: 0
+ content_length: 2095
+ nshared_objects: 0
+Page 1:
+ nobjects: 3
+ length: 339
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 2:
+ nobjects: 3
+ length: 339
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 3:
+ nobjects: 3
+ length: 339
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 4:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 5:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 6:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 7:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 8:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 9:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 10:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 11:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 12:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 13:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 14:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 15:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 16:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 17:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 18:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 19:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 20:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 21:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 22:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 23:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 24:
+ nobjects: 3
+ length: 344
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 25:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 26:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 27:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 28:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 29:
+ nobjects: 3
+ length: 345
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 16
+nshared_first_page: 17
+nshared_total: 17
+nbits_nobjects: 0
+min_group_length: 21
+nbits_delta_group_length: 8
+Shared Object 0:
+ group length: 195
+Shared Object 1:
+ group length: 80
+Shared Object 2:
+ group length: 189
+Shared Object 3:
+ group length: 141
+Shared Object 4:
+ group length: 167
+Shared Object 5:
+ group length: 174
+Shared Object 6:
+ group length: 163
+Shared Object 7:
+ group length: 160
+Shared Object 8:
+ group length: 183
+Shared Object 9:
+ group length: 202
+Shared Object 10:
+ group length: 149
+Shared Object 11:
+ group length: 164
+Shared Object 12:
+ group length: 164
+Shared Object 13:
+ group length: 132
+Shared Object 14:
+ group length: 116
+Shared Object 15:
+ group length: 21
+Shared Object 16:
+ group length: 34
+
+Outlines Hint Table
+
+first_object: 94
+first_object_offset: 1627
+nobjects: 12
+group_length: 1988
diff --git a/qpdf/qtest/qpdf/lin3.pdf b/qpdf/qtest/qpdf/lin3.pdf
new file mode 100644
index 00000000..e33c7019
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin3.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin4.out b/qpdf/qtest/qpdf/lin4.out
new file mode 100644
index 00000000..42c6282e
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin4.out
@@ -0,0 +1,353 @@
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 74: in hint table but not computed list
+lin4.pdf: linearization data:
+
+file_size: 13055
+first_page_object: 74
+first_page_end: 1539
+npages: 30
+xref_zero_offset: 11488
+first_page: 0
+H_offset: 946
+H_length: 180
+
+Page Offsets Hint Table
+
+min_nobjects: 2
+first_page_offset: 1126
+nbits_delta_nobjects: 2
+min_page_length: 259
+nbits_delta_page_length: 8
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 8
+nbits_nshared_objects: 2
+nbits_shared_identifier: 2
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 4
+ length: 413
+ content_offset: 0
+ content_length: 154
+ nshared_objects: 2
+ identifier 0: 0
+ numerator 0: 0
+ identifier 1: 0
+ numerator 1: 0
+Page 1:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 2:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 3:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 4:
+ nobjects: 2
+ length: 259
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 5:
+ nobjects: 2
+ length: 261
+ content_offset: 0
+ content_length: 2
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 6:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 7:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 8:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 9:
+ nobjects: 2
+ length: 262
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 10:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 11:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 12:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 13:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 14:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 15:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 16:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 17:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 18:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 19:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 20:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 21:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 22:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 23:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 24:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 25:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 26:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 27:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 28:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+Page 29:
+ nobjects: 2
+ length: 263
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 2
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 0
+nshared_first_page: 4
+nshared_total: 4
+nbits_nobjects: 0
+min_group_length: 34
+nbits_delta_group_length: 7
+Shared Object 0:
+ group length: 157
+Shared Object 1:
+ group length: 105
+Shared Object 2:
+ group length: 117
+Shared Object 3:
+ group length: 34
+
+Outlines Hint Table
+
+first_object: 60
+first_object_offset: 9413
+nobjects: 12
+group_length: 2064
diff --git a/qpdf/qtest/qpdf/lin4.pdf b/qpdf/qtest/qpdf/lin4.pdf
new file mode 100644
index 00000000..4778bd8a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin4.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin5.out b/qpdf/qtest/qpdf/lin5.out
new file mode 100644
index 00000000..b2261a1b
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin5.out
@@ -0,0 +1,318 @@
+WARNING: end of first page section (/E) mismatch: /E = 4213; computed = 4004..4005
+WARNING: page 1: shared object 170: in computed list but not hint table
+WARNING: page 1: shared object 172: in computed list but not hint table
+WARNING: page 2: shared object 170: in computed list but not hint table
+WARNING: page 2: shared object 172: in computed list but not hint table
+WARNING: page 3: shared object 170: in computed list but not hint table
+WARNING: page 3: shared object 172: in computed list but not hint table
+WARNING: page 4: shared object 170: in computed list but not hint table
+WARNING: page 4: shared object 172: in computed list but not hint table
+WARNING: page 5: shared object 170: in computed list but not hint table
+WARNING: page 5: shared object 172: in computed list but not hint table
+WARNING: page 6: shared object 170: in computed list but not hint table
+WARNING: page 6: shared object 172: in computed list but not hint table
+WARNING: page 7: shared object 170: in computed list but not hint table
+WARNING: page 7: shared object 172: in computed list but not hint table
+WARNING: page 8: shared object 170: in computed list but not hint table
+WARNING: page 8: shared object 172: in computed list but not hint table
+WARNING: page 9: shared object 170: in computed list but not hint table
+WARNING: page 9: shared object 172: in computed list but not hint table
+WARNING: page 10: shared object 170: in computed list but not hint table
+WARNING: page 10: shared object 172: in computed list but not hint table
+WARNING: page 11: shared object 170: in computed list but not hint table
+WARNING: page 11: shared object 172: in computed list but not hint table
+WARNING: page 12: shared object 170: in computed list but not hint table
+WARNING: page 12: shared object 172: in computed list but not hint table
+WARNING: page 13: shared object 170: in computed list but not hint table
+WARNING: page 13: shared object 172: in computed list but not hint table
+WARNING: page 14: shared object 170: in computed list but not hint table
+WARNING: page 14: shared object 172: in computed list but not hint table
+WARNING: page 15: shared object 170: in computed list but not hint table
+WARNING: page 15: shared object 172: in computed list but not hint table
+WARNING: page 16: shared object 170: in computed list but not hint table
+WARNING: page 16: shared object 172: in computed list but not hint table
+WARNING: page 17: shared object 170: in computed list but not hint table
+WARNING: page 17: shared object 172: in computed list but not hint table
+WARNING: page 18: shared object 170: in computed list but not hint table
+WARNING: page 18: shared object 172: in computed list but not hint table
+WARNING: page 19: shared object 170: in computed list but not hint table
+WARNING: page 19: shared object 172: in computed list but not hint table
+WARNING: page 20: shared object 170: in computed list but not hint table
+WARNING: page 20: shared object 172: in computed list but not hint table
+WARNING: page 21: shared object 170: in computed list but not hint table
+WARNING: page 21: shared object 172: in computed list but not hint table
+WARNING: page 22: shared object 170: in computed list but not hint table
+WARNING: page 22: shared object 172: in computed list but not hint table
+WARNING: page 23: shared object 170: in computed list but not hint table
+WARNING: page 23: shared object 172: in computed list but not hint table
+WARNING: page 24: shared object 170: in computed list but not hint table
+WARNING: page 24: shared object 172: in computed list but not hint table
+WARNING: page 25: shared object 170: in computed list but not hint table
+WARNING: page 25: shared object 172: in computed list but not hint table
+WARNING: page 26: shared object 170: in computed list but not hint table
+WARNING: page 26: shared object 172: in computed list but not hint table
+WARNING: page 27: shared object 170: in computed list but not hint table
+WARNING: page 27: shared object 172: in computed list but not hint table
+WARNING: page 28: shared object 170: in computed list but not hint table
+WARNING: page 28: shared object 172: in computed list but not hint table
+WARNING: page 29: shared object 170: in computed list but not hint table
+WARNING: page 29: shared object 172: in computed list but not hint table
+WARNING: incorrect offset in outlines table: hint table = 1710; computed = 1627
+WARNING: incorrect length in outlines table: hint table = 2124; computed = 2075
+lin5.pdf: linearization data:
+
+file_size: 27464
+first_page_object: 156
+first_page_end: 4213
+npages: 30
+xref_zero_offset: 24265
+first_page: 0
+H_offset: 1149
+H_length: 266
+
+Page Offsets Hint Table
+
+min_nobjects: 3
+first_page_offset: 1415
+nbits_delta_nobjects: 5
+min_page_length: 355
+nbits_delta_page_length: 12
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 12
+nbits_nshared_objects: 0
+nbits_shared_identifier: 5
+nbits_shared_numerator: 0
+shared_denominator: 8
+Page 0:
+ nobjects: 17
+ length: 2590
+ content_offset: 0
+ content_length: 2235
+ nshared_objects: 0
+Page 1:
+ nobjects: 3
+ length: 355
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 2:
+ nobjects: 3
+ length: 355
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 3:
+ nobjects: 3
+ length: 355
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 4:
+ nobjects: 3
+ length: 360
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 5:
+ nobjects: 3
+ length: 360
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 6:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 7:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 8:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 9:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 10:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 11:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 12:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 13:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 14:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 15:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 16:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 17:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 18:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 19:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 20:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 21:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 22:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 23:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 24:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 25:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 26:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 27:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 28:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+Page 29:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 7
+ nshared_objects: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 16
+nshared_first_page: 17
+nshared_total: 17
+nbits_nobjects: 0
+min_group_length: 21
+nbits_delta_group_length: 9
+Shared Object 0:
+ group length: 212
+Shared Object 1:
+ group length: 83
+Shared Object 2:
+ group length: 194
+Shared Object 3:
+ group length: 144
+Shared Object 4:
+ group length: 170
+Shared Object 5:
+ group length: 292
+Shared Object 6:
+ group length: 165
+Shared Object 7:
+ group length: 163
+Shared Object 8:
+ group length: 184
+Shared Object 9:
+ group length: 203
+Shared Object 10:
+ group length: 149
+Shared Object 11:
+ group length: 164
+Shared Object 12:
+ group length: 164
+Shared Object 13:
+ group length: 132
+Shared Object 14:
+ group length: 116
+Shared Object 15:
+ group length: 21
+Shared Object 16:
+ group length: 34
+
+Outlines Hint Table
+
+first_object: 157
+first_object_offset: 1710
+nobjects: 12
+group_length: 2124
diff --git a/qpdf/qtest/qpdf/lin5.pdf b/qpdf/qtest/qpdf/lin5.pdf
new file mode 100644
index 00000000..a41aa344
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin5.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin6.out b/qpdf/qtest/qpdf/lin6.out
new file mode 100644
index 00000000..3ed08aa8
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin6.out
@@ -0,0 +1,592 @@
+WARNING: end of first page section (/E) mismatch: /E = 2897; computed = 5005..5007
+WARNING: object count mismatch for page 0: hint table = 19; computed = 16
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 93: in hint table but not computed list
+WARNING: object count mismatch for page 1: hint table = 3; computed = 2
+WARNING: page 1: shared object 98: in hint table but not computed list
+WARNING: page 1: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 2: hint table = 3; computed = 2
+WARNING: page 2: shared object 98: in hint table but not computed list
+WARNING: page 2: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 3: hint table = 3; computed = 2
+WARNING: page 3: shared object 98: in hint table but not computed list
+WARNING: page 3: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 4: hint table = 3; computed = 2
+WARNING: page 4: shared object 98: in hint table but not computed list
+WARNING: page 4: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 5: hint table = 3; computed = 2
+WARNING: page 5: shared object 98: in hint table but not computed list
+WARNING: page 5: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 6: hint table = 3; computed = 2
+WARNING: page 6: shared object 98: in hint table but not computed list
+WARNING: page 6: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 7: hint table = 3; computed = 2
+WARNING: page 7: shared object 98: in hint table but not computed list
+WARNING: page 7: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 8: hint table = 3; computed = 2
+WARNING: page 8: shared object 98: in hint table but not computed list
+WARNING: page 8: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 9: hint table = 3; computed = 2
+WARNING: page 9: shared object 98: in hint table but not computed list
+WARNING: page 9: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 10: hint table = 3; computed = 2
+WARNING: page 10: shared object 98: in hint table but not computed list
+WARNING: page 10: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 11: hint table = 3; computed = 2
+WARNING: page 11: shared object 98: in hint table but not computed list
+WARNING: page 11: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 12: hint table = 3; computed = 2
+WARNING: page 12: shared object 98: in hint table but not computed list
+WARNING: page 12: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 13: hint table = 3; computed = 2
+WARNING: page 13: shared object 98: in hint table but not computed list
+WARNING: page 13: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 14: hint table = 3; computed = 2
+WARNING: page 14: shared object 98: in hint table but not computed list
+WARNING: page 14: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 15: hint table = 3; computed = 2
+WARNING: page 15: shared object 98: in hint table but not computed list
+WARNING: page 15: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 16: hint table = 3; computed = 2
+WARNING: page 16: shared object 98: in hint table but not computed list
+WARNING: page 16: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 17: hint table = 3; computed = 2
+WARNING: page 17: shared object 98: in hint table but not computed list
+WARNING: page 17: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 18: hint table = 3; computed = 2
+WARNING: page 18: shared object 98: in hint table but not computed list
+WARNING: page 18: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 19: hint table = 3; computed = 2
+WARNING: page 19: shared object 98: in hint table but not computed list
+WARNING: page 19: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 20: hint table = 3; computed = 2
+WARNING: page 20: shared object 98: in hint table but not computed list
+WARNING: page 20: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 21: hint table = 3; computed = 2
+WARNING: page 21: shared object 98: in hint table but not computed list
+WARNING: page 21: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 22: hint table = 3; computed = 2
+WARNING: page 22: shared object 98: in hint table but not computed list
+WARNING: page 22: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 23: hint table = 3; computed = 2
+WARNING: page 23: shared object 98: in hint table but not computed list
+WARNING: page 23: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 24: hint table = 3; computed = 2
+WARNING: page 24: shared object 98: in hint table but not computed list
+WARNING: page 24: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 25: hint table = 3; computed = 2
+WARNING: page 25: shared object 98: in hint table but not computed list
+WARNING: page 25: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 26: hint table = 3; computed = 2
+WARNING: page 26: shared object 98: in hint table but not computed list
+WARNING: page 26: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 27: hint table = 3; computed = 2
+WARNING: page 27: shared object 98: in hint table but not computed list
+WARNING: page 27: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 28: hint table = 3; computed = 2
+WARNING: page 28: shared object 98: in hint table but not computed list
+WARNING: page 28: shared object 99: in hint table but not computed list
+WARNING: object count mismatch for page 29: hint table = 3; computed = 2
+WARNING: page 29: shared object 98: in hint table but not computed list
+WARNING: page 29: shared object 99: in hint table but not computed list
+lin6.pdf: linearization data:
+
+file_size: 24824
+first_page_object: 93
+first_page_end: 2897
+npages: 30
+xref_zero_offset: 22877
+first_page: 0
+H_offset: 1291
+H_length: 232
+
+Page Offsets Hint Table
+
+min_nobjects: 3
+first_page_offset: 1523
+nbits_delta_nobjects: 5
+min_page_length: 580
+nbits_delta_page_length: 12
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 12
+nbits_nshared_objects: 3
+nbits_shared_identifier: 3
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 19
+ length: 3484
+ content_offset: 0
+ content_length: 2904
+ nshared_objects: 4
+ identifier 0: 0
+ numerator 0: 0
+ identifier 1: 0
+ numerator 1: 0
+ identifier 2: 0
+ numerator 2: 0
+ identifier 3: 0
+ numerator 3: 0
+Page 1:
+ nobjects: 3
+ length: 580
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 2:
+ nobjects: 3
+ length: 580
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 3:
+ nobjects: 3
+ length: 584
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 4:
+ nobjects: 3
+ length: 591
+ content_offset: 0
+ content_length: 11
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 5:
+ nobjects: 3
+ length: 583
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 6:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 7:
+ nobjects: 3
+ length: 583
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 8:
+ nobjects: 3
+ length: 591
+ content_offset: 0
+ content_length: 11
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 9:
+ nobjects: 3
+ length: 584
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 10:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 11:
+ nobjects: 3
+ length: 588
+ content_offset: 0
+ content_length: 8
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 12:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 13:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 14:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 15:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 16:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 17:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 18:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 19:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 20:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 21:
+ nobjects: 3
+ length: 588
+ content_offset: 0
+ content_length: 8
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 22:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 23:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 24:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 25:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 26:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 27:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 28:
+ nobjects: 3
+ length: 590
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 29:
+ nobjects: 3
+ length: 589
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 0
+nshared_first_page: 19
+nshared_total: 19
+nbits_nobjects: 0
+min_group_length: 34
+nbits_delta_group_length: 10
+Shared Object 0:
+ group length: 209
+Shared Object 1:
+ group length: 133
+Shared Object 2:
+ group length: 117
+Shared Object 3:
+ group length: 34
+Shared Object 4:
+ group length: 247
+Shared Object 5:
+ group length: 54
+Shared Object 6:
+ group length: 580
+Shared Object 7:
+ group length: 85
+Shared Object 8:
+ group length: 197
+Shared Object 9:
+ group length: 147
+Shared Object 10:
+ group length: 173
+Shared Object 11:
+ group length: 296
+Shared Object 12:
+ group length: 168
+Shared Object 13:
+ group length: 165
+Shared Object 14:
+ group length: 187
+Shared Object 15:
+ group length: 206
+Shared Object 16:
+ group length: 152
+Shared Object 17:
+ group length: 167
+Shared Object 18:
+ group length: 167
+
+Outlines Hint Table
+
+first_object: 100
+first_object_offset: 2897
+nobjects: 12
+group_length: 2110
diff --git a/qpdf/qtest/qpdf/lin6.pdf b/qpdf/qtest/qpdf/lin6.pdf
new file mode 100644
index 00000000..d76545f6
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin6.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin7.out b/qpdf/qtest/qpdf/lin7.out
new file mode 100644
index 00000000..c98d172a
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin7.out
@@ -0,0 +1,292 @@
+WARNING: end of first page section (/E) mismatch: /E = 1865; computed = 1655..1656
+WARNING: page 1: shared object 170: in computed list but not hint table
+WARNING: page 1: shared object 172: in computed list but not hint table
+WARNING: page 2: shared object 170: in computed list but not hint table
+WARNING: page 2: shared object 172: in computed list but not hint table
+WARNING: page 3: shared object 170: in computed list but not hint table
+WARNING: page 3: shared object 172: in computed list but not hint table
+WARNING: page 4: shared object 170: in computed list but not hint table
+WARNING: page 4: shared object 172: in computed list but not hint table
+WARNING: page 5: shared object 170: in computed list but not hint table
+WARNING: page 5: shared object 172: in computed list but not hint table
+WARNING: page 6: shared object 170: in computed list but not hint table
+WARNING: page 6: shared object 172: in computed list but not hint table
+WARNING: page 7: shared object 170: in computed list but not hint table
+WARNING: page 7: shared object 172: in computed list but not hint table
+WARNING: page 8: shared object 170: in computed list but not hint table
+WARNING: page 8: shared object 172: in computed list but not hint table
+WARNING: page 9: shared object 170: in computed list but not hint table
+WARNING: page 9: shared object 172: in computed list but not hint table
+WARNING: page 10: shared object 170: in computed list but not hint table
+WARNING: page 10: shared object 172: in computed list but not hint table
+WARNING: page 11: shared object 170: in computed list but not hint table
+WARNING: page 11: shared object 172: in computed list but not hint table
+WARNING: page 12: shared object 170: in computed list but not hint table
+WARNING: page 12: shared object 172: in computed list but not hint table
+WARNING: page 13: shared object 170: in computed list but not hint table
+WARNING: page 13: shared object 172: in computed list but not hint table
+WARNING: page 14: shared object 170: in computed list but not hint table
+WARNING: page 14: shared object 172: in computed list but not hint table
+WARNING: page 15: shared object 170: in computed list but not hint table
+WARNING: page 15: shared object 172: in computed list but not hint table
+WARNING: page 16: shared object 170: in computed list but not hint table
+WARNING: page 16: shared object 172: in computed list but not hint table
+WARNING: page 17: shared object 170: in computed list but not hint table
+WARNING: page 17: shared object 172: in computed list but not hint table
+WARNING: page 18: shared object 170: in computed list but not hint table
+WARNING: page 18: shared object 172: in computed list but not hint table
+WARNING: page 19: shared object 170: in computed list but not hint table
+WARNING: page 19: shared object 172: in computed list but not hint table
+WARNING: page 20: shared object 170: in computed list but not hint table
+WARNING: page 20: shared object 172: in computed list but not hint table
+WARNING: page 21: shared object 170: in computed list but not hint table
+WARNING: page 21: shared object 172: in computed list but not hint table
+WARNING: page 22: shared object 170: in computed list but not hint table
+WARNING: page 22: shared object 172: in computed list but not hint table
+WARNING: page 23: shared object 170: in computed list but not hint table
+WARNING: page 23: shared object 172: in computed list but not hint table
+WARNING: page 24: shared object 170: in computed list but not hint table
+WARNING: page 24: shared object 172: in computed list but not hint table
+WARNING: page 25: shared object 170: in computed list but not hint table
+WARNING: page 25: shared object 172: in computed list but not hint table
+WARNING: page 26: shared object 170: in computed list but not hint table
+WARNING: page 26: shared object 172: in computed list but not hint table
+WARNING: page 27: shared object 170: in computed list but not hint table
+WARNING: page 27: shared object 172: in computed list but not hint table
+WARNING: page 28: shared object 170: in computed list but not hint table
+WARNING: page 28: shared object 172: in computed list but not hint table
+WARNING: page 29: shared object 170: in computed list but not hint table
+WARNING: page 29: shared object 172: in computed list but not hint table
+lin7.pdf: linearization data:
+
+file_size: 27408
+first_page_object: 168
+first_page_end: 1865
+npages: 30
+xref_zero_offset: 23969
+first_page: 0
+H_offset: 905
+H_length: 235
+
+Page Offsets Hint Table
+
+min_nobjects: 3
+first_page_offset: 1140
+nbits_delta_nobjects: 3
+min_page_length: 356
+nbits_delta_page_length: 8
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 8
+nbits_nshared_objects: 0
+nbits_shared_identifier: 3
+nbits_shared_numerator: 0
+shared_denominator: 8
+Page 0:
+ nobjects: 5
+ length: 516
+ content_offset: 0
+ content_length: 160
+ nshared_objects: 0
+Page 1:
+ nobjects: 3
+ length: 356
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 2:
+ nobjects: 3
+ length: 356
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 3:
+ nobjects: 3
+ length: 356
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 0
+Page 4:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 5:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 6:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 7:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 8:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 9:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 10:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 11:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 12:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 13:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 14:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 15:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 16:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 17:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 18:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 19:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 20:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 21:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 22:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 23:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 24:
+ nobjects: 3
+ length: 361
+ content_offset: 0
+ content_length: 5
+ nshared_objects: 0
+Page 25:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 26:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 27:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 28:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+Page 29:
+ nobjects: 3
+ length: 362
+ content_offset: 0
+ content_length: 6
+ nshared_objects: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 16
+nshared_first_page: 5
+nshared_total: 5
+nbits_nobjects: 0
+min_group_length: 21
+nbits_delta_group_length: 8
+Shared Object 0:
+ group length: 213
+Shared Object 1:
+ group length: 132
+Shared Object 2:
+ group length: 116
+Shared Object 3:
+ group length: 21
+Shared Object 4:
+ group length: 34
+
+Outlines Hint Table
+
+first_object: 88
+first_object_offset: 12129
+nobjects: 12
+group_length: 2030
diff --git a/qpdf/qtest/qpdf/lin7.pdf b/qpdf/qtest/qpdf/lin7.pdf
new file mode 100644
index 00000000..011daa1d
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin7.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin8.out b/qpdf/qtest/qpdf/lin8.out
new file mode 100644
index 00000000..696b759c
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin8.out
@@ -0,0 +1,568 @@
+WARNING: end of first page section (/E) mismatch: /E = 2656; computed = 1768..1770
+WARNING: object count mismatch for page 0: hint table = 7; computed = 4
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 105: in hint table but not computed list
+WARNING: object count mismatch for page 1: hint table = 3; computed = 2
+WARNING: page 1: shared object 110: in hint table but not computed list
+WARNING: page 1: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 2: hint table = 3; computed = 2
+WARNING: page 2: shared object 110: in hint table but not computed list
+WARNING: page 2: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 3: hint table = 3; computed = 2
+WARNING: page 3: shared object 110: in hint table but not computed list
+WARNING: page 3: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 4: hint table = 3; computed = 2
+WARNING: page 4: shared object 110: in hint table but not computed list
+WARNING: page 4: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 5: hint table = 3; computed = 2
+WARNING: page 5: shared object 110: in hint table but not computed list
+WARNING: page 5: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 6: hint table = 3; computed = 2
+WARNING: page 6: shared object 110: in hint table but not computed list
+WARNING: page 6: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 7: hint table = 3; computed = 2
+WARNING: page 7: shared object 110: in hint table but not computed list
+WARNING: page 7: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 8: hint table = 3; computed = 2
+WARNING: page 8: shared object 110: in hint table but not computed list
+WARNING: page 8: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 9: hint table = 3; computed = 2
+WARNING: page 9: shared object 110: in hint table but not computed list
+WARNING: page 9: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 10: hint table = 3; computed = 2
+WARNING: page 10: shared object 110: in hint table but not computed list
+WARNING: page 10: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 11: hint table = 3; computed = 2
+WARNING: page 11: shared object 110: in hint table but not computed list
+WARNING: page 11: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 12: hint table = 3; computed = 2
+WARNING: page 12: shared object 110: in hint table but not computed list
+WARNING: page 12: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 13: hint table = 3; computed = 2
+WARNING: page 13: shared object 110: in hint table but not computed list
+WARNING: page 13: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 14: hint table = 3; computed = 2
+WARNING: page 14: shared object 110: in hint table but not computed list
+WARNING: page 14: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 15: hint table = 3; computed = 2
+WARNING: page 15: shared object 110: in hint table but not computed list
+WARNING: page 15: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 16: hint table = 3; computed = 2
+WARNING: page 16: shared object 110: in hint table but not computed list
+WARNING: page 16: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 17: hint table = 3; computed = 2
+WARNING: page 17: shared object 110: in hint table but not computed list
+WARNING: page 17: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 18: hint table = 3; computed = 2
+WARNING: page 18: shared object 110: in hint table but not computed list
+WARNING: page 18: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 19: hint table = 3; computed = 2
+WARNING: page 19: shared object 110: in hint table but not computed list
+WARNING: page 19: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 20: hint table = 3; computed = 2
+WARNING: page 20: shared object 110: in hint table but not computed list
+WARNING: page 20: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 21: hint table = 3; computed = 2
+WARNING: page 21: shared object 110: in hint table but not computed list
+WARNING: page 21: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 22: hint table = 3; computed = 2
+WARNING: page 22: shared object 110: in hint table but not computed list
+WARNING: page 22: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 23: hint table = 3; computed = 2
+WARNING: page 23: shared object 110: in hint table but not computed list
+WARNING: page 23: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 24: hint table = 3; computed = 2
+WARNING: page 24: shared object 110: in hint table but not computed list
+WARNING: page 24: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 25: hint table = 3; computed = 2
+WARNING: page 25: shared object 110: in hint table but not computed list
+WARNING: page 25: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 26: hint table = 3; computed = 2
+WARNING: page 26: shared object 110: in hint table but not computed list
+WARNING: page 26: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 27: hint table = 3; computed = 2
+WARNING: page 27: shared object 110: in hint table but not computed list
+WARNING: page 27: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 28: hint table = 3; computed = 2
+WARNING: page 28: shared object 110: in hint table but not computed list
+WARNING: page 28: shared object 111: in hint table but not computed list
+WARNING: object count mismatch for page 29: hint table = 3; computed = 2
+WARNING: page 29: shared object 110: in hint table but not computed list
+WARNING: page 29: shared object 111: in hint table but not computed list
+lin8.pdf: linearization data:
+
+file_size: 24875
+first_page_object: 105
+first_page_end: 2656
+npages: 30
+xref_zero_offset: 22687
+first_page: 0
+H_offset: 1052
+H_length: 217
+
+Page Offsets Hint Table
+
+min_nobjects: 3
+first_page_offset: 1269
+nbits_delta_nobjects: 3
+min_page_length: 583
+nbits_delta_page_length: 10
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 10
+nbits_nshared_objects: 3
+nbits_shared_identifier: 3
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 7
+ length: 1387
+ content_offset: 0
+ content_length: 804
+ nshared_objects: 4
+ identifier 0: 0
+ numerator 0: 0
+ identifier 1: 0
+ numerator 1: 0
+ identifier 2: 0
+ numerator 2: 0
+ identifier 3: 0
+ numerator 3: 0
+Page 1:
+ nobjects: 3
+ length: 583
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 2:
+ nobjects: 3
+ length: 583
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 3:
+ nobjects: 3
+ length: 587
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 4:
+ nobjects: 3
+ length: 594
+ content_offset: 0
+ content_length: 11
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 5:
+ nobjects: 3
+ length: 586
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 6:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 7:
+ nobjects: 3
+ length: 586
+ content_offset: 0
+ content_length: 3
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 8:
+ nobjects: 3
+ length: 594
+ content_offset: 0
+ content_length: 11
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 9:
+ nobjects: 3
+ length: 587
+ content_offset: 0
+ content_length: 4
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 10:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 11:
+ nobjects: 3
+ length: 591
+ content_offset: 0
+ content_length: 8
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 12:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 13:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 14:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 15:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 16:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 17:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 18:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 19:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 20:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 21:
+ nobjects: 3
+ length: 591
+ content_offset: 0
+ content_length: 8
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 22:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 23:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 24:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 25:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 26:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 27:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 28:
+ nobjects: 3
+ length: 593
+ content_offset: 0
+ content_length: 10
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+Page 29:
+ nobjects: 3
+ length: 592
+ content_offset: 0
+ content_length: 9
+ nshared_objects: 4
+ identifier 0: 2
+ numerator 0: 0
+ identifier 1: 3
+ numerator 1: 0
+ identifier 2: 5
+ numerator 2: 0
+ identifier 3: 6
+ numerator 3: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 0
+first_shared_offset: 0
+nshared_first_page: 7
+nshared_total: 7
+nbits_nobjects: 0
+min_group_length: 35
+nbits_delta_group_length: 10
+Shared Object 0:
+ group length: 214
+Shared Object 1:
+ group length: 134
+Shared Object 2:
+ group length: 118
+Shared Object 3:
+ group length: 35
+Shared Object 4:
+ group length: 249
+Shared Object 5:
+ group length: 56
+Shared Object 6:
+ group length: 581
+
+Outlines Hint Table
+
+first_object: 89
+first_object_offset: 20067
+nobjects: 12
+group_length: 2069
diff --git a/qpdf/qtest/qpdf/lin8.pdf b/qpdf/qtest/qpdf/lin8.pdf
new file mode 100644
index 00000000..388a21a2
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin8.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/lin9.out b/qpdf/qtest/qpdf/lin9.out
new file mode 100644
index 00000000..6fde8441
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin9.out
@@ -0,0 +1,104 @@
+WARNING: page 0 has shared identifier entries
+WARNING: page 0: shared object 19: in hint table but not computed list
+lin9.pdf: linearization data:
+
+file_size: 3316
+first_page_object: 19
+first_page_end: 1323
+npages: 5
+xref_zero_offset: 2849
+first_page: 0
+H_offset: 713
+H_length: 162
+
+Page Offsets Hint Table
+
+min_nobjects: 2
+first_page_offset: 875
+nbits_delta_nobjects: 2
+min_page_length: 221
+nbits_delta_page_length: 8
+min_content_offset: 0
+nbits_delta_content_offset: 0
+min_content_length: 0
+nbits_delta_content_length: 8
+nbits_nshared_objects: 2
+nbits_shared_identifier: 3
+nbits_shared_numerator: 4
+shared_denominator: 8
+Page 0:
+ nobjects: 5
+ length: 448
+ content_offset: 0
+ content_length: 227
+ nshared_objects: 1
+ identifier 0: 0
+ numerator 0: 0
+Page 1:
+ nobjects: 2
+ length: 221
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 3
+ identifier 0: 5
+ numerator 0: 0
+ identifier 1: 6
+ numerator 1: 0
+ identifier 2: 4
+ numerator 2: 0
+Page 2:
+ nobjects: 2
+ length: 234
+ content_offset: 0
+ content_length: 13
+ nshared_objects: 3
+ identifier 0: 5
+ numerator 0: 0
+ identifier 1: 6
+ numerator 1: 0
+ identifier 2: 4
+ numerator 2: 0
+Page 3:
+ nobjects: 3
+ length: 375
+ content_offset: 0
+ content_length: 154
+ nshared_objects: 1
+ identifier 0: 4
+ numerator 0: 0
+Page 4:
+ nobjects: 2
+ length: 221
+ content_offset: 0
+ content_length: 0
+ nshared_objects: 3
+ identifier 0: 5
+ numerator 0: 0
+ identifier 1: 6
+ numerator 1: 0
+ identifier 2: 4
+ numerator 2: 0
+
+Shared Objects Hint Table
+
+first_shared_obj: 10
+first_shared_offset: 2374
+nshared_first_page: 5
+nshared_total: 7
+nbits_nobjects: 0
+min_group_length: 34
+nbits_delta_group_length: 7
+Shared Object 0:
+ group length: 119
+Shared Object 1:
+ group length: 105
+Shared Object 2:
+ group length: 67
+Shared Object 3:
+ group length: 123
+Shared Object 4:
+ group length: 34
+Shared Object 5:
+ group length: 67
+Shared Object 6:
+ group length: 117
diff --git a/qpdf/qtest/qpdf/lin9.pdf b/qpdf/qtest/qpdf/lin9.pdf
new file mode 100644
index 00000000..40e76929
--- /dev/null
+++ b/qpdf/qtest/qpdf/lin9.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/misc-1.out b/qpdf/qtest/qpdf/misc-1.out
new file mode 100644
index 00000000..3cba139e
--- /dev/null
+++ b/qpdf/qtest/qpdf/misc-1.out
@@ -0,0 +1,15 @@
+page 1:
+ images:
+ /Im1: 5100 x 6600
+ content:
+ 5 0 R
+end page 1
+page 2:
+ images:
+ /Im2: 5100 x 6600
+ /Im3: 305 x 305
+ /Im4: 305 x 305
+ content:
+ 11 0 R
+end page 2
+test 5 done
diff --git a/qpdf/qtest/qpdf/misc-1.pdf b/qpdf/qtest/qpdf/misc-1.pdf
new file mode 100644
index 00000000..dec1d707
--- /dev/null
+++ b/qpdf/qtest/qpdf/misc-1.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/misc-2.out b/qpdf/qtest/qpdf/misc-2.out
new file mode 100644
index 00000000..139d64cc
--- /dev/null
+++ b/qpdf/qtest/qpdf/misc-2.out
@@ -0,0 +1,26 @@
+page 1:
+ images:
+ /Im1: 5100 x 6600
+ content:
+ 5 0 R
+end page 1
+page 2:
+ images:
+ /Im2: 5100 x 6600
+ /Im3: 305 x 305
+ content:
+ 10 0 R
+end page 2
+page 3:
+ images:
+ /Im4: 5100 x 6600
+ content:
+ 14 0 R
+end page 3
+page 4:
+ images:
+ /Im5: 5100 x 6600
+ content:
+ 18 0 R
+end page 4
+test 5 done
diff --git a/qpdf/qtest/qpdf/misc-2.pdf b/qpdf/qtest/qpdf/misc-2.pdf
new file mode 100644
index 00000000..a7a3a93c
--- /dev/null
+++ b/qpdf/qtest/qpdf/misc-2.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/misc-3.out b/qpdf/qtest/qpdf/misc-3.out
new file mode 100644
index 00000000..f9c89df2
--- /dev/null
+++ b/qpdf/qtest/qpdf/misc-3.out
@@ -0,0 +1,14 @@
+page 1:
+ images:
+ content:
+ 4 0 R
+ 6 0 R
+end page 1
+QStrings:
+No Special Characters
+These: ¿÷¢þ and no more
+πωτατω
+QNumbers:
+1.000
+3.142
+test 5 done
diff --git a/qpdf/qtest/qpdf/misc-3.pdf b/qpdf/qtest/qpdf/misc-3.pdf
new file mode 100644
index 00000000..6b9aa3c7
--- /dev/null
+++ b/qpdf/qtest/qpdf/misc-3.pdf
@@ -0,0 +1,127 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /QNumbers [
+ 1
+ 3.14159
+ ]
+ /QStrings [
+ (No Special Characters)
+ (These: ¿÷¢þ and no more)
+ <feff03c003c903c403b103c403c9>
+ ]
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents [
+ 4 0 R
+ 6 0 R
+ ]
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 8 0 R
+ >>
+ /ProcSet 9 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+%% Contents for page 1
+6 0 obj
+<<
+ /Length 7 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 696 Td
+ (Salad) Tj
+ET
+endstream
+endobj
+
+7 0 obj
+43
+endobj
+
+8 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+9 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 10
+0000000000 65535 f
+0000000025 00000 n
+0000000226 00000 n
+0000000308 00000 n
+0000000543 00000 n
+0000000642 00000 n
+0000000684 00000 n
+0000000782 00000 n
+0000000801 00000 n
+0000000919 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 10
+ /ID [<e017d8dc1fe53a81e40aa79bcb43fdec><76269ee0b6579446b731e060af8ef436>]
+>>
+startxref
+954
+%%EOF
diff --git a/qpdf/qtest/qpdf/multiple-mods.pdf b/qpdf/qtest/qpdf/multiple-mods.pdf
new file mode 100755
index 00000000..6370cd65
--- /dev/null
+++ b/qpdf/qtest/qpdf/multiple-mods.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/object-stream.1.check b/qpdf/qtest/qpdf/object-stream.1.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.1.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.10.check b/qpdf/qtest/qpdf/object-stream.10.check
new file mode 100644
index 00000000..0e0ed996
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.10.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.11.check b/qpdf/qtest/qpdf/object-stream.11.check
new file mode 100644
index 00000000..327d847a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.11.check
@@ -0,0 +1,5 @@
+checking a.pdf
+P = -4
+User password =
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.12.check b/qpdf/qtest/qpdf/object-stream.12.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.12.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.2.check b/qpdf/qtest/qpdf/object-stream.2.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.2.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.3.check b/qpdf/qtest/qpdf/object-stream.3.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.3.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.4.check b/qpdf/qtest/qpdf/object-stream.4.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.4.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.5.check b/qpdf/qtest/qpdf/object-stream.5.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.5.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.6.check b/qpdf/qtest/qpdf/object-stream.6.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.6.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.7.check b/qpdf/qtest/qpdf/object-stream.7.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.7.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.8.check b/qpdf/qtest/qpdf/object-stream.8.check
new file mode 100644
index 00000000..7284dd2a
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.8.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is not linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.9.check b/qpdf/qtest/qpdf/object-stream.9.check
new file mode 100644
index 00000000..37ea00cf
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.9.check
@@ -0,0 +1,4 @@
+checking a.pdf
+File is not encrypted
+File is linearized
+No errors found
diff --git a/qpdf/qtest/qpdf/object-stream.disable.exp b/qpdf/qtest/qpdf/object-stream.disable.exp
new file mode 100644
index 00000000..3b5e10fb
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.disable.exp
Binary files differ
diff --git a/qpdf/qtest/qpdf/object-stream.generate.exp b/qpdf/qtest/qpdf/object-stream.generate.exp
new file mode 100644
index 00000000..3f86a173
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.generate.exp
Binary files differ
diff --git a/qpdf/qtest/qpdf/object-stream.pdf b/qpdf/qtest/qpdf/object-stream.pdf
new file mode 100644
index 00000000..1a468202
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/object-stream.preserve.exp b/qpdf/qtest/qpdf/object-stream.preserve.exp
new file mode 100644
index 00000000..3f86a173
--- /dev/null
+++ b/qpdf/qtest/qpdf/object-stream.preserve.exp
Binary files differ
diff --git a/qpdf/qtest/qpdf/old-and-complex.pdf b/qpdf/qtest/qpdf/old-and-complex.pdf
new file mode 100644
index 00000000..74b8c255
--- /dev/null
+++ b/qpdf/qtest/qpdf/old-and-complex.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/p1-a-p2-a.pdf b/qpdf/qtest/qpdf/p1-a-p2-a.pdf
new file mode 100644
index 00000000..b8256cba
--- /dev/null
+++ b/qpdf/qtest/qpdf/p1-a-p2-a.pdf
@@ -0,0 +1,138 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 2
+ /Kids [
+ 3 0 R
+ 4 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 5 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 7 0 R
+ >>
+ /ProcSet 8 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 9 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 7 0 R
+ >>
+ /ProcSet 8 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+5 0 obj
+<<
+ /Length 6 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (A) Tj
+ET
+endstream
+endobj
+
+6 0 obj
+39
+endobj
+
+7 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+8 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+9 0 obj
+<<
+ /Length 10 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (A) Tj
+ET
+endstream
+endobj
+
+10 0 obj
+39
+endobj
+
+xref
+0 11
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000171 00000 n
+0000000373 00000 n
+0000000588 00000 n
+0000000682 00000 n
+0000000701 00000 n
+0000000819 00000 n
+0000000877 00000 n
+0000000972 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 11
+ /ID [<36b07232d7657658c548006151d4c57c><6de1f48ca16def200b3b655a24fa1b48>]
+>>
+startxref
+992
+%%EOF
diff --git a/qpdf/qtest/qpdf/p1-a-p2-b.pdf b/qpdf/qtest/qpdf/p1-a-p2-b.pdf
new file mode 100644
index 00000000..4e05d88a
--- /dev/null
+++ b/qpdf/qtest/qpdf/p1-a-p2-b.pdf
@@ -0,0 +1,138 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 2
+ /Kids [
+ 3 0 R
+ 4 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 5 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 7 0 R
+ >>
+ /ProcSet 8 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+4 0 obj
+<<
+ /Contents 9 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 7 0 R
+ >>
+ /ProcSet 8 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+5 0 obj
+<<
+ /Length 6 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (A) Tj
+ET
+endstream
+endobj
+
+6 0 obj
+39
+endobj
+
+7 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+8 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+9 0 obj
+<<
+ /Length 10 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (B) Tj
+ET
+endstream
+endobj
+
+10 0 obj
+39
+endobj
+
+xref
+0 11
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000171 00000 n
+0000000373 00000 n
+0000000588 00000 n
+0000000682 00000 n
+0000000701 00000 n
+0000000819 00000 n
+0000000877 00000 n
+0000000972 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 11
+ /ID [<36b07232d7657658c548006151d4c57c><6de1f48ca16def200b3b655a24fa1b48>]
+>>
+startxref
+992
+%%EOF
diff --git a/qpdf/qtest/qpdf/p1-a.pdf b/qpdf/qtest/qpdf/p1-a.pdf
new file mode 100644
index 00000000..8cb349c5
--- /dev/null
+++ b/qpdf/qtest/qpdf/p1-a.pdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (A) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+39
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000470 00000 n
+0000000489 00000 n
+0000000607 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+ /ID [<36b07232d7657658c548006151d4c57c><36b07232d7657658c548006151d4c57c>]
+>>
+startxref
+642
+%%EOF
diff --git a/qpdf/qtest/qpdf/p1-b.pdf b/qpdf/qtest/qpdf/p1-b.pdf
new file mode 100644
index 00000000..833e8088
--- /dev/null
+++ b/qpdf/qtest/qpdf/p1-b.pdf
@@ -0,0 +1,95 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (B) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+39
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 8
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000470 00000 n
+0000000489 00000 n
+0000000607 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+ /ID [<36b07232d7657658c548006151d4c57c><36b07232d7657658c548006151d4c57c>]
+>>
+startxref
+642
+%%EOF
diff --git a/qpdf/qtest/qpdf/show-page-1-content-filtered.out b/qpdf/qtest/qpdf/show-page-1-content-filtered.out
new file mode 100644
index 00000000..633a5c1f
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-page-1-content-filtered.out
@@ -0,0 +1 @@
+q 222 0 0 240 28.5 96 cm /Im1 Do Q q 185 0 0 200 313.5 296 cm /Im2 Do Q \ No newline at end of file
diff --git a/qpdf/qtest/qpdf/show-page-1-content-normalized.out b/qpdf/qtest/qpdf/show-page-1-content-normalized.out
new file mode 100644
index 00000000..32c115c8
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-page-1-content-normalized.out
@@ -0,0 +1,8 @@
+q
+222 0 0 240 28.5 96 cm
+/Im1 Do
+Q
+q
+185 0 0 200 313.5 296 cm
+/Im2 Do
+Q
diff --git a/qpdf/qtest/qpdf/show-page-1-content-raw.out b/qpdf/qtest/qpdf/show-page-1-content-raw.out
new file mode 100644
index 00000000..22440b51
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-page-1-content-raw.out
Binary files differ
diff --git a/qpdf/qtest/qpdf/show-page-1-image.out b/qpdf/qtest/qpdf/show-page-1-image.out
new file mode 100644
index 00000000..c2a3483f
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-page-1-image.out
Binary files differ
diff --git a/qpdf/qtest/qpdf/show-page-1.out b/qpdf/qtest/qpdf/show-page-1.out
new file mode 100644
index 00000000..f12237c4
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-page-1.out
@@ -0,0 +1 @@
+<< /Contents 7 0 R /MediaBox [ 0 0 612 792 ] /Parent 4 0 R /Resources << /ProcSet [ /PDF /ImageC ] /XObject << /Im1 8 0 R /Im2 9 0 R >> >> /Type /Page >>
diff --git a/qpdf/qtest/qpdf/show-pages-images.out b/qpdf/qtest/qpdf/show-pages-images.out
new file mode 100644
index 00000000..6d54e9fd
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-pages-images.out
@@ -0,0 +1,11 @@
+page 1: 5 0 R
+ images:
+ /Im1: 8 0 R, 555 x 600
+ /Im2: 9 0 R, 185 x 200
+ content:
+ 7 0 R
+page 2: 6 0 R
+ images:
+ /Im2: 9 0 R, 185 x 200
+ content:
+ 10 0 R
diff --git a/qpdf/qtest/qpdf/show-pages.out b/qpdf/qtest/qpdf/show-pages.out
new file mode 100644
index 00000000..01e0ea0a
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-pages.out
@@ -0,0 +1,6 @@
+page 1: 5 0 R
+ content:
+ 7 0 R
+page 2: 6 0 R
+ content:
+ 10 0 R
diff --git a/qpdf/qtest/qpdf/show-unfilterable.out b/qpdf/qtest/qpdf/show-unfilterable.out
new file mode 100644
index 00000000..464ca2c3
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-unfilterable.out
@@ -0,0 +1 @@
+Unable to filter stream data.
diff --git a/qpdf/qtest/qpdf/show-xref-by-id-filtered.out b/qpdf/qtest/qpdf/show-xref-by-id-filtered.out
new file mode 100644
index 00000000..3ecf4ed4
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-xref-by-id-filtered.out
Binary files differ
diff --git a/qpdf/qtest/qpdf/show-xref-by-id.out b/qpdf/qtest/qpdf/show-xref-by-id.out
new file mode 100644
index 00000000..62faf0ce
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-xref-by-id.out
@@ -0,0 +1,2 @@
+Object is stream. Dictionary:
+<< /DecodeParms << /Columns 4 /Predictor 12 >> /Encrypt 11 0 R /Filter /FlateDecode /ID [ (ª&\237þÂ\226±?>ø5ª¡:\n\b) (ím\023\021OµUt\bµ\026Ê9'\025\033) ] /Info 3 0 R /Length 52 /Root 1 0 R /Size 13 /Type /XRef /W [ 1 2 1 ] >>
diff --git a/qpdf/qtest/qpdf/show-xref.out b/qpdf/qtest/qpdf/show-xref.out
new file mode 100644
index 00000000..a0bb72d9
--- /dev/null
+++ b/qpdf/qtest/qpdf/show-xref.out
@@ -0,0 +1,12 @@
+1/0: uncompressed; offset = 15
+2/0: uncompressed; offset = 64
+3/0: compressed; stream = 2, index = 0
+4/0: compressed; stream = 2, index = 1
+5/0: compressed; stream = 2, index = 2
+6/0: compressed; stream = 2, index = 3
+7/0: uncompressed; offset = 390
+8/0: uncompressed; offset = 521
+9/0: uncompressed; offset = 39802
+10/0: uncompressed; offset = 49559
+11/0: uncompressed; offset = 49672
+12/0: uncompressed; offset = 49880
diff --git a/qpdf/qtest/qpdf/test4-1.pdf b/qpdf/qtest/qpdf/test4-1.pdf
new file mode 100644
index 00000000..9f4f980b
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-1.pdf
@@ -0,0 +1,126 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+8 0 obj
+<<
+ /Title 9 0 R
+ /Subject 10 0 R
+ /A 11 0 R
+ /B 12 0 R
+>>
+endobj
+
+9 0 obj
+(Some Title Is Here)
+endobj
+
+10 0 obj
+(Subject)
+endobj
+
+11 0 obj
+[ 1 2 3 ]
+endobj
+
+12 0 obj
+<< /A 11 0 R /B (B) >>
+endobj
+
+xref
+0 13
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+0000000647 00000 n
+0000000726 00000 n
+0000000763 00000 n
+0000000790 00000 n
+0000000817 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 13
+ /QTest 8 0 R
+ /ID [<c61bd35bada064f61e0a56aa9588064e><c61bd35bada064f61e0a56aa9588064e>]
+>>
+startxref
+857
+%%EOF
diff --git a/qpdf/qtest/qpdf/test4-1.qdf b/qpdf/qtest/qpdf/test4-1.qdf
new file mode 100644
index 00000000..98f93d0f
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-1.qdf
@@ -0,0 +1,145 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 4 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /A [
+ 1
+ 5
+ 3
+ ]
+ /Author (Mr. Potato Head)
+ /B <<
+ /A [
+ 1
+ 2
+ 3
+ ]
+ /B (B)
+ >>
+ /Title (Some Title Is Here)
+>>
+endobj
+
+3 0 obj
+<<
+ /A 5 0 R
+ /B 6 0 R
+ /Subject (Subject)
+ /Title (Some Title Is Here)
+>>
+endobj
+
+4 0 obj
+<<
+ /Count 1
+ /Kids [
+ 7 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+5 0 obj
+[
+ 1
+ 2
+ 3
+]
+endobj
+
+6 0 obj
+<<
+ /A 5 0 R
+ /B (B)
+>>
+endobj
+
+%% Page 1
+7 0 obj
+<<
+ /Contents 8 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 10 0 R
+ >>
+ /ProcSet 11 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+9 0 obj
+44
+endobj
+
+10 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+11 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 12
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000251 00000 n
+0000000346 00000 n
+0000000418 00000 n
+0000000450 00000 n
+0000000502 00000 n
+0000000719 00000 n
+0000000818 00000 n
+0000000837 00000 n
+0000000956 00000 n
+trailer <<
+ /Info 2 0 R
+ /QTest 3 0 R
+ /Root 1 0 R
+ /Size 12
+ /ID [<c61bd35bada064f61e0a56aa9588064e><31415926535897932384626433832795>]
+>>
+startxref
+992
+%%EOF
diff --git a/qpdf/qtest/qpdf/test4-2.out b/qpdf/qtest/qpdf/test4-2.out
new file mode 100644
index 00000000..e5e51762
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-2.out
@@ -0,0 +1 @@
+attempt to make a stream into a direct object
diff --git a/qpdf/qtest/qpdf/test4-2.pdf b/qpdf/qtest/qpdf/test4-2.pdf
new file mode 100644
index 00000000..0acf592c
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-2.pdf
@@ -0,0 +1,104 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+8 0 obj
+<<
+ % stream
+ /A 4 0 R
+>>
+endobj
+
+xref
+0 9
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+0000000647 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 9
+ /QTest 8 0 R
+ /ID [<c61bd35bada064f61e0a56aa9588064e><c61bd35bada064f61e0a56aa9588064e>]
+>>
+startxref
+691
+%%EOF
diff --git a/qpdf/qtest/qpdf/test4-3.out b/qpdf/qtest/qpdf/test4-3.out
new file mode 100644
index 00000000..b0deab16
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-3.out
@@ -0,0 +1 @@
+loop detected while converting object from indirect to direct
diff --git a/qpdf/qtest/qpdf/test4-3.pdf b/qpdf/qtest/qpdf/test4-3.pdf
new file mode 100644
index 00000000..6e212619
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-3.pdf
@@ -0,0 +1,109 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 2 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /Count 1
+ /Kids [
+ 3 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+3 0 obj
+<<
+ /Contents 4 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 6 0 R
+ >>
+ /ProcSet 7 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+4 0 obj
+<<
+ /Length 5 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+44
+endobj
+
+6 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+7 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+8 0 obj
+<<
+ % loop
+ /A [ 1 2 9 0 R ]
+>>
+endobj
+
+9 0 obj
+[ 4 5 8 0 R ]
+endobj
+
+xref
+0 10
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000161 00000 n
+0000000376 00000 n
+0000000475 00000 n
+0000000494 00000 n
+0000000612 00000 n
+0000000647 00000 n
+0000000699 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 10
+ /QTest 8 0 R
+ /ID [<c61bd35bada064f61e0a56aa9588064e><c61bd35bada064f61e0a56aa9588064e>]
+>>
+startxref
+730
+%%EOF
diff --git a/qpdf/qtest/qpdf/test4-4.pdf b/qpdf/qtest/qpdf/test4-4.pdf
new file mode 100644
index 00000000..e0856e3b
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-4.pdf
@@ -0,0 +1,123 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 3 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /A 4 0 R
+ /B 5 0 R
+ /Subject (Subject)
+ /Title (Some Title Is Here)
+>>
+endobj
+
+3 0 obj
+<<
+ /Count 1
+ /Kids [
+ 6 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+4 0 obj
+[
+ 1
+ 2
+ 3
+]
+endobj
+
+5 0 obj
+<<
+ /A 4 0 R
+ /B (B)
+>>
+endobj
+
+%% Page 1
+6 0 obj
+<<
+ /Contents 7 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 9 0 R
+ >>
+ /ProcSet 10 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+7 0 obj
+<<
+ /Length 8 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+8 0 obj
+44
+endobj
+
+9 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+10 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 11
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000174 00000 n
+0000000246 00000 n
+0000000278 00000 n
+0000000330 00000 n
+0000000546 00000 n
+0000000645 00000 n
+0000000664 00000 n
+0000000782 00000 n
+trailer <<
+ /QTest 2 0 R
+ /Root 1 0 R
+ /Size 11
+ /ID [<c61bd35bada064f61e0a56aa9588064e><c893e7330be149468080ad6518819868>]
+>>
+startxref
+818
+%%EOF
diff --git a/qpdf/qtest/qpdf/test4-4.qdf b/qpdf/qtest/qpdf/test4-4.qdf
new file mode 100644
index 00000000..98f93d0f
--- /dev/null
+++ b/qpdf/qtest/qpdf/test4-4.qdf
@@ -0,0 +1,145 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 4 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /A [
+ 1
+ 5
+ 3
+ ]
+ /Author (Mr. Potato Head)
+ /B <<
+ /A [
+ 1
+ 2
+ 3
+ ]
+ /B (B)
+ >>
+ /Title (Some Title Is Here)
+>>
+endobj
+
+3 0 obj
+<<
+ /A 5 0 R
+ /B 6 0 R
+ /Subject (Subject)
+ /Title (Some Title Is Here)
+>>
+endobj
+
+4 0 obj
+<<
+ /Count 1
+ /Kids [
+ 7 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+5 0 obj
+[
+ 1
+ 2
+ 3
+]
+endobj
+
+6 0 obj
+<<
+ /A 5 0 R
+ /B (B)
+>>
+endobj
+
+%% Page 1
+7 0 obj
+<<
+ /Contents 8 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 10 0 R
+ >>
+ /ProcSet 11 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+8 0 obj
+<<
+ /Length 9 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+9 0 obj
+44
+endobj
+
+10 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+11 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 12
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000251 00000 n
+0000000346 00000 n
+0000000418 00000 n
+0000000450 00000 n
+0000000502 00000 n
+0000000719 00000 n
+0000000818 00000 n
+0000000837 00000 n
+0000000956 00000 n
+trailer <<
+ /Info 2 0 R
+ /QTest 3 0 R
+ /Root 1 0 R
+ /Size 12
+ /ID [<c61bd35bada064f61e0a56aa9588064e><31415926535897932384626433832795>]
+>>
+startxref
+992
+%%EOF
diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc
new file mode 100644
index 00000000..7333cc69
--- /dev/null
+++ b/qpdf/test_driver.cc
@@ -0,0 +1,323 @@
+// This program tests miscellaneous functionality in the qpdf library
+// that we don't want to pollute the qpdf program with.
+
+#include <qpdf/QPDF.hh>
+
+#include <qpdf/QUtil.hh>
+#include <qpdf/QTC.hh>
+#include <qpdf/Pl_StdioFile.hh>
+#include <qpdf/QPDFWriter.hh>
+#include <iostream>
+#include <string.h>
+#include <map>
+
+static char const* whoami = 0;
+
+void usage()
+{
+ std::cerr << "Usage: " << whoami << " n filename" << std::endl;
+ exit(2);
+}
+
+void runtest(int n, char const* filename)
+{
+ QPDF pdf;
+ if (n == 0)
+ {
+ pdf.setAttemptRecovery(false);
+ }
+ pdf.processFile(filename);
+
+ if ((n == 0) || (n == 1))
+ {
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ QPDFObjectHandle qtest = trailer.getKey("/QTest");
+
+ if (! trailer.hasKey("/QTest"))
+ {
+ // This will always happen when /QTest is null because
+ // hasKey returns false for null keys regardless of
+ // whether the key exists or not. That way there's never
+ // any difference between a key that is present and null
+ // and a key that is absent.
+ QTC::TC("qpdf", "main QTest implicit");
+ std::cout << "/QTest is implicit" << std::endl;
+ }
+
+ QTC::TC("qpdf", "main QTest indirect",
+ qtest.isIndirect() ? 1 : 0);
+ std::cout << "/QTest is "
+ << (qtest.isIndirect() ? "in" : "")
+ << "direct" << std::endl;
+
+ if (qtest.isNull())
+ {
+ QTC::TC("qpdf", "main QTest null");
+ std::cout << "/QTest is null" << std::endl;
+ }
+ else if (qtest.isBool())
+ {
+ QTC::TC("qpdf", "main QTest bool",
+ qtest.getBoolValue() ? 1 : 0);
+ std::cout << "/QTest is Boolean with value "
+ << (qtest.getBoolValue() ? "true" : "false")
+ << std::endl;
+ }
+ else if (qtest.isInteger())
+ {
+ QTC::TC("qpdf", "main QTest int");
+ std::cout << "/QTest is an integer with value "
+ << qtest.getIntValue() << std::endl;
+ }
+ else if (qtest.isReal())
+ {
+ QTC::TC("qpdf", "main QTest real");
+ std::cout << "/QTest is a real number with value "
+ << qtest.getRealValue() << std::endl;
+ }
+ else if (qtest.isName())
+ {
+ QTC::TC("qpdf", "main QTest name");
+ std::cout << "/QTest is a name with value "
+ << qtest.getName() << std::endl;
+ }
+ else if (qtest.isString())
+ {
+ QTC::TC("qpdf", "main QTest string");
+ std::cout << "/QTest is a string with value "
+ << qtest.getStringValue() << std::endl;
+ }
+ else if (qtest.isArray())
+ {
+ QTC::TC("qpdf", "main QTest array");
+ int n = qtest.getArrayNItems();
+ std::cout << "/QTest is an array with "
+ << n << " items" << std::endl;
+ for (int i = 0; i < n; ++i)
+ {
+ QTC::TC("qpdf", "main QTest array indirect",
+ qtest.getArrayItem(i).isIndirect() ? 1 : 0);
+ std::cout << " item " << i << " is "
+ << (qtest.getArrayItem(i).isIndirect() ? "in" : "")
+ << "direct" << std::endl;
+ }
+ }
+ else if (qtest.isDictionary())
+ {
+ QTC::TC("qpdf", "main QTest dictionary");
+ std::cout << "/QTest is a dictionary" << std::endl;
+ std::set<std::string> keys = qtest.getKeys();
+ for (std::set<std::string>::iterator iter = keys.begin();
+ iter != keys.end(); ++iter)
+ {
+ QTC::TC("qpdf", "main QTest dictionary indirect",
+ (qtest.getKey(*iter).isIndirect() ? 1 : 0));
+ std::cout << " " << *iter << " is "
+ << (qtest.getKey(*iter).isIndirect() ? "in" : "")
+ << "direct" << std::endl;
+ }
+ }
+ else if (qtest.isStream())
+ {
+ QTC::TC("qpdf", "main QTest stream");
+ std::cout << "/QTest is a stream. Dictionary: "
+ << qtest.getDict().unparse() << std::endl;
+
+ std::cout << "Raw stream data:" << std::endl;
+ std::cout.flush();
+ PointerHolder<Pl_StdioFile> out = new Pl_StdioFile("raw", stdout);
+ qtest.pipeStreamData(out.getPointer(), false, false, false);
+
+ std::cout << std::endl << "Uncompressed stream data:" << std::endl;
+ if (qtest.pipeStreamData(0, true, false, false))
+ {
+ std::cout.flush();
+ out = new Pl_StdioFile("filtered", stdout);
+ qtest.pipeStreamData(out.getPointer(), true, false, false);
+ std::cout << std::endl << "End of stream data" << std::endl;
+ }
+ else
+ {
+ std::cout << "Stream data is not filterable." << std::endl;
+ }
+ }
+ else
+ {
+ // Should not happen!
+ std::cout << "/QTest is an unknown object" << std::endl;
+ }
+
+ std::cout << "unparse: " << qtest.unparse() << std::endl
+ << "unparseResolved: " << qtest.unparseResolved()
+ << std::endl;
+ }
+ else if (n == 2)
+ {
+ // Encrypted file. This test case is designed for a specific
+ // PDF file.
+
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ std::cout << trailer.getKey("/Info").
+ getKey("/CreationDate").getStringValue() << std::endl;
+ std::cout << trailer.getKey("/Info").
+ getKey("/Producer").getStringValue() << std::endl;
+
+ QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
+ std::cout << encrypt.getKey("/O").unparse() << std::endl;
+ std::cout << encrypt.getKey("/U").unparse() << std::endl;
+
+ QPDFObjectHandle root = pdf.getRoot();
+ QPDFObjectHandle pages = root.getKey("/Pages");
+ QPDFObjectHandle kids = pages.getKey("/Kids");
+ QPDFObjectHandle page = kids.getArrayItem(1); // second page
+ QPDFObjectHandle contents = page.getKey("/Contents");
+ PointerHolder<Pl_StdioFile> out = new Pl_StdioFile("filtered", stdout);
+ contents.pipeStreamData(out.getPointer(), true, false, false);
+ }
+ else if (n == 3)
+ {
+ QPDFObjectHandle streams = pdf.getTrailer().getKey("/QStreams");
+ for (int i = 0; i < streams.getArrayNItems(); ++i)
+ {
+ QPDFObjectHandle stream = streams.getArrayItem(i);
+ std::cout << "-- stream " << i << " --" << std::endl;
+ std::cout.flush();
+ PointerHolder<Pl_StdioFile> out =
+ new Pl_StdioFile("tokenized stream", stdout);
+ stream.pipeStreamData(out.getPointer(), true, true, false);
+ }
+ }
+ else if (n == 4)
+ {
+ // Mutability testing: Make /QTest direct recursively, then
+ // copy to /Info. Also make some other mutations so we can
+ // tell the difference and ensure that the original /QTest
+ // isn't effected.
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ QPDFObjectHandle qtest = trailer.getKey("/QTest");
+ qtest.makeDirect();
+ qtest.removeKey("/Subject");
+ qtest.replaceKey("/Author",
+ QPDFObjectHandle::newString("Mr. Potato Head"));
+ // qtest.A and qtest.B.A were originally the same object.
+ // They no longer are after makeDirect(). Mutate one of them
+ // and ensure the other is not changed.
+ qtest.getKey("/A").setArrayItem(1, QPDFObjectHandle::newInteger(5));
+ trailer.replaceKey("/Info", pdf.makeIndirectObject(qtest));
+ QPDFWriter w(pdf, 0);
+ w.setQDFMode(true);
+ w.setStaticID(true);
+ w.write();
+
+ // Prevent "done" message from getting appended
+ exit(0);
+ }
+ else if (n == 5)
+ {
+ std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
+ int pageno = 0;
+ for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
+ iter != pages.end(); ++iter)
+ {
+ QPDFObjectHandle& page = *iter;
+ ++pageno;
+
+ std::cout << "page " << pageno << ":" << std::endl;
+
+ std::cout << " images:" << std::endl;
+ std::map<std::string, QPDFObjectHandle> images =
+ page.getPageImages();
+ for (std::map<std::string, QPDFObjectHandle>::iterator iter =
+ images.begin(); iter != images.end(); ++iter)
+ {
+ std::string const& name = (*iter).first;
+ QPDFObjectHandle image = (*iter).second;
+ QPDFObjectHandle dict = image.getDict();
+ int width = dict.getKey("/Width").getIntValue();
+ int height = dict.getKey("/Height").getIntValue();
+ std::cout << " " << name
+ << ": " << width << " x " << height
+ << std::endl;
+ }
+
+ std::cout << " content:" << std::endl;
+ std::vector<QPDFObjectHandle> content = page.getPageContents();
+ for (std::vector<QPDFObjectHandle>::iterator iter = content.begin();
+ iter != content.end(); ++iter)
+ {
+ std::cout << " " << (*iter).unparse() << std::endl;
+ }
+
+ std::cout << "end page " << pageno << std::endl;
+ }
+
+ QPDFObjectHandle root = pdf.getRoot();
+ QPDFObjectHandle qstrings = root.getKey("/QStrings");
+ if (qstrings.isArray())
+ {
+ std::cout << "QStrings:" << std::endl;
+ int n = qstrings.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ std::cout << qstrings.getArrayItem(i).getUTF8Value()
+ << std::endl;
+ }
+ }
+
+ QPDFObjectHandle qnumbers = root.getKey("/QNumbers");
+ if (qnumbers.isArray())
+ {
+ std::cout << "QNumbers:" << std::endl;
+ int n = qnumbers.getArrayNItems();
+ for (int i = 0; i < n; ++i)
+ {
+ std::cout << QUtil::double_to_string(
+ qnumbers.getArrayItem(i).getNumericValue(), 3)
+ << std::endl;
+ }
+ }
+ }
+ else
+ {
+ throw QEXC::General(std::string("invalid test ") +
+ QUtil::int_to_string(n));
+ }
+
+ std::cout << "test " << n << " done" << std::endl;
+}
+
+int main(int argc, char* argv[])
+{
+ if ((whoami = strrchr(argv[0], '/')) == NULL)
+ {
+ whoami = argv[0];
+ }
+ else
+ {
+ ++whoami;
+ }
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if (argc != 3)
+ {
+ usage();
+ }
+
+ try
+ {
+ int n = atoi(argv[1]);
+ char const* filename = argv[2];
+ runtest(n, filename);
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}
diff --git a/qtest/QTC/perl/QTC.pm b/qtest/QTC/perl/QTC.pm
new file mode 100644
index 00000000..2f78b3a6
--- /dev/null
+++ b/qtest/QTC/perl/QTC.pm
@@ -0,0 +1,26 @@
+# -*- perl -*-
+
+require 5.005;
+use strict;
+use FileHandle;
+
+package QTC;
+
+sub TC
+{
+ my ($scope, $case, $n) = @_;
+ local $!;
+ $n = 0 unless defined $n;
+ return unless ($scope eq ($ENV{'TC_SCOPE'} || ""));
+ my $filename = $ENV{'TC_FILENAME'} || return;
+ my $fh = new FileHandle(">>$filename") or
+ die "open test coverage file: $!\n";
+ print $fh "$case $n\n";
+ $fh->close();
+}
+
+1;
+
+#
+# END OF QTC
+#
diff --git a/qtest/README.txt b/qtest/README.txt
new file mode 100644
index 00000000..a4e21b04
--- /dev/null
+++ b/qtest/README.txt
@@ -0,0 +1,3 @@
+This is a copy of qtest (http://qtest.qbilt.org) which is distributed
+under the terms of the Artistic license and has the same author as
+qpdf.
diff --git a/qtest/bin/qtest-driver b/qtest/bin/qtest-driver
new file mode 100755
index 00000000..9ca1ec44
--- /dev/null
+++ b/qtest/bin/qtest-driver
@@ -0,0 +1,798 @@
+#!/usr/bin/env perl
+#
+# This file is part of qtest.
+#
+# Copyright 1993-2007, Jay Berkenbilt
+#
+# QTest is distributed under the terms of version 2.0 of the Artistic
+# license which may be found in the source distribution.
+#
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+use IO::Handle;
+use IO::File;
+use IO::Socket;
+use Cwd 'abs_path';
+use Cwd;
+use Config;
+use File::Copy;
+use File::Basename;
+use File::Spec;
+
+my $whoami = basename($0);
+my $dirname = dirname(abs_path($0));
+my $cwd = getcwd();
+my $top = dirname($dirname);
+my $module_dir = "$top/module";
+my $qtc_dir = "$top/QTC/perl";
+
+unshift(@INC, $module_dir, $qtc_dir);
+require QTC;
+require TestDriver;
+
+if ((@ARGV == 1) && ($ARGV[0] eq '--version'))
+{
+ print "$whoami version 1.1\n";
+ exit 0;
+}
+if ((@ARGV == 1) && ($ARGV[0] eq '--print-path'))
+{
+ print $top, "\n";
+ exit 0;
+}
+
+my @bindirs = ();
+my $datadir = undef;
+my $covdir = '.';
+my $stdout_tty = (-t STDOUT) ? "1" : "0";
+
+while (@ARGV)
+{
+ my $arg = shift(@ARGV);
+ if ($arg eq '-bindirs')
+ {
+ usage() unless @ARGV;
+ push(@bindirs, split(':', shift(@ARGV)));
+ }
+ elsif ($arg eq '-datadir')
+ {
+ usage() unless @ARGV;
+ $datadir = shift(@ARGV);
+ }
+ elsif ($arg eq '-covdir')
+ {
+ usage() unless @ARGV;
+ $covdir = shift(@ARGV);
+ }
+ elsif ($arg =~ m/^-stdout-tty=([01])$/)
+ {
+ $stdout_tty = $1;
+ }
+ else
+ {
+ usage();
+ }
+}
+usage() unless defined($datadir);
+if (@bindirs)
+{
+ my @path = ();
+ foreach my $d (@bindirs)
+ {
+ my $abs = abs_path($d) or
+ fatal("can't canonicalize path to bindir $d: $!");
+ push(@path, $abs);
+ }
+ my $path = join(':', @path) . ':' . $ENV{'PATH'};
+ # Delete and explicitly recreate the PATH environment variable.
+ # This seems to be more reliable. If we just reassign, in some
+ # cases, the modified environment is not inherited by the child
+ # process. (This happens when qtest-driver is invoked from ant
+ # running from gjc-compat. I have no idea how or why.)
+ delete $ENV{'PATH'};
+ $ENV{'PATH'} = $path;
+}
+
+if ($stdout_tty)
+{
+ TestDriver::get_tty_features();
+}
+
+my $pid = undef;
+my $pid_cleanup = new TestDriver::PidKiller(\$pid);
+
+# $in_testsuite is whether the test driver itself is being run from a
+# test suite! Check before we set the environment variable.
+my $in_testsuite = $ENV{'IN_TESTSUITE'} || 0;
+
+$ENV{'IN_TESTSUITE'} = 1;
+
+# Temporary path is intended to be easy to locate so its contents can
+# be inspected by impatient test suite runners. It is not intended to
+# be a "secure" (unpredictable) path.
+my $tempdir = File::Spec->tmpdir() . "/testtemp.$$";
+
+my $file_cleanup = new TestDriver::TmpFileDeleter([$tempdir]);
+
+$| = 1;
+$SIG{'PIPE'} = 'IGNORE';
+$SIG{'INT'} = $SIG{'HUP'} = $SIG{'TERM'} = $SIG{'QUIT'} = sub { exit 2 };
+
+TestDriver::rmrf($tempdir);
+fatal("removal of $tempdir failed") if -e "$tempdir";
+
+mkdir($tempdir, 0777) || die "mkdir $tempdir: $!\n";
+$tempdir = abs_path($tempdir) or
+ fatal("can't canonicalize path to $tempdir: $!");
+
+my $errors = 0;
+
+my $tc_input = undef;
+my $tc_scope = undef;
+my @testcov = (<$covdir/*.testcov>);
+if (@testcov > 1)
+{
+ fatal("more than one testcov file exists");
+}
+elsif (@testcov)
+{
+ &QTC::TC("testdriver", "coverage directory",
+ ($covdir eq '.' ? 1 : 0));
+ $tc_input = $testcov[0];
+ $tc_input =~ s,^\./,,;
+ $tc_scope = basename($tc_input);
+ $tc_scope =~ s/\.testcov$// or
+ fatal("can't get scope from testcov filename");
+}
+
+my $testlogfile = 'qtest.log';
+my $testxmlfile = 'qtest-results.xml';
+unlink $testlogfile;
+unlink $testxmlfile;
+
+my $totmissing = 0;
+my $totextra = 0;
+my $tottests = 0;
+my $totpasses = 0;
+my $totfails = 0;
+my $totxpasses = 0;
+my $totxfails = 0;
+
+my $now = ($in_testsuite ? '---timestamp---' : localtime(time));
+my $msg = "STARTING TESTS on $now";
+print "\n";
+print_and_log(('*' x length($msg)) . "\n$msg\n" .
+ ('*' x length($msg)) . "\n\n");
+
+my $tc_log = undef;
+my $tc_winlog = undef;
+my %tc_cases = ();
+my %tc_ignored_scopes = ();
+parse_tc_file();
+tc_do_initial_checks();
+
+my $tests_to_run;
+defined($tests_to_run = $ENV{"TESTS"}) or $tests_to_run = "";
+my @tests = ();
+if ($tests_to_run ne "")
+{
+ @tests = split(/\s+/, $tests_to_run);
+ for (@tests)
+ {
+ &QTC::TC("testdriver", "driver tests specified");
+ $_ = "$datadir/$_.test";
+ }
+}
+else
+{
+ &QTC::TC("testdriver", "driver tests not specified");
+ @tests = <$datadir/*.test>;
+}
+
+print_xml("<?xml version=\"1.0\"?>\n" .
+ "<qtest-results version=\"1\" timestamp=\"$now\"");
+if (defined $tc_log)
+{
+ print_xml(" coverage-scope=\"$tc_scope\"");
+}
+print_xml(">\n");
+foreach my $test (@tests)
+{
+ print_and_log("\nRunning $test\n");
+ print_xml(" <testsuite file=\"$test\">\n");
+ my @results = run_test($test);
+ if (scalar(@results) != 5)
+ {
+ error("test driver $test returned invalid results");
+ }
+ else
+ {
+ my ($ntests, $passes, $fails, $xpasses, $xfails) = @results;
+ my $actual = $passes + $fails + $xpasses + $xfails;
+ my $extra = 0;
+ my $missing = 0;
+ if ($actual > $ntests)
+ {
+ &QTC::TC("testdriver", "driver extra tests");
+ my $n = ($actual - $ntests);
+ print_and_log(sprintf("\n*** WARNING: saw $n extra test%s\n\n",
+ ($n == 1 ? "" : "s")));
+ $extra = $n;
+ }
+ elsif ($actual < $ntests)
+ {
+ &QTC::TC("testdriver", "driver missing tests");
+ my $n = ($ntests - $actual);
+ print_and_log(sprintf("\n*** WARNING: missing $n test%s\n\n",
+ ($n == 1 ? "" : "s")));
+ $missing = $n;
+ }
+
+ $totmissing += $missing;
+ $totextra += $extra;
+ $totpasses += $passes;
+ $totfails += $fails;
+ $totxpasses += $xpasses;
+ $totxfails += $xfails;
+ $tottests += ($passes + $fails + $xpasses + $xfails);
+
+ my $passed = (($extra == 0) && ($missing == 0) &&
+ ($fails == 0) && ($xpasses == 0));
+
+ print_xml(" <testsummary\n" .
+ " overall-outcome=\"" .($passed ? 'pass' : 'fail') . "\"\n".
+ " total-cases=\"$actual\"\n" .
+ " passes=\"$passes\"\n" .
+ " failures=\"$fails\"\n" .
+ " unexpected-passes=\"$xpasses\"\n" .
+ " expected-failures=\"$xfails\"\n" .
+ " missing-cases=\"$missing\"\n" .
+ " extra-cases=\"$extra\"\n");
+ print_xml(" />\n");
+ }
+ print_xml(" </testsuite>\n");
+}
+
+my $coverage_okay = 1;
+tc_do_final_checks();
+
+my $okay = ((($totpasses + $totxfails) == $tottests) &&
+ ($errors == 0) && ($totmissing == 0) && ($totextra == 0) &&
+ ($coverage_okay));
+
+print "\n";
+print_and_pad("Overall test suite");
+if ($okay)
+{
+ &QTC::TC("testdriver", "driver overall pass");
+ print_results(pass(), pass());
+}
+else
+{
+ &QTC::TC("testdriver", "driver overall fail");
+ print_results(fail(), pass());
+ print "\nFailure summary may be found in $testlogfile\n";
+}
+
+my $summary = "\nTESTS COMPLETE. Summary:\n\n";
+$summary .=
+ sprintf("Total tests: %d\n" .
+ "Passes: %d\n" .
+ "Failures: %d\n" .
+ "Unexpected Passes: %d\n" .
+ "Expected Failures: %d\n" .
+ "Missing Tests: %d\n" .
+ "Extra Tests: %d\n",
+ $tottests, $totpasses, $totfails, $totxpasses, $totxfails,
+ $totmissing, $totextra);
+
+print_and_log($summary);
+print "\n";
+
+print_xml(" <testsummary\n" .
+ " overall-outcome=\"" . ($okay ? 'pass' : 'fail') . "\"\n" .
+ " total-cases=\"$tottests\"\n" .
+ " passes=\"$totpasses\"\n" .
+ " failures=\"$totfails\"\n" .
+ " unexpected-passes=\"$totxpasses\"\n" .
+ " expected-failures=\"$totxfails\"\n" .
+ " missing-cases=\"$totmissing\"\n" .
+ " extra-cases=\"$totextra\"\n");
+if (defined $tc_log)
+{
+ print_xml(" coverage-outcome=\"" .
+ ($coverage_okay ? 'pass' : 'fail') . "\"\n");
+}
+print_xml(" />\n" .
+ "</qtest-results>\n");
+
+exit ($okay ? 0 : 2);
+
+sub run_test
+{
+ my $prog = shift;
+ my @results = ();
+
+ # Open a socket for communication with subsidiary test drivers.
+ # Exchange some handshaking information over this socket. When
+ # the subsidiary test suite exits, it reports its results over the
+ # socket.
+
+ my $use_socketpair = (defined $Config{d_sockpair});
+ if ($Config{'osname'} eq 'cygwin')
+ {
+ $use_socketpair = 0;
+ }
+
+ my $listensock;
+ my $for_parent;
+ my $for_child;
+
+ my @comm_args = ();
+
+ if ($use_socketpair)
+ {
+ socketpair($for_child, $for_parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
+ or fatal("socketpair: $!");
+ my $fd = fileno($for_child);
+ close($for_child);
+ close($for_parent);
+ local $^F = $fd; # prevent control fd from being closed on exec
+ socketpair($for_child, $for_parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
+ or fatal("socketpair: $!");
+ if (fileno($for_child) != $fd)
+ {
+ fatal("FOR_CHILD socket has wrong file descriptor number: got " .
+ fileno($for_child) . "; wanted $fd");
+ }
+ $for_parent->autoflush(1);
+ $for_child->autoflush(1);
+ binmode $for_parent;
+ binmode $for_child;
+ @comm_args = ('-fd', $fd);
+ }
+ else
+ {
+ $listensock = IO::Socket::INET->new(
+ Listen => 1, Proto => 'tcp', LocalPort => 0) or
+ fatal("listen: $!");
+ my ($s_port, $s_addr) = unpack_sockaddr_in($listensock->sockname());
+ @comm_args = ('-port', $s_port);
+ }
+
+ my $pid = fork;
+ fatal("fork failed: $!") unless defined $pid;
+ if ($pid == 0)
+ {
+ if ($use_socketpair)
+ {
+ close($for_parent);
+ }
+ chdir($datadir) or fatal("chdir $datadir failed: $!");
+
+ if (defined $tc_log)
+ {
+ # Set these environment variables in the child process so
+ # that we can actually use the coverage system
+ # successfully to test the test driver itself.
+ $ENV{'TC_SCOPE'} = $tc_scope;
+ $ENV{'TC_FILENAME'} = $tc_log;
+ if (defined $tc_winlog)
+ {
+ $ENV{'TC_WIN_FILENAME'} = $tc_winlog;
+ }
+ }
+
+ # Clear this environment variable so that nested test suites
+ # don't inherit the value from this test suite. Note that as
+ # of perl 5.8.7 in cygwin, deleting an environment variable
+ # doesn't work.
+ $ENV{'TESTS'} = "";
+
+ exec +('perl', '-I', $module_dir, '-I', $qtc_dir,
+ basename($prog),
+ @comm_args,
+ '-origdir', $cwd,
+ '-tempdir', $tempdir,
+ '-testlog', "$cwd/$testlogfile",
+ '-testxml', "$cwd/$testxmlfile",
+ "-stdout-tty=$stdout_tty") or
+ fatal("exec $prog failed: $!");
+ }
+ if ($use_socketpair)
+ {
+ close($for_child);
+ }
+ else
+ {
+ $for_parent = $listensock->accept() or die $!;
+ $for_parent->autoflush();
+ $listensock->close();
+ }
+
+ eval
+ {
+ # Either CHLD or PIPE here indicates premature exiting of
+ # subsidiary process which will be detected by either a
+ # protocol error or a timeout on the select below.
+ local $SIG{'CHLD'} = local $SIG{'PIPE'} = 'IGNORE';
+ print $for_parent "TEST_DRIVER 1\n"
+ or die "--child--\n";
+ my $rin = '';
+ vec($rin, fileno($for_parent), 1) = 1;
+ my $nfound = select($rin, '', '', 5);
+ if ($nfound == 0)
+ {
+ fatal("timed out waiting for input on $for_parent");
+ }
+ # Setting to DEFAULT should be unnecessary because of "local"
+ # above, but there seems to be a race condition that this
+ # helps to correct.
+ $SIG{'CHLD'} = $SIG{'PIPE'} = 'DEFAULT';
+ };
+ if ($@)
+ {
+ if ($@ =~ m/--child--/)
+ {
+ error("subsidiary test driver exited");
+ }
+ else
+ {
+ die $@;
+ }
+ }
+ else
+ {
+ my $line = <$for_parent>;
+ if (! ((defined $line) && ($line =~ m/^TEST_DRIVER_CLIENT 1$/)))
+ {
+ error("invalid protocol with subdiary test driver");
+ kill 1, $pid;
+ }
+ waitpid $pid, 0;
+ my $results = <$for_parent>;
+ close($for_parent);
+ if (! ((defined $results) && ($results =~ m/^\d+(?: \d+){4}$/)))
+ {
+ &QTC::TC("testdriver", "driver test returned invalid results");
+ error("invalid results from subsidiary test driver");
+ }
+ else
+ {
+ @results = split(/ /, $results);
+ }
+ }
+ @results;
+}
+
+sub parse_tc_file
+{
+ return unless defined $tc_input;
+
+ my $tc = new IO::File("<$tc_input") or fatal("can't read $tc_input: $!");
+ while (<$tc>)
+ {
+ s/\r?\n$//s;
+ next if m/^\#/;
+ next if m/^\s*$/;
+ if (m/^ignored-scope: (\S+)$/)
+ {
+ $tc_ignored_scopes{$1} = 1;
+ }
+ elsif (m/^\s*?(\S.+?)\s+(\d+)$/)
+ {
+ my ($case, $n) = ($1, $2);
+ if (exists $tc_cases{$case})
+ {
+ &QTC::TC("testdriver", "driver duplicate coverage case");
+ error("$tc_input:$.: duplicate case");
+ }
+ $tc_cases{$case} = $n;
+ }
+ else
+ {
+ error("$tc_input:$.: invalid syntax");
+ }
+ }
+ $tc->close();
+}
+
+sub tc_do_initial_checks
+{
+ return unless defined $tc_input;
+
+ if (! exists $ENV{'TC_SRCS'})
+ {
+ fatal("TC_SRCS must be set");
+ }
+
+ my @tc_srcs = (grep { m/\S/ } (split(/\s+/, $ENV{'TC_SRCS'})));
+
+ my %seen_cases = ();
+ foreach my $src (@tc_srcs)
+ {
+ my $s = new IO::File("<$src") or die "$whoami: open $src: $!\n";
+ binmode $s;
+ while (<$s>)
+ {
+ # Look for coverage calls in the source subject to certain
+ # lexical constraints
+ my ($lscope, $case);
+ if (m/^\s*\&?QTC(?:::|\.)TC\(\"([^\"]+)\",\s*\"([^\"]+)\"/)
+ {
+ # C++, Java, Perl, etc.
+ ($lscope, $case) = ($1, $2);
+ }
+ elsif (m/^[^\#]*\$\(call QTC.TC,([^,]+),([^,\)]+)/)
+ {
+ # make
+ ($lscope, $case) = ($1, $2);
+ }
+ if ((defined $lscope) && (defined $case))
+ {
+ if ($lscope eq $tc_scope)
+ {
+ push(@{$seen_cases{$case}}, [$src, $.]);
+ }
+ elsif (exists $tc_ignored_scopes{$lscope})
+ {
+ &QTC::TC("testdriver", "driver ignored scope");
+ }
+ else
+ {
+ &QTC::TC("testdriver", "driver out-of-scope case");
+ error("$src:$.: out-of-scope coverage case");
+ }
+ }
+ }
+ $s->close();
+ }
+
+ my %wanted_cases = %tc_cases;
+ foreach my $case (sort keys %seen_cases)
+ {
+ my $wanted = 1;
+ my $whybad = undef;
+ if (exists $wanted_cases{$case})
+ {
+ delete $wanted_cases{$case};
+ }
+ else
+ {
+ &QTC::TC("testdriver", "driver unregistered coverage case");
+ $wanted = 0;
+ $whybad = "unregistered";
+ }
+ if (scalar(@{$seen_cases{$case}}) > $wanted)
+ {
+ $whybad = $whybad || "duplicate";
+ foreach my $d (@{$seen_cases{$case}})
+ {
+ my ($file, $lineno) = @$d;
+ &QTC::TC("testdriver", "driver coverage error in src",
+ ($whybad eq 'unregistered' ? 0 :
+ $whybad eq 'duplicate' ? 1 :
+ 9999));
+ error("$file:$lineno: $whybad coverage case \"$case\"");
+ }
+ }
+ }
+ foreach my $case (sort keys %wanted_cases)
+ {
+ &QTC::TC("testdriver", "driver unseen coverage case");
+ error("$whoami: coverage case \"$case\" was not seen");
+ }
+
+ fatal("errors detected; exiting") if $errors;
+
+ $tc_log = "$cwd/$tc_scope.cov_out";
+ if ($^O eq 'cygwin')
+ {
+ chop(my $f = `cygpath --windows $tc_log`);
+ $tc_winlog = $f;
+ }
+ unlink $tc_log;
+ print_and_log("Test coverage active in scope $tc_scope\n");
+}
+
+sub tc_do_final_checks
+{
+ return unless (defined $tc_log);
+
+ my %seen_cases = ();
+ my $tc = new IO::File("<$tc_log");
+ if ($tc)
+ {
+ binmode $tc;
+ while (<$tc>)
+ {
+ s/\r?\n$//s;
+ next if m/^\#/;
+ next if m/^\s*$/;
+ if (m/^(.+) (\d+)$/)
+ {
+ $seen_cases{$1}{$2} = 1;
+ }
+ }
+ $tc->close();
+ }
+
+ my $testlog = open_log();
+
+ $testlog->print("\nTest coverage results:\n");
+
+ my @problems = ();
+ foreach my $c (sort keys %tc_cases)
+ {
+ my ($case, $n) = ($c, $tc_cases{$c});
+ for (my $i = 0; $i <= $n; ++$i)
+ {
+ if (exists $seen_cases{$c}{$i})
+ {
+ delete $seen_cases{$c}{$i};
+ }
+ else
+ {
+ &QTC::TC("testdriver", "driver missing coverage case");
+ push(@problems, "missing: $c $i");
+ }
+ }
+ }
+ foreach my $c (sort keys %seen_cases)
+ {
+ foreach my $n (sort { $a <=> $b } (keys %{$seen_cases{$c}}))
+ {
+ &QTC::TC("testdriver", "driver extra coverage case");
+ push(@problems, "extra: $c $n");
+ }
+ }
+
+ if (@problems)
+ {
+ my $testxml = open_xml();
+ $testxml->print(" <coverage-errors count=\"" .
+ scalar(@problems) . "\">\n");
+ foreach my $p (@problems)
+ {
+ $testlog->print("$p\n");
+ $testxml->print(" <coverage-error case=\"$p\"/>\n");
+ }
+ $testxml->print(" </coverage-errors>\n");
+ $testxml->close();
+ $testlog->print("coverage errors: " . scalar(@problems) . "\n");
+ }
+ my $passed = (@problems == 0);
+ $testlog->print("\nCoverage analysis: ", ($passed ? 'PASSED' : 'FAILED'),
+ "\n");
+ $testlog->close();
+
+ print "\n";
+ print_and_pad("Coverage analysis");
+ if ($passed)
+ {
+ print_results(pass(), pass());
+ my $passlog = $tc_log;
+ $passlog =~ s/(\.[^\.]+)$/-passed$1/;
+ copy($tc_log, $passlog);
+ }
+ else
+ {
+ $coverage_okay = 0;
+ print_results(fail(), pass());
+ }
+}
+
+sub open_binary
+{
+ my $file = shift;
+ my $fh = new IO::File(">>$file") or fatal("can't open $file: $!");
+ binmode $fh;
+ $fh;
+}
+
+sub open_log
+{
+ open_binary($testlogfile);
+}
+
+sub open_xml
+{
+ open_binary($testxmlfile);
+}
+
+sub print_and_log
+{
+ my $fh = open_log();
+ print @_;
+ print $fh @_;
+ $fh->close();
+}
+
+sub print_xml
+{
+ my $fh = open_xml();
+ print $fh @_;
+ $fh->close();
+}
+
+sub print_and_pad
+{
+ TestDriver::print_and_pad(@_);
+}
+
+sub print_results
+{
+ TestDriver::print_results(@_);
+}
+
+sub pass
+{
+ TestDriver->PASS;
+}
+
+sub fail
+{
+ TestDriver->FAIL;
+}
+
+sub error
+{
+ my $msg = shift;
+ warn $msg, "\n";
+ ++$errors;
+}
+
+sub fatal
+{
+ my $msg = shift;
+ warn "$whoami: $msg\n";
+ exit 2;
+}
+
+sub usage
+{
+ warn "
+Usage: $whoami --print-path
+
+Prints full path to ${whoami}'s installation directory and exits.
+
+ - OR -
+
+Usage: $whoami options
+
+Options include:
+
+ -datadir datadir
+ -bindirs bindir[:bindir...]
+ [ -covdir [coverage-dir] ]
+ [ -stdout-tty=[01] ]
+
+Subsidiary test programs are run with the -bindirs argument (a
+colon-separated list of directories, which may be relative but will be
+internally converted to absolute) prepended to the path and with the
+-datadir argument set as the current working directory.
+
+By default, this program runs datadir/*.test as subsidiary test
+suites. If the TESTS environment variable is set, it is taken to be a
+space-separated list of test suite names. For each name n,
+datadir/n.test is run.
+
+Test coverage support is built in. If a file whose name matches
+*.testcov in the coverage directory (which defaults to \".\") that is
+a valid test coverage file, the full path to the file into which test
+coverage results are written will be placed in the TC_FILENAME
+environment variable. (If running under cygwin, the Windows path will
+be in TC_WIN_FILENAME.) The test coverage scope, which is equal to
+the part of the testcov file name excluding the extension, is placed
+in the TC_SCOPE environment variable.
+
+If the -stdout-tty option is passed, its value overrides ${whoami}'s
+determination of whether standard output is a terminal. This can be
+useful for cases in which another program is invoking ${whoami} and
+passing its output through a pipe to a terminal.
+
+";
+ exit 2;
+
+}
diff --git a/qtest/module/TestDriver.pm b/qtest/module/TestDriver.pm
new file mode 100644
index 00000000..6e1fa313
--- /dev/null
+++ b/qtest/module/TestDriver.pm
@@ -0,0 +1,1566 @@
+# -*- perl -*-
+#
+# This file is part of qtest.
+#
+# Copyright 1993-2007, Jay Berkenbilt
+#
+# QTest is distributed under the terms of version 2.0 of the Artistic
+# license which may be found in the source distribution.
+#
+
+# Search for "PUBLIC METHODS" to find the public methods and
+# documentation on how to use them.
+
+require 5.008;
+use strict;
+
+package TestDriver::PidKiller;
+
+use vars qw($f_pid);
+$f_pid = 'pid';
+
+sub new
+{
+ my $class = shift;
+ my $rep = +{+__PACKAGE__ => {} };
+ $rep->{+__PACKAGE__}{$f_pid} = shift;
+ bless $rep, $class;
+}
+
+sub DESTROY
+{
+ my $rep = shift;
+ my $pid = $rep->{+__PACKAGE__}{$f_pid};
+ defined($$pid) && $$pid && kill 15, $$pid;
+}
+
+package TestDriver::TmpFileDeleter;
+
+use vars qw($f_files);
+$f_files = 'files';
+
+sub new
+{
+ my $class = shift;
+ my $rep = +{+__PACKAGE__ => {} };
+ $rep->{+__PACKAGE__}{$f_files} = shift;
+ bless $rep, $class;
+}
+
+sub DESTROY
+{
+ local $?;
+ my $rep = shift;
+ my $files = ($rep->{+__PACKAGE__}{$f_files});
+ map { TestDriver::rmrf($_) } @$files;
+}
+
+package TestDriver;
+
+use IO::Handle;
+use IO::File;
+use IO::Socket;
+use IO::Select;
+use POSIX ':sys_wait_h';
+use File::Copy;
+use File::Find;
+use Carp;
+use Cwd;
+require QTC;
+
+# Constants
+
+# Possible test case outcomes
+use constant PASS => 'PASS';
+use constant FAIL => 'FAIL';
+
+# Input/Output keys
+use constant STRING => 'STRING';
+use constant FILE => 'FILE';
+use constant COMMAND => 'COMMAND';
+use constant FILTER => 'FILTER';
+use constant REGEXP => 'REGEXP';
+use constant EXIT_STATUS => 'EXIT_STATUS';
+use constant THREAD_DATA => 'THREAD_DATA';
+use constant TD_THREADS => 'TD_THREADS';
+use constant TD_SEQGROUPS => 'TD_SEQGROUPS';
+
+# Flags
+use constant NORMALIZE_NEWLINES => 1 << 0;
+use constant NORMALIZE_WHITESPACE => 1 << 1;
+use constant EXPECT_FAILURE => 1 << 2;
+
+# Field names
+use vars qw($f_socket $f_origdir $f_tempdir $f_testlog $f_testxml $f_suitename);
+$f_socket = 'socket';
+$f_origdir = 'origdir';
+$f_tempdir = 'tempdir';
+$f_testlog = 'testlog';
+$f_testxml = 'testxml';
+$f_suitename = 'suitename';
+
+use vars qw($f_passes $f_fails $f_xpasses $f_xfails $f_testnum);
+$f_passes = 'passes'; # expected passes
+$f_fails = 'fails'; # unexpected failures
+$f_xpasses = 'xpasses'; # unexpected passes
+$f_xfails = 'xfails'; # expected failures
+$f_testnum = 'testnum';
+
+# Static Variables
+
+# QTEST_MARGIN sets the number of spaces to after PASSED or FAILED and
+# before the rightmost column of the screen.
+my $margin = $ENV{'QTEST_MARGIN'} || 8;
+$margin += $ENV{'QTEST_EXTRA_MARGIN'} || 0;
+
+my $ncols = 80;
+
+my $color_reset = "";
+my $color_green = "";
+my $color_yellow = "";
+my $color_red = "";
+my $color_magenta = "";
+my $color_emph = "";
+
+sub get_tty_features
+{
+ my $got_size = 0;
+ eval
+ {
+ require Term::ReadKey;
+ ($ncols, undef, undef, undef) = Term::ReadKey::GetTerminalSize();
+ $got_size = 1;
+ };
+ if (! $got_size)
+ {
+ eval
+ {
+ # Get screen columns if possible
+ no strict;
+ local $^W = 0;
+ local *X;
+ require 'sys/ioctl.ph';
+ if ((defined &TIOCGWINSZ) && open(X, "+</dev/tty"))
+ {
+ my $winsize = "";
+ if (ioctl(X, &TIOCGWINSZ, $winsize))
+ {
+ (undef, $ncols) = unpack('S4', $winsize);
+ $got_size = 1;
+ }
+ close(X);
+ }
+ };
+ }
+ eval
+ {
+ require Term::ANSIColor;
+ $color_reset = Term::ANSIColor::RESET();
+ $color_green = Term::ANSIColor::GREEN();
+ $color_yellow = Term::ANSIColor::YELLOW();
+ $color_red = Term::ANSIColor::RED();
+ $color_magenta = Term::ANSIColor::MAGENTA();
+ $color_emph = Term::ANSIColor::color('bold blue on_black');
+ };
+}
+
+# Static Methods
+
+sub print_and_pad
+{
+ my $str = shift;
+ my $spaces = $ncols - 10 - length($str) - $margin;
+ $spaces = 0 if $spaces < 0;
+ print $str . (' ' x $spaces) . ' ... ';
+}
+
+sub print_results
+{
+ my ($outcome, $exp_outcome) = @_;
+
+ my $color = "";
+ my $outcome_text;
+ if ($outcome eq $exp_outcome)
+ {
+ if ($outcome eq PASS)
+ {
+ &QTC::TC("testdriver", "TestDriver expected pass");
+ $color = $color_green;
+ $outcome_text = "PASSED";
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver expected fail");
+ $color = $color_yellow;
+ # " (exp)" is fewer characters than the default margin
+ # which keeps this from wrapping lines with default
+ # settings.
+ $outcome_text = "FAILED (exp)";
+ }
+ }
+ else
+ {
+ if ($outcome eq PASS)
+ {
+ &QTC::TC("testdriver", "TestDriver unexpected pass");
+ $color = $color_magenta;
+ $outcome_text = "PASSED-UNEXP";
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver unexpected fail");
+ $color = $color_red;
+ $outcome_text = "FAILED";
+ }
+ }
+
+ print $color, $outcome_text, $color_reset, "\n";
+ $outcome_text;
+}
+
+# Normal Methods
+
+sub new
+{
+ my $class = shift;
+ my $rep = +{+__PACKAGE__ => {} };
+
+ if (@_ != 1)
+ {
+ croak "Usage: ", __PACKAGE__, "->new(\"test-suite name\")\n";
+ }
+ my $suitename = shift;
+
+ if (! ((@ARGV == 11) &&
+ (($ARGV[0] eq '-fd') || ($ARGV[0] eq '-port')) &&
+ ($ARGV[2] eq '-origdir') &&
+ ($ARGV[4] eq '-tempdir') &&
+ ($ARGV[6] eq '-testlog') &&
+ ($ARGV[8] eq '-testxml') &&
+ ($ARGV[10] =~ m/^-stdout-tty=([01])$/) &&
+ (-d $ARGV[5])))
+ {
+ die +__PACKAGE__, ": improper invocation of test driver $0\n";
+ }
+ my $fd = ($ARGV[0] eq '-fd') ? $ARGV[1] : undef;
+ my $port = ($ARGV[0] eq '-port') ? $ARGV[1] : undef;
+ my $origdir = $ARGV[3];
+ my $tempdir = $ARGV[5];
+ my $testlogfile = $ARGV[7];
+ my $testxmlfile = $ARGV[9];
+ my $testlog = new IO::File(">>$testlogfile");
+ binmode $testlog;
+ my $testxml = new IO::File(">>$testxmlfile");
+ binmode $testxml;
+ $ARGV[10] =~ m/=([01])/ or die +__PACKAGE__, ": INTERNAL ERROR in ARGV[10]";
+ my $stdout_is_tty = $1;
+ if ($stdout_is_tty)
+ {
+ get_tty_features();
+ }
+
+ my $socket;
+ if (defined $fd)
+ {
+ $socket = new IO::Handle;
+ if (! $socket->fdopen($fd, "w+"))
+ {
+ warn +__PACKAGE__, ": unable to open file descriptor $fd.\n";
+ warn +__PACKAGE__, " must be created from a program invoked by" .
+ " the test driver system\n";
+ die +__PACKAGE__, ": initialization failed";
+ }
+ }
+ else
+ {
+ $socket = IO::Socket::INET->new(
+ PeerAddr => '127.0.0.1', PeerPort => $port) or
+ die "unable to connect to port $port: $!\n";
+ }
+ $socket->autoflush();
+ binmode $socket;
+
+ # Do some setup that would ordinarily be reserved for a main
+ # program. We want test suites to behave in a certain way so tha
+ # the overall system works as desired.
+
+ # Killing the driver should cause to to exit. Without this, it
+ # may cause whatever subsidiary program is being run to exit and
+ # the driver to continue to the next test case.
+ $SIG{'INT'} = $SIG{'HUP'} = $SIG{'TERM'} = $SIG{'QUIT'} = sub { exit 2 };
+
+ # Unbuffer our output.
+ $| = 1;
+
+ $rep->{+__PACKAGE__}{$f_socket} = $socket;
+ $rep->{+__PACKAGE__}{$f_origdir} = $origdir;
+ $rep->{+__PACKAGE__}{$f_tempdir} = $tempdir;
+ $rep->{+__PACKAGE__}{$f_testlog} = $testlog;
+ $rep->{+__PACKAGE__}{$f_testxml} = $testxml;
+ $rep->{+__PACKAGE__}{$f_suitename} = $suitename;
+ $rep->{+__PACKAGE__}{$f_passes} = 0;
+ $rep->{+__PACKAGE__}{$f_fails} = 0;
+ $rep->{+__PACKAGE__}{$f_xpasses} = 0;
+ $rep->{+__PACKAGE__}{$f_xfails} = 0;
+ $rep->{+__PACKAGE__}{$f_testnum} = 1;
+
+ # Do protocol handshaking with the test driver system
+ my $init = scalar(<$socket>);
+ if ($init !~ m/^TEST_DRIVER 1$/)
+ {
+ die +__PACKAGE__, ": incorrect protocol with test driver system\n";
+ }
+ $socket->print("TEST_DRIVER_CLIENT 1\n");
+
+ bless $rep, $class;
+}
+
+sub _socket
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_socket};
+}
+
+sub _tempdir
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_tempdir};
+}
+
+sub _testlog
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_testlog};
+}
+
+sub _testxml
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_testxml};
+}
+
+sub _suitename
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_suitename};
+}
+
+sub _testnum
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_testnum} = $_[0] if @_;
+ $rep->{+__PACKAGE__}{$f_testnum};
+}
+
+# PUBLIC METHODS
+
+# Usage: report(n)
+# Specify the number of tests that are expected to have been run.
+# Please note: the purpose of reporting the number of test cases with
+# "report" is as an extra check to make sure that the test suite
+# itself didn't have a logic error that caused some test cases to be
+# skipped. The argument to "report" should therefore be a hard-coded
+# number or a number computed only from static features in the test
+# suite. It should not be a number that is counted up during the
+# process of running the test suite. Computing this number as a side
+# effect of running test cases would defeat the purpose of the number.
+# For example, if the test suite consists of an array of test cases,
+# and the test suite code iterates through that loop and calls
+# "runtest" twice for each element, it would be reasonable to pass an
+# expression that includes the size of the array as an argument to
+# "report", but it would not be appropriate to have a variable called
+# "$ntests" that is incremented each time "runtest" is called and then
+# passed to "report".
+sub report
+{
+ my $rep = shift;
+ croak "Usage: ", __PACKAGE__, "->report(num-tests-expected)\n"
+ unless @_ && $_[0] =~ m/^\d+$/;
+
+ # Message to test driver system:
+ # n-expected-tests passes fails unexpected-passes expected-fails
+
+ my @vals = (shift);
+ push(@vals, map { $rep->{+__PACKAGE__}{$_} } ($f_passes, $f_fails,
+ $f_xpasses, $f_xfails));
+ my $socket = $rep->_socket();
+ $socket->print(join(' ', @vals)), "\n";
+}
+
+# Usage: notify(string)
+# Prints the string followed by a newline to standard output of the
+# test suite.
+sub notify
+{
+ my $rep = shift;
+ my $msg = shift;
+ &QTC::TC("testdriver", "TestDriver notify");
+ print $msg, "\n";
+}
+
+# Usage: emphasize(string)
+# Prints the string followed by a newline to standard output of the
+# test suite. The string is printed with emphasis if the terminal
+# supports color.
+sub emphasize
+{
+ my $rep = shift;
+ my $msg = shift;
+ &QTC::TC("testdriver", "TestDriver emphasize");
+ print $color_emph, $msg, $color_reset, "\n";
+}
+
+# Usage: prompt(msg, env, default)
+# If the environment variable "env" is set, its value is returned.
+# Otherwise, if STDIN is a tty, the user is prompted for an answer
+# using msg as the prompt, or if STDIN is not a tty, the value
+# specified in "default" is returned. Note that careless use of
+# prompt in test suites may make the test suites unable to be run in
+# batch mode.
+sub prompt
+{
+ my $rep = shift;
+ my ($msg, $env, $default) = @_;
+ &QTC::TC("testdriver", "TestDriver prompt");
+ my $answer = $ENV{$env};
+ if (defined $answer)
+ {
+ print "$msg\n";
+ print "[Question answered from environment variable \$$env: $answer]\n";
+ }
+ else
+ {
+ print "To avoid question, place answer in" .
+ " environment variable \$$env\n";
+ if (-t STDIN)
+ {
+ print "$msg ";
+ chop($answer = <STDIN>);
+ if ($answer eq '')
+ {
+ print "[Using default answer for question: $default]\n";
+ $answer = $default;
+ }
+ }
+ else
+ {
+ print "$msg\n";
+ print "[Using default answer for question: $default]\n";
+ $answer = $default;
+ }
+ }
+ $answer;
+}
+
+# Usage: get_start_dir()
+# Returns the name of the directory from which the test driver was
+# originally invoked. This can be useful for test suites that are
+# designed to be run from read-only areas or from multiple locations
+# simultaneously: they can get the original invocation directory and
+# use it as a place to write temporary files.
+sub get_start_dir
+{
+ my $rep = shift;
+ $rep->{+__PACKAGE__}{$f_origdir};
+}
+
+# Usage: runtest description input output [ flags ]
+# Returns true iff test passes; i.e., input matches output
+
+# Parameters:
+
+# description: a short textual description of the test case
+
+# input: a hash reference that defines the input to the test case
+# input keys and associated values:
+
+# STRING: a string that is used verbatim as the test input
+
+# FILE: a file whose contents are used as the test input
+
+# COMMAND: an array reference containing a command and arguments
+# or a string representing the command. This is passed to exec,
+# so the rules that exec uses to determine whether to pass this
+# to a shell are followed. The command is run with STDIN set to
+# /dev/null, STDOUT redirected to an internal file, and STDERR
+# copied to STDOUT.
+
+# Note that exactly one of STRING, FILE, or COMMAND must appear.
+
+# FILTER: if specified, it is a program that is run on the test
+# input specified above to generate the true test input.
+
+# output: a hash reference that defines the expected output of the
+# test case
+
+# STRING: a string that contains the expected test output
+
+# FILE: a file that contains the expected test output
+
+# REGEXP: a regular expression that must match the test output
+
+# Note that exactly one of STRING, FILE, or REGEXP must appear.
+
+# EXIT_STATUS: the exit status of the command. Required iff the
+# intput is specified by COMMAND. A value of undef means that we
+# don't care about the exit status of a command. An integer
+# value is the ordinary exit status of a command. A string of
+# the form SIG:n indicates that the program has exited with
+# signal n.
+
+# THREAD_DATA: If specified, the test output is expected to
+# contain multithreaded output with output lines marked by thread
+# and sequence group identifiers. The value must be a hash that
+# contains required key TD_THREADS and optional key TD_SEQGROUPS.
+# The value of each key is an array reference containing a list
+# of threads or sequence groups as appropriate. When THREAD_DATA
+# is specified, the single call to runtest actually generates t +
+# s + 3 tests where "t" is the number of threads and "s" is the
+# number of sequence groups specified. See the documentation for
+# full details on how multithreaded output is handled by the test
+# driver.
+
+# flags: additional flags to control the test case; should be
+# logically orred together (e.g. NORMALIZE_WHITESPACE | EXPECT_FAILURE)
+
+# NORMALIZE_NEWLINES: If specified, all newlines or carriage
+# return/newline combinations in the input are translated to
+# straight UNIX-style newlines. This is done before writing
+# through any filter. Newlines are also normalized in the
+# expected output.
+
+# NORMALIZE_WHITESPACE: If specified, all carriage returns are
+# removed, and all strings of one or more space or tab characters
+# are replaced by a single space character in the input. This is
+# done before writing through any filter. The expected output
+# must be normalized in this way as well in order for the test to
+# pass.
+
+# EXPECT_FAILURE: If specified, the test case is expected to
+# fail. In this case, a test case failure will not generate
+# verbose output or cause overall test suite failure, and a pass
+# will generate test suite failure. This should be used for
+# place-holder test cases that exercise a known bug that cannot
+# yet be fixed.
+
+sub runtest
+{
+ my $rep = shift;
+
+ if (! ((@_ == 3) || (@_ == 4)))
+ {
+ croak +("Usage: ", +__PACKAGE__,
+ "->runtest(description, input, output[, flags])\n");
+ }
+
+ my ($description, $input, $output, $flags) = @_;
+ $flags = 0 unless defined $flags;
+
+ my $tempdir = $rep->_tempdir();
+
+ if (ref($description) ne '')
+ {
+ &QTC::TC("testdriver", "TestDriver description not string");
+ croak +__PACKAGE__, "->runtest: description must be a string\n";
+ }
+ if (ref($input) ne 'HASH')
+ {
+ &QTC::TC("testdriver", "TestDriver input not hash");
+ croak +__PACKAGE__, "->runtest: input must be a hash reference\n";
+ }
+ if (ref($output) ne 'HASH')
+ {
+ &QTC::TC("testdriver", "TestDriver output not hash");
+ croak +__PACKAGE__, "->runtest: output must be a hash reference\n";
+ }
+ if ((ref($flags) ne '') || ($flags !~ m/^\d+$/))
+ {
+ &QTC::TC("testdriver", "TestDriver flags not integer");
+ croak +__PACKAGE__, "->runtest: flags must be an integer\n";
+ }
+
+ my ($extra_in_keys, $in_string, $in_file, $in_command, $in_filter) =
+ check_hash_keys($input, $rep->STRING,
+ $rep->FILE, $rep->COMMAND, $rep->FILTER);
+ if ($extra_in_keys)
+ {
+ &QTC::TC("testdriver", "TestDriver extraneous input keys");
+ croak +(+__PACKAGE__,
+ "->runtest: extraneous keys in intput hash: $extra_in_keys\n");
+ }
+ my ($extra_out_keys, $out_string, $out_file, $out_regexp,
+ $out_exit_status, $thread_data) =
+ check_hash_keys($output, $rep->STRING,
+ $rep->FILE, $rep->REGEXP, $rep->EXIT_STATUS,
+ $rep->THREAD_DATA);
+ if ($extra_out_keys)
+ {
+ &QTC::TC("testdriver", "TestDriver extraneous output keys");
+ croak +(+__PACKAGE__,
+ "->runtest: extraneous keys in output hash: $extra_out_keys\n");
+ }
+
+ if ((((defined $in_string) ? 1 : 0) +
+ ((defined $in_file) ? 1 : 0) +
+ ((defined $in_command) ? 1 : 0)) != 1)
+ {
+ &QTC::TC("testdriver", "TestDriver invalid input");
+ croak +__PACKAGE__, "->runtest: exactly one of" .
+ " STRING, FILE, or COMMAND must be present for input\n";
+ }
+ if ((((defined $out_string) ? 1 : 0) +
+ ((defined $out_file) ? 1 : 0) +
+ ((defined $out_regexp) ? 1 : 0)) != 1)
+ {
+ &QTC::TC("testdriver", "TestDriver invalid output");
+ croak +__PACKAGE__, "->runtest: exactly one of" .
+ " STRING, FILE, or REGEXP must be present for output\n";
+ }
+ if ((defined $in_command) != (exists $output->{$rep->EXIT_STATUS}))
+ {
+ &QTC::TC("testdriver", "TestDriver invalid status");
+ croak +__PACKAGE__, "->runtest: input COMMAND and output EXIT_STATUS"
+ . " must either both appear both not appear\n";
+ }
+
+ my ($threads, $seqgroups) = (undef, undef);
+ if (defined $thread_data)
+ {
+ if (ref($thread_data) ne 'HASH')
+ {
+ &QTC::TC("testdriver", "TestDriver thread_data not hash");
+ croak +__PACKAGE__, "->runtest: THREAD_DATA" .
+ " must be a hash reference\n";
+ }
+ my $extra_thread_keys;
+ ($extra_thread_keys, $threads, $seqgroups) =
+ check_hash_keys($thread_data, $rep->TD_THREADS, $rep->TD_SEQGROUPS);
+ if ($extra_thread_keys)
+ {
+ &QTC::TC("testdriver", "TestDriver extraneous thread_data keys");
+ croak +(+__PACKAGE__,
+ "->runtest: extraneous keys in THREAD_DATA hash:" .
+ " $extra_thread_keys\n");
+ }
+ if (! defined $threads)
+ {
+ &QTC::TC("testdriver", "TestDriver thread_data no threads");
+ croak +__PACKAGE__, "->runtest: THREAD_DATA" .
+ " must contain TD_THREADS\n";
+ }
+ elsif (ref($threads) ne 'ARRAY')
+ {
+ &QTC::TC("testdriver", "TestDriver threads not array ref");
+ croak +__PACKAGE__, "->runtest: TD_THREADS" .
+ " must be an array reference\n";
+ }
+ if ((defined $seqgroups) && (ref($seqgroups) ne 'ARRAY'))
+ {
+ &QTC::TC("testdriver", "TestDriver seqgroups not array ref");
+ croak +__PACKAGE__, "->runtest: TD_SEQGROUPS" .
+ " must be an array reference\n";
+ }
+ }
+
+ # testnum is incremented by print_testid
+ my $testnum = $rep->_testnum();
+ my $category = $rep->_suitename();
+ $rep->print_testid($description);
+
+ # Open a file handle to read the raw (unfiltered) test input
+ my $pid = undef;
+ my $pid_killer = new TestDriver::PidKiller(\$pid);
+ my $in = new IO::Handle;
+ if (defined $in_string)
+ {
+ &QTC::TC("testdriver", "TestDriver input string");
+ open($in, '<', \$in_string) or
+ die +(+__PACKAGE__,
+ "->runtest: unable to read from input string: $!\n");
+ }
+ elsif (defined $in_file)
+ {
+ &QTC::TC("testdriver", "TestDriver input file");
+ open($in, '<', $in_file) or
+ croak +(+__PACKAGE__,
+ "->runtest: unable to read from input file $in_file: $!\n");
+ }
+ elsif (defined $in_command)
+ {
+ $pid = open($in, "-|");
+ croak +__PACKAGE__, "->runtest: fork failed: $!\n" unless defined $pid;
+ if ($pid == 0)
+ {
+ # child
+ open(STDERR, ">&STDOUT");
+ open(STDIN, '<', \ "");
+ if (ref($in_command) eq 'ARRAY')
+ {
+ &QTC::TC("testdriver", "TestDriver input command array");
+ exec @$in_command or
+ croak+(+__PACKAGE__,
+ "->runtest: unable to run command ",
+ join(' ', @$in_command), "\n");
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver input command string");
+ exec $in_command or
+ croak+(+__PACKAGE__,
+ "->runtest: unable to run command ",
+ $in_command, "\n");
+ }
+ }
+ }
+ else
+ {
+ die +__PACKAGE__, ": INTERNAL ERROR: invalid test input";
+ }
+ binmode $in;
+
+ # Open file handle into which to write the actual output
+ my $actual = new IO::File;
+ my $actual_file = "$tempdir/actual";
+ if (defined $in_filter)
+ {
+ &QTC::TC("testdriver", "TestDriver filter defined");
+ # Write through filter to actual file
+ open($actual, "| $in_filter > $actual_file") or
+ croak +(+__PACKAGE__, ": pipe to filter $in_filter failed: $!\n");
+ binmode $actual;
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver filter not defined");
+ open($actual, ">$actual_file") or
+ die +(+__PACKAGE__, ": write to $actual_file failed: $!\n");
+ binmode $actual;
+ }
+
+ # Write from input to actual output, normalizing spaces and
+ # newlines if needed
+ my $exit_status = undef;
+ while (1)
+ {
+ my ($line, $status) = read_line($in, $pid);
+ $exit_status = $status if defined $status;
+ last unless defined $line;
+ if ($flags & $rep->NORMALIZE_WHITESPACE)
+ {
+ &QTC::TC("testdriver", "TestDriver normalize whitespace");
+ $line =~ s/[ \t]+/ /g;
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver no normalize whitespace");
+ }
+ if ($flags & $rep->NORMALIZE_NEWLINES)
+ {
+ &QTC::TC("testdriver", "TestDriver normalize newlines");
+ $line =~ s/\r$//;
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver no normalize newlines");
+ }
+ $actual->print($line);
+ $actual->flush();
+ last if defined $exit_status;
+ }
+ $in->close();
+ if (defined $in_command)
+ {
+ if (! defined $exit_status)
+ {
+ $exit_status = $?;
+ }
+ if (($exit_status > 0) && ($exit_status < 256))
+ {
+ &QTC::TC("testdriver", "TestDriver exit status signal");
+ $exit_status &= 127; # clear core dump flag
+ $exit_status = "SIG:$exit_status";
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver exit status number");
+ $exit_status >>= 8;
+ }
+ }
+ $? = 0;
+ $actual->close();
+ $pid = undef;
+ if ($?)
+ {
+ die +(+__PACKAGE__,
+ "->runtest: failure closing actual output; status = $?\n");
+ }
+
+ # Compare exit statuses. This expression is always true when the
+ # input was not from a command.
+ my $status_match = ((! defined $out_exit_status) ||
+ ((defined $exit_status) &&
+ ($exit_status eq $out_exit_status)));
+
+ # Compare actual output with expected output.
+ my $expected_file = undef;
+ my $output_match = undef;
+ if (defined $out_string)
+ {
+ &QTC::TC("testdriver", "TestDriver output string");
+ # Write output string to a file so we can run diff
+ $expected_file = "$tempdir/expected";
+ my $e = new IO::File;
+ open($e, ">$expected_file") or
+ die +(__PACKAGE__,
+ "->runtest: unable to write to $expected_file: $!\n");
+ binmode $e;
+ $e->print($out_string);
+ $e->close();
+ }
+ elsif (defined $out_file)
+ {
+ &QTC::TC("testdriver", "TestDriver output file");
+ if ($flags & $rep->NORMALIZE_NEWLINES)
+ {
+ # Normalize newlines in expected output file
+ $expected_file = "$tempdir/expected";
+ unlink $expected_file;
+ my $in = new IO::File;
+ if (open($in, "<$out_file"))
+ {
+ binmode $in;
+ my $e = new IO::File;
+ open($e, ">$expected_file") or
+ die +(__PACKAGE__,
+ "->runtest: unable to write to $expected_file: $!\n");
+ binmode $e;
+ while (<$in>)
+ {
+ s/\r?$//;
+ $e->print($_);
+ }
+ $e->close();
+ $in->close();
+ }
+ }
+ else
+ {
+ $expected_file = $out_file;
+ }
+ }
+ elsif (defined $out_regexp)
+ {
+ &QTC::TC("testdriver", "TestDriver output regexp");
+ # No expected file; do regexp test to determine whether output
+ # matches
+ $actual = new IO::File;
+ open($actual, "<$actual_file") or
+ die +(__PACKAGE__,
+ "->runtest: unable to read $actual_file: $!\n");
+ binmode $actual;
+ local $/ = undef;
+ my $actual_output = <$actual>;
+ $actual->close();
+ $output_match = ($actual_output =~ m/$out_regexp/);
+ }
+ else
+ {
+ die +__PACKAGE__, ": INTERNAL ERROR: invalid test output";
+ }
+
+ my $output_diff = undef;
+ if (! defined $output_match)
+ {
+ if (! defined $expected_file)
+ {
+ die +__PACKAGE__, ": INTERNAL ERROR: expected_file not defined";
+ }
+ if (defined $threads)
+ {
+ # Real output comparisons are done later.
+ $output_match = 1;
+ }
+ else
+ {
+ $output_diff = "$tempdir/difference";
+ my $r = safe_pipe(['diff', '-a', '-u',
+ $expected_file, $actual_file],
+ $output_diff);
+ $output_match = ($r == 0);
+ }
+ }
+
+ my $outcome = ($output_match && $status_match) ? PASS : FAIL;
+ my $exp_outcome = (($flags & $rep->EXPECT_FAILURE) ? FAIL : PASS);
+ my $outcome_text = print_results($outcome, $exp_outcome);
+ my $passed = $rep->update_counters($outcome, $exp_outcome);
+
+ my $testxml = $rep->_testxml();
+ my $testlog = $rep->_testlog();
+ # $outcome_text is for the human-readable. We need something
+ # different for the xml file.
+ $testxml->print(" <testcase\n" .
+ " testid=\"$category $testnum\"\n" .
+ " description=\"$description\"\n" .
+ " outcome=\"" .
+ (($outcome eq PASS)
+ ? ($passed ? "pass" : "unexpected-pass")
+ : ($passed ? "expected-fail" : "fail")) .
+ "\"\n");
+
+ if (($outcome eq FAIL) && ($outcome ne $exp_outcome))
+ {
+ # Test failed and failure was not expected
+
+ $testxml->print(" >\n");
+ $testlog->printf("$category test %d (%s) FAILED\n",
+ $testnum, $description);
+ my $cwd = getcwd();
+ $testlog->print("cwd: $cwd\n");
+ $testxml->print(" <cwd>$cwd</cwd>\n");
+ my $cmd = $in_command;
+ if ((defined $cmd) && (ref($cmd) eq 'ARRAY'))
+ {
+ $cmd = join(' ', @$cmd);
+ }
+ if (defined $cmd)
+ {
+ $testlog->print("command: $cmd\n");
+ $testxml->print(" <command>$cmd</command>\n");
+ }
+ if (defined $out_file)
+ {
+ # Use $out_file, not $expected_file -- we are only
+ # interested in dispaying this information if the user's
+ # real output was original in a file.
+ $testlog->print("expected output in $out_file\n");
+ $testxml->print(
+ " <expected-output-file>$out_file</expected-output-file>\n");
+ }
+
+ # It would be nice if we could filter out internal calls for
+ # times when runtest is called inside of the module for
+ # multithreaded testing.
+ $testlog->print(Carp::longmess());
+
+ $testxml->print(" <stacktrace>test failure" .
+ Carp::longmess() .
+ "</stacktrace>\n");
+
+ if (! $status_match)
+ {
+ &QTC::TC("testdriver", "TestDriver status mismatch");
+ $testlog->printf("\tExpected status: %s\n", $out_exit_status);
+ $testlog->printf("\tActual status: %s\n", $exit_status);
+ $testxml->print(
+ " <expected-status>$out_exit_status</expected-status>\n");
+ $testxml->print(
+ " <actual-status>$exit_status</actual-status>\n");
+ }
+ if (! $output_match)
+ {
+ &QTC::TC("testdriver", "TestDriver output mismatch");
+ $testlog->print("--> BEGIN EXPECTED OUTPUT <--\n");
+ $testxml->print(" <expected-output>");
+ if (defined $expected_file)
+ {
+ write_file_to_fh($expected_file, $testlog);
+ xml_write_file_to_fh($expected_file, $testxml);
+ }
+ elsif (defined $out_regexp)
+ {
+ $testlog->print("regexp: " . $out_regexp);
+ if ($out_regexp !~ m/\n$/s)
+ {
+ $testlog->print("\n");
+ }
+ $testxml->print("regexp: " . $out_regexp);
+ }
+ else
+ {
+ die +(+__PACKAGE__,
+ "->runtest: INTERNAL ERROR: no expected output\n");
+ }
+ $testlog->print("--> END EXPECTED OUTPUT <--\n" .
+ "--> BEGIN ACTUAL OUTPUT <--\n");
+ $testxml->print("</expected-output>\n" .
+ " <actual-output>");
+ write_file_to_fh($actual_file, $testlog);
+ xml_write_file_to_fh($actual_file, $testxml);
+ $testlog->print("--> END ACTUAL OUTPUT <--\n");
+ $testxml->print("</actual-output>\n");
+ if (defined $output_diff)
+ {
+ &QTC::TC("testdriver", "TestDriver display diff");
+ $testlog->print("--> DIFF EXPECTED ACTUAL <--\n");
+ $testxml->print(" <diff-output>");
+ write_file_to_fh($output_diff, $testlog);
+ xml_write_file_to_fh($output_diff, $testxml);
+ $testlog->print("--> END DIFFERENCES <--\n");
+ $testxml->print("</diff-output>\n");
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver display no diff");
+ }
+ }
+ $testxml->print(" </testcase>\n");
+ }
+ else
+ {
+ $testxml->print(" />\n");
+ }
+
+ if (defined $threads)
+ {
+ if (! defined $expected_file)
+ {
+ &QTC::TC("testdriver", "TestDriver thread data but no exp output");
+ croak +(+__PACKAGE__,
+ "->runtest: thread data invalid".
+ " without fixed test output\n");
+ }
+
+ my $thread_expected = "$tempdir/thread-expected";
+ my $thread_actual = "$tempdir/thread-actual";
+ copy($actual_file, $thread_actual);
+ filter_seqgroups($expected_file, $thread_expected);
+
+ $passed =
+ $rep->analyze_thread_data($description,
+ $expected_file, $actual_file,
+ $threads, $seqgroups)
+ && $passed;
+
+ if ($passed)
+ {
+ $rep->runtest($description . ": all subcases passed",
+ {$rep->STRING => ""},
+ {$rep->STRING => ""});
+ }
+ else
+ {
+ $rep->runtest($description . ": original output",
+ {$rep->FILE => $thread_actual},
+ {$rep->FILE => $thread_expected});
+ }
+
+ unlink $thread_expected, $thread_actual;
+ }
+
+ $passed;
+}
+
+sub read_line
+{
+ my ($fh, $pid) = @_;
+ my $line = undef;
+ my $status = undef;
+
+ if (defined $pid)
+ {
+ # It doesn't work to just call <$fh> in this case. For some
+ # unknown reason, some programs occasionally exit and cause an
+ # interrupted system call return from read which perl just
+ # ignores, making the call to <$fh> hang. To protect
+ # ourselves, we explicitly check for the program having exited
+ # periodically if read hasn't returned anything.
+
+ while (1)
+ {
+ my $s = new IO::Select();
+ $s->add($fh);
+ my @ready = $s->can_read(1);
+ if (@ready == 0)
+ {
+ if (waitpid($pid, WNOHANG) > 0)
+ {
+ $status = $?;
+ last;
+ }
+ next;
+ }
+ else
+ {
+ my $buf = "";
+ my $status = sysread($fh, $buf, 1);
+ if ((defined $status) && ($status == 1))
+ {
+ $line = "" unless defined $line;
+ $line .= $buf;
+ last if $buf eq "\n";
+ }
+ else
+ {
+ last;
+ }
+ }
+ }
+ }
+ else
+ {
+ $line = <$fh>;
+ }
+ ($line, $status);
+}
+
+sub write_file_to_fh
+{
+ my ($file, $out) = @_;
+ my $in = new IO::File("<$file");
+ if (defined $in)
+ {
+ binmode $in;
+ my $ended_with_newline = 1;
+ while (<$in>)
+ {
+ $out->print($_);
+ $ended_with_newline = m/\n$/s;
+ }
+ if (! $ended_with_newline)
+ {
+ $out->print("[no newline at end of data]\n");
+ }
+ $in->close();
+ }
+ else
+ {
+ $out->print("[unable to open $file: $!]\n");
+ }
+}
+
+sub xml_write_file_to_fh
+{
+ my ($file, $out) = @_;
+ my $in = new IO::File("<$file");
+ if (defined $in)
+ {
+ binmode $in;
+ while (defined ($_ = <$in>))
+ {
+ s/\&/\&amp;/g;
+ s/</&lt;/g;
+ s/>/&gt;/g;
+ s/([\000-\011\013-\037\177-\377])/sprintf("&#x%02x;", ord($1))/ge;
+ $out->print($_);
+ }
+ $in->close();
+ }
+ else
+ {
+ $out->print("[unable to open $file: $!]");
+ }
+}
+
+sub check_hash_keys
+{
+ my ($hash, @keys) = @_;
+ my %actual_keys = ();
+ foreach my $k (keys %$hash)
+ {
+ $actual_keys{$k} = 1;
+ }
+ foreach my $k (@keys)
+ {
+ delete $actual_keys{$k};
+ }
+ my $extra_keys = join(', ', sort (keys %actual_keys));
+ ($extra_keys, (map { $hash->{$_} } @keys));
+}
+
+sub print_testid
+{
+ my $rep = shift;
+ my ($description) = @_;
+
+ my $testnum = $rep->_testnum();
+ my $category = $rep->_suitename();
+ print_and_pad(sprintf("$category %2d (%s)", $testnum, $description));
+ my $tc_filename = $ENV{'TC_FILENAME'} || "";
+ if ($tc_filename && open(F, ">>$tc_filename"))
+ {
+ printf F "# $category %2d (%s)\n", $testnum, $description;
+ close(F);
+ }
+ $rep->_testnum(++$testnum);
+}
+
+sub update_counters
+{
+ my $rep = shift;
+ my ($outcome, $exp_outcome) = @_;
+
+ (($outcome eq PASS) && ($exp_outcome eq PASS)) &&
+ $rep->{+__PACKAGE__}{$f_passes}++;
+ (($outcome eq PASS) && ($exp_outcome eq FAIL)) &&
+ $rep->{+__PACKAGE__}{$f_xpasses}++;
+ (($outcome eq FAIL) && ($exp_outcome eq PASS)) &&
+ $rep->{+__PACKAGE__}{$f_fails}++;
+ (($outcome eq FAIL) && ($exp_outcome eq FAIL)) &&
+ $rep->{+__PACKAGE__}{$f_xfails}++;
+
+ ($outcome eq PASS);
+}
+
+sub analyze_thread_data
+{
+ my $rep = shift;
+ my ($description, $expected, $actual,
+ $expected_threads, $expected_seqgroups) = @_;
+
+ my $tempdir = $rep->_tempdir();
+
+ my %actual_threads = ();
+ my %actual_seqgroups = ();
+ my @errors = ();
+
+ $rep->thread_cleanup();
+ $rep->split_combined($expected);
+ $rep->analyze_threaded_output
+ ($actual, \%actual_threads, \%actual_seqgroups, \@errors);
+
+ # Make sure we saw the right threads and sequences
+
+ my $desired = "threads:\n";
+ $desired .= join('', map { " $_\n" } (sort @$expected_threads));
+ $desired .= "sequence groups:\n";
+ if (defined $expected_seqgroups)
+ {
+ $desired .= join('', map { " $_\n" } (sort @$expected_seqgroups));
+ }
+
+ my $observed = "threads:\n";
+ $observed .= join('', map { " $_\n" } (sort keys %actual_threads));
+ $observed .= "sequence groups:\n";
+ $observed .= join('', map { " $_\n" } (sort keys %actual_seqgroups));
+
+ if (@errors)
+ {
+ $observed .= join('', @errors);
+ }
+
+ my $passed =
+ $rep->runtest("$description: multithreaded data",
+ {$rep->STRING => $observed},
+ {$rep->STRING => $desired});
+
+
+ foreach my $th (@{$expected_threads})
+ {
+ create_if_missing("$tempdir/$th.thread-actual",
+ "[no actual output]\n");
+ filter_seqgroups("$tempdir/$th.thread-expected",
+ "$tempdir/$th.thread-filtered");
+ $passed =
+ $rep->runtest($description . ": thread $th",
+ {$rep->FILE => "$tempdir/$th.thread-actual"},
+ {$rep->FILE => "$tempdir/$th.thread-filtered"})
+ && $passed;
+ }
+ if (defined $expected_seqgroups)
+ {
+ foreach my $sg (@{$expected_seqgroups})
+ {
+ create_if_missing("$tempdir/$sg.seq-actual",
+ "[no actual output]\n");
+ $passed =
+ $rep->runtest($description . ": seqgroup $sg",
+ {$rep->FILE => "$tempdir/$sg.seq-actual"},
+ {$rep->FILE => "$tempdir/$sg.seq-expected"})
+ && $passed;
+ }
+ }
+
+ $rep->thread_cleanup();
+
+ $passed;
+}
+
+sub analyze_threaded_output
+{
+ my $rep = shift;
+ my ($file, $threads, $seqgroups, $errors) = @_;
+ my $sequence_checking = 1;
+ open(F, "<$file") or die +__PACKAGE__, ": can't open $file: $!\n";
+ my $cur_thread = undef;
+ while (<F>)
+ {
+ if (m/^(\[\[(.+?)\]\]:)/)
+ {
+ my $tag = $1;
+ my $thread = $2;
+ my $rest = $'; #' [unconfuse emacs font lock mode]
+
+ $rep->handle_line($file, $., $tag, $thread, $rest,
+ \$sequence_checking, $threads, $seqgroups,
+ $errors);
+
+ $cur_thread = $thread;
+ }
+ else
+ {
+ $rep->handle_line($file, $., "", $cur_thread, $_,
+ \$sequence_checking, $threads, $seqgroups,
+ $errors);
+ }
+ }
+ close(F);
+}
+
+sub handle_line
+{
+ my $rep = shift;
+ my ($file, $lineno, $tag, $thread, $rest,
+ $sequence_checking, $threads, $seqgroups, $errors) = @_;
+
+ my $tempdir = $rep->_tempdir();
+
+ if (! exists $threads->{$thread})
+ {
+ my $fh = new IO::File("<$tempdir/$thread.thread-expected");
+ if (! $fh)
+ {
+ &QTC::TC("testdriver", "TestDriver no input file for thread");
+ $fh = undef;
+ $$sequence_checking = 0;
+ push(@$errors,
+ "$file:$.: no input file for thread $thread; " .
+ "sequence checking abandoned\n");
+ }
+ $threads->{$thread} = $fh;
+ }
+ my $known = defined($threads->{$thread});
+
+ my $seqs = "";
+ if ($$sequence_checking)
+ {
+ my $fh = $threads->{$thread};
+ my $next_input_line = scalar(<$fh>);
+ if (! defined $next_input_line)
+ {
+ $next_input_line = "[EOF]\n";
+ }
+ $seqs = $rep->strip_seqs(\$next_input_line);
+ if ($next_input_line eq $rest)
+ {
+ if ($seqs ne "")
+ {
+ $rep->handle_seqs($seqs, $tag . $rest, $seqgroups);
+ }
+ }
+ else
+ {
+ &QTC::TC("testdriver", "TestDriver thread mismatch");
+ $$sequence_checking = 0;
+ push(@$errors,
+ "$file:$.: thread $thread mismatch; " .
+ "sequencing checking abandoned\n" .
+ "actual $rest" .
+ "expected $next_input_line");
+ }
+ }
+ output_line("$tempdir/$thread.thread-actual", $rest);
+ if (! $known)
+ {
+ &QTC::TC("testdriver", "TestDriver output from unknown thread");
+ push(@$errors, "[[$thread]]:$rest");
+ }
+}
+
+sub strip_seqs
+{
+ my $rep = shift;
+ my $linep = shift;
+ my $seqs = "";
+ if ($$linep =~ s/^\(\(.*?\)\)//)
+ {
+ $seqs = $&;
+ }
+ $seqs;
+}
+
+sub handle_seqs
+{
+ my $rep = shift;
+ my ($seqs, $line, $seqgroups) = @_;
+ my $tempdir = $rep->_tempdir();
+ $seqs =~ s/^\(\((.*?)\)\)/$1/;
+ foreach my $seq (split(',', $seqs))
+ {
+ $seqgroups->{$seq} = 1;
+ output_line("$tempdir/$seq.seq-actual", $line);
+ }
+}
+
+sub filter_seqgroups
+{
+ my ($infile, $outfile) = @_;
+ open(F, "<$infile") or
+ die +__PACKAGE__, ": can't open $infile: $!\n";
+ binmode F;
+ open(O, ">$outfile") or
+ die +__PACKAGE__, ": can't create $outfile: $!\n";
+ binmode O;
+ while (<F>)
+ {
+ s/^((?:\[\[.+?\]\]:)?)\(\(.+?\)\)/$1/;
+ print O;
+ }
+ close(O);
+ close(F);
+}
+
+sub output_line
+{
+ my ($file, $line) = @_;
+ open(O, ">>$file") or die +__PACKAGE__, ": can't open $file: $!\n";
+ print O $line or die +__PACKAGE__, ": can't append to $file: $!\n";
+ close(O) or die +__PACKAGE__, ": close $file failed: $!\n";
+}
+
+sub create_if_missing
+{
+ my ($file, $line) = @_;
+ if (! -e $file)
+ {
+ open(O, ">$file") or die +__PACKAGE__, ": can't create $file: $!\n";
+ print O $line;
+ close(O);
+ }
+}
+
+sub split_combined
+{
+ my $rep = shift;
+ my $combined = shift;
+ my $tempdir = $rep->_tempdir();
+
+ open(C, "<$combined") or die +__PACKAGE__, ": can't open $combined: $!\n";
+ my %files = ();
+ my $last_thread_fh = undef;
+ while (<C>)
+ {
+ my $thread_fh = $last_thread_fh;
+ my $thread_out = undef;
+ if (m/^(\[\[(.+?)\]\]:)(\(\((.+?)\)\))?(.*\n?)$/)
+ {
+ my $thread_full = $1;
+ my $thread = $2;
+ my $seq_full = $3;
+ my $seq = $4;
+ my $rest = $5;
+ my $seq_out = undef;
+ $thread_out = $rest;
+
+ my @seq_files = ();
+ my $thread_file = "$tempdir/$thread.thread-expected";
+ if (defined $seq_full)
+ {
+ $thread_out = $seq_full . $thread_out;
+ $seq_out = $thread_full . $rest;
+ foreach my $s (split(/,/, $seq))
+ {
+ my $f = "$tempdir/$s.seq-expected";
+ my $fh = cache_open(\%files, $f);
+ $fh->print($seq_out);
+ }
+ }
+
+ $thread_fh = cache_open(\%files, $thread_file);
+ }
+ else
+ {
+ $thread_out = $_;
+ }
+ if ((defined $thread_out) && (! defined $thread_fh))
+ {
+ die +__PACKAGE__, ": no place to put output lines\n";
+ }
+ $thread_fh->print($thread_out) if defined $thread_out;
+ $last_thread_fh = $thread_fh;
+ }
+ close(C);
+ map { $_->close() } (values %files);
+}
+
+sub cache_open
+{
+ my ($cache, $file) = @_;
+ if (! defined $file)
+ {
+ return undef;
+ }
+ if (! exists $cache->{$file})
+ {
+ unlink $file;
+ my $fh = new IO::File(">$file") or
+ die +__PACKAGE__, ": can't open $file: $!\n";
+ $cache->{$file} = $fh;
+ }
+ $cache->{$file};
+}
+
+sub thread_cleanup
+{
+ my $rep = shift;
+ my $dir = $rep->_tempdir();
+ my @files = +(grep { m/\.(thread|seq)-(actual|expected|filtered)$/ }
+ (glob("$dir/*")));
+ if (@files)
+ {
+ unlink @files;
+ }
+}
+
+sub rmrf
+{
+ my $path = shift;
+ return unless -e $path;
+ my $wanted = sub
+ {
+ if ((-d $_) && (! -l $_))
+ {
+ rmdir $_ or die "rmdir $_ failed: $!\n";
+ }
+ else
+ {
+ unlink $_ or die "unlink $_ failed: $!\n";
+ }
+ };
+ finddepth({wanted => $wanted, no_chdir => 1}, $path);
+}
+
+sub safe_pipe
+{
+ my ($cmd, $outfile) = @_;
+ my $pid = open(C, "-|");
+ my $result = 0;
+
+ if ($pid)
+ {
+ # parent
+ my $out = new IO::File(">$outfile") or
+ die +__PACKAGE__, ": can't open $outfile: $!\n";
+ binmode C;
+ while (<C>)
+ {
+ $out->print($_);
+ }
+ close(C);
+ $result = $?;
+ $out->close();
+ }
+ else
+ {
+ # child
+ open(STDERR, ">&STDOUT");
+ exec(@$cmd) || die +__PACKAGE__, ": $cmd->[0] failed: $!\n";
+ }
+
+ $result;
+}
+1;
+
+#
+# END OF TestDriver
+#
diff --git a/zlib-flate/Makefile b/zlib-flate/Makefile
new file mode 100644
index 00000000..90899055
--- /dev/null
+++ b/zlib-flate/Makefile
@@ -0,0 +1 @@
+include ../make/proxy.mk
diff --git a/zlib-flate/build.mk b/zlib-flate/build.mk
new file mode 100644
index 00000000..57d2c98c
--- /dev/null
+++ b/zlib-flate/build.mk
@@ -0,0 +1,22 @@
+TARGETS_zlib-flate = \
+ zlib-flate/$(OUTPUT_DIR)/zlib-flate
+
+$(TARGETS_zlib-flate): $(TARGETS_libqpdf)
+
+INCLUDES_zlib-flate = include
+
+SRCS_zlib-flate = zlib-flate/zlib-flate.cc
+
+# -----
+
+OBJS_zlib-flate = $(call src_to_obj,$(SRCS_zlib-flate))
+
+ifeq ($(GENDEPS),1)
+-include $(call obj_to_dep,$(OBJS_zlib-flate))
+endif
+
+$(OBJS_zlib-flate): zlib-flate/$(OUTPUT_DIR)/%.o: zlib-flate/%.cc
+ $(call compile,$<,$(INCLUDES_zlib-flate))
+
+zlib-flate/$(OUTPUT_DIR)/zlib-flate: $(OBJS_zlib-flate)
+ $(call makebin,$(OBJS_zlib-flate),$@)
diff --git a/zlib-flate/qtest/1.compressed b/zlib-flate/qtest/1.compressed
new file mode 100644
index 00000000..3d05ab1c
--- /dev/null
+++ b/zlib-flate/qtest/1.compressed
Binary files differ
diff --git a/zlib-flate/qtest/1.uncompressed b/zlib-flate/qtest/1.uncompressed
new file mode 100644
index 00000000..0446561f
--- /dev/null
+++ b/zlib-flate/qtest/1.uncompressed
@@ -0,0 +1,5 @@
+Once upon a time there lived three qowws. They didn't like poridge
+much, so they had salad for breakfast. Goldilocks, upon breaking and
+entering, found this to be distasteful and so she just went away
+without eating any. This somewhat short-circuited the story. The
+End.
diff --git a/zlib-flate/qtest/zf.test b/zlib-flate/qtest/zf.test
new file mode 100644
index 00000000..39271e16
--- /dev/null
+++ b/zlib-flate/qtest/zf.test
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+require 5.008;
+BEGIN { $^W = 1; }
+use strict;
+
+require TestDriver;
+
+my $td = new TestDriver('zlib-flate');
+
+$td->runtest("compress",
+ {$td->COMMAND => "zlib-flate -compress < 1.uncompressed"},
+ {$td->FILE => "1.compressed",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("uncompress",
+ {$td->COMMAND => "zlib-flate -uncompress < 1.compressed"},
+ {$td->FILE => "1.uncompressed",
+ $td->EXIT_STATUS => 0});
+
+$td->runtest("error",
+ {$td->COMMAND => "zlib-flate -uncompress < 1.uncompressed"},
+ {$td->REGEXP => "flate: inflate: data: .*\n",
+ $td->EXIT_STATUS => 2},
+ $td->NORMALIZE_NEWLINES);
+
+$td->report(3);
diff --git a/zlib-flate/zlib-flate.cc b/zlib-flate/zlib-flate.cc
new file mode 100644
index 00000000..33a3cdd9
--- /dev/null
+++ b/zlib-flate/zlib-flate.cc
@@ -0,0 +1,92 @@
+
+#include <qpdf/Pl_Flate.hh>
+#include <qpdf/Pl_StdioFile.hh>
+
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char const* whoami = 0;
+
+void usage()
+{
+ std::cerr << "Usage: " << whoami << " { -uncompress | -compress }"
+ << std::endl;
+ exit(2);
+}
+
+int main(int argc, char* argv[])
+{
+ if ((whoami = strrchr(argv[0], '/')) == NULL)
+ {
+ whoami = argv[0];
+ }
+ else
+ {
+ ++whoami;
+ }
+ // For libtool's sake....
+ if (strncmp(whoami, "lt-", 3) == 0)
+ {
+ whoami += 3;
+ }
+
+ if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
+ {
+ std::cout << whoami << " version 1.0" << std::endl;
+ exit(0);
+ }
+
+ if (argc != 2)
+ {
+ usage();
+ }
+
+ Pl_Flate::action_e action = Pl_Flate::a_inflate;
+
+ if ((strcmp(argv[1], "-uncompress") == 0))
+ {
+ // okay
+ }
+ else if ((strcmp(argv[1], "-compress") == 0))
+ {
+ action = Pl_Flate::a_deflate;
+ }
+ else
+ {
+ usage();
+ }
+
+ Pl_StdioFile* out = new Pl_StdioFile("stdout", stdout);
+ Pl_Flate* flate = new Pl_Flate("flate", out, action);
+
+ try
+ {
+ unsigned char buf[10000];
+ bool done = false;
+ while (! done)
+ {
+ int len = read(0, buf, sizeof(buf));
+ if (len <= 0)
+ {
+ done = true;
+ }
+ else
+ {
+ flate->write(buf, len);
+ }
+ }
+ flate->finish();
+ delete flate;
+ delete out;
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ exit(2);
+ }
+
+ return 0;
+}