diff options
author | Karl Berry <karl@freefriends.org> | 2006-07-09 22:44:40 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-07-09 22:44:40 +0000 |
commit | 6684474324a04b457fe7019684c42eb68c4fea4b (patch) | |
tree | 63f0520f448252eb06342d5e0ea8e700c4976136 /Build | |
parent | bb92d19047f4437f2d13091072ec63a5641dc43c (diff) |
new graphics utility sam2p
git-svn-id: svn://tug.org/texlive/trunk@1792 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
151 files changed, 53967 insertions, 8 deletions
diff --git a/Build/source/Build b/Build/source/Build index 7c093740d99..9f73dd74133 100755 --- a/Build/source/Build +++ b/Build/source/Build @@ -21,8 +21,8 @@ cd Work || exit 1 rm -f tlbuild.log # Force building xdvi-xaw; motif is not always free and/or available. -# -(time ../configure --prefix=$H/inst --datadir=$H/inst \ - --with-xdvi-x-toolkit=xaw \ +# --enable-gif is for sam2p; the gif patent has expired worldwide. +(set -x; time ../configure --prefix=$H/inst --datadir=$H/inst \ + --with-xdvi-x-toolkit=xaw --enable-gif \ "$@" \ && time make world) 2>&1 | tee tlbuild.log diff --git a/Build/source/configure b/Build/source/configure index 7d61a8da2ee..a8b49f29894 100755 --- a/Build/source/configure +++ b/Build/source/configure @@ -4374,15 +4374,21 @@ test "$needs_freetype" = yes && test "$using_system_freetype" != yes \ subdirs="$subdirs libs" -PKGS='dialog lcdf-typetools pdfopen psutils t1utils texi2html texinfo' +PKGS='dialog lcdf-typetools pdfopen psutils sam2p t1utils texi2html texinfo' ESUBDIRS= +test -d utils || mkdir utils for pkg in $PKGS; do if test -d $srcdir/utils/$pkg; then if eval "test \"`echo '$with_'${pkg}`\" != no"; then ESUBDIRS="$ESUBDIRS utils/$pkg" + if test $pkg = sam2p; then + # this is a terrible kludge, but sam2p configure actively + # defeats srcdir!=objdir support, and Peter S. doesn't want to + # fix it. So copy the entire sam2p srcdir into objdir. + rm -rf utils/sam2p + cp -pr $srcdir/utils/sam2p utils + fi subdirs="$subdirs utils/$pkg" - - test -d utils || mkdir utils fi fi done diff --git a/Build/source/configure.in b/Build/source/configure.in index 97ff6747b2a..89d3c2ca62b 100644 --- a/Build/source/configure.in +++ b/Build/source/configure.in @@ -192,14 +192,21 @@ test "$needs_freetype" = yes && test "$using_system_freetype" != yes \ AC_CONFIG_SUBDIRS([libs]) -PKGS='dialog lcdf-typetools pdfopen psutils t1utils texi2html texinfo' +PKGS='dialog lcdf-typetools pdfopen psutils sam2p t1utils texi2html texinfo' ESUBDIRS= +test -d utils || mkdir utils for pkg in $PKGS; do if test -d $srcdir/utils/$pkg; then if eval "test \"`echo '$with_'${pkg}`\" != no"; then ESUBDIRS="$ESUBDIRS utils/$pkg" + if test $pkg = sam2p; then + # this is a terrible kludge, but sam2p configure actively + # defeats srcdir!=objdir support, and Peter S. doesn't want to + # fix it. So copy the entire sam2p srcdir into objdir. + rm -rf utils/sam2p + cp -pr $srcdir/utils/sam2p utils + fi AC_CONFIG_SUBDIRS([utils/$pkg]) - test -d utils || mkdir utils fi fi done diff --git a/Build/source/utils/sam2p/COPYING b/Build/source/utils/sam2p/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/Build/source/utils/sam2p/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Build/source/utils/sam2p/Makefile b/Build/source/utils/sam2p/Makefile new file mode 100644 index 00000000000..fe2394e3994 --- /dev/null +++ b/Build/source/utils/sam2p/Makefile @@ -0,0 +1,160 @@ +# +# Makefile +# by pts@fazekas.hu at Sun Feb 24 16:20:15 CET 2002 +# Sat Apr 20 19:14:11 CEST 2002 +# ccdep.pl at Sat Jun 1 15:51:36 CEST 2002 +# +# To create a .tar.gz, run: make MAKE_DIST=0 dist-noautoconf +# To install dist: make MAKE_DIST=0 dist-install +# + +ifndef MAKE_DIST +include Makehelp +endif + +BASH=bash +PERL_BADLANG=x +export PERL_BADLANG + +CXXX=$(CXD_assert) +LDALL=$(LDXX) -s $(LDFLAGS) $(LIBS) +ifeq ($(ENABLE_DEBUG), no) +CXXX=$(CXD_no) +endif +ifeq ($(ENABLE_DEBUG), yes) +CXXX=$(CXD_yes) +LDALL=$(LDXX) $(LDFLAGS) $(LIBS) +endif +ifeq ($(ENABLE_DEBUG), checker) +CXXX=$(CXD_checker) +LDALL=checkerg++ $(LDFLAGS) $(LIBS) +endif + +CXXALL=$(CXXX) $(CXXFLAGS) $(CXXFLAGSB) +CCALL =$(CXXX) $(CXXFLAGS) $(CXXFLAGSB) +CXDFAL=$(CXXFLAGS) $(CXXFLAGSB) $(LDFLAGS) $(LIBS) + +.PHONY: clean dist dist-noautoconf dist-more allclean distclean dist-install +.PHONY: most all all1 install + +ifndef MAKE_DIST + most all: sam2p + Makedep: ccdep.pl config.h; perl -x -S ./ccdep.pl --FAL=assert,no,yes,checker $(CXX) + include Makedep +endif + +all1: $(ALL) +# vvv for Epsilon at Thu Oct 31 09:58:58 CET 2002 +IDE_MODES := release debug +IDE_TARGETS_debug := $(patsubst %,%.yes, $(TARGETS)) +IDE_TARGETS_release := $(TARGETS) + +CXD_assert =$(CXX) -s -O2 +CXD_no =$(CXX) -s -DNDEBUG -O3 +# CXD_yes =$(CXX) $(GFLAG) -lefence +CXD_yes =$(CXX) $(GFLAG) +CXD_checker=checkerg++ $(GFLAG) + +# .PHONY: clean dist allclean distclean + +Makedep: config.h + +xpmc.h: cols2.pl + perl -x cols2.pl >xpmc.h + +#HQ=perl -e'$$_=join"",<STDIN>; s@([^\w\.\/\-])@sprintf"\\%03o",ord$$1@ge; print "\"$$_\"\n"' +HQ=perl -x hq.pl +#%.tth: %.tte +# <$< >$@ $(HQ) +#%.tth: %.ttm +# <$< >$@ $(HQ) +%.tth: %.ttt + $(HQ) <$< >$@ + +# Sun Sep 22 01:16:20 CEST 2002 +L1_LIST=l1g8z.pst l1ghz.pst l1gbz.pst \ + l1g8l.pst l1ghl.pst l1gbl.pst +PREPROC_STRIP=perl -ne's@/\s+(?=\w)@/@g;print if!/^\#/&&!/^\s*\Z/' +L1_FLAGS=-DCFG_FMT_ZLIB_ONLY=1 -DNDEBUG=1 \ + -DCFG_NO_VAR_S=1 -DUSE_NO_BIND=1 -DUSE_SHORT_NAMES=1 \ + -DUSE_CURRENTFILE=1 -DUSE_NO_EOF=1 \ + -DUSE_UNITLENGTH_8 -DUSE_EARLYCHANGE_1 -DUSE_LOWBITFIRST_FALSE \ + -DUSE_NO_NULLDEF=1 -DUSE_PIN=1 +# TTT_QUOTE=perl -e '$$s=$$_=join"",<STDIN>; s@%.*@@g; s@[(][^()]*[)]@@g; die if /[()\\]/ or $$ARGV[0]!~/^(\w+)/; print "\n% TTT_QUOTE\n/$$1 ($$s)\n\n"' -- +TTT_QUOTE=perl -e '$$s=$$_=join"",<STDIN>; $$s=~s@([()\\])@\\$$1@g; die if $$ARGV[0]!~/^(\w+)/; print "\n% TTT_QUOTE\n/$$1 ($$s)\n\n"' -- +# vvv Dat: input file for `g++ -E' must have .h extension +l1g8z.pst: l1zip.psm psmlib.psm ps_tiny + <$< >tmp.h perl -pe0 + $(CXX) -E $(L1_FLAGS) -DUSE_A85D=1 tmp.h >tmp.i + <tmp.i >tmp.pin $(PREPROC_STRIP) + <tmp.pin >tmp.ps0 ./ps_tiny + <tmp.ps0 >tmp.pst $(TTT_QUOTE) $@ + mv -f tmp.pst $@ +l1ghz.pst: l1zip.psm psmlib.psm ps_tiny + <$< >tmp.h perl -pe0 + $(CXX) -E $(L1_FLAGS) -DUSE_HEXD=1 tmp.h >tmp.i + <tmp.i >tmp.pin $(PREPROC_STRIP) + <tmp.pin >tmp.ps0 ./ps_tiny + <tmp.ps0 >tmp.pst $(TTT_QUOTE) $@ + mv -f tmp.pst $@ +l1gbz.pst: l1zip.psm psmlib.psm ps_tiny + <$< >tmp.h perl -pe0 + $(CXX) -E $(L1_FLAGS) -DUSE_BINARY=1 tmp.h >tmp.i + <tmp.i >tmp.pin $(PREPROC_STRIP) + <tmp.pin >tmp.ps0 ./ps_tiny + <tmp.ps0 >tmp.pst $(TTT_QUOTE) $@ + mv -f tmp.pst $@ +l1g8l.pst: l1lzw.psm psmlib.psm ps_tiny + <$< >tmp.h perl -pe0 + $(CXX) -E $(L1_FLAGS) -DUSE_A85D=1 tmp.h >tmp.i + <tmp.i >tmp.pin $(PREPROC_STRIP) + <tmp.pin >tmp.ps0 ./ps_tiny + <tmp.ps0 >tmp.pst $(TTT_QUOTE) $@ + mv -f tmp.pst $@ +l1ghl.pst: l1lzw.psm psmlib.psm ps_tiny + <$< >tmp.h perl -pe0 + $(CXX) -E $(L1_FLAGS) -DUSE_HEXD=1 tmp.h >tmp.i + <tmp.i >tmp.pin $(PREPROC_STRIP) + <tmp.pin >tmp.ps0 ./ps_tiny + <tmp.ps0 >tmp.pst $(TTT_QUOTE) $@ + mv -f tmp.pst $@ +l1gbl.pst: l1lzw.psm psmlib.psm ps_tiny + <$< >tmp.h perl -pe0 + $(CXX) -E $(L1_FLAGS) -DUSE_BINARY=1 tmp.h >tmp.i + <tmp.i >tmp.pin $(PREPROC_STRIP) + <tmp.pin >tmp.ps0 ./ps_tiny + <tmp.ps0 >tmp.pst $(TTT_QUOTE) $@ + mv -f tmp.pst $@ +# vvv copy the .ttt, not the .tth +# The perl program down there is a portable cat(1) implementation. +bts1.ttt: bts.ttt $(L1_LIST) + perl -pe0 $^ >$@ +bts2.ttt: bts1.ttt ps_tiny + ./ps_tiny --copy <$< >$@ + +clean: + rm -f *~ a.out DEADJOE core *.o *.tth .rgd *.rgd tmp.pin tmp.i tmp.ps0 tmp.h tmp.pst autom4te.cache/* + rm -f debian/changelog.dch debian/*~ + rm -f $(ALL) $(ALL:=.yes) $(ALL:=.no) $(ALL:=.assert) $(ALL:=.checker) + -rmdir -- autom4te.cache +allclean: clean + rm -f configure config.h Makehelp config.cache config.log \ + config.status test.eps test.pdf build build-stamp +distclean: allclean + -autoconf +dist: distclean dist-noautoconf +dist-noautoconf: + chmod 755 configure + $(BASH) mkdist.sh +# vvv Create a distribution with more files to aid compilation +dist-more: bts2.tth + $(BASH) mkdist.sh sam2p-more bts2.tth +dist-install: dist-noautoconf + chmod 600 ../sam2p-*.tar.gz + scp ../sam2p-*.tar.gz kozma:public_html + +install: sam2p + -mkdir -p '$(bindir)' + cp -a sam2p '$(bindir)' + +# __END__ of Makefile diff --git a/Build/source/utils/sam2p/Makehelp.in b/Build/source/utils/sam2p/Makehelp.in new file mode 100644 index 00000000000..638345a5abf --- /dev/null +++ b/Build/source/utils/sam2p/Makehelp.in @@ -0,0 +1,9 @@ +CXX=@CXX@ +LDXX=@LDXX@ +CXXFLAGS=-DHAVE_CONFIG2_H @CXXFLAGS@ +CXXFLAGSB=@CXXFLAGSB@ +ENABLE_DEBUG=@ENABLE_DEBUG@ +GFLAG=@GFLAG@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ diff --git a/Build/source/utils/sam2p/README b/Build/source/utils/sam2p/README new file mode 100644 index 00000000000..8d42d5d60a9 --- /dev/null +++ b/Build/source/utils/sam2p/README @@ -0,0 +1,2979 @@ +README for sam2p +by pts@fazekas.hu +at Sun Dec 30 19:30:17 CET 2001 -- Fri Mar 22 19:25:03 CET 2002 +Sat Apr 27 00:39:12 CEST 2002 +Wed Jul 3 01:20:40 CEST 2002 +Wed Feb 5 19:46:51 CET 2003 +grammatical corrections by Steve Turner at Mon Jan 10 00:53:46 CET 2005 + +This is the README file for sam2p, a raster to PostScript/PDF image +conversion program. This file contains a 5-minute turbo tutorial for new and +impatient users (search for the phrase `Turbo tutorial' in your text editor). +As of now, this README file is the only, and definitive, documentation of sam2p. + +sam2p is a UNIX command line utility written in ANSI C++ that converts many +raster (bitmap) image formats into Adobe PostScript or PDF files and several +other formats. The images are not vectorized. sam2p gives full control to +the user to specify standards-compliance, compression, and bit depths. In +some cases sam2p can compress an image 100 times smaller than the PostScript +output of many other common image converters. sam2p provides ZIP, RLE and +LZW (de)compression filters even on Level1 PostScript devices. + +A testimonial from Grant Ingram, UK: Anyway this is just a quick note to say +thanks for writing the sam2p utility which I am using to create EPS figures +of photographs for my thesis -- it works very well producing image sizes +that are some 3% of the ones produced by ImageMagick. + +Does sam2p generate small EPS (and PDF) files? +A testimonial from Tom Schneider, US: + + -rw------- 1 toms delila 88628 Mar 3 17:38 prototype-small.eps + -rw------- 1 toms delila 7979299 Feb 24 12:25 prototype.eps + + Good GRIEF you have written a nice program!!!! The file is 90 fold + smaller than the one from Imagemagick's convert. + + That image that was 90x smaller had been bugging me because it was so + large that xdvi would strongly hesitate while I passed by the page. + Now it just has a minor delay, thanks to you. + +Many thanks to Steve Turner for reviewing and making corrections to this +documentation. + +The author of sam2p recommends his program over other image converters +because of the following reasons: + +-- sam2p produces much smaller output +-- sam2p gives the user complete control over the data layout of the output + image. This includes Compression, SampleFormat and TransferEncoding. +-- sam2p is fast +-- sam2p doesn't depend on external libraries. (But it does depend on external + programs for _reading_ JPEG, TIFF and PNG files.) +-- sam2p supports the mainstream image formats of today without compromise. + sam2p has many file format fine-tuning features that are missing from + most other converter utilities. For example: + TIFF ZIP compression, TIFF LZW compression, TIFF + JPEG compression, transparent PNG files, BMP RLE-4 and RLE-8 + compression, etc. +-- sam2p supports all levels (versions) of the PostScript language and + output images have the smallest file size allowed by the LanguageLevel. +-- PostScript ZIP, RLE and LZW compression is provided for _all_ + LanguageLevels (!), even for PSL1 (which appeared in 1980). You can print + your ZIP-compressed images onto your ancient printer of the 1980s. +-- sam2p supports all versions of PDF, and as with PostScript, + output images have the smallest file size allowed by the version. +-- output images of sam2p are always compliant to the standard selected by + the user +-- output images of sam2p are real-world compatible, i.e the author has + tested them with many common image processing programs, for example: + Ghostscript, pdfTeX, xpdf, Acrobat Reader, The GIMP, ImageMagick, xv, + Acrobat Distiller, QuarkXPress, InDesign. The author has also tested + PostScript files on HP and OkiData printers. +-- sam2p converts every pixel faithfully, preserving all the 24 RGB bits + intact. There is no quality or information loss unless you ask for it. +-- sam2p uses only a minimal number of libraries. You don't have to install + 33Mb of ballast software to use sam2p. Image libraries (libtiff etc.) are + _not_ used, the math library is not used, libstdc++ is not used, zlib is + not used. + +Long-term limitations: + +-- only DeviceRGB color space, with the Indexed, Gray and RGB image types +-- Indexed images are limited to a maximum of 256 colors +-- alpha channel and transparency supported only for Indexed images: only + one color may be transparent +-- the entire input image is read into memory. During operation both the + input and the output images may be held in memory. + +Status +~~~~~~ +sam2p is currently beta software. It is available from: + + http://www.inf.bme.hu/~pts/sam2p/ + http://www.inf.bme.hu/~pts/sam2p-latest.tar.gz + http://sam2p.sf.net/ + +The documentation is incomplete, but -- together with the examples -- it is +quite useful. Please have a look at the home page to find articles and more +documentation (the PDF docs are much more eye-pleasing than this README). +The source code contains valuable comments, but they may be hard to find +unless you're deeply into developing sam2p. + +The author is developing sam2p in his free time. (He is studying and +working in non-free time.) + +The imaging model is complete. Image output routines are stable and +adequate. Reasonable defaults are provided for all command line options. +sam2p can usually find the best SampleFormat automatically. There is +an educated (but not perfect) default guess for the Compression. + +See subsection {OutputRule combinations} about all planned formats. + +The most important short-term limitations: + +-- The code hasn't been extensively tested. The author welcomes bug reports. +-- The code hasn't been profiled for speed bottlenecks. (Although it seems + to be faster than ImageMagick convert(1) in most situations.) + +Turbo tutorial +~~~~~~~~~~~~~~ +Quick compilation instructions: + +1. ./configure --enable-lzw --enable-gif +2. make +3. Copy the `sam2p' executable to your $PATH, or invoke it as `./sam2p'. + +Quick try: + +-- ./sam2p examples/pts2.pbm try.eps +-- ./sam2p examples/pts2.pbm try.pdf +-- ./sam2p examples/pts2.pbm try.ps +-- ./sam2p examples/pts2.pbm try.png +-- ./sam2p examples/pts2.pbm try.tiff +-- ./sam2p examples/pts2.pbm try.xpm +-- ./sam2p examples/pts2.pbm try.bmp +-- ./sam2p examples/pts2.pbm try.jpg + +A really short User's guide +""""""""""""""""""""""""""" +To convert an image, call: + + ./sam2p <INPUT.IMG> <OUTPUT.IMG> + Example: ./sam2p examples/pts2.pbm try.eps + +To print an image as a full PostScript page, call: + + ./sam2p [MARGIN-SPECS] <INPUT.IMG> ps: - | lpr + Example: ./sam2p -m:1cm examples/pts2.pbm ps: - | lpr + +To convert an image to be included as EPS (Encapsulated PostScript) into +(La)TeX documents, call: + + ./sam2p <INPUT.IMG> <OUTPUT.eps> + Example: ./sam2p examples/pts2.pbm test.eps + In file.tex: \usepackage{graphicx} ... \includegraphics{test} + +To convert an image to be included as PDF into pdf(La)TeX documents, call: + + ./sam2p <INPUT.IMG> <OUTPUT.pdf> + Example: ./sam2p examples/pts2.pbm test.pdf + In file.tex: \usepackage{graphicx} ... \includegraphics{test} + +If you have a large image file (possibly originating from dumb software), +you can reduce the image size and keep the same filename. (Please note that +some meta-information may be lost using this method.) This operation is +_DANGEROUS_ if you don't have a backup, because due to a software or +hardware problem, sam2p might clobber time image file so the actual image +gets lost. To overwrite a file in-place, call: + + ./sam2p <INPUT-OUTPUT.IMG> -- + Example: ./sam2p test.tiff -- + +You may specify a compression method (or supply other command line options) +to make a file even smaller, call: + + ./sam2p [OPTIONS] <INPUT.IMG> <OUTPUT.IMG> + Example: ./sam2p -c:zip test.tiff test2.tiff + +See the detailed documentation of available command-line options elsewhere +in this document. You may also read section {FAQ} for more information. + +Too see a list about the supported input and output image file formats, call: + + ./sam2p + +Example output: + + This is sam2p v0.39. + Available Loaders: JAI PNG JPEG TIFF PNM BMP GIF LBM XPM PCX TGA. + Available Appliers: XWD Meta Empty BMP PNG TIFF6 TIFF6-JAI JPEG-JAI JPEG PNM GIF89a XPM PSL1C PSL23+PDF PDF-JAI PSL2-JAI l1fa85g P-TrOpBb. + Usage: [...] + +The list of ``Available Loaders'' lists the input image file formats. All +except for JAI are self-explanatory. JAI is JPEG-as-is, it means reading a +JPEG file and writing back the exactly same image into an other JPEG variant, +without quality loss. + +From the list of ``Available Appliers'' one can derive the supported output +image file formats. XWD, BMP, PNG, TIFF6, JPEG, PNM, GIF89a and XPM are +self-explanatory. TIFF6-JAI, JPEG-JAI, PDF-JAI and PSL2-JAI are JPEG +variants into which JAI files (see above) can be saved. While the names of +the remaining appliers may be quite cryptic to the beginner user; most of +those appliers provide sam2p's excellent support for writing PS, EPS and +PDF files. + +sam2p operation modes +~~~~~~~~~~~~~~~~~~~~~ +sam2p is a command line utility (i.e, without a graphical user +interface), so it can be used by composing a command line with the +appropriate options and parameters, and launching it. See sections ``Turbo +tutorial'' and ``One-liner mode'' for more details. + +sam2p is not interactive, it doesn't ask questions; thus it is completely +suitable for batch processing and automation. sam2p doesn't log errors, but +its STDERR can be redirected to a log file quite easily. + +There are three modes sam2p can operate in: + +-- one-liner mode: (since sam2p 0.37) + the user, perhaps, has to type a long command line, specifying the input + and the output file name, output file format, compression options, etc. + Most of the functionality of sam2p is available in a quite intuitive way + in one-liner mode. Users of the `convert' utility from ImageMagick and + `tiff2ps' and `tiffcp' will find that one-liner mode of sam2p is very + similar to them. This mode is recommended for impatient users. + + Due to the nature of sam2p development, some new functionality of job mode + might be missing from one-liner mode. Please report this as a bug. + +-- job mode: the user has to write a ``job'' file (recommended extension: + .job), which specifies all conversion parameters, including the input and + output file name. The name of the job file must be passed to sam2p. This + mode is recommended for expert users who want to retain full control of + all aspects of the final output. All functionality is available in job + mode. This is especially useful in repetative but time separated jobs. + +-- GUI mode: This is completely experimental, and will be very probably + dropped in the near future. Try executing sam2p.tk (TCL/Tk is required). + Please don't use GUI mode, use one-liner mode instead! The flexability + of a one-liner (or job) mode is nearly imposible to encompas in a GUI. + No more documentation is provided for GUI mode. + + There might be a Micro$oft Windoze version of sam2p available in the near + future, but very probably you won't get real GUI with radio boxes, lists + and file selection dialogs. You'll have to start sam2p from the DOS + prompt... + +One-liner mode +~~~~~~~~~~~~~~ +This section contains a reference-style summary for the one-liner mode. +The author knows that this section is quite incomprehensible, and a bit old. +He is planning to completely rewrite it to be readable for the novice user. + +The order of the arguments and options is significant. + +Input file extension is discarded. The file format is recognised by its +magic number. + +Output file extension gives a hint for /FileFormat: + +.ps :\ + .eps : \ where PS: implies scale to fit page + .epsi : > PSL1 PSLC PSL2 PSL3 and + .epsf : / EPS: implies no scale changes + [E]PS::/ also see Q9 in FAQs below +.pdf : \ PDF1.0 PDF1.2 (and) + PDF: : / PDFB1.0 PDFB1.2 +.gif : GIF89a +.pnm : PNM (for use with transparency) +.pbm : PNM /SampleFormat/Gray1 +.pgm : PNM /SampleFormat/Gray8 +.ppm : PNM /SampleForamt/Rgb8 +.pam : PAM +.pip : PIP +.empty : Empty +.meta : Meta +.jpeg : JPEG + .jpg : " +.tiff : TIFF + .tif : " +.png : PNG +.xpm : XPM +.bmp : BMP /Compression/RLE +.rle : BMP /Compression/RLE + +Options (case insensitive): + +-- -j -j:job : display in-memory .job file +-- -j:warn : be verbose and display warnings about impossible combinations in + the .job file +-- -j:quiet : print only error and fatal error messages, suppress + warnings, notices etc. Must be put at the beginning of the + command line to suppress initial banners, too. For example, + `sam2p -j:quiet in.gif out.eps'. +-- -s:Indexed1:Indexed4:Indexed8: Try /SampleFormats in this order, and try + all others after these. Can be specified separately + (e.g `-s Indexed1 -s Indexed2:Indexed8') +-- -s:Indexed1:Indexed4:Indexed8:stop: Try only these /SampleFormats in + this order. Can be specified separately + (e.g `-s Indexed1:Indexed2 -s Indexed8:stop') +-- -s:Indexed1:Indexed4:Indexed8:stopq: Try only these /SampleFormats in + this order, be quiet (no warnings on failures). Can be + specified separately (e.g `-s Indexed1:Indexed2 -s Indexed8:stop') +-- -s:tr equivalent to `-s Transparent:Opaque:Mask:Transparent2:Transparent4:Transparent8' +-- -l:... : /LoadHints(...) +-- disabled: -a: /LoadHints(asis) extra /Compression/JAI; load JPEG files (and others as-is) + +-- -1 -ps:1 PSL1: : [tiff2ps] hint /FileFormat/PSL1 among /PSL* +-- -1c -ps:1c -ps:c PSLC: : [pts] hint /FileFormat/PSLC among /PSL* +-- -2 -ps:2 PSL2: EPS2: : [tiff2ps,imagemagick] default hint /FileFormat/PSL2 among /PSL* +-- -3 -ps:3 PSL3: : [pts] hint /FileFormat/PSL3 among /PSL* +-- -pdf:b0 PDFB1.0: : [pts] hint /FileFormat/PDFB1.0 among /PDF* +-- -pdf:b2 PDFB1.2: : [pts] default hint /FileFormat/PDFB1.2 among /PDF* +-- -pdf:0 PDF1.0: : [pts] hint /FileFormat/PDF1.0 among /PDF* +-- -pdf:2 PDF1.2: : [pts] hint /FileFormat/PDF1.2 among /PDF* +-- EPS: EPSF: : [pts] hint /FileFormat/PSL2 or + /FileFormat/PSL3 (for /Compression/ZIP) +-- PDF: : [pts] hint /FileFormat/PDFB1.0 or + /FileFormat/PDFB1.2 (for /Compression/ZIP) +-- PS: : [pts] hint /Scale/RotateOK /FileFormat/PSL2 or + /FileFormat/PSL3 (for /Compression/ZIP) +-- PS2: : [imagemagick] hint /Scale/RotateOK + /FileFormat/PSL2. Deprecated, please use PS:. + +-- -e:0 -e:none : /Scale/None +-- -e -e:1 -e:scale : /Scale/OK +-- -e:rot -e:rotate : /Scale/RotateOK + +-- GIF: GIF89a: : [imagemagick,pts] /FileFormat/GIF89a +-- JPEG: JPG: : [imagemagick,pts] /FileFormat/JPEG +-- TIFF: TIF: : [imagemagick,pts] /FileFormat/TIFF +-- PNG: : [imagemagick] /FileFormat/PNG +-- XPM: : [imagemagick] /FileFormat/XPM +-- BMP: : [imagemagick] /FileFormat/BMP +-- Empty: : [pts] /FileFormat/Empty +-- Meta: : [pts] /FileFormat/Meta +-- PIP: : [pts] /FileFormat/PIP +-- PAM: : [pts] /FileFormat/PAM +-- PNM: : [imagemagick] /FileFormat/PNM (for use with transparency) +-- PBM: : [imagemagick] /FileFormat/PNM /SampleFormat/Gray1 +-- PGM: : [imagemagick] /FileFormat/PNM /SampleFormat/Gray8 +-- PPM: : [imagemagick] /FileFormat/PNM /SampleFormat/Rgb8 + +-- -t:bin : [pts] hint /TransferEncoding/Binary (default unless /PS*) +-- -t:hex : [pts] hint /TransferEncoding/Hex (default for /PSL1 /PSLC) +-- -t:a85 : [pts] hint /TransferEncoding/A85 (default for /PSL2 /PSL3) +-- -t:ascii : [pts] hint /TransferEncoding/ASCII +-- -t:lsb1 -f:lsb2msb : [pts,tiffcp] hint /TransferEncoding/LSBfirst +-- -t:msb1 -f:msb2lsb : [pts,tiffcp] hint /TransferEncoding/MSBfirst + +-- -c:none : [pts,tiffcp] non-default hint /Compression/None +-- -c:lzw : [pts,tiffcp] hint /Compression/LZW +-- -c:lzw:(1..99) : [pts] hint /Compression/LZW /Predictor ... +-- -c:zip : [pts,tiffcp] hint /Compression/ZIP +-- -c:zip:(1..99) : [pts] hint /Compression/ZIP /Predictor ... +-- -c:zip:(1..99):(-1..9) : [pts] hint /Compression/ZIP /Predictor ... /Effort ... +-- -c:(rle|packbits) : [pts,tiffcp] hint /Compression/RLE +-- -c:(rle|packbits):(0..) : [pts] hint /Compression/RLE /RecordSize ... +-- -c:fax : [pts] hint /Compression/Fax +-- -c:fax:(-1..) : [pts] hint /Compression/Fax /K ... +-- -c:dct : [pts] hint /Compression/DCT /DCT<<>> +-- -c:dct:... : [pts] hint /Compression/DCT /DCT<<...>> +-- -c:jpeg : [pts,tiffcp] hint /Compression/JAI, /Compression/IJG +-- -c:jpeg:(0..100) : [pts] hint /Compression/JAI, /Compression/IJG /Quality ... +-- -c:ijgi : [pts,tiffcp] hint /Compression/IJG +-- -c:ijg:(0..100) : [pts] hint /Compression/IJG /Quality ... +-- -c:g4 : [pts] equivalent to -c:fax:-1 +-- -c:g3 -c:g3:1d : [pts] equivalent to -c:fax:0, -c:fax +-- -c:g3:2d : [pts] equivalent to -c:fax:-2 +-- -c:jai : [pts] hint /Compression/JAI + +-- -m:dpi:(dimen) : set /ImageDPI to `dimen' +-- -m:(dimen) \ : set all margins (/TopMargin,/BottomMargin, /LeftMargin, /RightMargin) to `dimen' + -m:all:(dimen) \ : /LeftMargin, /RightMargin) to `dimen' + -m:a:(dimen) : +-- -m:horiz:(dimen) \ : set /LeftMargin and /RightMargin to `dimen' + -m:h:(dimen) \ : + -m:x:(dimen) : +-- -m:vert:(dimen) \ : set /TopMargin and /BottomMargin to `dimen' + -m:v:(dimen) \ : + -m:y:(dimen) : +-- -m:left:(dimen) \ : set /LeftMargin to `dimen' + -m:l:(dimen) : +-- -m:right:(dimen) \ : set /RightMargin to `dimen' + -m:r:(dimen) : +-- -m:top:(dimen) \ : set /TopMargin to `dimen' + -m:t:(dimen) \ : + -m:up:(dimen) \ : + -m:u:(dimen) : +-- -m:bottom:(dimen) \ : set /BottomMargin to `dimen' + -m:b:(dimen) \ : + -m:down:(dimen) \ : + -m:d:(dimen) : + +-- -- : if given as last arg, then OutputFile:=InputFile +-- -- : if given earlier than last arg, then treat other args as filenames +-- -transparent:(rgb) Change the all pixels having the specified RGB color + to transparent. Previously transparent pixels are not changed. See FAQ + answer A44 for an exampe. + +Default and fallback compression types for each file format: + +-- PSL1 PSLC : /RLE +-- PSL2 PDFB1.0 PDF1.0 : /JAI /RLE +-- PSL3 PDFB1.2 PDF1.2 : /JAI /ZIP +-- GIF89a : /LZW +-- XPM PNM PAM PIP Empty Meta : )/None) +-- JPEG : /JAI /IJG +-- TIFF : /JAI /LZW? /RLE +-- PNG : /ZIP +-- BMP : /RLE + +Overview of job mode +~~~~~~~~~~~~~~~~~~~~ +In the ``job mode'' sam2p doesn't accept any command line options. It must be +controlled from the ``job'' files. In ''job mode'' sam2p expects a single command +line argument: the name of the Job file (file format described in section +{Jobs}). sam2p runs that single job, prints debug, info, notice, warning and +error messages (etc.), and creates a single output file: a PS or a PDF. For +multiple jobs and/or multiple output files, one has to run sam2p multiple +times. + +The details about the output file format (including standards-compliance, +compression and transfer encoding) are specified in the Job file and other +files. Thus, in order to make use of the (basic and) advanced +features of sam2p in job mode, you have to: + +1. Understand the basic concepts (i.e read through this manual, and have a + look at the examples). +2. Prepare the input raster (bitmap) graphics file in one of the supported + input formats (see section {Supported input formats}). +3. Decide the name of the output file. +4. Decide some or all details of the output format. +5. Create a Job file that describes those details. +6. Invoke the program `sam2p' with the name of the Job file as a single + command-line argument (or `-' if the Job file is fed on STDIN). +7. Read warning and error messages (printed to STDOUT and STDERR), and retry + if necessary. + +Compilation and installation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +External software required for running sam2p: + +-- a UNIX system with a fairly standard BSD or POSIX C library (C++ + libraries are not required), or a Win32 system with MSVCRT.DLL (install + Wordpad to get MSVCRT.DLL) +-- optionally: the libjpeg `cjpeg' utility for /Compression/IJG +-- optionally: the libjpeg `djpeg' utility for reading JPEG files +-- optionally: tif22pnm (uses libtiff) from the author of sam2p +-- optionally: png22pnm (uses libpng) from the author of sam2p +-- optionally: the Ghostscript `gs' utility for /Compression/DCT +-- optionally: the Ghostscript `gs' utility for /Compression/Fax + +These do not work yet (in version 0.44): + +-- optionally: the `lzw_codec' utility for alternative /Compression/LZW +-- optionally: the GNU `gzip' utility for alternative /Compression/ZIP +-- optionally: the Info-ZIP `zip' utility for alternative /Compression/ZIP + +For Win32 compilation, see later. + +Software required for UNIX compilation: + +-- a UNIX system +-- a working, GNU-compatible C++ compiler (preferably GNU G++ >=2.91. Known + working compilers: g++-2.91 g++-2.95 g++-3.0 g++-3.1 g++-3.2) +-- GNU Make (`make -v' should print `GNU Make') +-- Perl >=5.004 (no external Perl modules are required) +-- a Bourne-compatible shell (preferably GNU Bash >=2.0) +-- the following libraries are _not_ required: libjpeg, libtiff, libpng, + libungif, PDFlib, zlib, libm, libstdc++ +-- optionally: GNU autoconf >=2.53 (version number is important, see + AC_C_CONST) + +Compilation: + + # compile and install required programs + autoconf # optional, for experts only + export CC=gcc-3.2 CXX=g++-3.2 # optional, for experts only + ./configure --enable-gif --enable-lzw + make + # the stand-alone utility `./sam2p' is now built + make install # optional, may not work + +If installation doesn't work, please copy the file `sam2p' to somewhere in +your $PATH, for example /usr/local/bin. Please also copy the README to a +directory like /usr/share/doc/sam2p. There is no man page -- the +documentation is the readme. + +Testing: + + ./sam2p + ./sam2p examples/ptsbanner_zip.job + ./sam2p examples/pts2.pbm try.eps + gs test.ps + # try other examples: examples/*.job + +On Debian systems, you'll need GNU Make, Perl, GNU Bash and any of the +following packages for compilation: + + apt-get install libc6-dev gcc-2.95 g++-2.95 + apt-get install libc6-dev gcc-3.0 g++-3.0 + apt-get install libc6-dev gcc-3.1 g++-3.1 + apt-get install libc6-dev gcc-3.2 g++-3.2 + apt-get install libc6-dev gcc-3.3 g++-3.3 + apt-get install libc6-dev gcc-3.4 g++-3.4 + +Please also run any of the following before ./configure: + + export CC=gcc-2.95 CXX=g++-2.95 + export CC=gcc-3.0 CXX=g++-3.0 # or g++-3.1 etc. + +Optionally, you may install any of + + apt-get install gccchecker + apt-get install autoconf + +sam2p has been tested with a wide variety of GNU C++ compilers, including +g++-2.91, g++-2.95, g++-3.0, g++-3.1, g++-3.2, i386-uclibc-g++-2.95, +checkerg++-2.95. The program must be compilable _without_ _warnings_ with +any of g++-2.91, g++-2.95, g++-3.0, g++-3.1, g++-3.2. If there is a +compilation error, send a brief e-mail to the author immediately! + +Portability +~~~~~~~~~~~ +sam2p is quite portable on UNIX systems. It runs on: + + Debian GNU/Linux Slink 2.2.13 glibc-2.0.7 (development platform) + Debian GNU/Linux Potato 2.2.18 glibc-2.1.3 + Debian GNU/Linux Sid 2.4.17 glibc-2.2.5 + Digital OSF1 V4.0 1229 alpha + Slackware 8.0/8.1 2.4.5 libc-2.2.3 gcc-2.95.3 + SunOS 5.7 Generic_106541-17 sun4u sparc SUNW,Ultra-2 gcc-2.95.2 + SunOS 5.8 Generic_108528-12 sun4u sparc gcc-3.0.4 + +Also it runs on Win32 in command line (sam2p.exe) and GUI mode (vcsam2p.exe). +Command line mode is stable and it is recommended on this platform. + +It should work on any Linux or BSD system without modification. Porting to +other Unices should be quite easy. The author welcomes portability patches. + +Porting to non-UNIX systems may be hard. Reasons: + +-- Those systems might not have GNU Make, Perl or a Bourne-compatible shell + installed. So the Makefile supplied won't work, and many man hours of extra + work would be necessary. +-- sam2p uses the popen(3) library call to communicate with external + processes. This call might not be available on non-UNIX systems. +-- sam2p expects that the $PATH contains the external binaries. Some systems + tend to have empty or misconfigured $PATH. On some systems, `gs' is + called `gswin32c.exe' etc. + +sam2p 0.38 has been compiled and run successfully on: + +-- Linux 2.2.8 Debian Slink, g++-2.91 +-- Linux 2.4.18-ac3 Debian SID, g++-2.95, g++-3.0, g++-3.1, g++-3.2 + Executable size: 318kB. +-- Linux 2.4.2 Debian Potato, gcc version 2.95.2 20000220 (Debian GNU/Linux) + No warnings. + Compilation took 0:47, executable size: 330kB. +-- Linux 2.2.16-3 Red Hat Linux release 6.2 (Zoot), gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) + No warnings. + Compilation took 0:44, executable size: 324kB. +-- OSF1 V4.0 564 alpha, gcc version 2.7.2.2 + (tons of: warning: cast discards `const' from pointer target type, + tons of: warning: the meaning of `\x' varies with -traditional + tons of: warning: cast increases required alignment of target type) + Compilation took 5 minutes, executable size: 550kB. +-- SunOS 5.7 Generic_106541-19 sun4u sparc SUNW,Ultra-2, gcc version 3.1 + (some: warning: cast from `char*' to `int*' increases required alignment of target type) + Compilation took 2:50, executable size: 437kB. +-- SunOS 5.8 Generic_108528-15 sun4u sparc, gcc version 3.1.1 + (some: warning: cast from `char*' to `int*' increases required alignment of target type) + Compilation took 1:26, executable size: 437kB. +-- Slackware 8.0/8.1, kernel 2.4.5, libc.6.so (libc-2.2.3) gcc-2.95.3 + +sam2p 0.42 has been compiled and run successfully on: + +-- Windows 98, Visual C++ 6.0 +-- Windows 98, MSYS, MingGW, G++ 3.2 + +Win32 compilation instructions for command-line mode +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To compile sam2p.exe, the Win32 equivalent of the UNIX utility sam2p, you +have to install these build dependencies first: + +-- MinGW and MSYS, available from http://www.mingw.org + +-- Perl 5.004 or newer (only perl.exe and perl5*.dll are required), available + from http://www.perl.com. Note that this will be a long download and a + bloated install, but after that, just copy perl.exe and the single + perl5*.dll to your C:\WINDOWS directory, and uninstall the rest. + +To build sam2p: + +1. Install all the build dependencies. + +2. Open the MSYS terminal window from the start menu. + +3. Run `explorer .' to figure out what is the current working directory. + Let's call this directory the MSYS home. + +4. Download the sam2p sources into the MSYS home: + + http://www.inf.bme.hu/~pts/sam2p-latest.tar.gz + +5. Unpack the sources. Run: + + tar xzvf sam2p-latest.tar.gz + tar xvf sam2p-latest.tar.gz # if the previous one doesn't work + +6. Run `cd sam2p-*.*' to enter the sam2p source directory. It should contain + a newer version of this README and the file sam2p_main.cpp. + +7. Run `perl -edie' to check whether Perl is correctly installed. It should + print a line beginning with `Died '. If no such line appears (or you get + a `command not found' error message), go and install Perl first. Run + `echo $PATH' to find out where MSYS is searching for perl.exe. Copy + perl.exe to one of those directories. + +8. Run + + ./configure --enable-gif --enable-lzw + make + +9. The file sam2p.exe is now created in the current directory. Use it. You + may copy it to another directory right now: + + cp sam2p.exe 'C:\Program Files' + +10. You should invoke sam2p.exe from the command line (COMMAND.COM or + CMD.EXE) with the _appropriate_ arguments, described elsewhere in + this document. Don't put it into the Start menu, it won't work. + (a window will flash in and disappear, showing an error message that you + haven't supplied the right arguments). + +11. The file bts2.tth is also created. It is an important file, because it + is required for the GUI compilation. + +12. Don't forget to install tif22pnm.exe to load TIFF files, djpeg.exe to + load JPEG files, cjpeg.exe to save JPEG files, and png22pnm.exe to load + PNG files. The installation instructions for these programs are not + given here. + +Win32 compilation instructions for GUI mode +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +vcsam2p.exe is a preliminary, alpha-stage attempt to provide a Win32 GUI for +sam2p.exe. Currently it can load and display images, but not cannot save +them. vcsam2p.exe is not ready for production use. Feel free to enhance the +code. Just remember to semd me copies. + +You'll need Visual Studio 6.0 installed. + +1. Download the sam2p sources: + + http://www.inf.bme.hu/~pts/sam2p-latest.tar.gz + +2. Download untarka.exe to be able to unpack the sources: + + http://www.inf.bme.hu/~pts/untarka.exe + +3. Unpack the sources. Run: + + untarka.exe sam2p-latest.tar.gz + + A directory sam2p-*.* will be created, containing a newer version of this + README and the file config-vc6.h + +4. You'll need bts2.tth. You can get an old, possibly outdated and buggy + version directly: + + http://www.inf.bme.hu/~pts/bts2.tth + + Or, you may compile sam2p under Linux (or Win32 command-line), and copy + the generated bts2.tth from there. + + Copy bts2.tth to the same directory as config-vc6.h + +5. Start the Visual C++ 6.0 environment. + +6. File / Open Workspace / File type: Projects + Filename: vcsam2p.dsp + Build / Set Active Configuration: vcsam2p - Win32 Release + Build / Build vcsam2p.exe + Build / Execute vcsam2p.exe + +7. Don't forget to install tif22pnm.exe to load TIFF files, djpeg.exe to + load JPEG files, cjpeg.exe to save JPEG files, and png22pnm.exe to load + PNG files. The installation instructions for these programs are not + given here. + +Please report and fix bugs in vcsam2p.exe + +Copyright +~~~~~~~~~ +sam2p is written and owned by Szabó Péter <pts@fazekas.hu>. sam2p contains +code from various people. + +sam2p may be used, modified and redistributed only under the terms of the +GNU General Public License, found in the file COPYING in the distribution, +or at + + http://www.fsf.org/licenses/gpl.html + +Supported input formats +~~~~~~~~~~~~~~~~~~~~~~~ +-- PNM, PBM, PGM, PPM (preferred formats for non-transparent images) +-- PNM+PGM, PNM+PBM. The input is a concatenation of a PNM and a P[GB]M + file with the same dimensions. The second P[GB]M contains the alpha + channel. +-- XPM (preferred formats for indexed images with transparency) +-- BMP +-- GIF, with transparency +-- LBM (IFF ILBM), with transparency +-- TGA (Targa) +-- baseline JPEG JFIF (limited by /Compression/JAI) +-- PCX +-- JPEG, is supported with libjpeg/djpeg +-- TIFF, is supported with the author's tif22pnm, with transparency; also + works in a limited way with tifftopnm (Debian package libtiff-tools) +-- PNG, is supported with the author's png22pnm, with transparency + (part of the tif22pnm sources); also works in a limited way with + libpng/pngtopnm (Debian package graphics/pnmtopng); with transparency +-- PS, EPS, PDF: Ghostscript is needed (`gs' or `gswin32c.exe'), see also FAQ + question Q39. + +Note that only the major features of these file formats are supported. sam2p +is able to load most of these files, but not all of them. + +Important, but unsupported input formats: + +-- XBM +-- XWD +-- Utah RLE + +Input image model +~~~~~~~~~~~~~~~~~ +A (sampled, raster, bitmap) image is a rectangular array of pixels (dots) +plus some metadata. Each pixel is represented by an unsigned integer which +is BPC (BitsPerComponent) and CPP (ComponentsPerPixel) wide. The image +coordinate system (X,Y) is defined as: upper left corner is (0,0), upper +right corner is (Width-1,0), lower right corner is (Width-1,Height-1). +(Note that this is the natural, traditional top->down, left->right system, +and it is different from PostScript and PDF!). + +Some pixels of the image may be without color: they're transparent. A +transparent pixel is not painted, so whatever was left under it on the +paper, remains visible. (On the other hand, a colored pixel overrides the +pixel below unconditionally. E.g a white pixel overrides a black pixel, a +half-gray pixel, and also another white pixel; but a transparent pixel +leaves the original one visible.). Notions referring to transparent pixels +are: transparency, opacity, transparent, opaque, alpha channel, matte +channel. + +Images are read from image files on disk. The file format is autodetected +(see section {Supported input formats}), and it can also be specified in the +Job file (NOT implemented yet). Not all file formats are able to specify all +pixel data and metadata, so additional hints (such as the transparent color +or the name of the image author) can be specified in Job files. + +Sample formats +~~~~~~~~~~~~~~ +The image pixels could be packed to bytes according to several sample +formats. Each output file (both EPS and PDF) has its own SampleFormat +(notation: capitals). + +A color is either transparent or it is an opaque RGB triplet (8*3 bits). + +The number of colors is the number of colors actually _used_. So unused +palette entries, and e.g unused #555555 in gray-4 are not counted. + +If PSLC is required, but the printer is only PSL1, then the color image will +be printed grayscale. + +When _choosing_ the output format, sam2p doesn't degrade image quality. For +example, if an image has only two colors: #000001 and #ffffff, sam2p won't +allow the gray-1 sample format, but with #000000 and #ffffff, it will. The +user is expected to have an image editor in which she can adjust image +colors precisely (such as in the Dialogs/(Indexed palette) dialog of The +GIMP). + +Supported Sample Formats: + +Name: + Fast compatibility + Slow compatibility + Criteria for the image + -- Comment(...) + +transparent: (specialisation of mask) + all + - + the whole image is transparent + -- implemented with empty image body +opaque: (specialisation of mask and indexed-1) + all + - + the whole image contains the same, opaque color + -- implemented with `setrgbcolor', `fill' +mask: (specialisation of transparent-2) + all + - + a transparent and a non-transparent color (any may be missing) + -- display a Warning if the whole image is transparent or opaque, + because transparent or opaque would be a better choice + -- implemented with a single call to `imagemask' +indexed-1: + all + - + exactly 2 non-transparent colors or 1 non-transparent color + -- display a Warning if only 1 non-transparent color, because + opaque would be a better choice + -- display a Notice if colors are in black (#000000) and white + (#ffffff), beacuse gray-1 would be a better choice + -- implemented with a `setrgbcolor', `fill', and a single call to + `imagemask' +indexed-2: + PSL2, PDF1.0?? + PSLC + 3 or 4 non-transparent colors or 1..2 non-transparent colors + -- display a Warning if only 1..2 non-transparent colors, because + opaque or indexed-1 would be a better choice + -- display a Notice if colors are in (#000000, #555555, #aaaaaa, + #ffffff), beacuse gray-2 would be a better choice + -- implemented with the /Indexed color space or colorimage + + manual palette lookup + -- users with a PSL1 printer without PSLC should use transparent-* +indexed-4: + PSL2, PDF1.0?? + PSLC + 5..16 non-transparent colors or 1..4 non-transparent colors + -- display a Warning if only 1..4 non-transparent colors, because + opaque, indexed-1 or indexed-2 would be a better choice + -- display a Warning if all components are #00 or #ff, + because rgb-1 would be a better choice (3 bits over 4 bits) + -- display a Notice if colors are in (#000000, #111111, ..., + #ffffff), beacuse gray-4 would be a better choice + -- implemented with the /Indexed color space or colorimage + + manual palette lookup + -- users with a PSL1 printer without PSLC should use transparent-* +indexed-8: + PSL2, PDF1.0?? + PSLC + 17..256 non-transparent colors or 1..16 non-transparent colors + -- display a Warning if only 1..16 non-transparent colors, because + opaque, indexed-1, indexed-2, indexed-4 would be a better + choice + -- display a Warning if all components are #00, #55, #aa or #ff, + because rgb-2 would be a better choice (6 bits over 8 bits) + -- display a Notice if all colors are gray, beacuse gray-8 would be + a better choice + -- implemented with the /Indexed color space or colorimage + + manual palette lookup + -- users with a PSL1 printer without PSLC should use transparent-* +transparent-2: + all + - + 0..1 transparent and 1..3 non-transparent colors + -- display a Notice that color separation was done (which can + decrease speed and compression) + -- display a Warning if no transparent color, because `indexed-2' + would be a better choice + -- display a Warning if only 1 non-transparent color, because `mask' + would be a better choice + -- implemented with multiple calls to `setrgbcolor', `imagemask' +transparent-4: + all + - + a transparent and 1..15 non-transparent colors + -- display a Notice that color separation was done (which can + seriously decrease speed and compression) + -- display a Warning if only 1..3 non-transparent colors, because + `mask' or `transparent-2' would be a better choice + -- implemented with multiple calls to `setrgbcolor', `imagemask' +transparent-8: + all + - + a transparent and 1..255 non-transparent colors + -- display a Warning that color separation was done (which can + seriously decrease speed and compression) + -- display a Warning if only 1..15 non-transparent colors, because + `mask', `transparent-2' or `transparent-4' would be a better + choice + -- implemented with multiple calls to `setrgbcolor', `imagemask' +gray-1: + all + - + colors are in black (#000000) and white (#ffffff) + -- display a Warning if only 1 color, because opaque would be a + better choice + -- implemented with the multiple-argument `image' +gray-2: + all + - + colors are in (#000000, #555555, #aaaaaa, #ffffff) + -- display a Warning if only 1..2 colors, because opaque, + indexed-1, or gray-1 would be a better choice + -- implemented with the multiple-argument `image' +gray-4: + all + - + colors are in (#000000, #111111, ..., #ffffff) + -- display a Warning if only 1..4 colors, because opaque, + indexed-1, gray-1, indexed-2 or gray-2 would be a better choice + -- implemented with the multiple-argument `image' +gray-8: + all + - + colors must be gray + -- display a Warning if only 1..16 colors, because opaque, + indexed-1, gray-1, indexed-2, gray-2, indexed-4 or gray-4 + would be a better choice + -- implemented with the multiple-argument `image' +rgb-1: + PSLC, PDF1.0 + - + color components must be #00 or #ff (8 colors max) + -- display a Warning if all colors are gray + -- display a Warning if only 1..4 colors, because opaque, + indexed-1, indexed-2 (or gray-*) would be a better choice + -- implemented with `colorimage' +rgb-2: + PSLC, PDF1.0 + - + color components must be #00, #55, #aa or #ff (64 colors max) + -- display a Warning if all colors are gray + -- display a Warning if only 1..16 colors, because opaque, + indexed-1, indexed-2 or indexed-4 (or gray-*) would be a better choice + choice (this includes the case when color components are in + #00, #ff) + -- implemented with `colorimage' +rgb-4: + PSLC, PDF1.0 + - + color components must be #00, #11, ... #ff (4096 colors max) + -- display a Warning if all colors are gray + -- display a Warning if only 1..256 colors, because opaque, + indexed-1, indexed-2, indexed-4 or indexed-8 (or gray-*) would be a better + choice (this includes the case when color components are in + #00, #55, #aa, #ff) + -- implemented with `colorimage' +rgb-8: + PSLC, PDF1.0 + - + no transparency + -- display a Warning if all colors are gray + -- display a Warning if only 1..256 colors, because opaque, + indexed-1, indexed-2, indexed-4 or indexed-8 (or gray-*) would be a better + choice + -- display a Warning if all color components are in + #00, #11, ... #ff, because rgb-4 would be a better choice + -- implemented with `colorimage' + +The following directed (acyclic) graph represents that some formats should +be tried earlier than others to avoid most Warning and Notice messages. The +graph was created according to the descriptions above. + + EarlierFormat LaterFormat + + transparent mask + opaque mask + opaque indexed-1 + indexed-1 indexed-2 + indexed-2 indexed-4 + indexed-4 indexed-8 + gray-1 gray-2 + gray-2 gray-4 + gray-4 gray-8 + rgb-1 rgb-2 + rgb-2 rgb-4 + rgb-4 rgb-8 + gray-1 indexed-1 + gray-2 indexed-2 + gray-4 indexed-4 + gray-8 indexed-8 + rgb-1 indexed-4 + rgb-2 indexed-8 + mask transparent-2 + transparent-2 transparent-4 + transparent-4 transparent-8 + opaque gray-1 + indexed-1 gray-2 + indexed-2 gray-4 + indexed-4 gray-8 + opaque rgb-1 + gray-1 rgb-1 + gray-2 rgb-2 + gray-4 rgb-4 + gray-8 rgb-8 + indexed-2 rgb-1 + indexed-4 rgb-2 + indexed-8 rgb-4 + indexed-8 rgb-8 + +Every directed acyclic graph (DAG) has a topological ordering on its nodes. +Such an ordering can be computed by the UNIX (Version 7 AT&T UNIX) utility +tsort(1). Its output on the author's machine: + + opaque + transparent + gray-1 + indexed-1 + mask + transparent-2 + gray-2 + indexed-2 + transparent-4 + rgb-1 + gray-4 + indexed-4 + transparent-8 + rgb-2 + gray-8 + indexed-8 + rgb-4 + rgb-8 + +This ordering should be taken into account when someone develops her +Rule Profile. Rules having SampleFormats listed earlier should be earlier in +the Rule Profile to avoid Warning and Notice messages. + +The availability (and also Warnings and Notices) of a Sample Format for a +particular image can be easily decided after answering the following +characteristic questions: + +-- Is transparency _used_? +-- How many _used_ non-transparent colors are there? (257 if >=257) +-- Is there a non-gray color? +-- How many bits are required (maximum) for each component? + +Output rules +~~~~~~~~~~~~ +Every detail of the output file format is precisely determined by the Output +Rule. The Output Rule may be specified in the Job file, or is +automatically chosen from several pre-defined output rules in the Output +Profile (see section {Output profiles} elsewhere in this document). + +Output rule entries: + +-- FileFormat: enum (see section {Standards} for detailed information), no + default + /PSL1 -- PostScript Level1 + /PSLC -- PostScript Level1 with the CMYK and `colorimage' extension + /PSL2 -- PostScript Level2 (default) + /PSL3 -- PostScript Level3 + /PDFB1.0 -- PDF version 1.0, BI inline image, see 4.8.6 in PDFRef.pdf + /PDFB1.2 -- PDF version 1.2, BI inline image, see 4.8.6 in PDFRef.pdf + /PDF1.0 -- PDF version 1.0, XObject image, see 4.8.4 in PDFRef.pdf + /PDF1.2 -- PDF version 1.2, XObject image, see 4.8.4 in PDFRef.pdf + /GIF89a + /Empty + /Meta + /PNM + /PAM + /PIP + /TIFF + /JPEG + /PNG + /XPM + +-- SampleFormat: enum, no default, see section {Sample formats} + /Opaque + /Transparent + /Gray1 + /Indexed1 + /Mask + /Transparent2 + /Gray2 + /Indexed2 + /Transparent4 + /Rgb1 + /Gray4 + /Indexed4 + /Transparent8 + /Rgb2 + /Gray8 + /Indexed8 + /Rgb4 + /Rgb8 + /Asis -- accept contents of the JAI file + /Bbox -- no image, only bounding box information +-- WarningOK: boolean; this Output Rule is enabled iff WarningOK is true or + SampleFormat causes no warnings, default: true +-- TransferEncoding: enum, no default + /Binary -- Binary (RawBits, see pbm(5), pgm(5), ppm(5)) (Binary integers + are stored in any byte order allowed by /FileFormat) + /ASCII -- ASCII (text, chars: 9,10,13,32..126), used with transparent and opaque + /Hex /AHx -- Hex ((PSL1), PDF1.0, PSL2 ASCIIHexEncode filter) + /A85 -- A85 (PSL2 PDF1.0, ASCII85Encode filter) + /MSBfirst -- Binary data with integers stored in MSB first byte order. + If 0x41424344 is represented as "ABCD", the byte order is called: big + endian, MSB, MSB first (preferred), most significant byte first, most + significant bit first, MSB-to-LSB, network byte order, m68k byte order. + QuarkXPress 3 can read only TIFF files with MSB-to-LSB byte order. + /LSBfirst -- Binary data with integers stored in LSB first byte order. + If 0x41424344 is represented as "DCBA", the byte order is called: + little endian, LSB, LSB first (preferred), least significant byte + first, least significant bit first, LSB-to-MSB, VAX byte order, PC + (i386) byte order. +-- Compression: enum + /None -- None (default) + /LZW -- LZW (PSL2 PDF1.0 LZWEncode filter EarlyChange=true, UnitLength=8 + LowBitFirst=false) + /ZIP /Flate /Fl -- ZIP (PSL3 PDF1.2 FlateEncode filter without options) + /RLE /RunLength /RunLengthEncoded /RL /PackBits -- RLE (PSL2 PDF1.0 + RunLengthEncode filter, similar to TIFF PackBits) + /Fax /CCITTFax /CCF -- Fax (PSL2 PDF1.0 CCITTFaxEncode filter, + Uncompressed=true!, K=-1,0,1, EndOfLine=false, EncodedByteAlign=false, + Columns=..., Rows=0, EndOfBlock=true, BlackIs1=false, + DamagedRowsBeforeError=0) + /DCT -- DCT (PSL2 PDF1.0 DCTEncode, options in JPEG + stream) + /IJG /JPEG /JPG /JFIF -- IJG (PSL2 PDF1.0 DCTEncode, options in JPEG + stream; the IJG libjpeg library is used for compression, respecting the + quality value 0..100). This requires /SampleFormat/Rgb8 or + /SampleFormat/Gray8. This doesn't work with /SampleFormat/Asis. + /JAI -- JAI (PSL2 PDF1.0 DCTEncode, options in JPEG stream; JPEG-as-is: the + input file must be a JPEG file -- its contents are transferred + unmodified into the /DCTDecode JPEG stream). This requires + /SampleFormat/Asis, and doesn't work with any other /SampleFormats +-- Predictor: enum (see later), numbering same as PSL1 filter. + 1 -- no predictor. (default) Must be this unless Compression is /LZW or + /Flate + 2 -- TIFF predictor 2 (horizontal differencing) + 10 -- PNG predictor, None function + 11 -- PNG predictor, Sub function + 12 -- PNG predictor, Up function + 13 -- PNG predictor, Average function + 14 -- PNG predictor, Paeth function + 15 -- PNG predcitor, individually chosen for each line (signed minimum) + 45 -- PNG predcitor, individually chosen for each line (unsigned minimum) +-- Transparent: color. Default: null. Specify a color forced to be + transparent. Old transparency, if exists, is blacked! +-- Hints: dict + see below + +The Hints member of the Output Rule contains a dict with the following +elements: + +-- TopMargin : dimen; desired vertical gap between the top line of the page + and the top line of the raster. Default: 0. Ignored unless for PS + and PDF output. See docs about `dimen' elsewhere in this document. +-- BottomMargin : dimen; desired vertical gap between the bottom line of the + raster and the bottom line of the page. Default: 0. Ignored unless + for PS and PDF output. See docs about `dimen' elsewhere in this document. +-- LeftMargin : dimen; desired horizontal gap between the left line of the page and + the left line of the raster. Default: 0. Ignored unless for PS and PDF + output. See docs about `dimen' elsewhere in this document. +-- RightMargin : dimen; desired horizontal gap between the right line of the raster and + the right line of the page. Default: 0. Ignored unless for PS and PDF + output. See docs about `dimen' elsewhere in this document. +-- ImageDPI : positive number; resolution of bitmap image in dots per inch. + Default: 72, which means no scaling. +-- Scale : enum /None -- don't scale (zoom, magnify) the image (default) + /OK -- scale PS image to fit page (x factor == y factor) + /RotateOK -- scale and/or rotate PS image to fit page (x factor == y factor) +-- EncoderBPL : int >=1 (bits per scanline, <= rlen) +-- EncoderCoumns : int >=1 (pixels per scanline) +-- EncoderRows : int >=1 +-- EncoderColors : int >=1 +-- PredictorColumns : uint; also used if compression is /Fax (reasonable default) +-- PredictorColors : 1..3; number of color _components_ (reasonable default) +-- PredictorBPC : 1, 2, 4, 8 (reasonable default), /BitsPerComponent entry in PS and PDF +-- Effort : -1..9, must be -1 unless Compression is /ZIP (-1 means 5, default) +-- RecordSize : uint, default: 0. Compression must be /RLE +-- K : int, default: 0 (-2..infty). Compression must be /Fax. + -1 means G4 1d encoding, + 0 meangs G3 1D encoding, + -2 means G3 2D encoding with arbitrary height, positive value + means G3 2D encoding with that height. +-- Quality : 0..100, used by IJG libjpeg when compression is /IJG. default: 75 +-- ColorTransform : 0..2. For IJG, this _must_ be 0 for Gray and 1 for RGB, so its value + is ignored. For DCT, its value is respected: use 0 or 1 only. See DCTEncode + in subsubsection 3.13.3 in PLRM.pdf, and for a better documentation: see the + sources and docs of libjpeg. +-- TransferCPL : number of data characters per line. Must be positive when TransferEncoding is + /Hex or /A85, and must be zero otherwise. Default: 78 +-- DCT : dict, default: <<>>. Additional parameters for the /DCTEncode filter +-- Comment : string, default: empty +-- Title : string, default: empty +-- Subject : string, default: empty +-- Author : string, default: empty +-- Creator : string, default: empty +-- Producer : string, default: empty +-- Created : string, default: now +-- Produced : string: default: now + +Metric units +"""""""""""" +Certain parameters have type `dimen'. This is a metric dimension, measured +in any of the following real-word distance metric units: + +-- 1 bp = 1 bp (big point) +-- 1 in = 72 bp (inch) +-- 1 pt = 72/72.27 bp (point) +-- 1 pc = 12*72/72.27 bp (pica) +-- 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] +-- 1 cc = 12*1238/1157*72/72.27 bp (cicero) +-- 1 sp = 72/72.27/65536 bp (scaled point) +-- 1 cm = 72/2.54 bp (centimeter) +-- 1 mm = 7.2/2.54 bp (millimeter) + +Note: If it helps: American typesetters use 72 points per US inch, +thus 10 pt text will yield 72 chars per normal line of US Letter + (like an IBM Selectric) + 12 pt text will yield 65 chars per normal line of US Letter + (US normal typewritter). + +Each image pixel is assumed to be 1 bp wide and 1 bp tall. A dimen is an +integer or real number, followed by optional whitespace and an optional unit +(any of `bp', `in', `pt', `pc', `dd', `cc', `sp', `cm', `mm'). The default +unit is `bp', i.e a bare number is a dimen measured in `bp'. The following +dimens are all one inch long: `72', `72bp', `72 bp', `1in', `1 in', +`2.54cm', `25.4mm', `72.27pt', `6pc', `4736286.72sp'. + +Note: MiniPS and TeX use the same units. + +OutputRule combinations +~~~~~~~~~~~~~~~~~~~~~~~ +In the final version of sam2p, the following combinations will be supported: + +LZW >=2 Binary|Hex|A85 >=PSL2|>=PDF1.0 Mask|Gray*|RGB*|Indexed* +LZW >=2 Binary|Hex|A85 >=PSL2|>=PDF1.0 Transparent+ +ZIP >=2 Binary|Hex|A85 >=PSL3|>=PDF1.2 Mask|Gray*|RGB*|Indexed* +ZIP >=2 Binary|Hex|A85 >=PSL3|>=PDF1.2 Transparent+ +None|ZIP|LZW|RLE|Fax|DCT|IJG 1 Binary|Hex|A85 >=PSL2|>=PDF1.0 Mask|Gray*|RGB*|Indexed* +None|ZIP|LZW|RLE|Fax|DCT|IJG 1 Binary|Hex|A85 >=PSL2|>=PDF1.0 Transparent+ +None 1 ASCII >=PSL1|>=PDF1.0 Opaque +None 1 ASCII >=PSL1|>=PDF1.0 Transparent +ZIP 1 Binary|Hex|A85 >=PSL1 Gray*|RGB*|Indexed* +ZIP 1 Binary|Hex|A85 >=PSL1 Mask|Gray1|Indexed1 +ZIP 1 Binary|Hex|A85 >=PSL1 Transparent+ +None 1 Binary|Hex|A85 >=PSL1 Gray*|RGB*|Indexed* +None 1 Binary|Hex|A85 >=PSL1 Mask|Gray1|Indexed1 +None 1 Binary|Hex|A85 >=PSL1 Transparent+ +RLE 1 Binary|Hex|A85 >=PSL1 Gray*|RGB*|Indexed* +RLE 1 Binary|Hex|A85 >=PSL1 Mask|Gray1|Indexed1 +RLE 1 Binary|Hex|A85 >=PSL1 Transparent+ +JAI 1 Binary|Hex|A85 >=PSL2|>=PDF1.0 Asis + +TTM files +~~~~~~~~~ +TTM stands for Template Toy Macro. + +A TTM file is a dirty hack for generating templates with auto-calculated +lengths and offsets. Currently they are used for generating PDF output files +(/FileFormat/PDFB10 etc.). The syntax +of a TTM file is MiniPS (i.e a minimalistic PostScript, similar to .job +files). The TTM file must contain a single MiniPS array. + +The elements of the array are called chunks. Each chunk causes some bytes +to be appended to the output file. Data is appended in the order the +chunks are listed in the TTM file, but the data calculation order may be +different. This way it is possible to write (calc) the length of a chunk +not written (filled in) yet. The very first chunk has number zero. +different. This way it is possible to write the length of a chunk not +written yet. The very first chunk has number zero. + +The chunk types: + +-- string: backtick-sequences will be substituted (e.g ``w' to the width of + the image, in pixels) by writeTemplate(). The result is appended to the + output file. +-- positive integer: The offset (zero-based byte-position of the very first + character of chunk 0) of the specified chunk will be appended to + the output file. Only chunks already appearead may be specified this + way. If the specified chunk is an array, then printf("%10u") will be + called to print the number (this is useful for making PDF xref tables), + otherwise printf("%u") will be called. +-- negative integer: The length (measured in bytes, after substitutions) + of the specified chunk will be appended to the output file, using + printf("%u"). Only chunks already calculated may be specified this way. +-- zero: error +-- array: the array is interpreted as a standalone TTM subfile, and the rules + are applied recursively. This subfile contains sub-chunks, and the + subchunks may be arrays themselves. +-- other MiniPS types: error + +The chunks are calculated in the following order: first the array chunks are +calculated (recursively) in order of appearance, followed by the non-array +chunks in order of appearance. + +A TTM file can have up to 64 top-level chunks. + +Example: + + [ 1 %0 + [ (pts) ] %1.0 + -1 %2 + ] + +The output file will be: `3pts0000000001' since chunk 1 has length 3 and +offset 1. + +Example job file +~~~~~~~~~~~~~~~~ + <<%sam2p job + % This is file (named test0.job). + /InputFile (test0.pbm) + /OutputFile (test0.pdf) + /Profile [ + % This in-line profile is preferred over the defaults + << /FileFormat/PDF10 /SampleFormat/Gray1 /TransferEncoding/Binary + /Compression/Fax /Hints<</K 99>> >> + (pdf10.jib) run % elements found in external file + ] + >> + +See the directory examples/*.job in the sam2p sources. + +FAQ +~~~ +Q1. Should I care about /LoadHints (,asis,) when loading JPEG files? + +A1. No, sam2p guesses it by magic (in both job mode and one-liner mode). + However, you may want to set it manually in job mode: + + /LoadHints () % use djpeg + /LoadHints (,asis,) % don't use djpeg + % nothing: automatic guess, based on /Compression/JAI + +Q2. How do I convert a JPEG file to PostScript Level2 EPS? + +A2. In one-liner mode, just run: + + ./sam2p <INPUT.jpg> <OUTPUT.eps> + Example: ./sam2p try.jpg try.eps + + In one-liner mode, if you have both the djpeg and cjpeg utilities + (budled with libjpeg from IJG (Independent JPEG Group)), _and_ you want + to adjust quality vs size of the output, just run: + + ./sam2p -c:jpeg:<QUALITY> <INPUT.jpg> <OUTPUT.eps> + Example: ./sam2p -c:jpeg:60 try.jpg try.eps + + In job mode, just run sam2p with the following .job file: + + <<%sam2p-job; + % conversion is possible without external utilities cjpeg and djpeg + % No quality loss, just verbatim adata copying. + /InputFile (INPUT.jpg) + /OutputFile (OUTPUT.eps) + /Profile [ + << /FileFormat/PSL2 /SampleFormat/Asis /TransferEncoding/A85 + /Compression/JAI >> + ] >> + + Alternatively, to adjust quality vs size, use the following .job file: + + <<%sam2p-job; + % external utilities cjpeg and djpeg are required + % This uses a JPEG decompression (djpeg), plus lossy JPEG compression + % (cjpeg), so there might be quality loss! + /InputFile (INPUT.jpg) + /OutputFile (OUTPUT.eps) + /Profile [ + << /FileFormat/PSL2 /SampleFormat/Rgb8 /TransferEncoding/A85 + /Compression/IJG /Hints << + /Quality 40 % 0..100 (should be at least around 30) + >> >> + ] >> + +Q3. How do I convert a GIF file to PostScript Level2 EPS? + +A3. Check that sam2p has been compiled with GIF support: run sam2p, and + examine its console output. It should contain a line: + + Available Loaders: ... GIF ... + + If GIF doesn't appear in the line, please recompile sam2p with: + + make clean + ./configure --enable-gif --enable-lzw + make + cp sam2p /usr/local/bin + + After that, run sam2p again, and check for the line above again. + + In one-liner mode, just run: + + ./sam2p <INPUT.gif> <OUTPUT.eps> + Example: ./sam2p try.gif try.eps + + In job mode, if the GIF file doesn't have transparent pixels, run sam2p + with the following .job file: + + <<%sam2p-job; + /InputFile (INPUT.gif) + /OutputFile (OUTPUT.eps) + /Profile [ + << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/A85 + /Compression/None >> + ] >> + + If the GIF file has transparent pixels, run sam2p with the following .job + file: + + <<%sam2p-job; + /InputFile (INPUT.gif) + /OutputFile (OUTPUT.eps) + /Profile [ + << /FileFormat/PSL2 /SampleFormat/Transparent8 /TransferEncoding/A85 + /Compression/None >> + ] >> + +Q4. How do I covert a JPEG file to a TIFF/JPEG output file? + +A4. A TIFF/JPEG file is a TIFF file (_not_ a JPEG file!), in which the image + data is compressed with JPEG (DCTEncode compression). The Compression + TIFF tag value is 7. (There is also Compression==6, which corresponds to + the old, obsolete JPEG format defined in the old TIFF6.0 spec.) + + In one-liner mode, autodetection is magical. Just run: + + ./sam2p <INPUT.jpg> <OUTPUT.tiff> + Example: ./sam2p try.jpg try.tiff + + In job mode, run sam2p with the following .job file: + + <<%sam2p-job; + /InputFile (INPUT.jpg) + /OutputFile (OUTPUT.tiff) + %/LoadHints (asis) % default for /Compression/JAI + /Profile [ + << /FileFormat/TIFF /SampleFormat/Asis /TransferEncoding/Binary + /Compression/JAI >> + ] >> + + See also {FAQ question Q5} for compatibility notes. + +Q5. The TIFF/JPEG file generated by sam2p is invalid! I cannot read it with + any programs. + +A5. No, it isn't invalid, but most of the programs (including those found in + libtiff) cannot deal with TIFF files with JPEG compression. + + Compatibility notes: + + -- tif22pnm 0.03 (from the author of sam2p) can read TIFF/JPEG files + perfectly. That's because it calls the TIFFRGBAImageGet() function + of libtiff, which works. + + -- sam2p 0.37 can read TIFF/JPEG files, beacuse it calls tif22pnm to do + the job. Sam2p can write TIFF/JPEG files as well. + + -- GIMP 1.0.2: error message: `Unknown photometric number 6'. GIMP TIFF + import filter cannot deal with the YCbCr color space (which is the + most common and de facto standard color space in non-grayscale JPEG + files). It works, however, with grayscale JPEGs. + + -- tifftopnm from libtiff-tools 3.4beta037-5.1: `unknown photometric: + 6'. Ditto. (Unfortunately tifftopnm doesn't call TIFFRGBAImageGet(), + it just tries to re-implement an obsolete version of the function.) + + -- `tiffcp -c jpeg' from libtiff-tools 3.4beta037-5.1 creates a + perfectly legal TIFF/JPEG file. + + -- tiffcp from libtiff-tools 3.4beta037-5.1 cannot load a file created + by itself (`tiffcp -c jpeg')! There is no problem with grayscale + images, but color images have one component removed. + + -- xv 3.10a: Ditto. + + -- display from ImageMagick 4.04: strange error message about libraries: + `JPEGLib: Wrong JPEG library version: library is 61, caller expects 62.' + + Simple conclusion: + + -- Use sam2p or `tiffcp -c jpeg' to create a TIFF/JPEG. (Be aware that + `tiffcp -c jpeg' cannot read a TIFF/JPEG: it can only create one.) + -- Use tif22pnm to load or decode a TIFF/JPEG. + -- In your own C programs, call the TIFFRGBAImageGet() function to read + TIFF image data. + -- Don't use anything else if you want to avoid compatibility problems. + +Q6. Does sam2p support transparency and alpha channels? + +A6. sam2p supports only bilevel transparency (i.e a pixel is either fully + opaque or fully transparent), and only with indexed images. Transparency + is supported when loading indexed PNG, TIFF, PNM, GIF, LBM and XPM files. + A PNM file with transparency is a regular PBM/PGM/PPM file with a + PBM image appended to it as the alpha channel (black pixel is + transparent). + + For transparent output, the user has to specify /Transparent, /Mask, + /Transparent2, /Transparent4 or /Transparent8 as /SampleFormat. This + works with: + + -- /FileFormat/PSL1+ /SampleFormat/Transparent + -- /FileFormat/PDF1.0+ /SampleFormat/Transparent + -- /FileFormat/PDFB1.0+ /SampleFormat/Transparent + -- /FileFormat/PSL1+ /SampleFormat/Mask + -- /FileFormat/PDF1.0+ /SampleFormat/Mask + -- /FileFormat/PDFB1.0+ /SampleFormat/Mask + -- /FileFormat/GIF89a /SampleFormat/Mask + -- /FileFormat/PNM /SampleFormat/Mask + -- /FileFormat/TIFF /SampleFormat/Mask + -- /FileFormat/PNG /SampleFormat/Mask + -- /FileFormat/XPM /SampleFormat/Mask + -- /FileFormat/PSL1+ /SampleFromat/Transparent+ + -- /FileFormat/GIF89a /SampleFormat/Transparent+ + -- /FileFormat/PNM /SampleFormat/Transparent+ + -- /FileFormat/TIFF /SampleFormat/Transparent+ + -- /FileFormat/PNG /SampleFormat/Transparent+ + -- /FileFormat/XPM /SampleFormat/Transparent+ + +Q7. How large is a pixel of PostScript and PDF files generated by sam2p in + real-world metric units (inches or centimeters)? + +A7. 72 big points == 1 inch == 2.54 centimeters + + 1 pixel == 1 big point + +Q8. I have an image with transparent pixels. What happens if I convert it to + /Rgb* or /Gray*? + +A8. Either of the following will happen: + + -- You get an error message, sam2p refuses to ignore transparency. + Please use /SampleFormat/Transparent+, or call an image manipulation + program to remove transparency from the image before feeding it to + sam2p. + -- Transparency information will be lost, and the color of formerly + transparent pixels will be undefined. This would be a bug in sam2p, + you should report it. + + However, if you loaded a GIF file, and + transformed it to /Gray8 or /Rgb8, the original palette entry (RGB + triplet) is faithfully preserved. + +Q9. How do I generate a PostScript page ready for immediate printing with + margins and the image properly scaled to fit the page? + How do I create a PostScript file that will automatically scale the + image to the maximum when printed? + + +A9. To print an image as a full PostScript page, call: + + ./sam2p [MARGIN-SPECS] <INPUT.IMG> ps: - | lpr + Example: ./sam2p -m:1cm examples/pts2.pbm ps: - | lpr + + To create a PostScript file for printing, call: + + ./sam2p [MARGIN-SPECS] <INPUT.IMG> [ps:] <OUTPUT.ps> + Example: ./sam2p -m:1cm examples/pts2.pbm try.ps + + The `-m' option above is sets all four margins to `1 cm'. You can + set the margins individually: + + Example: ./sam2p -m:left:7mm -m:right:1cm -m:top:0.5in \ + -m:bottom:18bp examples/pts2.pbm try.ps + + As you can see in this example, you may specify dimensions in various + metric units, see subsection {Metric units}. + + You are strongly encouraged to print raster images with sam2p. Be aware + that The GIMP 1.2 printing plugin has several weird contrast setting + problems (even for /Gray1 images); white pixels will be gray etc. Other + utilities may add unnecessary text banners or scale the image + inappropriately. + + In one-liner mode, sam2p guesses from the file extension and the selector + (`ps:') whether the desired output file format is PostScript (fit single + page) or Encapsulated PostScript (leave size as-is, suitable for + inclusion into TeX documents). + + In job mode, without /Scale/OK and /Scale/RotateOK in /Hints, + sam2p outputs EPS (Encapsulated PostScript) with /FileFormat/PSL*. EPS + files should be included as figures into other documents (such as TeX + and InDesign), not printed alone. If you just want to print a sampled + image alone, please use your favourite graphics manipulation program + instead of sam2p. + + In job mode, create a .job file for the EPS file, and add /Hints. For + example: + + <<%sam2p-job; + /InputFile (test.in) + /OutputFile (test.ps) + /Profile [ + << /FileFormat/PSL2 /SampleFormat/Rgb8 /TransferEncoding/A85 + /Compression/None /Predictor 1 + /Hints << /Scale/OK % or /Scale/RotateOK + /LeftMargin 12 % measured as number/72 inches + /Rightargin 12 % measured as number/72 inches + /TopMargin 12 % measured as number/72 inches + /BottomMargin 12 % measured as number/72 inches + >> + >> + ] + >> + +Q10. Do the EPS files created by sam2p conform to some specifications? + + The EPS output of sam2p conforms to the following Adobe specifications: + + 5001.DSC_Spec.pdf + 5002.EPSF_Spec.pdf + + DSC and ADSC are: Adobe Document Structuring Conventions. They are + comments with lines beginning with `%!' and `%%' in PS and EPS files. + + An excerpt: + + The following example illustrates the proper use of DSC comments in a + typical page description that an application might produce when including an + EPS file. For an EPS file that is represented as + + %!PS-Adobe-3.0 EPSF-3.0 + %%BoundingBox: 4 4 608 407 + %%Title: (ARTWORK.EPS) + %%CreationDate: (10/17/89) (5:04 PM) + %%EndComments + ...PostScript code for illustration.. + showpage + %%EOF + + DSC comments discussion: + + %!PS-Adobe-3.0 EPSF-3.0 (mandatory) + %%BoundingBox: ... ... ... ... (mandatory) + + %%Extensions: CMYK (optional, for /PSLC) + %%LanguageLevel: 2 (optional, for /PSL2) + %%LanguageLevel: 3 (optional, for /PSL3) + %%Creation (strongly recommended) + %%Title (strongly recommended) + %%CreationDate (strongly recommended) + %%Trailer (optional) + %%EOF (optional) + %%DocumentData: Clean7Bit (optional) + %%DocumentData: Binary (optional) + +Q11. I get the error message `sam2p: Error: applyProfile: invalid + combination, no applicable OutputRule'. Help! + +A11. This error message means you have requested an invalid combination of + FileFormat, SampleFormat, Compression etc. parameters. If you use + one-liner mode, and you're sure that you've specified your will + correctly in the command line, please report this error message as a + sam2p bug (also specify -j in the command line). If you use job mode, + please read on. + + Example 1: + /Compression/Fax is not allowed in /PSL1. + + Solution 1: + specify /FileFormat/PSL2 /Compression/Fax. + + Example 2: + /Compression/IJG requires /SampleFormat/Gray8 or /SampleFormat/Rgb8. + Please have a look at the messages `sam2p: Warning: check_rule: ...' + to get more specific information. After that, correct your request. + + Solution 2: + specify /Compression/IJG /SampleFormat/Rgb8. + + Another cause for this message is that your request cannot be applied + to the image you've specified. In this case, there is no relevant + `sam2p: Warning: check_rule: ...' message. + + Example 1: + you've requested /SampleFormat/Indexed4, + but the input image has more than 16 colors. + + Solution 1: + specify /SampleFormat/Rgb8. + + Example 2: + you've requested /SampleFormat/Indexed4, + but the input image has transparency. + + Solution 2: + specify /SampleFormat/Transparent8. + + It is possible, but very unlikely that this error message is caused by + a bug in sam2p. + +Q12. Can I use /Compression/Fax when bits-per-pixel > 1 ? + +A12. With /FileFormat/PS* and /FileFormat/PDF*, you can (but you shouldn't, + because of the possibly poor compression ratio). With /FileFormat/TIFF, + you're not allowed to, because the TIFF specification forbids it. + Example one-liners: + + sam2p -s:Indexed8 -c:fax test.gif test.pdf # OK + sam2p -s:Indexed8 -c:fax test.gif test.eps # OK + sam2p -s:Indexed8 -c:fax test.gif test.tiff # forbidden + +Q13. Bad luck? + +A13. Not for me. + +Q14. Can I use negative margins (i.e /TopMargin -20) to crop the output + image? + +A14. No. Margins are ignored by sam2p unless /FileFormat is /PSL* or /PDF*. + Even with these formats, the image is only moved, not cropped. Please + use an image manipulation program (e.g The GIMP) to crop your images + before feeding them to sam2p. + +Q15. When I try to print the PostScript output of sam2p, the edge of the + image is missing (white). + +A15. Many printers cannot print to the edge of the paper (so that region is + left white). Please increase the margins to a safe value, for example: + + ./sam2p -m:7mm test.ppm test.ps + lpr test.ps + + See also {FAQ question Q9} for more information about margins. + +Q16. How do I report a bug in sam2p? + +A16. Please send an e-mail to the author (pts@fazekas.hu, see more in + section {Copyright}) describing the problem. Don't forget to: + + -- download the latest version of sam2p, and try it with the same image + -- describe what sam2p does (incorrectly) + -- describe what sam2p should do if there was no bug + -- run sam2p without arguments, and attach its output (STDOUT) to the + bug report + -- attach the exact command line with which you call sam2p to the bug + report + -- if you spot the bug in one-liner mode, specify the `-j' option in + the command line, and attach the messages printed by sam2p (both + STDOUT and STDERR) to the bug report + -- if you spot the bug in job mode, attach the .job file you are using + to the bug report + -- attach the input image file to the bug report. Try to attach a file + as small as possible. + -- if sam2p runs successfully (i.e it prints `Success.'), and it + creates an output image, but you think that the output image is + incorrect, attach the output image to your bug report + -- if you have a similar input image, for which sam2p works fine, + attach it to the bug report + +Q17. How long does the LZW patent held by Unisys last? + +A17. mcb@cloanto.com (author of http://lzw.info) wrote: + + Thank you for your interest and mail. I must stress that the "exact" + answers you may be looking for may come only from lawyers and courts, + and I am none of these. If you consider the IBM, the BT and Unisys US + patents, then the last of the three would be the Unisys one, expiring, + as the article I think mentions, on June 19, 2003, 24:00. There cannot + be other (new) patents on LZW, as far as I know. Please let me know if + you find different information. + +Q18. I want to create an RGB PostScript image, but sam2p creates a Gray one, + or it gives me an error message. + For example: `./sam2p -1 -s:rgb1 examples/ptsbanner.gif test.eps'. + +A18. /PSL1 doesn't support RGB images. There are two solutions: + + -- Use /PSLC or /PSL2 or /PSL3 instead or drop the '-1' + alltogether. Examples: + + ./sam2p -1c -s:rgb1 examples/ptsbanner.gif test.eps # /PSLC + ./sam2p -2 -s:rgb1 examples/ptsbanner.gif test.eps # /PSL2 + ./sam2p -s:rgb1 examples/ptsbanner.gif test.eps # /PSL2 or /PSL3 + + -- Use /Mask or /Transparent+. Note that you'll very probably get poor + compression ratio. + + ./sam2p -1 -s:tr:stop examples/ptsbanner.gif test.eps # /PSL1 + + You can get more (and more useful) error messages from sam2p if you + specify the `-j:warn' option. You may also try specifying + `-s:rgb1:stop' instead of `-s:rgb1' to force sam2p try /SampleFormat/Rgb1 + only. + +Q19. sam2p doesn't allow me to use /Compression /Fax. For example: + `./sam2p -c fax examples/ptsbanner.gif test.eps'. The same command + works fine without `-c fax'. + +A19. /Compression/Fax is intended to be used with images with 1 bit per + pixel. However, in PostScript and PDF, you can use it for any image + data, but compression ratio will be very poor for other than /Gray1, + /Indexed1 or /Mask, of course. You can force sam2p to use /Fax by + specifying the desired SampleFormat in option `-s'. Examples: + + sam2p -s:Indexed8 -c:fax test.gif test.pdf # OK + sam2p -s:Indexed8 -c:fax test.gif test.eps # OK + sam2p -s:Indexed8 -c:fax test.gif test.tiff # forbidden by TIFF std + + See {FAQ question Q12} for more information. + +Q20. Can sam2p convert images with transparency to PDF? + +A20. Only if the image has at most 1 non-transprent color + (/SampleFormat/Mask). See {FAQ question Q6} for details. + + Although PDF-1.3 supports transparency masks for arbitrary PDF images, + sam2p 0.39 doesn't. That's because the author of sam2p hasn't + implemented it yet. + +Q21. I get the error message `sam2p: Warning: buildProfile: ignoring, no + handlers for OutputRule'. Help! + +A21. This means that sam2p doesn't know how to do the conversion you've + requested (and it even doesn't know whether the request is erroneous or + not). This might be because your request is bad (it is impossible to + be fulfilled), or your request is good, but sam2p doesn't know how to + deal with it. If you think that the latter is the case, please report + this message as a bug. + + See {FAQ question Q11} for more information. + +Q22. How do I compile with G++ 3.2? + +A22. See the answer in section {Compilation and installation}. Don't forget + + export CC=gcc-3.2 CXX=g++-3.2 + +Q23. How do I do a `make dist' without running configure again? + +A23. Just issue + + make MAKE_DIST=1 dist + +Q24. I cannot open a JPEG file in the Win32 version. + +A24. Make sure you have djpeg.exe on your PATH. Simply copy it to your + C:\WINDOWS directory. + +Q25. I cannot open a TIFF file in the Win32 version. + +A25. Make sure you have tif22pnm.exe on your PATH. Simply copy it to your + C:\WINDOWS directory. + +Q26. I cannot open a PNG file in the Win32 version. + +A26. Make sure you have png22pnm.exe on your PATH. Simply copy it to your + C:\WINDOWS directory. + +Q27. What is tif22pnm? + +A27. tif22pnm is a TIFF -> PNM converter written by the author of sam2p. It + can load more TIFF files correctly than tifftopnm, ImageMagick convert, + xv and The GIMP. The TIFF loader code is based on GIMP 1.3, but has + many bugfixes and improvements. sam2p uses tif22pnm to load TIFF files. + You can download tif22pnm from + + http://www.inf.bme.hu/~pts/tif22pnm-latest.tar.gz + +Q28. What is png22pnm? + +A28. png22pnm is a PNG -> PNM converter compiled by the author of sam2p. It + is based on the excellent pngtopnm utility, but doesn't depend on the + NetPBM library (only libpng). sam2p uses png22pnm (or, as a fallback: + pngtopm) to load PNG files. png22pnm is part of the tif22pnm package, + so you can download it from + + http://www.inf.bme.hu/~pts/tif22pnm-latest.tar.gz + +Q29. Can sam2p convert a transparent GIF to PDF? + +A29. The PDF-1.3 file format supports transparent images, but sam2p doesn't. + However, if the image contains at most two colors (including the + transparent pixel), sam2p can create a working PDF-1.2 file; use + Ghostscript to view it, because Acrobat Reader 5.0 is buggy. However, + sam2p supports generating transparent EPS, GIF, PNG, PNM, XPM and TIFF + files up to 256 colors. + +Q30. How do I build my own sam2p debian package? + +A30. Please download the newest sources from + + http://www.inf.bme.hu/~pts/sam2p-latest.tar.gz + + As root, run + + apt-get update + apt-get install debmake fakeroot dpkg + apt-get install make g++ gcc perl sed + + As normal user, run (in the directory containing sam2p_main.cpp): + + debian/rules clean + rm -f build* + debian/rules build + fakeroot debian/rules binary + ls -l ../sam2p_*.deb + + As root, substitute X and Y, and run: + + dpkg -i sam2p_X_Y.deb + + Please also install the tif22pnm and png22pnm packages from the author + of sam2p (and the Debian standard libjpeg-progs package), available as + Debian source from: + + http://www.inf.bme.hu/~pts/tif22pnm-latest.tar.gz + +Q31. Why not use libjpeg/libtiff/libpng/zlib or any other library with + sam2p? + +A31. -- library and .h incompatibilities (the binary would be less portable + across Linux systems) + -- to avoid forced dependencies + -- checkergcc wouldn't work + +Q32. How do I specify the page size when printing a .ps file (-m and -e + command line options)? + +A32. You cannot. (Use -m to specify the margins.) The page size is + autodetected by your printer when the page is + printed. So you can print the same .ps file on different printers, and the + margins will be all right on all of them. + + If you really have to specify the page size, edit the .ps file and + insert the `a4 ' or `letter ' command after the last line of the + first block of lines starting with %%. You may also use something like + `1 dict dup /PageSize [ 595 842 ] put setpagedevice ' to exactly specify + the page width and height in 1/72 inches. + + For example, change the PostScript file + + %!PS-Adobe-3.0 + %%Pages: 1 + %%DocumentData: Clean7Bit + %%LanguageLevel: 1 + %%EndComments + %%Page: 1 1 + save + ... % many lines omitted + %%Trailer + %%EOF + + to + + %!PS-Adobe-3.0 + %%Pages: 1 + %%DocumentData: Clean7Bit + %%LanguageLevel: 1 + %%EndComments + %%Page: 1 1 + 1 dict dup /PageSize [ 595 842 ] put setpagedevice + save + ... % many lines omitted + %%Trailer + %%EOF + + Please note that PostScript is a programming language, so your changes + might be undone by instructions later in the file. You might find the + a2ping.pl utility (written by the author of sam2p) useful: + + a2ping.pl -v --papersize=a4 in.ps out.ps + +Q33. How do I control ZIP compression ratio? + +A33. Use + + sam2p -c:zip:1:0 in.img out.png # uncompressed ZIP carrier + sam2p -c:zip:1:1 in.img out.png # normal compression + sam2p -c:zip:1:9 in.img out.png # maximum compression + +Q34. ImageMagick convert creates smaller PNGs. Why? + +A34. I don't know the real reason. Probably because ImageMagick uses libpng, + which is smarter than sam2p. + + You are probably trying to convert a JPEG or other true color photo to + PNG. Try one of the following compression options: + + sam2p -c:zip:12:7 # 464727 bytes + sam2p -c:zip:12:8 # 454271 bytes + sam2p -c:zip:12:9 # 447525 bytes + sam2p -c:zip:13:9 # 488748 bytes + sam2p -c:zip:14:9 # 454182 bytes + sam2p -c:zip:15:9 # 453080 bytes + convert -quality ? # 454438 bytes + +Q35. Can sam2p convert large JPEGs to smaller ones (with loss of + quality and resolution)? + +A35. sam2p cannot resize or scale images. So the pixel width and height of + the input and output image cannot be changed. If you need that (for + example you want to create thumbnails), use the famous convert(1) + utility of ImageMagick. For example: + + convert -scale 444 -quality 50 in.jpg out.jpg # specify out width + convert -scale x444 -quality 50 in.jpg out.jpg # specify out height + convert -scale "10%" -quality 50 in.jpg out.jpg # specify scale ratio + + However, it is possible to specify the quality of the JPEG output of + sam2p. The quality of 0 means ugly output with small file size, and the + quality of 100 means nice output with big file sizes. You can specify + intermediate integer quality values (50 and 75 are recommended). Be + prepared that qualties above 30 (or so) may not work on all JPEG viewers. + For example: + + sam2p -c ijg:10 large_input.jpg small_output.jpg + + sam2p uses the cjpeg(1) and djpeg(1) utilities from libjpeg to write + and read JPEG files, respectively. If you need more control over your + JPEG output, then forget sam2p, and please consult the documentation of + those utilities. + +Q36. Can sam2p convert JPEG to GIF? + +A36. Yes, it can, but usually not directly. GIF allows a maximum of 256 + different + colors in an image. A typical RGB JPEG image contains many more colors, + so it has to be quantized down to 256 colors first. For example, if the + console output of ``sam2p in.jpg out.gif'' contains ``applyProfile: + invalid combination, no applicable OutputRule'', then in.jpg must be + quantized first: + + convert in.jpg out1.gif # does the quantization automatically + sam2p out1.gif out2.gif # compresses the output image further + + From out1.gif and out2.gif keep the one with the smaller file size. It + is common that convert(1) creates huge GIF files because LZW compression + is disabled inside it. sam2p should be compiled with LZW compression + and GIF input/output enabled. To check this, run sam2p, and + examine its console output. It should contain a line: + + Available Appliers: ... GIF89a+LZW ... + + If GIF89a+LZW doesn't appear in the line, please recompile sam2p with: + + make clean + ./configure --enable-gif --enable-lzw + make + cp sam2p /usr/local/bin + + , and try again. + +Q37. I need to transform GIF images of 15 colors to BMPs of 256 colors not + compressed. sam2p converts it to BMP 16 colors... + +A37. Use + + sam2p -c none -s rgb8 in.gif out.bmp + + If you get an error message `Error: applyProfile: invalid combination, + no applicable OutputRule', it very probably means that your GIF is + transparent. Remove the transparent color within an image editor first. + +Q38. Can sam2p _load_ PDF or EPS files? + +A38. Yes, if you have Ghostscript installed, and your input EPS file is not + too exotic. This has been tested on Linux only. If you experience + problems loading EPS files, but no problems loading PDF files, please + run a2ping.pl written by the author of sam2p to make your EPS file more + compatible. + +Q39. Can sam2p load an EPS or PDF file with an arbitrary resoultion? + +A39. Yes. For example use one of + + sam2p -l:gs=-r216 in.eps out.png + sam2p -l:gs=-r216 in.pdf out.png + + to have resoultion 216 DPI (image scaled 3 times to both directions). + Without scaling, 72 DPI is the default. + +Q40. Can sam2p emit a multi-page PDF or a multi-page PS? + +A40. No, it can't. Emitting a multi-page document would need a fundamental + change of the sam2p architecture. (Should the 2nd page be compressed with + a different method? What if the 2nd contains too many colors? Should we + keep all previous pages in memory?) + + I think another program should be written that is able to concatenate + EPS/PS or PDF files. I've already written a PDF-merger called pdfconcat, + available from http://www.inf.bme.hu/~pts/pdfconcat.c . + An EPS-merger would be even easier. But I don't have time to + implement these features directly into sam2p soon. + +Q41. Can sam2p read a multi-page TIFF? + +A41. sam2p reads only the first page. + + The auxilary utility tif22pnm could be patched so it extracts other + pages, and a new command line option can be added to sam2p that passes + the required page number to tif22pnm. But I don't have time to + implement these features soon. + + By the way, multi-page TIFFs can be created with the following command: + + tiffcp -c g4 d1.tiff d2.tiff d3.tiff output.tiff + +Q42. Can sam2p convert a multi-page TIFF to a multi-page PDF? + +A42. No. There are two main problems: See also Q40 and Q41. + +Q43. How do I convert a TIFF image to a 1-bit black-and-white PDF? Should I + use `sam2p -c:fax test.tif test.pdf'? + +A43. The above will ensure that fax compression is used. What you need for + ensuring that the output is 1-bit black-and-white is: + + sam2p -s:gray1:stop test.tif test.pdf + + You can also specify a compression algorithm (I recommend -c:zip): + + sam2p -c:fax -s:gray1:stop test.tif test.pdf + sam2p -c:lzw -s:gray1:stop test.tif test.pdf + sam2p -c:zip -s:gray1:stop test.tif test.pdf + + If you get the error message + + sam2p: Error: applyProfile: invalid combination, no applicable OutputRule + + then your input test.tif is not really black-and-white. Open it in an + image editing program and ensure that the colors are #000000 and + #ffffff only. + + > The tiff is black and white, bilevel - I just want to avoid the + > test.pdf from using 8bpp by default (like it does in imagemagick) + + The default for sam2p is not 8bpp. To see what the default is, run sam2p + with the `-j' option and check `OutputRule #1' on the console output. + What you are interested in is the /SampleFormat field. + +Q43. Acrobat Reader (5.0 and 6.0) cannot read the PDFs converted from a JPEG + with sam2p. I get the message: `There was an error processing a page. + Expected `EI' while parsing an image.'. + (The same problem happens with Ghostscript 6.50 with a different error + message. xpdf-1.0 reports: bad DCT trailer.) + +A43. Very probably the JPEG stream of your original input image file is + rejected by the PDF viewers. (In fact, Ghostscript 7.x doesn't + complain.) sam2p doesn't do strict JPEG validation when converting JPEG + to PDF -- it just blindly assumes that the JPEG file is correct. To + ensure this, you have to re-encode the JPEG. + + Instead of this: + + sam2p bad.jpeg bad.pdf + + do this: + + sam2p -c ijg:50 bad.jpeg good.pdf # much slower! + + or this: + + <bad.jpeg djpeg | cjpeg -quality 50 | sam2p - good.pdf + + or this: + + djpeg <bad.jpeg >temp.pnm + cjpeg -quality 50 <temp.pnm >temp.jpeg + sam2p temp.jpeg good.pdf + + The real reason why Acrobat Reader rejects the JPEG is unknown to me. + I also don't know of any baseline JPEG compliance testing software. + (But if you re-encode with djpeg and cjpeg, it becomes compliant.) + + (thanks to Thomas Kraemer for reporting the problem) + +Q44. How do I create an 1x1 transparent GIF and PNG? + +A44. Do + + echo "P1 1 1 0" >one.pbm + sam2p -transparent:ffffff one.pbm one.gif + sam2p -transparent:ffffff one.pbm one.png + +Q45. Is it possible to specify a resolution other than 72 DPI, so that the + dimensions of the resulting PDF are accurate for print-resolution images? + +A45. In the most recent version of sam2p, now it is. Just use `-m:dpi:144' + to have the output EPS or PDF scaled to double size, or use + `-m:dpi:<real>' to have it scaled by a factor of <real>/72. Note that + this works only for EPS and PDF output. For all other FileFormat{}s, + `-m:dpi:' is ignored. The `-m:dpi:' option doesn't scale the values + specified for the other `-m:...' options. + + To proper way of scaling an image, however, is + using your DTP or word processor program to resize it properly. For + example, after running `sam2p foo.png foo.pdf', in LaTeX, use + + % \usepackage{graphicx} + \includegraphics[height=10cm]{foo} + +Q46. Is it legal to use LZW compression? + +A46. I think so. Also look at Q17. + +Q47. Help! I cannot compile it on SunOS/Solaris. I get + + /usr/include/sys/wait.h:90: type specifier omitted for parameter + /usr/include/sys/wait.h:90: parse error before `*' + +A47. Until someone adds a test to ./configure, try adding the line + + #define siginfo_t void + + to the end of config2.h, just before running `make'. + +Q48. Should I run sam2p overy all my EPS (or PDF) files, to see if they + would become smaller? + +A48. No! This is a bad idea in general, because you loose information, since + the EPS output of sam2p is always rasterized, so it is not scalable + anymore. + + But you may run sam2p over all those EPS files which contain raster + graphics. But please be aware that sam2p re-renders everything at 72 + DPI (can be overridden by `-l:gs=-r<DPI>', and the gs rendering + sometimes adjusts RGB color values slightly (+-2 on in the 0..255 + domain), so there might be quality loss during the _reading_ of the + original EPS. There is absolutely no quality loss when sam2p _writes_ + the EPS. + +Q49. Should I run sam2p over all my GIF, TIFF and XPM files, to see if they + would become smaller? + +A49. Yes, run `sam2p <filename> --' if you have a backup copy of the + original. Otherwise, choose a different filename for output. + +Q50. Should I run sam2p over all my PNG files, to see if they + would become smaller? + +A50. You might try it, there will be no quality loss, but the general + experience of the author is that the tools using libpng (e.g. pnmtopng) + produce slightly smaller PNG than sam2p. If you are an image + compression specialist, please help the author to find the reason of + this, and enhance sam2p. + +Q51. Should I run sam2p over all my JPEG files, to see if they + would become smaller? + +A51. sam2p doesn't change the file by default. Use the `-c:ijg' option + (possibly with a JPEG quality parameter, e.g. `-c:ijg:50') to make + sam2p re-encode the JPEG. This is a lossy operation, and the size of + the output file depends on quality parameter specified, so it might + actually become larger than the original. Please also note that JPEG + meta-information (such as EXIF tags inserted by digital cameras) gets + completely lost with `-c:ijg'. + +Q52. How do I use ZIP (Deflate) compression in LanguageLevel 2? + +A52. Run this: + + sam2p -c:zip PSL2: in.image out.eps + + This will make sam2p emit the image decoding procedure so the image + will be viewable (veeeery slowly) on LanguageLevel 2 devices, too. It + doesn't affect the rendering speed on LanguageLevel 3 devices. + +Upsampling +~~~~~~~~~~ +Here is a figure about upsampling samples bits 1 -> 2 -> 4 -> 8: + + 0 -> 00 0 + 1 -> 11 3 + + 00 -> 0000 0 + 01 -> 0101 5 + 10 -> 1010 10 + 11 -> 1111 15 + + 0000 -> 0000 0000 0 + 0001 -> 0001 0001 17 + 0010 -> 0010 0010 34 + ... + 1110 -> 1110 1110 238 + 1111 -> 1111 1111 255 + +A 1-bit image has a palette of 2 colors: #00 and #ff. + +A 2-bit image has a palette of 4 colors: #00, #55, #aa and #ff. + +A 4-bit image has a palette of 16 colors: #00, #11, #22, ... #ff. + +An 8-bit image has a palette of 256 colors: #00, #01, #02, ... #ff. + +Standards +~~~~~~~~~ +-- PSL1 is PostScript LanguageLevel1, as defined by Adobe's PostScript + Language Reference Manual. +-- PSLC is PSL1 with the CMYK extension (including the `colorimage' + operator). Supersedes PSL1. +-- PSL2 is PostScript LanguageLevel2, as defined by Adobe's PostScript + Language Reference Manual. Supersedes PSLC. +-- PSL3 is PostScript LanguageLevel3, as defined by Adobe's PostScript + Language Reference Manual (PLRM.pdf). Supersedes PSL2. +-- PDF1.0 is PDF version 1.0, as defined by Adobe's PDF Reference. +-- PDF1.1 is PDF version 1.1, as defined by Adobe's PDF Reference. + Supersedes PDF1.0. +-- PDF1.2 is PDF version 1.2, as defined by Adobe's PDF Reference. + Supersedes PDF1.1. +-- PDF1.3 is PDF version 1.3, as defined by Adobe's PDF Reference. + Supersedes PDF1.2. +-- PDF1.4 is PDF version 1.4, as defined by Adobe's PDF Reference + (PDFRef.pdf). Supersedes PDF1.3. +-- PDF1.5 is PDF version 1.4, as defined by Adobe's PDF Reference + (PDFRef.pdf). Supersedes PDF1.4. +-- PBM is Portable Bitmap file format, as defined in NetPBM's pbm(5) UNIX + manual page. +-- PGM is Portable Graymap file format, as defined in NetPBM's pgm(5) UNIX + manual page. +-- PPM is Portable Pixmap file format, as defined in NetPBM's ppm(5) UNIX + manual page. +-- PNM is Portable Anymap file format, as defined in NetPBM's pnm(5) UNIX + manual page. It is the union of PGM, PPM and PPM. +-- PAM is the new, Portable ...map file format, as defined in NetPBM's pam(5) + UNIX manual page. We don't support it yet. +-- TIFF is ... v6.0. +-- JPEG is baseline JPEG JFIF file format as defined by the Joint Picture + Expert Group. +-- PNG is Portable Network Graphics file format v1.0, as defined by + RFC 2083. + + +Obsolete: Image metadata +~~~~~~~~~~~~~~~~~~~~~~~~ +-- Width: uint +-- Height: uint +-- ColorSpace: enum (see later), determines PixBits +-- PixBits: 1..24 +-- Origin: coord +-- Comment: string +-- FileFormat: +-- Predictor: enum (see later), same as PSLanguageLevel1 filter + /Predictor + 1 -- no predictor + 2 -- TIFF predictor 2 (horizontal differencing) + 10 -- PNG predictor, None function + 11 -- PNG predictor, Sub function + 12 -- PNG predictor, Up function + 13 -- PNG predictor, Average function + 14 -- PNG predictor, Paeth function + 15 -- PNG predcitor, individually chosen for each line +-- PredictorColumns: uint +-- PredictorColors: 1..3 +-- PredictorBitsPerComponent: 1, 2, 4, 8 +-- CompressionEffort: -1..9 (ZIP) +-- CompressionRecordSize: uint (RLE, Fax: K) +-- Compression: enum + 0 -- None + 1 -- LZW (PSL2 PDF1.0 LZWEncode filter EarlyChange=true, UnitLength=8 + LowBitFirst=false) + 2 -- ZIP (PSL3 PDF1.2 FlateEncode filter without options) + 3 -- RLE (PSL2 PDF1.0 RunLengthEncode filter, similar to TIFF PackBits) + 4 -- Fax (PSL2 PDF1.0 CCITTFaxEncode filter, Uncompressed=true!, K=-1,0,1, + EndOfLine=false, EncodedByteAlign=false, Columns=..., Rows=0, + EndOfBlock=true, BlackIs1=false, DamagedRowsBeforeError=0) + 5 -- DCT (PSL2 PDF1.0 DCTEncode, options in JPEG stream) + 6 -- IJG (PSL2 PDF1.0 DCTEncode, options in JPEG stream; the IJG libjpeg + library is used for compression, respecting the quality value 0..100) + 7 -- JAI (PSL2 PDF1.0 DCTEncode, options in JPEG stream; JPEG-as-is: the + input file must be a JPEG file -- its contents are transferred + unmodified into the /DCTDecode JPEG stream) +-- TransferEncoding: enum + 0 -- Binary (RawBits, see pbm(5), pgm(5), ppm(5)) + 1 -- ASCII (text, chars: 9,10,13,32..126) + 2 -- Hex ((PSL1), PDF1.0, PSL2 ASCIIHexEncode filter) + 3 -- 85 (PSL2 PDF1.0, ASCII85Encode filter) + 4 -- base64, _not_ implemented + 5 -- quoted-printable, _not_ implemented + 6 -- URLencode, _not_ implemented + +Compatibility notes +~~~~~~~~~~~~~~~~~~~ +by pts@fazekas.hu at Wed Nov 14 12:14:15 CET 2001 +Fri Mar 22 11:48:36 CET 2002 +Sat Apr 20 19:57:44 CEST 2002 +Fri Feb 7 11:15:39 CET 2003 + +-- Ghostscript 6.50 has problems with /FileFormat/PDFB1.0 + /SampleFormat/JAI|/IJG/DCT + (Error: /syntaxerror in ID). The problem has been fixed in Ghostscript + 7.04. With the buggy Ghostscript use /FileFormat/PDF1.0 instead. +-- /FileFormat/PDF[B]1.0 /SampleFormat/Mask|/Indexed1 doesn't + work on Acrobat Reader 5.0 on Linux: a fully opaque, one-color rectangle is + painted. This works fine on gs 6.50 and xpdf 1.0, so Acrobat Reader is + assumed to be buggy. +-- The GIMP 1.0 cannot load PlanarConfig Separated TIFF images of type + GrayA. (But can load PlanarConfig Contiguous GrayA.) +-- xv cannot display gray TIFF images with transparency. + xv: Sorry, can not handle 2-channel images. +-- (lib)tiff FAX compression an PS /CCITTFaxEncode have black and white the + opposite way. So `/CCITTFaxEncode <</BlackIs1 true>>' has to be applied + when creating a TIFF file. +-- libtiff 3.5.4 doesn't read or write an indexed image with transparency: + Sorry, can not handle contiguous data with PhotometricInterpretation=1, + and Samples/pixel=2. (Doesn't work with convert or GIMP.) +-- libtiff 3.5.4 doesn't read or write a gray with transparency: + Sorry, can not handle contiguous data with PhotometricInterpretation=2, + and Samples/pixel=2. (Doesn't work with convert, works with GIMP.) +-- libtiff doesn't read or write TIFFTAG_SUBFILETYPE/FILETYPE_MASK + + TIFFTAG_PHOTOMETRIC/PHOTOMETRIC_MASK. One has to use TIFFTAG_EXTRASAMPLES + instead. +-- libtiff (and the TIFF file format) supports only /Predictor 1 and + /Predictor 2, with /Compression/LZW and /Compression/ZIP. +-- libtiff supports only bpc=8 and bpc=16 with /Predictor 2 +-- libtiff and most TIFF-handling utils have buggy support for TIFF/JPEG. + See FAQ answer Q4. +-- libtiff supports only files with all components having the same + BitsPerSample. +-- acroread 4.0 can display all possible /Predictor values with /Indexed1. +-- Ghostscript 5.50 renders (PDF?) images inaccurately: the last bit of + the 8-bit palette sometimes gets wrong. +-- Netscape Navigator 4.7 displays transparent PNG images with their bKGD + (or an arbitrary color if bKGD not present) as a solid background. This + is a bug. +-- pdftops 0.92 has serious problems displaying images if /Predictor != 1. + The image will be obscured without an error message. Ghostscript 5.50 and + Acrobat Reader 4 do not have such problems. +-- Ghostscript 5.50 cannot display a PDF with /ColorSpace[/Indexed/DeviceRGB + ...]. Acrobat Reader 4, Ghostscript 7.04 and pdftops 0.92 can. +-- /Decode is not required in PDF. +-- GIMP 1.0 completely ignores the PNG tRNS chunk! (Thus it won't recognise + such a transparency in PNG.) Use `pngtopnm -alpha' instead! +-- pngtopnm honors the PNG bKGD chunk only if called as `pngtopnm -mix' + (and does mixing) +-- convert honors the PNG bKGD chunk (and does mixing) +-- display doesn't honor the PNG bKGD chunk, but has `-bg' command line option +-- xv honors the PNG bKGD chunk (and does mixing) +-- PDF procsets (subsection 8.1 of PDFRef.pdf) + /PDF + /Text + /ImageB Grayscale images or image masks + /ImageC Color images + /ImageI Indexed (color-table) images +-- Ghostscript always requires the /Decode entry in image dicts +-- /DCTEncode and /DCTDecode supports only BitsPerComponent==8. +-- Actually PostScript supports 1,2,4,8,12 BitsPerComponent. PDF1.3 supports + only 1,2,4,8. We support only 1, 2, 4 and 8. +-- PostScript also supports the CMYK color space, not just gray and RGB. + (And also the HSB, which can be transformed to RGB in an ugly way.) +-- PostScript supports PNG predictors to enhance compression. +-- The PLRM 4.10.6 describes a trick with patterns and imagemask to do + transparent images. Unfortunately this doesn't work in Ghostscript 5.50 + and xpdf 0.92 (but it works in acroread 4.0), so we don't use it. That's + why we have only two *-transparent-* entries. +-- ImageMagick EPSI is an EPS with preview (%%BeginPreview .. %%EndPreview) +-- ImageMagick EPSF and EPS are equivalent +-- ImageMagick EPS* is incredibly slooow because of the bad design, even for + LanguageLevel 2. +-- ImageMagick EPS* cannot display color images without the colorimage + opertor. (We could do some trickery with multiple calls to imagemask.) +-- tiff2ps cannot display color images without the colorimage + opertor. (We could do some trickery with multiple calls to imagemask.) +-- Timing: 1495 x 935 RGB, gs -sDEVICE=bmp16m -sOutputFile=/dev/null + time gs -q -sDEVICE=ppmraw -sOutputFile=t.ppm $IN.eps </dev/null + ImageMagick 6620 ms user + tiff2ps-readhexstring 2320 ms user + currentfile-colorimage 2120 ms user + readstring-colorimage 2170 ms user + currentfile-/FlateDecode-colorimage 2670 ms user +-- There is a NullEncode filter, but NullDecode doesn't exist +-- speed conclusions: + 1. Use currentfile as data source (LanguageLevel2) if possible. + 2. /FlateDecode adds a 25% speed penalty. But it compresses quite well, + so use it! +-- PostScript LanguageLevel2 supports the indexed color space: + + /colormap colors 3 mul string def + currentfile colormap readhexstring pop pop + [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace + +-- EPS comments: (ImageMagick) + + %%DocumentData: Clean7Bit + %%LanguageLevel: 1 + +-- PSL1/PSL2 supports the following color setting operators: (all operands + are between 0.0 and 1.0) + + <num> setgray currentgray % PSL1, 0.0=black 1.0=white + <hue> <saturation> <brightness> sethsbcolor % PSL1 + <red> <green> <blue> setrgbcolor % PSL1 + <cyan> <magenta> <yellow> <black> setcmykcolor % PSL2; not in PSL1 + +Algorithms, code comments +~~~~~~~~~~~~~~~~~~~~~~~~~ +RGB -> Gray +""""""""""" + gray = 0.299*red + 0.587*green + 0.114*blue (NTSC video std) + gray = (306.176*red + 601.088*green + 116.736*blue) >> 10 + perl -e 'no integer;for(@ARGV){y/#//d;$N=hex($_);$R=0.299*($N>>16)+0.587*(($N>>8)&255)+0.114*($N&255);print $R/255," ",sprintf("#%02x",int($R+0.5)),"\n"}' '#0f0f0f' + +Rgb2 -> Gray +"""""""""""" + perl -e 'no integer;for(@ARGV){print"$_ + ";y/#//d;$N=hex($_);$R=0.299*($N>>16)+0.587*(($N>>8)&255)+0.114*($N&255); + print "",$R/255," ",sprintf("#%02x",int($R+0.5)),"\n"}' 000000 000055 0000aa + 0000ff 005500 005555 0055aa 0055ff 00aa00 00aa55 00aaaa 00aaff 00ff00 + 00ff55 00ffaa 00ffff 550000 550055 5500aa 5500ff 555500 555555 5555aa + 5555ff 55aa00 55aa55 55aaaa 55aaff 55ff00 55ff55 55ffaa 55ffff aa0000 + aa0055 aa00aa aa00ff aa5500 aa5555 aa55aa aa55ff aaaa00 aaaa55 aaaaaa + aaaaff aaff00 aaff55 aaffaa aaffff ff0000 ff0055 ff00aa ff00ff ff5500 + ff5555 ff55aa ff55ff ffaa00 ffaa55 ffaaaa ffaaff ffff00 ffff55 ffffaa + ffffff + +000000 0 #00 +000055 0.038 #0a +0000aa 0.076 #13 +0000ff 0.114 #1d +005500 0.195666666666667 #32 +005555 0.233666666666667 #3c +0055aa 0.271666666666667 #45 +0055ff 0.309666666666667 #4f +00aa00 0.391333333333333 #64 +00aa55 0.429333333333333 #6d +00aaaa 0.467333333333333 #77 +00aaff 0.505333333333333 #81 +00ff00 0.587 #96 +00ff55 0.625 #9f +00ffaa 0.663 #a9 +00ffff 0.701 #b3 +550000 0.0996666666666667 #19 +550055 0.137666666666667 #23 +5500aa 0.175666666666667 #2d +5500ff 0.213666666666667 #36 +555500 0.295333333333333 #4b +555555 0.333333333333333 #55 +5555aa 0.371333333333333 #5f +5555ff 0.409333333333333 #68 +55aa00 0.491 #7d +55aa55 0.529 #87 +55aaaa 0.567 #91 +55aaff 0.605 #9a +55ff00 0.686666666666667 #af +55ff55 0.724666666666667 #b9 +55ffaa 0.762666666666667 #c2 +55ffff 0.800666666666667 #cc +aa0000 0.199333333333333 #33 +aa0055 0.237333333333333 #3d +aa00aa 0.275333333333333 #46 +aa00ff 0.313333333333333 #50 +aa5500 0.395 #65 +aa5555 0.433 #6e +aa55aa 0.471 #78 +aa55ff 0.509 #82 +aaaa00 0.590666666666667 #97 +aaaa55 0.628666666666667 #a0 +aaaaaa 0.666666666666667 #aa +aaaaff 0.704666666666667 #b4 +aaff00 0.786333333333333 #c9 +aaff55 0.824333333333333 #d2 +aaffaa 0.862333333333333 #dc +aaffff 0.900333333333333 #e6 +ff0000 0.299 #4c +ff0055 0.337 #56 +ff00aa 0.375 #60 +ff00ff 0.413 #69 +ff5500 0.494666666666667 #7e +ff5555 0.532666666666667 #88 +ff55aa 0.570666666666667 #92 +ff55ff 0.608666666666667 #9b +ffaa00 0.690333333333333 #b0 +ffaa55 0.728333333333333 #ba +ffaaaa 0.766333333333333 #c3 +ffaaff 0.804333333333333 #cd +ffff00 0.886 #e2 +ffff55 0.924 #ec +ffffaa 0.962 #f5 +ffffff 1 #ff + +Building the palette for Paletted image -> PSLC colorimage +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +{ Buf3 0 0 currentfile Bufx readstring pop + % /i 0 def + % Stack: Buf3 0 0 Bufx + { % Stack: Buf3 <Buf3-dst-i> <0-1-2> <byte-read> + exch + { { % Stack: Buf3 <Buf3-dst-i> <byte-read> + dup -2 bitshift Pal exch get + % Stack: Buf3 <Buf3-dst-i> <byte-read> <byte-to-write> + exch 4 bitshift /Carry exch def + % Stack: Buf3 <Buf3-dst-i> <byte-to-write> + 3 copy put pop 1 add 1 + % Stack: Buf3 <Buf3-dst-i+1> 1 + }{dup -4 bitshift Carry add Pal exch get + exch 15 and 2 bitshift /Carry exch def + 3 copy put pop 1 add 2 + }{dup -6 bitshift Carry add Pal exch get + % Stack: Buf3 <Buf3-dst-i> <byte-read> <byte-to-write-first> + exch 4 copy + % Stack: Buf3 <Buf3-dst-i> <byte-to-write-first> <byte-read> Buf3 <Buf3-dst-i> <byte-to-write-first> <byte-read> + pop put + % Stack: Buf3 <Buf3-dst-i> <byte-to-write-first> <byte-read> + 63 and Pal exch get pop + % Stack: Buf3 <Buf3-dst-i> <byte-to-write-second> + exch 1 add exch + 3 copy put pop 1 add 0 + % Stack: Buf3 <Buf3-dst-i+2> 0 + } + } exch + % Stack: Buf3 <Buf3-dst-i> <byte-read> {code3} <0-1-2> + get exec + % Stack: Buf3 <Buf3-dst-i++> <1-2-0> + } forall + % Stack: Buf3 <i> + pop pop + Bufr +} + +Color space conversion: (unfinished) +"""""""""""""""""""""""""""""""""""" +-- Ripped from jccolor.c from libjpeg: + + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + + + + -- RGB -> YCbCr: + Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + -- CMYK -> YCCK: + R=1-C, G=1-M, B=1-Y, K=K, RGB -> YCbCr + -- YCbCr -> RGB: (Cb < CENTERJSAMPLE, Cr < CENTERJSAMPLE) + R = Y + 1.40200 * Cr + G = Y - 0.34414 * Cb - 0.71414 * Cr + B = Y + 1.77200 * Cb + -- YCCK -> CMYK: + YCbCr -> RGB, C=1-R, M=1-G, Y=1-B, K=K. + -- (YCbCrK == YCCK) + -- Gray -> RGB: red = gray, green = gray, blue = gray + -- RGB -> Gray: gray = 0.299*red + 0.587*green + 0.114*blue (NTSC video std) + : gray = (306.176*red + 601.088*green + 116.736*blue) >> 10 + : gray = (19595.264*red + 38469.632*green + 7471.104*blue) >> 16 + -- Obsolete: RGB -> YCbCr: (YCbCr == YUV) + y:luminance = 0.299*red + 0.587*green + 0.114*blue (0..1) + cb:chrominance-b = blue - y = - 0.299*red - 0.587*green + 0.886*blue (-0.886 .. 0.886) + cr:chrominance-r = red - y = 0.701*red - 0.587*green - 0.114*blue (-0.701 .. 0.701) + Chrominance components can be represented less accurately since the + human eye is around twice as sensitive to luminance as to chrominance. + -- RGB <-> HSB: quite obfuscated. See gshsb.c in Aladdin Ghostscript's + source. + +Word frequency counting in PostScript source +"""""""""""""""""""""""""""""""""""""""""""" +perl -e '$C=0; $X=join"",<STDIN>; for (split" ",$X) { print "$_.\n"; +$C+=length($_)-1 if /[0-9]/ }; print STDERR "C=$C\n"' + +</tmp/t perl -e '$C=0; $X=join"",<STDIN>; $X=~s@([{}])@ $1 @g; $X=~s@/@ /@g; +for (split" ",$X) { print "$_.\n" if length>=2; $C++ if length($_)>=2 }; +print STDERR "C=$C\n"' | sort | uniq + +</tmp/t perl -e '$C=0; $X=join"",<STDIN>; $X=~s@([{}])@ $1 @g; $X=~s@/@ /@g; +$Y=""; for (split" ",$X) { $_=" $_ " if length($_)>=2; $Y.=$_ }; $Y=~s@ +/@/@g; print $Y' >t + +How tiff2ps displays a gray version of a PSLC Rgb8 image on PSL1 +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +gsave +100 dict begin +1495.000000 935.000000 scale +/bwproc { + rgbproc + dup length 3 idiv string 0 3 0 + 5 -1 roll { + add 2 1 roll 1 sub dup 0 eq { + pop 3 idiv + 3 -1 roll + dup 4 -1 roll + dup 3 1 roll + 5 -1 roll put + 1 add 3 0 + } { 2 1 roll } ifelse + } forall + pop pop pop +} def +/colorimage where {pop} { + /colorimage {pop pop /rgbproc exch def {bwproc} image} bind def +} ifelse +%ImageData: 1495 935 8 3 0 1 2 "false 3 colorimage" +/line 4485 string def +1495 935 8 +[1495 0 0 -935 0 935] +{currentfile line readhexstring pop} bind +false 3 colorimage + +pts_defl.c which function calls which function +"""""""""""""""""""""""""""""""""""""""""""""" +send_bits + rengeteg +flush_outbuf + send_bits + flush_block 2* +build_tree + flush_block 3* +flush_block + deflate2 5* +ct_tally + deflate2 sok* +longest_match + deflate2 2* +fill_window + deflate2 4* + +gen_codes + 2, reentrant +deflate2 + 1.. +pts_deflate_init + 1 + +Answers from Taco +""""""""""""""""" +Are the problems I'm concerned about already solved? + + -- Is there a pixel image converter that can create small and compatible + EPS documents with all the RunLength, CCITTFax, LZW and Flate + compression types? + + -- Is there a PDF version of psfrag.sty? Is there a utility for splitting + and assebling PDF files? Is there a utility for changing text labels + inside a PDF file? + + -- Is there a utility for creating (semi-)transparent EPS or PDF files + from pixel images? + +Compilation problems +"""""""""""""""""""" +-- Mårten Svantesson wrote: + + > Another problem was that the configure script didn't realise that it + > couldn't use the forte CC-compiler. This lead to several errors. For + > example it doesn't accept the option -ansi, so several tests fail for + > this reason. + + I don't have access to the a forte CC-compiler. The configure script has + been designed for use with GCC and G++. + +-- Peter Dyballa wrote (unquoted): + + > > leads to PTS_lstat being #define'd as lstat -- while stat would be correct. + > + > Why do you think that stat would be correct? + + Because /usr/include/sys/stat.h contains this: + + __BEGIN_DECLS + int chmod __P((const char *, mode_t)); + int fstat __P((int, struct stat *)); + int mkdir __P((const char *, mode_t)); + int mkfifo __P((const char *, mode_t)); + int stat __P((const char *, struct stat *)); + mode_t umask __P((mode_t)); + #ifndef _POSIX_SOURCE + int chflags __P((const char *, u_long)); + int fchflags __P((int, u_long)); + int fchmod __P((int, mode_t)); + int lstat __P((const char *, struct stat *)); + #endif + __END_DECLS + + and gensio.cpp #define's _POSIX_SOURCE. + + > I think that that PTS_lstat is defined as it should, but configure should generate the poper condition for #if. Please submit a patch to configure. + > + + This makes it compile in Mac OS X 10.3.9 (Panther): + + diff -Naur gensio.cpp~ gensio.cpp + --- gensio.cpp~ Thu Mar 3 23:00:06 2005 + +++ gensio.cpp Mon Oct 31 15:07:53 2005 + @@ -16,7 +16,9 @@ + #else + #undef __STRICT_ANSI__ /* for __MINGW32__ */ + #define _BSD_SOURCE 1 /* vsnprintf(); may be emulated with fixup_vsnprintf() */ + +#ifndef __APPLE__ + #define _POSIX_SOURCE 1 /* also popen() */ + +#endif + #define _POSIX_C_SOURCE 2 /* also popen() */ + #define _XOPEN_SOURCE_EXTENDED 1 /* Digital UNIX lstat */ + #ifndef _XPG4_2 + + --- + + I've integrated his #ifndef __APPLE__ patch. There should be a better way + to handle this situation, though. + +Revision history +~~~~~~~~~~~~~~~~ +See in the file debian/changelog. + +Missing feature list +~~~~~~~~~~~~~~~~~~~~ +!! make mkdist-noautoconf creates .tar.gz w/o leading directory part +!! cannot read t.pnm "P4 1 1 1" doesn't end with \S +!! ./sam2p ../pts.ppm t.gif -> sam2p: out_gif.cpp:260: void out_gif_write(GenBuffer::Writable&, Image::Indexed*): Assertion `bits_per_pixel<=8' failed. +!! why so large PNG? sam2p examples/chessboard_ascii.pnm t.png +!! easy seek back to 0 in in_*.cpp +!! rxvt_bug.png -> useful Win98 .bmp +?? + (expected) !! + --invert option, for tif22pnm users + complete turbo tutorial, + MIFF input, _output_ + full BMP output compressed, + faster GIF input??, make install, .deb (debhelper?), .rpm, + normal `image' instead of `colorimage' + CUPS raster input and output, + /Background option (-bg) to change transparent pixels -> bg color + LZW and ZIP compressed for indexed etc. +/* OK : PS and PDF input */ +/* Imp: parse bts2.ttt just after generating (balance of [ << ... >> ]) +/* Imp: command line option for /Transparent */ +/* Imp: avoid 3 warnings in: ./sam2p examples/pts2.pbm t.ppm */ +/* OK : margins for all PS, EPS and PDF (Sat Sep 7 16:17:58 CEST 2002 */ +/* Imp: howto in pts_defl.h */ +/* Imp: check for fixed bugs new zlib */ +/* OK : built-in CCITTFaxEncode */ +/* Imp: one-liner eliminate automatically invalid BMP SampleFormats with compression */ +/* OK : more transferencodings for l1fa85g.tte */ +/* Imp: eliminate long line (>120) from l1fa85g.tte */ +/* Imp: one-liner -s gray|indexed|rgb|transparent */ +/* OK : read bad.txt, and move it to section {Fixed bugs} */ +/* OK : verify /Compression/Fax /K 1|2 with gs 5.50|7.04 */ +/* Imp: in-memory dump when scanf_dict Error */ +/* Imp: optimal, non-mem-hungry RLE compression filter (hardly possible...) */ +/* Imp: possibility to write RGB (non-YCbCr) JPEG with /Compression/IJG etc. */ +/* Imp: ability to load .gz and .zip compressed input files. Example: + * .pbm.gz + */ +/* Imp: no return DONT_KNOW from *_work() */ +/* Imp: Meta output */ +/* Imp: PSL1 auto fallback to grayscale `image' in absence of `colorimage' */ +/* Imp: full support for ZIP compression in PSL1 (similar to RLE) */ +/* OK: TIFF output */ +/* Imp: implement as a library (throw/catch exceptions, memory management, reentrance) */ +/* Imp: check for proper inner dict usage in l1fa85g.tte */ +/* Imp: add /Transparent2, /Transparent4, /Transparent8 for PDF */ +/* Imp: add all #warning REQUIRES: */ +/* OK : ccdep.pl, --enable-debug (Sat Jun 1 16:27:58 CEST 2002) */ +/* Imp: show binary/ASCII in PDF and PS header comments */ +/* Imp: `available loaders: (TIFF)' if tifftopnm not found (run-time) */ +/* Imp: make LZW-unsupported not an Error, but a Warning */ +/* Imp: create output profile */ +/* OK: a real string hashing lib */ +/* Imp: GIF reader is too slow (maybe LZW reading? ?). Change to xvgif.c?? */ +/* OK : XPM reader (>=256 colors) is too slow */ +/* OK : specify transparent color in the Job file */ +/* Imp: run-time detect the absence of external progs */ +/* Imp: make install */ +/* Imp: make .deb, .rpm */ +/* No : NDEBUG by default */ +/* Imp: substitute char (1) for bool (8) on Digital UNIX */ +/* OK : real replacement of vsnprintf() (Digital UNIX, Solaris) -- Tue Jun 11 15:20:22 CEST 2002 */ +/* OK : close both filters in l23.tte, but _never_ close currentfile */ +/* Imp: run-time choice from FlateEncode filter implemenetations etc. */ +/* Imp: convert bilevel indexed image to grayscale more quickly */ +/* OK : add quick and effective command line interface (one-liner mode) */ +/* No : read external .tte files (runtime) instead of built-in .tth */ +/* Imp: possibility to store several profiles in the same .jib file */ +/* Imp: real, PDF-style dates into Created, Produced */ +/* OK : real hashing in MiniPS::Dict */ +/* Imp: enforce magic numbers for .job and .jib files */ +/* OK : /TransferEncoding: * -> ascii if ... */ +/* Imp: (early check, special handler) make everything work when wd==0 || ht==0; especially encoding filters */ +/* Imp: better Job option for specifying and removing transparent color (better than /Transparent) */ +/* Imp: log date(now) */ +/* OK : DCT options in Output Rule */ +/* OK : implement JAI */ +/* Imp: support LargeBBox */ +/* Imp: support Comment */ +/* Imp: support PDF metadata: Title Subject Author Creator Producer */ +/* Imp: support PDF dates: Created Produced */ +/* Imp: support Comment */ +/* Imp: add PAM file format support from NetPBM */ +/* OK : verify ADSC EPSF-3.0 compatibility */ +/* Imp: pre-transformation: making grayscale */ +/* Imp: pre-transformation: down-bit-sampling */ +/* Imp: pre-transformation: down-palette-sampling (``generate optimal palette'') */ +/* Imp: tif22pnm warning - non-square pixels; to fix do a 'pnmscale -yscale nan'P6 2840 2138 255 */ +==6750== +==6750== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +==6750== malloc/free: in use at exit: 3741 bytes in 102 blocks. +==6750== malloc/free: 2296 allocs, 2194 frees, 170451 bytes allocated. +==6750== For counts of detected errors, rerun with: -v +==6750== searching for pointers to 102 not-freed blocks. +==6750== checked 4227304 bytes. +==6750== +==6750== 12 bytes in 1 blocks are definitely lost in loss record 3 of 15 +==6750== at 0x400254FF: __builtin_new (vg_replace_malloc.c:172) +==6750== by 0x806ABC3: MiniPS::Parser::parse1(int, int) (minips.cpp:789) +==6750== by 0x806B378: MiniPS::Parser::parse1(int, int) (minips.cpp:856) +==6750== by 0x804DBD5: run_sam2p_engine(Files::FILEW &, Files::FILEW &, char const *const *, bool) (sam2p_main.cpp:923) +==6750== +==6750== +==6750== 808 bytes in 81 blocks are possibly lost in loss record 14 of 15 +==6750== at 0x400255E9: __builtin_vec_new (vg_replace_malloc.c:197) +==6750== by 0x8060C94: Mapping::DoubleHash::set(char const *, unsigned int, char const *) (mapping.cpp:43) +==6750== by 0x806A18B: MiniPS::Dict::put(char const *, unsigned int, int) (minips.cpp:461) +==6750== by 0x8069FF1: MiniPS::Dict::put(char const *, int) (minips.cpp:431) +==6750== +==6750== LEAK SUMMARY: +==6750== definitely lost: 12 bytes in 1 blocks. +==6750== possibly lost: 808 bytes in 81 blocks. +==6750== still reachable: 2921 bytes in 20 blocks. +==6750== suppressed: 0 bytes in 0 blocks. + +Known bugs +~~~~~~~~~~ +(reported by Stefan Fritsch) + +> I got a bug report [1] about sam2p 0.44-10 not including a length +> after the %%BeginData: line. As I understand it, the length is not +> optional (see [2] p.44 (and gsview output?)). Sam2p 0.44-11 adds a +> ";" after to this line. What does this ";" do? Is this supposed to be +> conforming to the postscript standard? If not, are you planning to +> write a real fix? +> +> [1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=315046 +> [2] http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf + +Fixing it would require a major rewrite. +However, I don't have free time for that right now. If you really care about +standards, remove the %%BeginData...%%EndData pair from the +PostScript file or remove it altogether from the sam2p sources. The `;' is +there so GSView won't complain. + +!! compiling on Debian SID with uclibc-toolchain + i386-uclibc-linux-g++, the statically linked sam2p executable becomes + quite biiiig: 668268 bytes. + for configure: export CXX='i386-uclibc-linux-gcc -x c++ -static' + Also, Makehelp has to be modified after running configure: + LDXX=i386-uclibc-linux-g++ -static + +!! .eps import bad shift of BBX (LLX,LLY) with never Ghostscript + +Fixed bugs +~~~~~~~~~~ +(this section was formerly bad.txt) + +./sam2p -j examples/ptsbanner2.jpg test.pdf + discover at Sun Sep 22 14:38:39 CEST 2002 + BUGFIX at Sun Sep 22 15:03:33 CEST 2002 + +./sam2p -1 -s:rgb1 -c:none examples/pts2.pbm test.eps + discover at Sun Sep 22 14:29:59 CEST 2002 + BUGFIX (add -s:...:stopq) at Sun Sep 22 16:20:41 CEST 2002 + (behaviour correct, specifying -s:rgb1:stop gives more error messages) + +./sam2p -c:fax:2 examples/shot.gif y.pdf + BUGFIX /EndOfLine true is forced + old gs: /ioerror in --%image_file_continue-- + old acroread: `read less image data' (PDFB1.0: `expected EI') +./sam2p -c:fax:1 examples/shot.gif y.pdf + BUGFIX /EndOfLine true is forced + gs: OK + old acroread: `read less image data' (PDFB1.0: `problem 115') +./sam2p -c:fax:0 examples/shot.gif y.pdf + gs, acroread: OK +./sam2p -c:fax:-1 examples/shot.gif y.pdf + gs, acroread: OK + +./sam2p -c:fax examples/pts2.pbm y.tiff + BUGFIX black-white inversion +./sam2p -c:fax examples/shot.gif y.tiff + BUGFIX black-white inversion + +./sam2p -j -c jpeg examples/pts2.pbm y.tiff + seems to be OK now +./sam2p -j -c jpeg examples/pts2.pbm y.tiff + seems to be OK now + +./sam2p -j -c fax examples/ptsbanner.gif y.eps + BUGFIX guard against applying /Compression/Fax to non-1-bit data +./sam2p -j -c fax -s:Indexed8 examples/ptsbanner.gif y.eps + OK, no guard +./sam2p -j -c fax -c none examples/ptsbanner.gif y.eps + OK, no guard +./sam2p -j -c fax examples/ptsbanner.gif y.tiff + BUGFIX forbidden applying /Compression/Fax to non-1-bit data + +./sam2p -c fax csanyi_torok_old.png csanyi_torok.eps +./sam2p -c fax examples/ptsbanner.gif csanyi_torok.eps + error: Impossible combination + OK, the user should specify `-s Indexed8' for unexpected use of `-c fax' + +__END__ diff --git a/Build/source/utils/sam2p/StdAfx.cpp b/Build/source/utils/sam2p/StdAfx.cpp new file mode 100644 index 00000000000..943d8bfa0fb --- /dev/null +++ b/Build/source/utils/sam2p/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// vcsam2p.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Build/source/utils/sam2p/StdAfx.h b/Build/source/utils/sam2p/StdAfx.h new file mode 100644 index 00000000000..7b8cbb5debf --- /dev/null +++ b/Build/source/utils/sam2p/StdAfx.h @@ -0,0 +1,37 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) +#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + + +// Windows Header Files: +#include <windows.h> + +#include <process.h> /* _getpid() */ +#include <shellapi.h> /* ShellExecute() */ + +// C RunTime Header Files +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> +#include <stdio.h> /* sprintf() */ +#include <oledlg.h> /* OPENFILENAME */ + +// Local Header Files + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) diff --git a/Build/source/utils/sam2p/aclocal.m4 b/Build/source/utils/sam2p/aclocal.m4 new file mode 100644 index 00000000000..a3198f42002 --- /dev/null +++ b/Build/source/utils/sam2p/aclocal.m4 @@ -0,0 +1,1238 @@ +dnl +dnl aclocal.m4, read by configure +dnl by pts@fazekas.hu at Thu Nov 1 23:07:16 CET 2001 +dnl advanced integer checks Sat Apr 6 12:32:02 CEST 2002 +dnl +dnl Imp: is shell `elif' compatible +dnl Imp: less autoconf warnings +dnl Dat: m4 SUXX, no normal error message for missing ')' +dnl Dat: FILE *f=fopen("conftestval", "w"); is autoconf trad + +dnl autoconf-2.13 generates bad code for AC_C_CONST in g++-3.2 +dnl autoconf-2.54 is good (verified at Wed Dec 11 15:28:28 CET 2002) +AC_PREREQ([2.14]) + +dnl stupid autoconf-2.54 does #include <stdlib.h> +m4_define([_AC_PROG_CXX_EXIT_DECLARATION],[:]) + +AC_DEFUN([AC_PTS_CHECK_INTEGRALS],[ +dnl Checks for integral sizes. +AC_REQUIRE([AC_HEADER_STDC]) +AC_PTS_C_CHAR_UNSIGNED +dnl ^^^ eliminates autoconf warning `warning: AC_TRY_RUN called without default to allow cross compiling' + +dnl by pts@fazekas.hu at Sat Apr 6 12:43:48 CEST 2002 +dnl Run some tests in a single burst. +if test x"$ac_cv_sizeof_char" = x; then +AC_MSG_CHECKING(size of char) +AC_CACHE_VAL(ac_cv_sizeof_char, +[ac_cv_sizeof_char_p=-1;ac_cv_sizeof_short=-1;ac_cv_sizeof_int=-1 +ac_cv_sizeof_long=-1 +AC_TRY_RUN([ +#undef const +#undef volatile +#undef inline +#include <stdio.h> +int main(){FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "ac_cv_sizeof_char=%d\n", sizeof(char)); + fprintf(f, "ac_cv_sizeof_char_p=%d\n", sizeof(char*)); + fprintf(f, "ac_cv_sizeof_short=%d\n", sizeof(short)); + fprintf(f, "ac_cv_sizeof_int=%d\n", sizeof(int)); + fprintf(f, "ac_cv_sizeof_long=%d\n", sizeof(long)); + return 0; /* exit(0); -- return is more portable */ +}], eval "`cat conftestval`", , ac_cv_sizeof_char=-1)]) +AC_MSG_RESULT($ac_cv_sizeof_char) +AC_DEFINE_UNQUOTED(SIZEOF_CHAR, $ac_cv_sizeof_char) +AC_DEFINE_UNQUOTED(SIZEOF_CHAR_P, $ac_cv_sizeof_char_p) +AC_DEFINE_UNQUOTED(SIZEOF_SHORT, $ac_cv_sizeof_short) +AC_DEFINE_UNQUOTED(SIZEOF_INT, $ac_cv_sizeof_int) +AC_DEFINE_UNQUOTED(SIZEOF_LONG, $ac_cv_sizeof_long) +fi +dnl AC_PTS_CHECK_SIZEOF(char, -1) + +if test $ac_cv_sizeof_char = -1; then + AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_INTEGRALS) +fi +AC_PTS_CHECK_SIZEOF(short, -1) +AC_PTS_CHECK_SIZEOF(int, -1) +AC_PTS_CHECK_SIZEOF(long, -1) +AC_PTS_CHECK_SIZEOF(long long, -1) +if test $ac_cv_sizeof_long_long = 8 +then ac_cv_sizeof___int64=0; ac_cv_sizeof_very_long=0; fi +AC_PTS_CHECK_SIZEOF(very long, -1) +if test $ac_cv_sizeof_very_long = 8; then ac_cv_sizeof___int64=0; fi +AC_PTS_CHECK_SIZEOF(__int64, -1) +dnl ^^^ very long type doesn't exit in any C standard. + +dnl Imp: make these cached +# echo $ac_cv_sizeof_long_long +if test $ac_cv_sizeof_char != 1; then + AC_MSG_ERROR(sizeof(char)!=1) +fi +if test $ac_cv_sizeof_short = 2; then + ac_cv_pts_int16_t=short +elif test $ac_cv_sizeof_int = 2; then + ac_cv_pts_int16_t=int +else + AC_MSG_ERROR(cannot find inttype: sizeof(inttype)==2) +fi +AC_DEFINE_UNQUOTED(PTS_INT16_T, $ac_cv_pts_int16_t) +if test $ac_cv_sizeof_int = 4; then + ac_cv_pts_int32_t=int +elif test $ac_cv_sizeof_long = 4; then + ac_cv_pts_int32_t=long +elif test $ac_cv_sizeof_long -lt 4; then + AC_MSG_ERROR(sizeof(long)<4) +else + AC_MSG_ERROR(cannot find inttype: sizeof(inttype)==4) +fi +AC_DEFINE_UNQUOTED(PTS_INT32_T, $ac_cv_pts_int32_t) +if test $ac_cv_sizeof_long = 8; then + ac_cv_pts_int64_t=long +elif test $ac_cv_sizeof_long_long = 8; then + ac_cv_pts_int64_t="long long" +elif test $ac_cv_sizeof_very_long = 8; then + ac_cv_pts_int64_t="very long" +elif test $ac_cv_sizeof___int64 = 8; then + ac_cv_pts_int64_t="__int64" +else + dnl AC_DEFINE(PTS_INT64_T, 0) -- skip AC_DEFINE(); #undef is OK in aclocal.h + dnl Imp: put a real #undef into config.h (configure comments it out :-< ) + ac_cv_pts_int64_t=0 + AC_MSG_WARN(cannot find inttype: sizeof(inttype)==8) +fi +AC_DEFINE_UNQUOTED(PTS_INT64_T, $ac_cv_pts_int64_t) +if test $ac_cv_sizeof_long = 16; then + ac_cv_pts_int128_t=long +elif test $ac_cv_sizeof_long_long = 16; then + ac_cv_pts_int128_t="long long" +elif test $ac_cv_sizeof_very_long = 16; then + ac_cv_pts_int128_t="very long" +else + dnl AC_DEFINE(PTS_INT128_T, 0) -- skip AC_DEFINE(); #undef is OK in aclocal.h + dnl Imp: put a real #undef into config.h (configure comments it out :-< ) + ac_cv_pts_int128_t=0 + AC_MSG_WARN(cannot find inttype: sizeof(inttype)==16) +fi +AC_DEFINE_UNQUOTED(PTS_INT128_T, $ac_cv_pts_int128_t) +]) + +dnl ripped from autoconf-2.13 (ruined by autoconf-2.50) +dnl by pts@fazekas.hu at Wed Dec 11 12:33:53 CET 2002 +dnl AC_PTS_CHECK_SIZEOF(TYPE [, CROSS-SIZE]) +AC_DEFUN(AC_PTS_CHECK_SIZEOF, +[changequote(<<, >>)dnl +dnl The name to #define. +define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[AC_TRY_RUN([#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof($1)); + return 0; +}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + + + +AC_DEFUN([AC_PTS_CHECK_POINTERS],[ +AC_REQUIRE([AC_PTS_CHECK_INTEGRALS]) +AC_PTS_CHECK_SIZEOF(char *, -1) +AC_PTS_CHECK_SIZEOF(void *, -1) +dnl no need for checking for -1, AC_PTS_CHECK_INTEGRALS already did it +AC_MSG_CHECKING(for an integral type to hold a ptr) +AC_CACHE_VAL(ac_cv_pts_intp_t, [ +if test $ac_cv_sizeof_char_p != $ac_cv_sizeof_void_p; then + AC_MSG_ERROR($ac_cv_sizeof_char_p==sizeof(char*)!=sizeof(void*)) +fi +if test $ac_cv_sizeof_char_p -le 2; then + ac_cv_pts_intp_t=$ac_cv_pts_int16_t +elif test $ac_cv_sizeof_char_p -le 4; then + ac_cv_pts_intp_t=$ac_cv_pts_int32_t +elif test $ac_cv_sizeof_char_p -le 8; then + ac_cv_pts_intp_t=$ac_cv_pts_int64_t +elif test $ac_cv_sizeof_char_p -le 16; then + ac_cv_pts_intp_t=$ac_cv_pts_int128_t +else + # :; fi; if true; then + AC_MSG_RESULT(not found!) + AC_MSG_ERROR(no integral type for sizeof(char*)==$ac_cv_sizeof_char_p) +fi +])dnl AC_CACHE_VAL +AC_DEFINE_UNQUOTED(PTS_INTP_T, $ac_cv_pts_intp_t) +AC_MSG_RESULT($ac_cv_pts_intp_t) +AC_MSG_CHECKING(for ptr <-> integral conversion) +AC_CACHE_VAL(ac_cv_pts_intp_ok, [ + AC_TRY_RUN([ +/* #include "confdefs.h" -- automatic */ +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +/* #ifndef __cplusplus; #define const; #endif -- automatic config.h */ + {char const*p="The quick brown fox."+5; + PTS_INTP_T i; + while (*p!='r') p++; /* prevent compiler optimisations */ + i=(PTS_INTP_T)p; + while (*p!='w') p++; /* prevent compiler optimisations */ + return p!=(char*)(i+2); } + ], ac_cv_pts_intp_ok=yes, ac_cv_pts_intp_ok=no, + [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_POINTERS)] +)])dnl AC_CACHE_VAL +if test x"$ac_cv_pts_intp_ok" = xyes; then + AC_DEFINE(PTS_INTP_OK) +fi +AC_MSG_RESULT($ac_cv_pts_intp_ok) +]) + +dnl Ballast code elmiminated at Sat Apr 6 11:47:08 CEST 2002 +dnl [AC_MSG_RESULT(not found); AC_MSG_ERROR(This is fatal.)], +dnl [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPE)] +dnl) +dnlAC_MSG_RESULT($ac_cv_integral_type_$1) +dnl]) + +AC_DEFUN([AC_PTS_CHECK_INTEGRAL_TYPEX],[ +dnl @param $1: name of type +dnl @param $2: substitution type +dnl @param $3: stored name for the variable +dnl errs out if specified type doesn't exist +dnl please invoke AC_CHECK_HEADERS(unistd.h) 1st +dnl Imp: make it work even if specified type doesn't exist +dnl AC_TYPE_SIZE_T +AC_REQUIRE([AC_HEADER_STDC]) +AC_MSG_CHECKING(for integral type $3) +AC_CACHE_VAL(ac_cv_integral_type_$3, [ +AC_TRY_RUN([ +#include <stdio.h> +/* #include "confdefs.h" -- automatic */ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <stdio.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#define MY_TYPE $1 +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, 0<(MY_TYPE)-1 ? "unsigned " : "signed "); + if (sizeof(MY_TYPE)==1) fprintf(f, "char"); + else if (sizeof(MY_TYPE)==sizeof(char)) fprintf(f, "char"); + else if (sizeof(MY_TYPE)==sizeof(short)) fprintf(f, "short"); + else if (sizeof(MY_TYPE)==sizeof(int)) fprintf(f, "int"); + else if (sizeof(MY_TYPE)==sizeof(long)) fprintf(f, "long"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT16_T)) fprintf(f, "PTS_INT16_T"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT32_T)) fprintf(f, "PTS_INT32_T"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT64_T)) fprintf(f, "PTS_INT64_T"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT128_T)) fprintf(f, "PTS_INT128_T"); + else return 3; /* fprintf(f, "???"); */ + if (ferror(f)) return 2; /* printf("\n"); */ + return 0; +}], + [ac_cv_integral_type_$3="`cat conftestval`"; + ], + dnl vvv Imp: make this a macro + [if test x"$2" = x; then AC_MSG_RESULT(not found); AC_MSG_ERROR(This is fatal.); fi + ac_cv_integral_type_$3="$2" + echo -n "substituting " + dnl ^^^ Imp: echo -n... + dnl AC_MSG_RESULT(substituting $2) # doesn't work because of AC_CACHE_VAL + ], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPEX)] +) +])dnl AC_CACHE_VAL +AC_DEFINE_UNQUOTED(PTS_$3, $ac_cv_integral_type_$3) +AC_MSG_RESULT($ac_cv_integral_type_$3) +]) + +AC_DEFUN([AC_PTS_CHECK_INTEGRAL_TYPE],[ + AC_PTS_CHECK_INTEGRAL_TYPEX($1,$2,$1) +]) + +AC_DEFUN([AC_PTS_TYPE_GETGROUPS], [ + AC_REQUIRE([AC_TYPE_GETGROUPS]) + dnl echo ,$ac_cv_type_getgroups, + AC_PTS_CHECK_INTEGRAL_TYPEX($ac_cv_type_getgroups, [], getgroups_t) +]) + + +dnl ripped from ruby-1.6.2 +AC_DEFUN([AC_PTS_HAVE_PROTOTYPES], [ + AC_CACHE_CHECK(whether cc supports prototypes, ac_cv_pts_have_prototypes, [ + AC_TRY_COMPILE( + [int foo(int x) { return 0; }], [return foo(10);], + ac_cv_pts_have_prototypes=yes, + ac_cv_pts_have_prototypes=no + ) + ]) + if test x"$ac_cv_pts_have_prototypes" = xyes; then + AC_DEFINE(HAVE_PROTOTYPES) + fi +]) + +dnl by pts@fazekas.hu at Wed Dec 11 12:09:14 CET 2002 +AC_DEFUN([AC_PTS_HAVE_STATIC_CONST], [ + AC_CACHE_CHECK(whether c++ supports static const, ac_cv_pts_have_static_const, [ + AC_TRY_COMPILE( + [#undef const +class A { public: static const int i=1; };], [return A::i==0;], + ac_cv_pts_have_static_const=yes, + ac_cv_pts_have_static_const=no + ) + ]) + if test x"$ac_cv_pts_have_static_const" = xyes; then + AC_DEFINE(HAVE_STATIC_CONST) + fi +]) +class A { static const int i=1; }; + + + +dnl by pts@fazekas.hu at Fri Nov 2 13:15:27 CET 2001 +AC_DEFUN([AC_PTS_HAVE_STDC], [ +dnl Check for working standard C (also called as ANSI C) +dnl implies check for AC_PTS_HAVE_PROTOTYPES, AC_HEADER_STDC + AC_REQUIRE([AC_HEADER_STDC]) + AC_REQUIRE([AC_PTS_HAVE_PROTOTYPES]) + AC_CACHE_CHECK(whether cc compiles standard C, ac_cv_pts_have_stdc, [ + AC_EGREP_CPP(nope, [ +#if defined(__STDC__) && __STDC__ + /* note: the starting spaces are deliberate in the next line */ + #if 0 + nope + #endif +#else +#if defined(__cplusplus) && __cplusplus + #if 0 + nope + #endif +#else + nope +#endif +#endif + ], ac_cv_pts_have_stdc=no, [ + if test x"$ac_cv_pts_have_prototypes" = xyes; then + ac_cv_pts_have_stdc=yes + else + ac_cv_pts_have_stdc=no + fi + ]) + ]) + if test x"$ac_cv_pts_have_stdc" = xyes; then + AC_DEFINE(HAVE_PTS_STDC) + fi +]) + +dnl by pts@fazekas.hu at Fri Nov 2 13:46:39 CET 2001 +AC_DEFUN([AC_PTS_C_VOLATILE], [ + AC_CACHE_CHECK(for C keyword volatile, ac_cv_pts_have_volatile, [ + AC_TRY_COMPILE( + [volatile int i;], [i=5; i++; return i-6;], + ac_cv_pts_have_volatile=yes, + ac_cv_pts_have_volatile=no + ) + ]) + if test x"$ac_cv_pts_have_volatile" = xno; then + AC_DEFINE(volatile, ) + fi +]) + +AC_DEFUN([AC_PTS_CHECK_HEADER], [ +dnl @param $1 file to be #included +dnl @param $2 function to be tested +dnl @param $3 cache name, such as `strcpy_in_string' +dnl @param $4 test code (main() function) +dnl better than AC_CHECK_HEADERS because it undefines const and volatile +dnl before including + AC_CACHE_CHECK(for working $2 in $1, ac_cv_pts_$3, [ + AC_TRY_RUN([ +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <$1> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + $4 + return 1; +}], + ac_cv_pts_$3=yes, + ac_cv_pts_$3=no, + [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_HEADER)] + ) + ]) + if test x"$ac_cv_pts_$3" = xyes; then + AC_DEFINE_UNQUOTED(HAVE_$3) + fi +]) + +dnl by pts@fazekas.hu at Fri Nov 2 15:05:19 CET 2001 +AC_DEFUN([AC_PTS_CHECK_STRING], [ +dnl defines ac_cv_pts_have_string +dnl defines ac_cv_pts_have_memcmpy_builtin +dnl defines ac_cv_pts_string_header + AC_PTS_CHECK_HEADER(string.h, strcpy, strcpy_in_string, [char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H';] ) + ac_cv_pts_have_string=no + if test x"$ac_cv_pts_strcpy_in_string" = xyes; then + ac_cv_pts_have_string=yes + ac_cv_pts_string_header=string + else + AC_PTS_CHECK_HEADER(strings.h, strcpy, strcpy_in_strings, [char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H';] ) + if test x"$ac_cv_pts_strcpy_in_strings" = xyes; then + ac_cv_pts_have_string=yes + ac_cv_pts_string_header=strings + fi + fi + if test x"$ac_cv_pts_have_string" = xyes; then + AC_DEFINE(HAVE_STRING) + fi + CC_bak="$CC" + CC="${CC:-cc} -Werror" + AC_PTS_CHECK_HEADER($ac_cv_pts_string_header.h, memcpy, memcpy_in_stringxs, [char s[42]="X"; memcpy(s, "Hello, World!", 2); return *s!='H'; ]) + CC="$CC_bak" + + AC_CACHE_CHECK(whether memcmp and memcpy are built-in, ac_cv_pts_have_memcmpy_builtin, [ + ac_cv_pts_have_memcmpy_builtin=no + if test x"$ac_cv_pts_have_string" = xyes; then + dnl They are built-in for gcc 2.7.2.3 -traditional + if test x"$ac_cv_pts_memcpy_in_stringxs" = xno; then + AC_TRY_RUN([ +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char s[42]="X"; memcpy(s, "Hello, World!", 2); return memcmp(s, "H", 1)!=0; +}], + [ac_cv_pts_have_memcmpy_builtin=yes], + [AC_MSG_ERROR(missing memcmp and memcpy)], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_STRING)] + ) + fi + fi + ]) + if test x"$ac_cv_pts_have_memcmpy_builtin" = xyes; then + AC_DEFINE(HAVE_MEMCMPY_BUILTIN) + fi +]) + +dnl by pts@fazekas.hu at Tue Sep 3 19:27:50 CEST 2002 +dnl g++-3.2: cc1plus: warning: ignoring command line option '-Wnested-externs' +dnl Usage: AC_PTS_CHECK_IGNORING(nebfcmd,-Wnested-externs -Wbad-function-cast -Wmissing-declarations) +AC_DEFUN([AC_PTS_CHECK_IGNORING], [ + XTRA="$2" + CC_bak="$CC" CC="${CC:-cc} -Werror $2" + CXX_bak="$CXX" CXX="${CXX:-c++} -Werror $2" + AC_CACHE_CHECK([for ignored $2],ac_cv_pts_ignoring_$1, [ + AC_TRY_COMPILE([],[], + ac_cv_pts_ignoring_$1=no,ac_cv_pts_ignoring_$1=yes)]) + CC="$CC_bak" + CXX="$CXX_bak" +]) + +dnl by pts@fazekas.hu at Fri Nov 2 15:05:27 CET 2001 +AC_DEFUN([AC_PTS_CHECK_MALLOC], [ +dnl never fails + AC_PTS_CHECK_HEADER(stdlib.h, malloc, malloc_in_stdlib, [char *p=(char*)malloc(42); if (p!=0) free((void*)p); return p==0;]) + if test x"$ac_cv_pts_malloc_in_stdlib" != xyes; then + AC_PTS_CHECK_HEADER(malloc.h, malloc, malloc_in_malloc, [char *p=malloc(42); if (p!=0) free(p); return p==0;]) + fi +]) + + +dnl by pts@fazekas.hu at Fri Nov 2 16:51:13 CET 2001 +AC_DEFUN([AC_PTS_HAVE_SWITCH_ENUM_BUG], [ + AC_CACHE_CHECK(for switch(enum) bug, ac_cv_pts_have_switch_enum_bug, [ + AC_TRY_RUN([ +enum what { foo, bar }; +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + switch ((enum what)1) { + case foo: return 1; + case bar: return 0; + } + return 1; +}], + [ac_cv_pts_have_switch_enum_bug=no], + [ac_cv_pts_have_switch_enum_bug=yes], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_SWITCH_ENUM_BUG)] + ) + ]) + if test x"$ac_cv_pts_have_switch_enum_bug" = xyes; then + AC_DEFINE(HAVE_SWITCH_ENUM_BUG) + fi +]) + +dnl by pts@fazekas.hu at Mon Mar 4 09:17:43 CET 2002 +AC_DEFUN([AC_PTS_HAVE_ASCII_SYSTEM], [ + AC_CACHE_CHECK(for ASCII system, ac_cv_pts_have_ascii_system, [ + AC_EGREP_CPP(ascii_yes,[ +#if 'a'!=97 || '!'!=33 +#error You need an ASCII system to compile this. +#else +ascii_yes +#endif +], + ac_cv_pts_have_ascii_system=yes, ac_cv_pts_have_ascii_system=no + ) + ]) + if test x"$ac_cv_pts_have_ascii_system" = xyes; then + AC_DEFINE(HAVE_ASCII_SYSTEM) + fi +]) + +AC_DEFUN([AC_PTS_ENSURE_ASCII_SYSTEM], [ + AC_PTS_HAVE_ASCII_SYSTEM + if test x"$ac_cv_pts_have_ascii_system" != xyes; then + AC_MSG_ERROR(you need an ASCII system) + fi +]) + +dnl by pts@fazekas.hu at Fri Nov 2 16:51:13 CET 2001 +AC_DEFUN([AC_PTS_CFG_P_TMPDIR], [ + AC_CACHE_CHECK(for tmpdir, ac_cv_pts_cfg_p_tmpdir, [ + AC_TRY_RUN([ +#define __USE_SVID 1 +#define __USE_GNU 1 +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + FILE *f=fopen("conftestval","w"); + if (!f) return 1; + fputs(P_tmpdir,f); + return 0; +}], + [ac_cv_pts_cfg_p_tmpdir=\""`cat conftestval`"\"], + [ac_cv_pts_cfg_p_tmpdir=0], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_CFG_P_TMPDIR)] + ) + ]) + AC_DEFINE_UNQUOTED(PTS_CFG_P_TMPDIR, $ac_cv_pts_cfg_p_tmpdir) +]) + +dnl by pts@fazekas.hu at Wed Oct 1 19:14:28 CEST 2003 +dnl on i386: +dnl perl -e 'die sprintf"%.16f",(1/3)' ## 0.3333333333333333 (we chose 16) +dnl perl -e 'die sprintf"%.17f",(1/3)' ## 0.33333333333333331 +AC_DEFUN([AC_PTS_CFG_PRINTFGLEN], [ + AC_CACHE_CHECK(for width of printf .g, ac_cv_pts_cfg_printfglen, [ + AC_TRY_RUN([ +#define __USE_SVID 1 +#define __USE_GNU 1 +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + unsigned i; + char tmp[64], pat[10], *p; + FILE *f=fopen("conftestval","w"); + if (!f) return 1; + for (i=1;i<61;i++) { + sprintf(pat, "%%.%ug", i); + sprintf(tmp, pat, 1.0/3); + if (tmp[0]=='0' && tmp[1]=='.') { + p=tmp+2; while (*p=='3') p++; + if (*p!='\0') break; + } + } + if (i>1) fprintf(f,".%u",i-1); + return 0; +}], + [ac_cv_pts_cfg_printfglen=\""`cat conftestval`"\"], + [ac_cv_pts_cfg_printfglen=""], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_CFG_PRINTFGLEN)] + ) + test x"$ac_cv_pts_cfg_printfglen" = x && ac_cv_pts_cfg_printfglen=no + ]) + if test x"$ac_cv_pts_cfg_printfglen" = xno; then :; else + AC_DEFINE_UNQUOTED(PTS_CFG_PRINTFGLEN, $ac_cv_pts_cfg_printfglen) + fi +]) + +dnl by pts@fazekas.hu at Thu Dec 12 20:20:41 CET 2002 +AC_DEFUN([AC_PTS_HAVE_SYSTEMF], [ + echo no-original >conftestval + AC_CACHE_CHECK(for working system(3), ac_cv_pts_systemf, [ + AC_TRY_RUN([ +#include <stdio.h> +#include <stdlib.h> /* system() */ + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + (void)argc; + (void)argv; + if (0!=system("echo t >conftestval && echo \"let it\" be e >conftestval")) { + FILE *f=fopen("conftestval","w"); + if (f) { + fprintf(f,"runtime-error\n"); + fclose(f); + } + } + return 0; +} +], [ac_cv_pts_systemf="`cat conftestval`"; ac_cv_pts_systemf="${ac_cv_pts_systemf:-invalid}"], + [ac_cv_pts_systemf=compile-error], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_VSNPRINTF)] + ) + # echo "($ac_cv_pts_systemf)" + # if test x"$ac_cv_pts_systemf" = x'"let it" be e '; then + if test x"$ac_cv_pts_systemf" = x't && echo "let it" be e '; then + # Win32 COMMAND.COM + ac_cv_pts_systemf=win32 + elif test x"$ac_cv_pts_systemf" = x"let it be e"; then + # UNIX /bin/sh + ac_cv_pts_systemf=unix + fi + ]) + if test x"$ac_cv_pts_systemf" = xwin32; then + ac_cv_pts_have_systemf=yes + AC_DEFINE(HAVE_PTS_SYSTEMF) + AC_DEFINE(HAVE_PTS_SYSTEMF_WIN32) + elif test x"$ac_cv_pts_systemf" = xunix; then + ac_cv_pts_have_systemf=yes + AC_DEFINE(HAVE_PTS_SYSTEMF) + AC_DEFINE(HAVE_PTS_SYSTEMF_UNIX) + elif test x"$ac_cv_pts_systemf" = x"invalid"; then + ac_cv_pts_have_systemf=no + elif test x"$ac_cv_pts_systemf" = x"compile-error"; then + ac_cv_pts_have_systemf=no + elif test x"$ac_cv_pts_systemf" = x"runtime-error"; then + ac_cv_pts_have_systemf=no + elif test x"$ac_cv_pts_systemf" = x"no-original"; then + ac_cv_pts_have_systemf=no + else + ac_cv_pts_have_systemf=yes + # ac_cv_pts_systemf=other + AC_DEFINE(HAVE_PTS_SYSTEMF) + AC_DEFINE(HAVE_PTS_SYSTEMF_OTHER) + fi +]) + +dnl by pts@fazekas.hu at Fri Mar 22 16:40:22 CET 2002 +AC_DEFUN([AC_PTS_HAVE_POPEN_B], [ + AC_CACHE_CHECK(for binary popen_b, ac_cv_pts_have_popen_b, [ + AC_TRY_RUN([ +#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */ +#define _POSIX_SOURCE 1 /* popen() */ +#define _POSIX_C_SOURCE 2 /* popen() */ +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ FILE *p=popen("echo Ko rt5","rb"); + int i; + (void)argc; (void)argv; + if (p==0) return 1; + if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2; + if (getc(p)!='r' || getc(p)!='t') return 3; + if (getc(p)!='f'-'a'+'0') return 4; + if (getc(p)!='\n') return 5; + if (getc(p)!=-1) return 6; + if (0!=pclose(p)) return 7; + + p=popen("cat >conftestval","wb"); + if (p==0) return 31; + for (i=0;i<666;i++) putc(i,p); + if (ferror(p)) return 32; + if (0!=pclose(p)) return 33; + p=fopen("conftestval","rb"); + if (p==0) return 34; + for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35; + if (fclose(p)!=0) return 36; + + return 0; +} +], [ac_cv_pts_have_popen_b=yes], + [ac_cv_pts_have_popen_b=no], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_POPEN_B)] + ) + ]) +dnl AC_DEFINE_UNQUOTED(HAVE_PTS_POPEN_B, $ac_cv_pts_have_popen_b) + if test x"$ac_cv_pts_have_popen_b" = xyes; then + AC_DEFINE(HAVE_PTS_POPEN_B) + fi +]) + +dnl by pts@fazekas.hu at Fri Mar 22 16:40:22 CET 2002 +AC_DEFUN([AC_PTS_HAVE_POPEN_], [ + AC_CACHE_CHECK(for binary popen_, ac_cv_pts_have_popen_, [ + AC_TRY_RUN([ +#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */ +#define _POSIX_SOURCE 1 /* popen() */ +#define _POSIX_C_SOURCE 2 /* popen() */ +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ FILE *p=popen("echo Ko rt5","r"); + int i; + (void)argc; (void)argv; + if (p==0) return 1; + if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2; + if (getc(p)!='r' || getc(p)!='t') return 3; + if (getc(p)!='f'-'a'+'0') return 4; + if (getc(p)!='\n') return 5; + if (getc(p)!=-1) return 6; + if (0!=pclose(p)) return 7; + + p=popen("cat >conftestval","w"); + if (p==0) return 31; + for (i=0;i<666;i++) putc(i,p); + if (ferror(p)) return 32; + if (0!=pclose(p)) return 33; + p=fopen("conftestval","rb"); + if (p==0) return 34; + for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35; + if (fclose(p)!=0) return 36; + + return 0; +} +], [ac_cv_pts_have_popen_=yes], + [ac_cv_pts_have_popen_=no], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_POPEN_)] + ) + ]) +dnl AC_DEFINE_UNQUOTED(HAVE_PTS_POPEN_, $ac_cv_pts_have_popen_) + if test x"$ac_cv_pts_have_popen_" = xyes; then + AC_DEFINE(HAVE_PTS_POPEN_) + fi +]) + +dnl by pts@fazekas.hu at Fri Mar 22 19:36:26 CET 2002 +dnl huge BUGFIX at Tue Jun 11 13:38:30 CEST 2002 +dnl on kempelen: ac_cv_pts_vsnprintf=bad +AC_DEFUN([AC_PTS_HAVE_VSNPRINTF], [ + AC_CACHE_CHECK(for working vsnprintf, ac_cv_pts_vsnprintf, [ + AC_TRY_RUN([ +#if 0 /* autoconf-2.54 */ + extern "C" void std::exit (int) throw (); using std::exit; + extern "C" void std::exit (int); using std::exit; + extern "C" void exit (int) throw (); + extern "C" void exit (int); + void exit (int); +#endif +#ifdef __cplusplus +extern "C" void exit(int); +#endif +#define _BSD_SOURCE 1 /* vsnprintf */ +#define _POSIX_SOURCE 1 +#define _POSIX_C_SOURCE 2 +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +static int myprintf(int max, char *dstr, char *fmt, ...) { + int i; + va_list ap; + #if defined(__STDC__) + va_start(ap, fmt); + #else + va_start(ap); + #endif + i=vsnprintf(dstr, max, fmt, ap); + va_end(ap); + return i; +} + +int c99t[]={13,9,10,10,10}, oldt[]={-1,9,-1,0,-1}, sun99t[]={13,9,10,-1,10}; +/* wincrtt[]={-1,9,10,-1,-1}, but it modifies the string in a completely + * bogus way (passes 1 test of 5) + */ + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ char buf[40]; + int i; + int g[5], gg; + int *t=oldt; + FILE *f=fopen("conftestval","w"); + (void)argc; + (void)argv; + + if (f) { + for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='X'; buf[i]='\0'; + i=myprintf(10, buf, "%s-%ld", "Alma", -1234567L); + if (i==c99t[0]) t=c99t; /* oldt[0]!=c99t[0] */ + g[0]=(i==t[0] && 0==memcmp(buf, "Alma--123\0X", 11)); + /* printf("(%s) %d %d\n", buf, i, g[0]); */ + + for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Y'; buf[i]='\0'; + i=myprintf(10, buf, "%s-%ld", "Alma", -123L); + g[1]=(i==t[1] && 0==memcmp(buf, "Alma--123\0Y", 11)); + /* printf("(%s) %d %d\n", buf, i, g[1]); */ + + for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Z'; buf[i]='\0'; + i=myprintf(10, buf, "%s-%ld", "Alma", -1234L); + g[2]=(i==t[2] && 0==memcmp(buf, "Alma--123\0Z", 11)); + /* printf("(%s) %d %d\n", buf, i, g[2]); */ + + buf[0]='#'; + i=myprintf(0, buf, "%s-%ld", "Alma", -1234L); + if (t==c99t && i==sun99t[3]) t=sun99t; + g[3]=(i==t[3] && buf[0]=='#'); + /* printf("(%s) %d %d\n", buf, i, g[3]); */ + + buf[0]=buf[1]='$'; + i=myprintf(1, buf, "%s-%ld", "Alma", -1234L); + g[4]=(i==t[4] && buf[0]=='\0' && buf[1]=='$'); + /* printf("(%s) %d %d\n", buf, i, g[4]); */ + + gg=g[0] && g[1] && g[2] && g[3] && g[4]; + fputs(!gg ? "bad\n" : t==oldt ? "old\n" : t==sun99t ? "sun99\n" : "c99\n", f); + fclose(f); + } + return 0; +} +], [ac_cv_pts_vsnprintf="`cat conftestval`"; ac_cv_pts_vsnprintf="${ac_cv_pts_vsnprintf:-invalid}"], + [ac_cv_pts_vsnprintf=no], + [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_VSNPRINTF)] + ) + ]) + if test x"$ac_cv_pts_vsnprintf" = xold; then + ac_cv_pts_have_vsnprintf=yes + AC_DEFINE(HAVE_PTS_VSNPRINTF) + AC_DEFINE(HAVE_PTS_VSNPRINTF_OLD) + elif test x"$ac_cv_pts_have_vsnprintf" = xc99; then + ac_cv_pts_have_vsnprintf=yes + AC_DEFINE(HAVE_PTS_VSNPRINTF) + AC_DEFINE(HAVE_PTS_VSNPRINTF_C99) + else + ac_cv_pts_have_vsnprintf=no + ac_cv_pts_vsnprintf=no + fi +]) + +dnl by pts@fazekas.hu at Sun Mar 31 17:26:01 CEST 2002 +AC_DEFUN([AC_PTS_HAVE_ERRNO_DECL], [ + AC_CACHE_CHECK([for errno in errno.h],ac_cv_pts_errno_decl, [ + AC_TRY_COMPILE([#include <errno.h>],[int i = errno], + ac_cv_pts_errno_decl=yes,ac_cv_pts_have_errno_decl=no)]) + if test x"$ac_cv_pts_errno_decl" = x"yes"; then + AC_DEFINE(HAVE_ERRNO_DECL, 1, [ ]) + fi +]) + +dnl by pts@fazekas.hu at Sun Mar 31 22:19:16 CEST 2002 +dnl modeled after Autoconf internal AC_EGREP_CPP +dnl AC_PTS_SED_EGREP_CPP(SED-PATTERN, EGREP-PATTERN, PROGRAM, [ACTION-IF-FOUND [, +dnl ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_PTS_SED_EGREP_CPP, +[AC_REQUIRE_CPP()dnl +cat > conftest.$ac_ext <<EOF +[#]line __oline__ "configure" +#include "confdefs.h" +[$3] +EOF +dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +if (eval "$ac_cpp conftest.$ac_ext") 2>&AC_FD_CC | +dnl Prevent m4 from eating regexp character classes: +changequote(, )dnl + sed -n '$1' | egrep '$2' >/dev/null 2>&1; then +changequote([, ])dnl + ifelse([$4], , :, [rm -rf conftest* + $4]) +ifelse([$5], , , [else + rm -rf conftest* + $5 +])dnl +fi +rm -f conftest* +]) + +dnl by pts@fazekas.hu at Sun Mar 31 22:23:48 CEST 2002 +dnl Digital UNIX OSF/1 has it in _some_ cases. +AC_DEFUN([AC_PTS_HAVE_GETSOCKNAME_SIZE_T], [ + AC_CACHE_CHECK(whether getsockname accepts size_t, ac_cv_pts_have_getsockname_size_t, [ + AC_PTS_SED_EGREP_CPP([/getsockname/,/)/p], [size_t], + [#include <sys/socket.h>], + [ac_cv_pts_have_getsockname_size_t=yes], + [ac_cv_pts_have_getsockname_size_t=no] + ) + ]) + if test x"$ac_cv_pts_have_getsockname_size_t" = xyes; then + AC_DEFINE(HAVE_PTS_GETSOCKNAME_SIZE_T) + fi +]) + +dnl by pts@fazekas.hu at Sun Mar 31 22:23:48 CEST 2002 +dnl Digital UNIX OSF/1 has it. +AC_DEFUN([AC_PTS_HAVE_GETSOCKNAME_SOCKLEN_T], [ + AC_CACHE_CHECK(whether getsockname accepts socklen_t, ac_cv_pts_have_getsockname_socklen_t, [ + AC_PTS_SED_EGREP_CPP([/getsockname/,/)/p], [socklen_t], + [#include <sys/socket.h>], + [ac_cv_pts_have_getsockname_socklen_t=yes], + [ac_cv_pts_have_getsockname_socklen_t=no] + ) + ]) + if test x"$ac_cv_pts_have_getsockname_socklen_t" = xyes; then + AC_DEFINE(HAVE_PTS_GETSOCKNAME_SOCKLEN_T) + fi +]) + +dnl by pts@fazekas.hu at Sun Mar 31 23:50:05 CEST 2002 +dnl Digital UNIX OSF/1 has it. +AC_DEFUN([AC_PTS_ENABLE_DEBUG], [ + AC_MSG_CHECKING([for --enable-debug]) + AC_SUBST(ENABLE_DEBUG) + AC_ARG_ENABLE(debug, + [ --enable-debug[=val] val: no, assert(default), yes, checker], + [], []) + ENABLE_DEBUG="$enable_debug" + if test x"$enable_debug" = xno; then + AC_MSG_RESULT(no) + elif test x"$enable_debug" = x || test x"$enable_debug" = xassert; then + AC_MSG_RESULT(assert) + ENABLE_DEBUG=assert + elif test x"$enable_debug" = xyes; then + AC_MSG_RESULT(yes) + elif test x"$enable_debug" = xchecker; then + AC_MSG_RESULT(checker) + else + AC_MSG_RESULT("?? $enable_debug") + AC_MSG_ERROR(Invalid --enable--debug option specified.) + fi +]) + +dnl by pts@fazekas.hu at Thu Apr 4 13:25:20 CEST 2002 +dnl Keeps conftest* +AC_DEFUN(AC_PTS_TRY_COMPILE_NORM, +[cat > conftest.$ac_ext <<EOF +dnl vvv Dat: breaks newer autoconfs :-( +dnl ifelse(AC_LANG, [FORTRAN77], +ifelse(not_AC_LANG, [FORTRAN77], +[ program main +[$2] + end], +[dnl This sometimes fails to find confdefs.h, for some reason. +dnl [#]line __oline__ "[$]0" +[#]line __oline__ "configure" +#include "confdefs.h" +[$1] +int main() { +[$2] +; return 0; } +])EOF +if AC_TRY_EVAL(ac_compile); then + ifelse([$3], , :, [ + $3]) +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$4], , , [ + $4 +])dnl +fi +rm -f conftest*]) + +dnl by pts@fazekas.hu at Thu Apr 4 13:00:08 CEST 2002 +dnl Checks whether `gcc' can link C++ programs (and thus libstdc++ is +dnl avoided). +AC_DEFUN([AC_PTS_GCC_LINKS_CXX], [ + AC_REQUIRE([AC_LANG_CPLUSPLUS]) + AC_REQUIRE([AC_PROG_CXX]) + AC_CACHE_CHECK(whether gcc can link C++ code, ac_cv_pts_gcc_links_cxx, [ + CXX_saved="$CXX" + LIBS_saved="$LIBS" + CXX_new="$CXX" + ac_ext_saved="$ac_ext" + AC_PTS_TRY_COMPILE_NORM([ + #include <stdio.h> + struct B { virtual int f()=0; int x() { return f(); } }; + struct C1: public B { virtual int f() {return 1;}}; + struct C2: public B { virtual int f() {return 2;}}; + C1 global; /* global.x() will cause segfault in i386-uclibc-gcc */ + ],[ + /* vvv (B*) cast added for gcc-3.1 */ + B *p=(ferror(stderr))?(B*)new C1():(B*)new C2(); /* Imp: argc... */ + /* if (p==0) throw long(42); */ /* doesn't work with -fno-rtti */ + int ok2=p->x()==2; + delete p; + return !(ok2 && global.x()==1); + ],[ + case x"$CC" in + xgcc-*) CXX="$CC" ;; # gcc-3.2 + x*-gcc-*) CXX="$CC" ;; # + x*-gcc) CXX="$CC" ;; # i386-uclibc-gcc + *) CXX=gcc ;; + esac + CXX_new="$CXX" + ac_ext="$ac_objext" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && ./conftest${ac_exeext} + then ac_cv_pts_gcc_links_cxx=yes + else + LIBS="$LIBS_saved c_lgcc.cpp" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && ./conftest${ac_exeext} + then ac_cv_pts_gcc_links_cxx=yes-with-help + else + LIBS="$LIBS_saved c_lgcc3.cpp" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && ./conftest${ac_exeext} + then ac_cv_pts_gcc_links_cxx=yes-with-help3 + else ac_cv_pts_gcc_links_cxx=no; CXX_new="$CXX_saved"; fi + fi + fi + ],[ac_cv_pts_gcc_links_cxx=compilation-failed]) + CXX="$CXX_saved" + LIBS="$LIBS_saved" + ac_ext="$ac_ext_saved" + ]) + AC_SUBST(LDXX) + case x"$ac_cv_pts_gcc_links_cxx" in + xyes-with-help) LDXX="$CXX_new"; AC_DEFINE(HAVE_PTS_C_LGCC_CPP_REQUIRED) ;; + xyes-with-help3) LDXX="$CXX_new"; AC_DEFINE(HAVE_PTS_C_LGCC3_CPP_REQUIRED) ;; + xyes) LDXX="$CXX_new" ;; + xno) LDXX="$CXX_new" ;; + *) AC_MSG_ERROR([Compilation failed, aborting.]) ;; + esac +]) + +dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002 +dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf +dnl Appends the specified flags to CXXFLAGS, so it will affect subsequent AC_* +dnl tests. +dnl Example: AC_PTS_PROG_CXXFLAGS(nrne, -fno-rtti -fno-exceptions) +AC_DEFUN(AC_PTS_PROG_CXXFLAGS, +[AC_REQUIRE([AC_PROG_CXX]) +AC_CACHE_CHECK(whether ${CXX-g++} accepts $2, ac_cv_prog_cxx_$1, +[echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} $2 -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_$1=yes; +else ac_cv_prog_cxx_$1=no; fi +rm -f conftest* +]) +if test $ac_cv_prog_cxx_$1 = yes; then CXXFLAGS="$CXXFLAGS $2"; fi +]) + +dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002 +dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf +dnl Appends the specified flags to CXXFLAGSB, so it won't affect subsequent +dnl AC_* tests. +dnl Example: AC_PTS_PROG_CXXFLAGSB(apwaw, -ansi -pedantic -Wall -W) +AC_DEFUN(AC_PTS_PROG_CXXFLAGSB, +[AC_REQUIRE([AC_PROG_CXX]) +AC_SUBST(CXXFLAGSB) +AC_CACHE_CHECK(whether ${CXX-g++} accepts $2, ac_cv_prog_cxx_$1, +[echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} $2 -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_$1=yes; +else ac_cv_prog_cxx_$1=no; fi +rm -f conftest* +]) +if test $ac_cv_prog_cxx_$1 = yes; then CXXFLAGSB="$CXXFLAGSB $2"; fi +]) + +dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002 +dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf +dnl Appends the specified flags to CFLAGS, so it will affect subsequent AC_* +dnl tests. +dnl Example: AC_PTS_PROG_CFLAGS(nrne, -fno-rtti -fno-exceptions) +AC_DEFUN(AC_PTS_PROG_CFLAGS, +[AC_REQUIRE([AC_PROG_CC]) +AC_CACHE_CHECK(whether ${CC-gcc} accepts $2, ac_cv_prog_cc_$1, +[echo 'void f(void);void f(void){}' > conftest.c +if test -z "`${CC-gcc} $2 -c conftest.c 2>&1`" +then ac_cv_prog_cc_$1=yes; +else ac_cv_prog_cc_$1=no; fi +rm -f conftest* +]) +if test $ac_cv_prog_cc_$1 = yes; then CFLAGS="$CFLAGS $2"; fi +]) + +dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002 +dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf +dnl Appends the specified flags to CFLAGSB, so it won't affect subsequent +dnl AC_* tests. +dnl Example: AC_PTS_PROG_CFLAGSB(apwaw, -ansi -pedantic -Wall -W) +AC_DEFUN(AC_PTS_PROG_CFLAGSB, +[AC_REQUIRE([AC_PROG_CC]) +AC_SUBST(CFLAGSB) +AC_CACHE_CHECK(whether ${CC-gcc} accepts $2, ac_cv_prog_cc_$1, +[echo 'void f(void);void f(void){}' > conftest.c +if test -z "`${CC-gcc} $2 -c conftest.c 2>&1`" +then ac_cv_prog_cc_$1=yes; +else ac_cv_prog_cc_$1=no; fi +rm -f conftest* +]) +if test $ac_cv_prog_cc_$1 = yes; then CFLAGSB="$CFLAGSB $2"; fi +]) + +dnl by pts@fazekas.hu at Sat Apr 6 11:49:59 CEST 2002 +dnl Similar to AC_C_CHAR_UNSIGNED, but without the +dnl `warning: AC_TRY_RUN called without default to allow cross compiling'. +AC_DEFUN(AC_PTS_C_CHAR_UNSIGNED, +[AC_CACHE_CHECK(whether char is unsigned, ac_cv_c_char_unsigned, +[if test "$GCC" = yes; then + # GCC predefines this symbol on systems where it applies. +AC_EGREP_CPP(yes, +[#ifdef __CHAR_UNSIGNED__ + yes +#endif +], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no) +else +AC_TRY_RUN( +[/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +int main() { + volatile char c = 255; return(c < 0); +}], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no, + [AC_MSG_ERROR(cross compiling not supported by .._PTS_C_CHAR_UNSIGNED)]) +fi]) +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + AC_DEFINE(__CHAR_UNSIGNED__) +fi +]) + +dnl by pts@fazekas.hu at Sun Apr 14 22:08:04 CEST 2002 + +dnl Ripped from autoconf's acgeneral.m4. Tests with `test -x'. +dnl AC_PTS_PATH_XPROG(VARIABLE, PROG-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AC_PTS_PATH_XPROG, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +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([$4], , $PATH, [$4])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" +dnl If no 3rd arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$3], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$3" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +dnl by pts@fazekas.hu at Sun Apr 14 21:50:13 CEST 2002 + +dnl Usage: AC_PTS_WARN_PROG(zip, [zip might become useful for /Compression/ZIP]) +AC_DEFUN(AC_PTS_WARN_PROG, +[AC_PTS_PATH_XPROG(pts_$1, $1) +if test x"$ac_cv_path_pts_$1" = x; then + AC_MSG_WARN($1 would provide increased functionality to this program:) + AC_MSG_WARN($2) +fi +]) +dnl Usage: AC_PTS_ERR_PROG(make, [make is required for compiling this program]) +AC_DEFUN(AC_PTS_ERR_PROG, +[AC_PTS_PATH_XPROG(pts_$1, $1) +if test x"$ac_cv_path_pts_$1" = x; then + AC_MSG_WARN($1 is required:) + AC_MSG_ERROR($2) +fi +]) + +dnl by pts@fazekas.hu at Sat Jun 1 15:00:44 CEST 2002 +dnl ac_n=... autoconf2.13 -> autoconf2.50 +dnl Usage: AC_PTS_RUN_OK(CMDLINE, ACTION-OF-EXITCODE-0, ACTION-IF-ERROR) +AC_DEFUN(AC_PTS_RUN_OK, +[ac_n="${ac_n:-$ECHO_N}" +echo $ac_n "running $1""... $ac_c" 1>&AC_FD_MSG +echo "configure:__oline__: running $1" >&AC_FD_CC +if >&AC_FD_CC 2>&AC_FD_CC $1; then : + AC_MSG_RESULT(ok) + $2 +else + AC_MSG_RESULT(error) + $3 +fi +]) + +dnl by pts@fazekas.hu at Sat Jun 1 15:13:36 CEST 2002 +AC_DEFUN(AC_PTS_OK, [echo "configure:__oline__: all OK" >&AC_FD_CC +]) + +dnl __EOF__ diff --git a/Build/source/utils/sam2p/appliers.cpp b/Build/source/utils/sam2p/appliers.cpp new file mode 100644 index 00000000000..88f1449ea0a --- /dev/null +++ b/Build/source/utils/sam2p/appliers.cpp @@ -0,0 +1,2236 @@ +/* + * appliers.cpp -- specific OutputRule implementations + * by pts@fazekas.hu at Sat Mar 16 14:45:02 CET 2002 + * Blanca JAI additions at Tue May 21 13:18:26 CEST 2002 + * TIFF output at Tue Jun 4 19:50:45 CEST 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "rule.hpp" +#include "error.hpp" +#include "encoder.hpp" +#include "in_jai.hpp" +#include "crc32.h" /* crc32() used by out_png_work() */ +#include <string.h> + +/** Appends 4 bytes in MSB first (network) byte order */ +static inline void mf32(char *&p, slen_t u32) { + p[0]=(u32>>24)&255; + p[1]=(u32>>16)&255; + p[2]=(u32>> 8)&255; + p[3]=(u32 )&255; + p+=4; +} +/** Appends 4 bytes in LSB first (PC) byte order */ +static inline void lf32(char *&p, slen_t u32) { + p[0]=(u32 )&255; + p[1]=(u32>> 8)&255; + p[2]=(u32>>16)&255; + p[3]=(u32>>24)&255; + p+=4; +} +/** Appends 2 bytes in LSB first (PC) byte order */ +static inline void lf16(char *&p, unsigned u16) { + p[0]=(u16 )&255; + p[1]=(u16>> 8)&255; + p+=2; +} + + +/* --- at Sat Mar 23 15:42:17 CET 2002, removed obsolete + * PostScript Level2 FlateEncode or LZWEncode filter, predictors supported + * written at Mar 16 14:48:27 CET 2002 + */ + +/* --- Sun Mar 17 15:43:20 CET 2002 */ + +#if 0 +/* l1fa85g.tte was a special .tte that is not built in to bts.ttt, but I've + * integrated it into bts2.ttt at Sun Sep 22 00:48:21 CEST 2002. I've also + * integrated _l1fa85g_ to _l1c_ that day. + */ +static char *l1fa85g_tte= +#include "l1fa85g.tth" + +/** PostScript Level1 FlateEncode, A85, without Predictor */ +Rule::Applier::cons_t out_l1fa85g_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (!cache->isPS() + || cache->Compression!=Rule::Cache::CO_ZIP + || cache->hasPredictor() + || !cache->isGray() + || cache->TransferEncoding!=cache->TE_A85 + || (!cache->WarningOK && !cache->isPSL3()) + ) return Rule::Applier::DONT_KNOW; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_l1fa85g_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + /* by pts@fazekas.hu at Sun Mar 17 15:52:48 CET 2002 */ + // Imp: two other TransferEncodings [no more, since #if 0] + if (out_l1fa85g_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + if (!or_->cache.isPSL3()) + Error::sev(Error::WARNING_DEFER) << "l1fa85g: /ZIP without /PSL3 will be slow" << (Error*)0; + or_->doSampleFormat(sf); + PSEncoder *bp=PSEncoder::newASCII85Encode(out, or_->cacheHints.TransferCPL); + PSEncoder *cp=PSEncoder::newFlateEncode(*bp, or_->cacheHints.Effort); + Rule::writeTTE(out, out, *cp, l1fa85g_tte, or_, sf, Rule::writeData); + delete bp; + delete cp; + return Rule::Applier::OK; +} + +Rule::Applier out_l1fa85g_applier = { "l1fa85g", out_l1fa85g_check_rule, out_l1fa85g_work, 0 }; +#endif + +/* l2jbin --- Sun Mar 17 21:45:22 CET 2002 + * p0jbin (integrated to p0jbin) --- Mon Apr 15 23:29:13 CEST 2002 + */ + +//static char *l2jbin_tte= +//#include "l2jbin.tth" + +/** PostScript Level2 DCTEncode (Baseline JPEG), Binary */ +Rule::Applier::cons_t out_l2jbin_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if ((!cache->isPS() && !cache->isPDF()) + || cache->Compression!=Rule::Cache::CO_JAI + ) return Rule::Applier::DONT_KNOW; + /* Dat: not unrequired anymore: cache->TransferEncoding!=cache->TE_Binary */ + bool badp=false; + if (cache->isPS() && !cache->isPSL2()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PSL* /Compression/JAI requires /PSL2+" << (Error*)0; + badp=true; + } + if (cache->SampleFormat!=Image::SF_Asis) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PSL*|PDF* /Compression/JAI requires /SampleFormat/Asis" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PSL*|PDF* /Compression/JAI requires /Predictor 1" << (Error*)0; + badp=true; + } + return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK); + /* ^^^ 0+: pacify g++-3.1 */ +} +Rule::Applier::cons_t out_l2jbin_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + char *strings[]={ (char*)NULLP/*LanguageLevel, PDF-1.`0'*/, ""/*colorSpace*/ }; + //, " F closefile T closefile"/*closes*/ }; + // Error::sev(Error::WARNING_DEFER) << "l2jbin: /ZIP without /PSL3 will be slow" << (Error*)0; + if (out_l2jbin_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + assert(sf->getImg()->getBpc()==8); + or_->doSampleFormat(sf); + // PSEncoder *bp=PSEncoder::newASCII85Encode(out, or_->cacheHints.TransferCPL); + Rule::Cache *cache=&or_->cache; + Filter::VerbatimE outve(out); /* required since template /p0jbin is TTM */ + GenBuffer::Writable *op=cache->isPDF() ? &outve : &out, *tp=op; + strings[0]=const_cast<char*>(cache->isPDF() ? (char const*)"0" : (char const*)"2"); + if (cache->TransferEncoding==cache->TE_A85) tp=PSEncoder::newASCII85Encode (*op, or_->cacheHints.TransferCPL); + else if (cache->TransferEncoding==cache->TE_Hex) tp=PSEncoder::newASCIIHexEncode(*op, or_->cacheHints.TransferCPL); + // else strings[2]=" F closefile"; + Rule::writeTTT(*op, *tp, *tp, !cache->isPDF()?"l2jbin":cache->isPDFB()?"p0jbb":"p0jbin", or_, sf, Rule::writePalData, strings); + if (tp!=op) delete tp; + /* Dat: outve is deleted by C++ scope */ + // if (tp!=op) delete tp; /* BUGFIX at Thu Jan 20 15:04:47 CET 2005 */ + return Rule::Applier::OK; +} + +Rule::Applier out_l2jbin_applier = { "PSL2+PDF-JAI", out_l2jbin_check_rule, out_l2jbin_work, 0 }; + +/* --- */ + +#if 0 /* integrated to _l2jbin_ at Sun Sep 22 14:29:13 CEST 2002 */ +//static char *p0jbin_ttm= +//#include "p0jbin.tth" + +/** PostScript Level2 DCTEncode (Baseline JPEG), Binary */ +Rule::Applier::cons_t out_p0jbin_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (!cache->isPDF() + || cache->Compression!=Rule::Cache::CO_JAI + ) return Rule::Applier::DONT_KNOW; + /* Dat: not unrequired anymore: cache->TransferEncoding!=cache->TE_Binary */ + bool badp=false; + if (cache->SampleFormat!=Image::SF_Asis) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PDF* /Compression/JAI requires /SampleFormat/Asis" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PDF* /Compression/JAI requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_p0jbin_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + char *strings[]={ "0"/*PDF-1.`0'*/, ""/*colorSpace*/ }; + // " F closefile"/*closes*/ }; + if (out_p0jbin_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + assert(sf->getImg()->getBpc()==8); + or_->doSampleFormat(sf); + Rule::Cache *cache=&or_->cache; + + Filter::VerbatimE outve(out); /* required since template /p0jbin is TTM */ + GenBuffer::Writable *tp=&outve; + if (cache->TransferEncoding==cache->TE_A85) tp=PSEncoder::newASCII85Encode (outve, or_->cacheHints.TransferCPL); + else if (cache->TransferEncoding==cache->TE_Hex) tp=PSEncoder::newASCIIHexEncode(outve, or_->cacheHints.TransferCPL); + else strings[2]=""; + +#if 0 /* old */ + MiniPS::VALUE ttm; + { Filter::FlatR flatD(p0jbin_ttm); + MiniPS::Parser p(&flatD); + ttm=p.parse1(); + if (p.parse1(p.EOF_ALLOWED)!=MiniPS::Qundef || MiniPS::getType(ttm)!=MiniPS::T_ARRAY) + Error::sev(Error::EERROR) << "TTM: the TTM file should contain a single array" << (Error*)0; + /* ^^^ Dat: the result of the second p.parse1() doesn't get delete0(...)d */ + } + Filter::VerbatimE outve(out); + Rule::writeTTM(outve, outve, outve, MiniPS::RARRAY(ttm), or_, sf, Rule::writePalData, strings); + MiniPS::delete0(ttm); +#else /* new */ + Rule::writeTTT(outve, *tp, *tp, cache->isPDFB()?"p0jbb":"p0jbin", or_, sf, Rule::writePalData, strings); +#endif + if (tp!=&outve)delete tp; + return Rule::Applier::OK; +} + +Rule::Applier out_p0jbin_applier = { "PDF-JAI", out_p0jbin_check_rule, out_p0jbin_work, 0 }; +#endif + +/* --- Fri Mar 22 11:52:53 CET 2002 */ +/* PDF added at Sat Apr 20 20:07:34 CEST 2002 */ +/* Integrated l23ind1 at Sat Apr 20 20:24:21 CEST 2002 */ + +//static char *l23_tte= +//#include "l23.tth" + +/** PostScript Level2 and PDF generic non-transparent */ +Rule::Applier::cons_t out_l23_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + unsigned char sf=cache->SampleFormat; + if (cache->hasPredictor() && cache->Compression!=Rule::Cache::CO_ZIP && cache->Compression!=Rule::Cache::CO_LZW) { + Error::sev(Error::WARNING_DEFER) << "check_rule: real /Predictor requires /ZIP or /LZW" << (Error*)0; + return Rule::Applier::BAD; + } + + // assert(cache->isPSL2() && (sf==Image::SF_Transparent2 || sf==Image::SF_Transparent4 || sf==Image::SF_Transparent8)); + + if (!cache->isPSL2() && !cache->isPDF() + || (sf!=Image::SF_Gray1 && sf!=Image::SF_Gray2 && sf!=Image::SF_Gray4 && sf!=Image::SF_Gray8 + && sf!=Image::SF_Indexed1 && sf!=Image::SF_Indexed2 && sf!=Image::SF_Indexed4 && sf!=Image::SF_Indexed8 + && sf!=Image::SF_Rgb1 && sf!=Image::SF_Rgb2 && sf!=Image::SF_Rgb4 && sf!=Image::SF_Rgb8 + && sf!=Image::SF_Transparent2 && sf!=Image::SF_Transparent4 && sf!=Image::SF_Transparent8 + && sf!=Image::SF_Mask) + || cache->TransferEncoding==cache->TE_ASCII + || !cache->isZIPOK() + ) return Rule::Applier::DONT_KNOW; + #if !HAVE_LZW + if (cache->Compression==Rule::Cache::CO_LZW) return Rule::Applier::DONT_KNOW; + #endif + + // if (cache->isDCTE() && !cache->isRGB() && !cache->isGray()) { + bool badp=false; + if (cache->isDCTE() && cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Indexed8) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /DCTEncode requires /Rgb8 or /Gray8 (or /Indexed8)" << (Error*)0; + badp=true; + } + if (sf==Image::SF_Transparent2 || sf==Image::SF_Transparent4 || sf==Image::SF_Transparent8) { + if (cache->isPDF()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: unsupported /Transparent+ for /PDF*" << (Error*)0; + badp=true; + } else assert(cache->isPSL2()); + } + return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK); +} +Rule::Applier::cons_t out_l23_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + Rule::stream_writer_t writeXData=Rule::writePalData; + char LanguageLevel[2]="2", closes[30]; + SimBuffer::B colorSpace; + char const*strings[]={ LanguageLevel, (char*)NULLP /*colorSpace*/, closes }; + Rule::Cache *cache=&or_->cache; + // assert(0); + if (out_l23_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf, true); + if (cache->Compression==Rule::Cache::CO_ZIP) { + if (!cache->isPDF()) LanguageLevel[0]='3'; + } else if (cache->isPDF()) LanguageLevel[0]='0'; + if (cache->isIndexed() || cache->isTransparentM()) { + unsigned ncols=PTS_dynamic_cast(Image::Indexed*,sf->getImg())->getNcols(); + colorSpace << "[/Indexed/DeviceRGB " << ncols-1; + if (ncols==0) { /* Avoid writing zero bytes to the filters */ + /* Imp: verify this in Acrobat Reader */ + colorSpace << "()]"; + } else if (!cache->isPDF()) { /* Insert an in-line hexdump. No better way :-( */ + /*sprintf(colorSpace, "[/Indexed/DeviceRGB %u T %u string readstring pop]", ncols-1, ncols*3); */ + colorSpace << " T " << ncols*3 << " string readstring pop]"; + } else { /* Insert an in-line hexdump. No shorter way for PDF */ +#if 0 + colorSpace="/DeviceGray "; +#else + /* SUXX: gs5.50 & PDF & /Indexed doesn't work */ + colorSpace << "\n<"; + GenBuffer::Writable *hp=PSEncoder::newASCIIHexEncode(colorSpace, or_->cacheHints.TransferCPL); + hp->vi_write(sf->getImg()->getHeadp(), ncols*3); + hp->vi_write(0,0); + colorSpace << ']'; /* Dat: '>' is appended by ASCIIHexEncode */ +#endif + writeXData=Rule::writeData; /* The palette has already been written. */ + } + } else if (cache->isGray()) colorSpace="/DeviceGray "; + else { assert(cache->isRGB()); colorSpace="/DeviceRGB "; } + if (cache->SampleFormat==Image::SF_Mask || cache->SampleFormat==Image::SF_Indexed1) writeXData=Rule::writeData; + + GenBuffer::Writable *vp=&out; + if (cache->isPDF()) vp=new Filter::VerbatimE(out); /* required since template /p02* is TTM */ + + GenBuffer::Writable *tp=vp; + if (cache->TransferEncoding==cache->TE_A85) tp=PSEncoder::newASCII85Encode (*vp, or_->cacheHints.TransferCPL); + else if (cache->TransferEncoding==cache->TE_Hex) tp=PSEncoder::newASCIIHexEncode(*vp, or_->cacheHints.TransferCPL); + + GenBuffer::Writable *cp=tp; + switch (cache->Compression) { + case Rule::Cache::CO_None: break; + case Rule::Cache::CO_ZIP: cp=PSEncoder::newFlateEncode(*tp, or_->cacheHints.Effort); break; + case Rule::Cache::CO_LZW: cp=PSEncoder::newLZWEncode(*tp); break; + case Rule::Cache::CO_RLE: cp=PSEncoder::newRunLengthEncode(*tp, or_->cacheHints.RecordSize); break; + case Rule::Cache::CO_Fax: cp=PSEncoder::newCCITTFaxEncode(*tp, or_->cacheHints.K, or_->cacheHints.EncoderBPL, /*EndOfLine:*/ or_->cacheHints.K>0); break; + /* ^^^ getBpp() BUGFIX at Wed Jul 3 20:00:30 CEST 2002 */ + /* ^^^ EndOfLine BUGFIX at Wed Jul 3 21:12:54 CEST 2002 + * With EndOfLine==false, `sam2p -c:fax:1', acroread triggers the bug. + * With EndOfLine==false, `sam2p -c:fax:2', acroread and gs trigger the bug. + */ + + case Rule::Cache::CO_IJG: cp=PSEncoder::newDCTIJGEncode(*tp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.Quality); break; + case Rule::Cache::CO_DCT: { SimBuffer::B other_parameters; + or_->cacheHints.DCT->dump(other_parameters, 0, false); + cp=PSEncoder::newDCTEncode(*tp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.ColorTransform, other_parameters); + break; } + default: assert(0); + } + + GenBuffer::Writable *pp=cp; + if (cache->hasPredictor()) pp=PSEncoder::newPredictor(*cp, cache->Predictor, or_->cacheHints.PredictorBPC, or_->cacheHints.PredictorColumns, or_->cacheHints.PredictorColors); + + #if 0 /* Sun Sep 22 20:40:51 CEST 2002 */ + if (cp!=tp) strcpy(closes," F closefile"); else closes[0]='\0'; + if (tp!=vp) strcpy(closes+strlen(closes)," T closefile"); + #endif + + strings[1]=colorSpace.term0()(); + Rule::writeTTT(*vp, *tp, *pp, + !cache->isPDF() ? ( + cache->SampleFormat==Image::SF_Indexed1 ? "l23ind1" : + cache->SampleFormat==Image::SF_Mask ? "l23mask" : + cache->isTransparentM() ? "l23tran2" : + "l23" + ) : cache->isPDFB() ? ( + cache->SampleFormat==Image::SF_Indexed1 ? "p02ind1bb" : + cache->SampleFormat==Image::SF_Mask ? "p02maskbb" : + "p02bb" + ) : ( + cache->SampleFormat==Image::SF_Indexed1 ? "p02ind1" : + cache->SampleFormat==Image::SF_Mask ? "p02mask" : + "p02" + ), or_, sf, writeXData, strings); + if (pp!=cp) delete pp; + if (cp!=tp) delete cp; + if (tp!=vp) delete tp; + if (vp!=&out)delete vp; + return Rule::Applier::OK; +} + +Rule::Applier out_l23_applier = { "PSL23+PDF", out_l23_check_rule, out_l23_work, 0 }; + +/* --- Fri Mar 22 17:22:40 CET 2002 -- Sat Jun 15 16:03:06 CEST 2002 */ + +/* integrated l1tr at Sat Jun 15 16:03:03 CEST 2002 */ +/* added /Bbox at Sat Jun 15 16:03:31 CEST 2002 */ + +//static char *l1tr_tte= +//#include "l1tr.tth" + +/** PostScript Level1 or PDF Fully transparent image */ +Rule::Applier::cons_t out_l1tr_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (!(cache->isPS() || cache->isPDF()) + || (cache->SampleFormat!=Image::SF_Transparent && cache->SampleFormat!=Image::SF_Bbox && cache->SampleFormat!=Image::SF_Opaque) + ) return Rule::Applier::DONT_KNOW; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_l1tr_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + char t[]="...."; + if (out_l1tr_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf); + Rule::Cache *cache=&or_->cache; + Filter::VerbatimE outve(out); /* required since template /p0* is TTM */ + if (cache->isPS()) { t[0]='l'; t[1]='1'; } + else { t[0]='p'; t[1]='0'; } + switch (cache->SampleFormat) { + case Image::SF_Transparent: t[2]='t'; t[3]='r'; break; + case Image::SF_Opaque: t[2]='o'; t[3]='p'; break; + case Image::SF_Bbox: t[2]='b'; t[3]='b'; break; + default: assert(0); + } + Rule::writeTTT(outve, outve, outve, t, or_, sf, 0/*NULLP*/); + return Rule::Applier::OK; +} + +Rule::Applier out_l1tr_applier = { "P-TrOpBb", out_l1tr_check_rule, out_l1tr_work, 0 }; + +/* --- */ + +/* --- l23mask Fri Mar 22 18:11:12 CET 2002 + * --- l23ind1 Fri Mar 22 18:11:12 CET 2002 + * removed (integrated to l23) at Sat Apr 20 20:25:57 CEST 2002 + */ + +/* --- l1mask Fri Mar 22 18:33:01 CET 2002 + * --- l1mashex Sun Apr 14 15:25:25 CEST 2002 + * --- l1in1 Fri Mar 22 18:33:37 CET 2002 + * --- l1in1hex Fri Mar 22 18:33:37 CET 2002 + * removed (integrated to l1c) at Sat Apr 20 20:25:57 CEST 2002 + * --- lcr Sat Jun 1 17:09:57 CEST 2002 + * removed (integrated to l1c) at Sun Jun 2 16:48:31 CEST 2002 + * --- l1gbh + * removed (integrated to l1c) at Sun Jun 2 16:48:31 CEST 2002 + * --- l1fa85g.tte: PostScript Level1 FlateEncode, A85, without Predictor + * removed (integrated to l1c) at Sun Sep 22 00:48:21 CEST 2002 + */ + +/* --- Sun Jun 2 16:48:44 CEST 2002 */ + +//static char *l1mask_tte= +//#include "l1mask.tth" + +static void gen_tkey(char *tkey, GenBuffer::Writable& out, GenBuffer::Writable*&tp, GenBuffer::Writable*& cp, Rule::OutputRule*or_) { + Rule::Cache *cache=&or_->cache; + tp=&out; + if (cache->TransferEncoding==cache->TE_A85) { tkey[3]='8'; tp=PSEncoder::newASCII85Encode (out, or_->cacheHints.TransferCPL); } + else if (cache->TransferEncoding==cache->TE_Hex) { tkey[3]='h'; tp=PSEncoder::newASCIIHexEncode(out, or_->cacheHints.TransferCPL); } + else tkey[3]='b'; + cp=tp; + if (cache->Compression==Rule::Cache::CO_RLE) { tkey[4]='r'; cp=PSEncoder::newRunLengthEncode(*tp, or_->cacheHints.RecordSize); } + else if (cache->Compression==Rule::Cache::CO_ZIP) { tkey[4]='z'; cp=PSEncoder::newFlateEncode(*tp, or_->cacheHints.Effort); } + else if (cache->Compression==Rule::Cache::CO_LZW) { tkey[4]='l'; cp=PSEncoder::newLZWEncode(*tp); } + else tkey[4]='n'; + /* vvv removed 'm' and '1' at Sun Sep 22 17:53:08 CEST 2002 */ + tkey[2]=// cache->SampleFormat==Image::SF_Mask ? 'm' : + // cache->SampleFormat==Image::SF_Indexed1 ? '1' : + cache->SampleFormat==Image::SF_Indexed2 ? '2' : + cache->SampleFormat==Image::SF_Indexed4 ? '4' : + cache->SampleFormat==Image::SF_Indexed8 ? '8' : + cache->SampleFormat==Image::SF_Transparent2 ? 't' : + cache->SampleFormat==Image::SF_Transparent4 ? 't' : + cache->SampleFormat==Image::SF_Transparent8 ? 't' : + 'g'; /* /Gray*, /Rgb*, /Mask, /Indexed1 */ +} + +/** PostScript Level1 uncompressed binary or hex */ +Rule::Applier::cons_t out_l1c_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if ((cache->FileFormat!=cache->FF_PSL1 && cache->FileFormat!=cache->FF_PSLC && cache->FileFormat!=cache->FF_PSL2) + || (cache->FileFormat==cache->FF_PSL2 && cache->Compression!=Rule::Cache::CO_ZIP) + || (cache->TransferEncoding!=cache->TE_Binary && cache->TransferEncoding!=cache->TE_Hex && cache->TransferEncoding!=cache->TE_A85) + || (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_RLE && cache->Compression!=Rule::Cache::CO_ZIP && cache->Compression!=Rule::Cache::CO_LZW) + || cache->hasPredictor() + || !(cache->isTransparentM() || cache->isIndexed() || cache->isGray() || cache->isRGB()) + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + if (cache->FileFormat==cache->FF_PSL1 && cache->SampleFormat!=Image::SF_Indexed1 && cache->isIndexed()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /SampleFormat/Indexed+ doesn't work with /FileFormat/PSL1 (use /PSLC or /PSL2)" << (Error*)0; + badp=true; + } + if (cache->FileFormat==cache->FF_PSL1 && cache->isRGB()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /SampleFormat/RGB* doesn't work with /FileFormat/PSL1 (use /PSLC or /PSL2)" << (Error*)0; + badp=true; + } + char tkey[]="l1..."; /* /l1{2,4,8,t}{8,h}{r,z,l} */ + GenBuffer::Writable *tp0,*cp0,*out=(GenBuffer::Writable*)NULLP; + gen_tkey(tkey, *out, tp0, cp0, or_); + /* fprintf(stderr,"tkey=%s\n", tkey); */ + if (!badp && Rule::Templates->get(tkey, strlen(tkey))==MiniPS::Qundef) return Rule::Applier::DONT_KNOW; + return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK); + /* ^^^ Dat: 0+: pacify gcc-3.1 */ +} +Rule::Applier::cons_t out_l1c_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + if (out_l1c_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + /* Dat: only these have been defined so far: grep '^/l1[248tg][8h][rzl]' bts2.ttt + * /l1thr /l1g8r /l1ghr /l128r /l12hr /l148r /l14hr /l188r /l18hr /l1g8z /l1ghz /l1g8l /l1ghl + */ + or_->doSampleFormat(sf, true); /* Dat: `true': because of /Transparent+ */ + char tkey[]="l1..."; /* /l1{2,4,8,t}{8,h}{r,z,l} */ + GenBuffer::Writable *tp, *cp; + gen_tkey(tkey, out, tp, cp, or_); + // fprintf(stderr, "tkey=(%s)\n", tkey); + Rule::writeTTT(out, *tp, *cp, tkey, or_, sf, + tkey[2]=='2' || tkey[2]=='4' || tkey[2]=='8' || tkey[2]=='t' ? Rule::writePalData : Rule::writeData + ); + // Rule::writeTTT(out, *tp, *cp, tkey, or_, sf, Rule::writePalData); + if (cp!=tp) delete cp; + if (tp!=&out)delete tp; + return Rule::Applier::OK; +} + +Rule::Applier out_l1c_applier = { "PSL1C", out_l1c_check_rule, out_l1c_work, 0 }; + +/* lcrbin (lcrb) --- Sun Apr 14 16:50:14 CEST 2002 + * lcrhex (lcr8, lcrh) --- Sun Apr 14 16:50:22 CEST 2002 + * removed (integrated to _l1c_) at Sat Jun 1 17:09:52 CEST 2002 + */ + +#if 0 +/* --- Sat Jun 1 17:09:57 CEST 2002 */ + +//static char *lcrbin_tte= +//#include "lcrbin.tth" + +/** PostScript Level1+C uncompressed RGB image */ +Rule::Applier::cons_t out_lcr_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (!cache->isPS() + || cache->FileFormat==cache->FF_PSL1 + || (cache->TransferEncoding!=cache->TE_Binary && cache->TransferEncoding!=cache->TE_Hex && cache->TransferEncoding!=cache->TE_A85) + || cache->Compression!=Rule::Cache::CO_None + || cache->hasPredictor() + || !cache->isRGB() + ) return Rule::Applier::DONT_KNOW; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_lcr_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + Rule::Cache *cache=&or_->cache; + if (out_lcr_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf); + char tkey[]="lcr."; + GenBuffer::Writable *tp=&out; + if (cache->TransferEncoding==cache->TE_A85) { tkey[3]='8'; tp=PSEncoder::newASCII85Encode (out, or_->cacheHints.TransferCPL); } + else if (cache->TransferEncoding==cache->TE_Hex) { tkey[3]='h'; tp=PSEncoder::newASCIIHexEncode(out, or_->cacheHints.TransferCPL); } + else tkey[3]='b'; + Rule::writeTTT(out, *tp, *tp, tkey, or_, sf, Rule::writeData); + if (tp!=&out)delete tp; + return Rule::Applier::OK; +} + +Rule::Applier out_lcr_applier = { "PSLC-RGB", out_lcr_check_rule, out_lcr_work, 0 }; +#endif + +/* --- Sat Mar 23 12:37:04 CET 2002; Tue Jul 2 10:23:44 CEST 2002 */ + +Rule::Applier::cons_t out_gif89a_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + bool badp=false; + if (cache->FileFormat!=cache->FF_GIF89a + ) return Rule::Applier::DONT_KNOW; + if (!cache->isIndexed() && !cache->isTransparentM()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a must be /Indexed*, /Mask or /Transparent+" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_Binary) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a requires /Binary" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_LZW) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a requires /LZW" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a requires /Predictor 1" << (Error*)0; + badp=true; + } + #if !USE_OUT_GIF + Error::sev(Error::WARNING_DEFER) << "check_rule: please `configure --enable-gif' for /GIF89a" << (Error*)0; + badp=true; + #endif + if (badp) return Rule::Applier::BAD; + or_->cache.WarningOK=true; + return Rule::Applier::OK; +} +#if USE_OUT_GIF + #if OBJDEP + # warning REQUIRES: out_gif.o + #endif + extern void out_gif_write(GenBuffer::Writable& out, Image::Indexed *img); /* out_gif.cpp */ + Rule::Applier::cons_t out_gif89a_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + if (out_gif89a_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->cache.SampleFormat=(Image::sf_t)(or_->cache.isIndexed()? 0+Image::SF_Indexed8: 0+Image::SF_Transparent8); + /* ^^^ Dat: 0+: pacify gcc-3.1; (Image::sf_t): pacify VC6.0 */ + or_->doSampleFormat(sf); + out_gif_write(out, PTS_dynamic_cast(Image::Indexed*,sf->getImg())); + return Rule::Applier::OK; + } +#else +/*# define out_gif89a_check_rule (Rule::Applier::check_rule_t)NULLP*/ +# define out_gif89a_work (Rule::Applier::work_t) NULLP +#endif + +Rule::Applier out_gif89a_applier = { +#if HAVE_LZW + "GIF89a+LZW" +#else + "GIF89a" +#endif + , out_gif89a_check_rule, out_gif89a_work, 0 }; + +/* --- Tue Jun 4 19:51:03 CEST 2002 */ + +Rule::Applier::cons_t out_xpm_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + bool badp=false; + if (cache->FileFormat!=cache->FF_XPM + ) return Rule::Applier::DONT_KNOW; + if (!cache->isIndexed() && !cache->isTransparentM()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM must be /Indexed*, /Mask or /Transparent+" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_ASCII && cache->TransferEncoding!=cache->TE_Binary) { + /* ^^^ && BUGFIX at Thu Jul 11 21:57:09 CEST 2002 */ + Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM requires /TransferEncoding/ASCII" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM requires /Compression/None" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + or_->cache.WarningOK=true; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_xpm_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + if (out_xpm_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->cache.SampleFormat=(Image::sf_t)(or_->cache.isIndexed()? 0+Image::SF_Indexed8: 0+Image::SF_Transparent8); + /* ^^^ force 8-bit; may trigger warnings... */ + /* ^^^ Dat: 0+: pacify gcc-3.1 */ + or_->doSampleFormat(sf); + Image::Indexed *iimg=PTS_dynamic_cast(Image::Indexed*,sf->getImg()); + /* vvv 93 useful ASCII chars (+ '\0'), missing: " and \ ; plus a hextable */ + static char const xpmc=93; + static char const xpms[xpmc+1]="0123456789abcdef !#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`ghijklmnopqrstuvwxyz{|}~"; + + Image::Sampled::dimen_t wd=iimg->getWd(), htc=iimg->getHt(); + bool pal2ch=iimg->getNcols()>xpmc; + // pal2ch=true; + out << "/* XPM */\nstatic char *sam2p_xpm[] = {\n" + "/* columns rows colors chars-per-pixel */\n\"" + << wd << ' ' << htc << ' ' << iimg->getNcols() + << ' ' << (pal2ch?2:1) << "\",\n"; + char const *p=iimg->getHeadp(), *pend=iimg->getRowbeg(), *phend; + char coline3[]="\".. c #ABCDEF\",\n"; + char cotran3[]="\".. c None s None \",\n"; + assert((pend-p)%3==0); + unsigned i=0; + bool transp=false; + if (iimg->getTransp()>=0) { pend-=3; assert((iimg->getTransp())*3+p==pend); transp=true; } + if (pal2ch) { + while (p!=pend) { + coline3[ 1]=xpms[i>>2]; + coline3[ 2]=xpms[i++&3]; + coline3[ 7]=xpms[*(unsigned char const*)p>>4]; + coline3[ 8]=xpms[*(unsigned char const*)p++&15]; + coline3[ 9]=xpms[*(unsigned char const*)p>>4]; + coline3[10]=xpms[*(unsigned char const*)p++&15]; + coline3[11]=xpms[*(unsigned char const*)p>>4]; + coline3[12]=xpms[*(unsigned char const*)p++&15]; + out << coline3; + } + if (transp) { + cotran3[ 1]=xpms[i>>2]; + cotran3[ 2]=xpms[i++&3]; + out << cotran3; + p+=3; + } + pend=iimg->getRowbeg()+wd*htc; + out << "/* Pixels */\n"; + char *obuf=new char[4+2*wd], *op; + obuf[0]='"'; + obuf[2*wd+1]='"'; + obuf[2*wd+2]=','; /* Dat: it's OK to have a comma in the last line */ + obuf[2*wd+3]='\n'; + while (htc--!=0) { + phend=p+wd; + op=obuf; + while (p!=phend) { *++op=xpms[*p>>2]; *++op=xpms[*p++&3]; } + out.vi_write(obuf, 2*wd+4); + } + } else { + coline3[1]='"'; + while (p!=pend) { + coline3[ 2]=xpms[i++]; + coline3[ 7]=xpms[*(unsigned char const*)p>>4]; + coline3[ 8]=xpms[*(unsigned char const*)p++&15]; + coline3[ 9]=xpms[*(unsigned char const*)p>>4]; + coline3[10]=xpms[*(unsigned char const*)p++&15]; + coline3[11]=xpms[*(unsigned char const*)p>>4]; + coline3[12]=xpms[*(unsigned char const*)p++&15]; + out << (coline3+1); + } + if (transp) { + cotran3[1]='"'; + cotran3[ 2]=xpms[i]; + out << (cotran3+1); + p+=3; + } + pend=iimg->getRowbeg()+wd*htc; + out << "/* Pixels */\n"; + char *obuf=new char[4+wd], *op; + obuf[0]='"'; + obuf[wd+1]='"'; + obuf[wd+2]=','; /* Dat: it's OK to have a comma in the last line */ + obuf[wd+3]='\n'; + while (htc--!=0) { + phend=p+wd; + op=obuf; + while (p!=phend) *++op=xpms[0U+*p++]; + out.vi_write(obuf, wd+4); + } + } + assert(p==pend); + out << "};\n"; + return Rule::Applier::OK; +} + +Rule::Applier out_xpm_applier = { "XPM", out_xpm_check_rule, out_xpm_work, 0 }; + +/* --- Sat Mar 23 13:18:07 CET 2002 */ + +Rule::Applier::cons_t out_pnm_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_PNM + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + // if (cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Gray1) { + if (!cache->isGray() && !cache->isRGB() && !cache->isIndexed() && !cache->isTransparentM()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM must be /Rgb8, /Gray8 or /Gray1" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_Binary && cache->TransferEncoding!=cache->TE_ASCII) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM requires /Binary or /ASCII" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM requires /Compression/None" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + or_->cache.WarningOK=true; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_pnm_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + /*static*/ char head[]={ 'P', 0, '\n', '#', ' ', 'b', 'y', ' ' }; + /*static*/ char tmp[72]; + Image::sf_t sfo=or_->cache.SampleFormat; + Image::Indexed *alphaChannel=(Image::Indexed*)NULLP; + if (out_pnm_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + if (or_->cache.SampleFormat==Image::SF_Gray1 || or_->cache.SampleFormat==Image::SF_Gray8) { + if (or_->cache.TransferEncoding==or_->cache.TE_ASCII) or_->cache.SampleFormat=Image::SF_Gray8; + } else if (or_->cache.SampleFormat==Image::SF_Gray2 || or_->cache.SampleFormat==Image::SF_Gray4) { + or_->cache.SampleFormat=Image::SF_Gray8; + } else if (or_->cache.isRGB()) { + or_->cache.SampleFormat=Image::SF_Rgb8; + } else { + assert(or_->cache.isIndexed() || or_->cache.isTransparentM()); + if (or_->cache.isTransparentM()) { + alphaChannel=PTS_dynamic_cast(Image::Indexed*,sf->getImg())->calcAlpha(); + sf->clearTransp(); /* BUGFIX at Tue Sep 17 10:05:47 CEST 2002 */ + } + or_->cache.SampleFormat=(Image::sf_t)( + !sf->canGrayy() ? 0+Image::SF_Rgb8 + : sf->minRGBBpcc()==1 ? 0+Image::SF_Gray1 : 0+Image::SF_Gray8); + /* ^^^ Dat: 0+: pacify gcc-3.1 */ + } + if (or_->cache.SampleFormat==Image::SF_Gray1 && or_->cache.TransferEncoding==or_->cache.TE_ASCII) + or_->cache.SampleFormat=Image::SF_Gray8; + or_->doSampleFormat(sf); + sfo=or_->cache.SampleFormat; + head[1]=(sfo==Image::SF_Rgb8 ? '3' : sfo==Image::SF_Gray8 ? '2' : '1') + +(or_->cache.TransferEncoding==or_->cache.TE_Binary)*3; + out.vi_write(head, sizeof(head)); + out << Error::banner0; + Image::Sampled *img=sf->getImg(); + out << '\n' << img->getWd() << ' ' << img->getHt(); + out << " 255\n"+(sfo==Image::SF_Gray1?4:0); + /* ^^^ SF_Gray1 BUGFIX at Tue Jun 4 21:44:17 CEST 2002 */ + register char *p=img->getRowbeg(), *t=(char*)NULLP; + slen_t len=img->getRlen()*img->getHt(); + // fprintf(stderr, "len=%u\n", len); + register unsigned smallen, i; + switch (head[1]) { + case '1': /* PBM ASCII */ + while (len>=70) { + smallen=70; t=tmp; while (smallen--!=0) *t++=(*p++==0)?'1':'0'; + /* ^^^ note the swapping of '0' and '1' above */ + *t++='\n'; out.vi_write(tmp, 71); + len-=70; + } + while (len--!=0) *t++=(*p++==0)?'0':'1'; + /* Dat: xv requires a whitespace just before EOF */ + *t++='\n'; out.vi_write(tmp, t-tmp); + break; + case '2': case '3': /* PGM ASCII, PPM ASCII */ + while (len!=0) { + if (len>17) { smallen=17; len-=17; } else { smallen=len; len=0; } + t=tmp; while (smallen--!=0) { + if ((i=*(unsigned char*)p++)<10) *t++=i+'0'; + else if (i<100) { *t++=i/10+'0'; *t++=i%10+'0'; } + else if (i<200) { *t++='1'; *t++=(i-100)/10+'0'; *t++=i%10+'0'; } + else { *t++='2'; *t++=(i-200)/10+'0'; *t++=i%10+'0'; } + *t++=' '; + } + /* Dat: xv requires a whitespace just before EOF */ + t[-1]='\n'; out.vi_write(tmp, t-tmp/*-(len==0)*/); + } + break; + case '4': /* PBM RAWBITS */ + /* Invert the image */ + while (len--!=0) *p++^=-1; + p=img->getRowbeg(); + len=img->getRlen()*img->getHt(); + /* fall through */ + default: /* PBM RAWBITS, PGM RAWBITS, PPM RAWBITS */ + /* fwrite(p, 1, len, stdout); */ + out.vi_write(p, len); + } + if (alphaChannel!=NULLP) { + /* OK: don't always output rawbits PBM file */ + assert(alphaChannel->getBpc()==1); + assert(alphaChannel->getWd()==img->getWd()); + assert(alphaChannel->getHt()==img->getHt()); + /* write PBM RAWBITS subfile (alpha channel) */ + if (or_->cache.TransferEncoding==or_->cache.TE_Binary) { + out << "P4 " << img->getWd() << ' ' << img->getHt() << '\n'; + out.vi_write(alphaChannel->getRowbeg(), alphaChannel->getRlen()*alphaChannel->getHt()); + /* ^^^ BUGFIX at Tue Sep 17 10:18:28 CEST 2002 */ + } else { + out << "P1 " << img->getWd() << ' ' << img->getHt() << '\n'; + alphaChannel->to8(); + p=alphaChannel->getRowbeg(); len=alphaChannel->getRlen()*alphaChannel->getHt(); + while (len>=70) { + smallen=70; t=tmp; while (smallen--!=0) *t++=(*p++!=0)?'1':'0'; + /* ^^^ note the non-swapping of '0' and '1' above */ + *t++='\n'; out.vi_write(tmp, 71); + len-=70; + } + while (len--!=0) *t++=(*p++!=0)?'0':'1'; + /* Dat: xv requires a whitespace just before EOF */ + *t++='\n'; out.vi_write(tmp, t-tmp); + } + delete alphaChannel; + } + return Rule::Applier::OK; +} + +Rule::Applier out_pnm_applier = { "PNM", out_pnm_check_rule, out_pnm_work, 0 }; + +/* --- Sat Aug 10 22:18:33 CEST 2002 */ + +Rule::Applier::cons_t out_xwd_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_XWD + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + if (cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Indexed8) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD must be /Rgb8, /Gray8 or /Indexed8" << (Error*)0; + return Rule::Applier::BAD; + } + if (cache->TransferEncoding!=cache->TE_Binary) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD requires /Binary" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD requires /Compression/None" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_xwd_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + static const unsigned + XWD_FILE_VERSION=7, + ZPixmap=2, + MSBFirst=1, + DirectColor=5, + PseudoColor=3, + //GrayScale=1, + StaticGray=0; + Image::sf_t sfo=or_->cache.SampleFormat; + if (out_xwd_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf); + sfo=or_->cache.SampleFormat; + char head[101], *p=head; + Image::Sampled *img=sf->getImg(); + slen_t bits_per_pixel, bitmap_pad, bytes_per_line; + unsigned ncolors; + + memset(head, '\0', 101); + /*header_size*/ mf32(p,101); + /*file_version*/ (p+=4)[-1]=XWD_FILE_VERSION; + /*pixmap_format*/ (p+=4)[-1]=ZPixmap; + /*pixmap_depth*/ (p+=4)[-1]=sfo==Image::SF_Rgb8 ? 24 : 8; + /*pixmap_width */ mf32(p, img->getWd()); + /*pixmap_height*/ mf32(p, img->getHt()); + /*xoffset*/ p+=4; + /*byte_order*/ (p+=4)[-1]=MSBFirst; + /*bitmap_unit*/ (p+=4)[-1]=8; // sfo==Image::SF_Rgb8 ? 32 : 8; + /*bitmap_bit_order*/ (p+=4)[-1]=MSBFirst; + /*bitmap_pad*/ bitmap_pad=(p+=4)[-1]=8; // sfo==Image::SF_Rgb8 ? 32 : 8; + /* ^^^ force no padding at all */ + /*bits_per_pixel*/ bits_per_pixel=(p+=4)[-1]=sfo==Image::SF_Rgb8 ? 24 : 8; + /*bytes_per_line*/ mf32(p, bytes_per_line=((bits_per_pixel*img->getWd()+bitmap_pad-1)&~(bitmap_pad-1))>>3); + /*visual_class*/ (p+=4)[-1]=sfo==Image::SF_Rgb8 ? DirectColor : sfo==Image::SF_Indexed8 ? PseudoColor : StaticGray; + /*red_mask */ (p+=4)[-3]=(char)(sfo==Image::SF_Rgb8 ? 255 : 0); + /*green_mask*/ (p+=4)[-2]=(char)(sfo==Image::SF_Rgb8 ? 255 : 0); + /*blue_mask */ (p+=4)[-1]=(char)(sfo==Image::SF_Rgb8 ? 255 : 0); + /*bits_per_rgb*/ (p+=4)[-1]=sfo==Image::SF_Rgb8 ? 24 : 8; + /*colormap_entries*/ (p+=4)[-2]=1; /*256*/ + /*ncolors*/ mf32(p, ncolors=sfo==Image::SF_Rgb8 ? 0 : sfo==Image::SF_Indexed8 ? ((Image::Indexed*)img)->getNcols() : 256); + /*window_width */ mf32(p, img->getWd()); + /*window_height*/ mf32(p, img->getHt()); + assert(p+13==head+101); + /*window_x*/ /*0*/ + /*window_y*/ /*0*/ + /*window_bdrwidth*/ /*0*/ + /*filename*/ /*""*/ + out.vi_write(head, 101); + + if (sfo!=Image::SF_Rgb8) { + char *pal=new char[ncolors*12], *pp=pal; + unsigned pixel; + if (sfo==Image::SF_Indexed8) { + char const* q=img->getHeadp(); + for (pixel=0;pixel<ncolors;pixel++) { + *pp++=0; *pp++=0; *pp++=0; *pp++=pixel; + *pp++=*q; *pp++=*q++; /* red */ + *pp++=*q; *pp++=*q++; /* green */ + *pp++=*q; *pp++=*q++; /* blue */ + *pp++=7; + *pp++=0; + } + } else { assert(sfo==Image::SF_Gray8); + for (pixel=0;pixel<ncolors;pixel++) { + *pp++=0; *pp++=0; *pp++=0; *pp++=pixel; + *pp++=pixel; *pp++=pixel; /* red */ + *pp++=pixel; *pp++=pixel; /* green */ + *pp++=pixel; *pp++=pixel; /* blue */ + *pp++=7; + *pp++=0; + } + } + out.vi_write(pal, ncolors*12); + delete [] pal; + } + + slen_t rlen=img->getRlen(); + Image::Sampled::dimen_t htc=img->getHt(); + char const* rp=img->getRowbeg(); + unsigned scanline_pad=bytes_per_line-rlen; + // assert(*rp=='\xff'); + if (scanline_pad!=0) { + assert(1<=scanline_pad && scanline_pad<=3); + while (htc--!=0) { + out.vi_write(rp, rlen); + rp+=rlen; + if (scanline_pad!=0) out.vi_write("\0\0", scanline_pad); + } + } else out.vi_write(rp, rlen*htc); + + return Rule::Applier::OK; +} + +Rule::Applier out_xwd_applier = { "XWD", out_xwd_check_rule, out_xwd_work, 0 }; + +Rule::Applier out_x11_applier = { "X11", 0/*out_x11_check_rule*/, 0/*out_x11_work*/, 0 }; + +/* --- Sat Apr 20 11:49:56 CEST 2002 */ + +/** Baseline (lossy) JPEG */ +Rule::Applier::cons_t out_jpeg_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_JPEG + || cache->Compression==Rule::Cache::CO_JAI + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + if (cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /DCTEncode requires /Rgb8 or /Gray8" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_Binary) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /JPEG requires /Binary" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_DCT && cache->Compression!=Rule::Cache::CO_IJG) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /JPEG requires /DCT or /IJG" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /JPEG requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + or_->cache.WarningOK=true; /* ?? */ + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_jpeg_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + Rule::Cache *cache=&or_->cache; + // assert(0); + if (out_jpeg_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf); + // GenBuffer::Writable *tp=&out; /* always binary */ + GenBuffer::Writable *cp=&out; + /* SUXX: cjpeg(1) won't create a color JPEG for a grayscale image */ + if (cache->Compression==Rule::Cache::CO_DCT) { + SimBuffer::B other_parameters; + or_->cacheHints.DCT->dump(other_parameters, 0, false); + cp=PSEncoder::newDCTEncode(out, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.ColorTransform, other_parameters); + } else { + assert(cache->Compression==Rule::Cache::CO_None || cache->Compression==Rule::Cache::CO_IJG); + cp=PSEncoder::newDCTIJGEncode(out, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.Quality); + } + Rule::writePalData(out, *cp, sf); + delete cp; + return Rule::Applier::OK; +} + +Rule::Applier out_jpeg_applier = { "JPEG", out_jpeg_check_rule, out_jpeg_work, 0 }; + +/* --- Wed Apr 17 13:32:46 CEST 2002 */ + +Rule::Applier::cons_t out_jpegjai_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_JPEG + || cache->Compression!=Rule::Cache::CO_JAI + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + if (cache->SampleFormat!=Image::SF_Asis) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/JPEG /Compression/JAI requires /SampleFormat/Asis" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_Binary) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/JPEG /Compression/JAI requires /TransferEncoding/Binary" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/JPEG /Compression/JAI requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_jpegjai_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + /* This is the second simplest Applier I've ever written. */ + if (out_jpegjai_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + Image::Sampled *img=sf->getImg(); + // out.vi_write(img->getHeadp(), img->end_()-img->getHeadp()); + /* ^^^ end_() BUGFIX by pts@fazekas.hu at Sun Jun 2 22:24:32 CEST 2002 */ + /* ^^^ end_() contains 8 extra bytes */ + out.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); + return Rule::Applier::OK; +} + +Rule::Applier out_jpegjai_applier = { "JPEG-JAI", out_jpegjai_check_rule, out_jpegjai_work, 0 }; + +/* --- Sun Jun 2 22:25:16 CEST 2002 */ + +class TIFFPrinter { + GenBuffer::Writable& out; + /** true iff little endian == LSB first */ + bool le; + SimBuffer::B s, dir; + public: + TIFFPrinter(GenBuffer::Writable &out_, bool le_); + inline SimBuffer::B& getS() { return s; } + inline SimBuffer::B const& getDir() const { return dir; } + void aSHORT(SimBuffer::B &s, unsigned count, unsigned short const*val); + void aLONG (SimBuffer::B &s, unsigned count, slen_t const*val); + void dirSHORT(unsigned short tag, slen_t count, unsigned short const*val); + void dirLONG(unsigned short tag, slen_t count, slen_t const*val); + void dirSL(unsigned short tag, slen_t val); + void dirLONG(unsigned short tag, slen_t val); + void dirRATIONAL(unsigned short tag, slen_t count, slen_t const*val); + void dirUNDEFINED(unsigned short tag, slen_t count, char const*val); + void dirUNDEFINED(unsigned short tag, slen_t count, char const*val, slen_t count2, char const*val2); + void dirClose(); + BEGIN_STATIC_ENUM1(unsigned short) + EXTRASAMPLE_ASSOCALPHA=1, /* !associated alpha data */ + EXTRASAMPLE_UNASSALPHA=2 /* !unassociated alpha data */ + END_STATIC_ENUM() + BEGIN_STATIC_ENUM1(unsigned short) + COMPRESSION_NONE =1, /* dump mode */ + COMPRESSION_CCITTRLE =2, /* CCITT modified Huffman RLE; unused in sam2p */ + COMPRESSION_CCITTFAX3=3, /* CCITT Group 3 fax encoding */ + COMPRESSION_CCITTFAX4=4, /* CCITT Group 4 fax encoding */ + COMPRESSION_LZW =5, /* Lempel-Ziv & Welch */ + COMPRESSION_OJPEG =6, /* !6.0 JPEG; obsolete, unused in sam2p */ + COMPRESSION_JPEG =7, /* %JPEG DCT compression */ + COMPRESSION_CCITTRLEW=32771,/* #1 w/ word alignment; unused in sam2p */ + COMPRESSION_PACKBITS =32773,/* Macintosh RLE */ + COMPRESSION_DEFLATE =32946 /* Deflate compression */ + END_STATIC_ENUM() + BEGIN_STATIC_ENUM1(unsigned short) + PHOTOMETRIC_MINISBLACK=1, + PHOTOMETRIC_RGB=2, + PHOTOMETRIC_PALETTE=3, + PHOTOMETRIC_MASK=4, + PHOTOMETRIC_SEPARATED=5, /* possibly CMYK */ + PHOTOMETRIC_YCBCR=6 + END_STATIC_ENUM() + BEGIN_STATIC_ENUM1(unsigned short) + GROUP3OPT_2DENCODING=0x1, + GROUP3OPT_UNCOMPRESSED=0x2, + GROUP3OPT_FILLBITS=0x4, + GROUP4OPT_UNCOMPRESSED=0x2 + END_STATIC_ENUM() + BEGIN_STATIC_ENUM1(unsigned short) + ImageWidth=256, + ImageLength=257, + BitsPerSample=258, + Compression=259, + Photometric=262, + FillOrder=266, + StripOffsets=273, + SamplesPerPixel=277, + RowsPerStrip=278, + StripByteCounts=279, + XResolution=282, + YResolution=283, + PlanarConfig=284, + Group3Options=292, + Group4Options=293, + ResolutionUnit=296, + Predictor=317, + ColorMap=320, + InkSet=332, + ExtraSamples=338, + JPEGTables=347, + YCbCrSubsampling=530, + ReferenceBlackWhite=532 + END_STATIC_ENUM() +}; + +TIFFPrinter::TIFFPrinter(GenBuffer::Writable &out_, bool le_) :out(out_), le(le_) { + /* Directory now at unknown offset (will be set by .dirClose()) */ + s.vi_write(le_ ? "II*\0\0\0\0\0" : "MM\0*\0\0\0\0", 8); + dir.vi_write("\0",2); /* initial number of directory entries */ +} + +void TIFFPrinter::aSHORT(SimBuffer::B &s, unsigned count, unsigned short const*val) { + if (le) while (count--!=0) { s << (char)(*val) << (char)(*val>>8); val++; } + else while (count--!=0) { s << (char)(*val>>8) << (char)(*val); val++; } +} +void TIFFPrinter::aLONG (SimBuffer::B &s, unsigned count, slen_t const*val) { + /* Imp: is vi_write(..., 4); faster ? */ + if (le) while (count--!=0) { s << (char)(*val) << (char)(*val>>8) << (char)(*val>>16) << (char)(*val>>24); val++; } + else while (count--!=0) { s << (char)(*val>>24) << (char)(*val>>16) << (char)(*val>>8) << (char)(*val); val++; } +} + +void TIFFPrinter::dirSHORT(unsigned short const tag, slen_t const count, unsigned short const*val) { + slen_t offs; + aSHORT(dir, 1U, &tag); + dir.vi_write("\0\3"+(le?1:0), 2); + aLONG(dir, 1U, &count); + switch (count) { + case 0: dir.vi_write("\0\0\0", 4); break; + case 1: aSHORT(dir, 1, val); dir.vi_write("\0", 2); break; + case 2: aSHORT(dir, 2, val); break; + default:offs=s.getLength(); aSHORT(s, count, val); aLONG(dir, 1, &offs); + } +} +void TIFFPrinter::dirLONG(unsigned short const tag, slen_t const count, slen_t const*val) { + slen_t offs; + aSHORT(dir, 1U, &tag); + dir.vi_write("\0\4"+(le?1:0), 2); + aLONG(dir, 1U, &count); + switch (count) { + case 0: dir.vi_write("\0\0\0", 4); break; + case 1: aLONG(dir, 1, val); break; + default:offs=s.getLength(); aLONG(s, count, val); aLONG(dir, 1, &offs); + } +} +void TIFFPrinter::dirRATIONAL(unsigned short tag, slen_t count, slen_t const*val) { + slen_t offs; + aSHORT(dir, 1U, &tag); + dir.vi_write("\0\5"+(le?1:0), 2); + aLONG(dir, 1U, &count); + switch (count) { + case 0: dir.vi_write("\0\0\0", 4); break; + default:offs=s.getLength(); aLONG(s, count*2, val); aLONG(dir, 1, &offs); + } +} +void TIFFPrinter::dirUNDEFINED(unsigned short tag, slen_t count, char const*val) { + slen_t offs; + aSHORT(dir, 1U, &tag); + dir.vi_write("\0\7"+(le?1:0), 2); + aLONG(dir, 1U, &count); + if (count<=4) { + dir.vi_write(val, count); + if (count!=4) dir.vi_write("\0\0\0", 4-count); + } else { + offs=s.getLength(); s.vi_write(val, count); aLONG(dir, 1, &offs); + } +} +void TIFFPrinter::dirUNDEFINED(unsigned short tag, slen_t count, char const*val, slen_t count2, char const*val2) { + slen_t offs, countx=count+count2; + aSHORT(dir, 1U, &tag); + dir.vi_write("\0\7"+(le?1:0), 2); + aLONG(dir, 1U, &countx); + if (countx<=4) { + dir.vi_write(val, count); + dir.vi_write(val2, count2); + if (countx!=4) dir.vi_write("\0\0\0", 4-countx); + } else { + offs=s.getLength(); + s.vi_write(val, count); + s.vi_write(val2, count2); + aLONG(dir, 1, &offs); + } +} +void TIFFPrinter::dirSL(unsigned short tag, slen_t val) { + unsigned short sh; + if (val<1<<16U) { sh=val; dirSHORT(tag, 1, &sh); } + else dirLONG(tag, 1, &val); +} +void TIFFPrinter::dirLONG(unsigned short tag, slen_t val) { + dirLONG(tag, 1, &val); +} +void TIFFPrinter::dirClose() { + char *ss=s.begin_(); + slen_t len=s.getLength(); + if (le) { ss[4]=len; ss[5]=len>>8; ss[6]=len>>16; ss[7]=len>>24; } + else { ss[4]=len>>24; ss[5]=len>>16; ss[6]=len>>8; ss[7]=len; } + /* ^^^ dir offset: end of file */ + out.vi_write(ss, len); + assert(dir.getLength()%12==2); + unsigned dirc=(dir.getLength()-2)/12; + ss=dir.begin_(); + if (le) { ss[0]=dirc; ss[1]=dirc>>8; } + else { ss[0]=dirc>>8; ss[1]=dirc; } + out.vi_write(dir(), dir.getLength()); + out.vi_write("", 0); +} + +/* tiffjai --- Sun Jun 2 22:25:16 CEST 2002 */ + +Rule::Applier::cons_t out_tiffjai_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_TIFF + || cache->Compression!=Rule::Cache::CO_JAI + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + if (cache->SampleFormat!=Image::SF_Asis) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/JAI requires /SampleFormat/Asis" << (Error*)0; + badp=true; + } + if (!cache->isBinSB()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /TransferEncoding/Binary|/?SBFirst" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/JAI requires /Prediror 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_tiffjai_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + if (out_tiffjai_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + Image::Sampled *img=sf->getImg(); + unsigned char cs=img->getCs(); /* color space */ + if (cs!=Image::Sampled::CS_GRAYSCALE && cs!=Image::Sampled::CS_RGB && cs!=Image::Sampled::CS_YCbCr && cs!=Image::Sampled::CS_CMYK) { + /* Dat: CS_YCCK is supported by JPEG, but unsupported by TIFF-JPEG */ + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/JAI doesn't support this color space" << (Error*)0; + return Rule::Applier::BAD; + } + /* Imp: test all CMYK TIFF tags */ + /* Imp: test with RGB and CMYK images */ + TIFFPrinter tp(out, or_->cache.TransferEncoding==or_->cache.TE_LSBfirst); + /* ^^^ Dat: Binary defaults to MSBfirst, beacuse QuarkXPress 3 can read only + * MSBfirst TIFF files. + */ + char const *databeg=img->getHeadp()+img->getXoffs(); + assert(databeg[-2]=='\xFF' && databeg[-1]=='\xC0'); + slen_t datalen=img->getRowbeg()-databeg; + // printf("LEN=%u gl=%u datalen=%u\n", img->end_()-img->begin_(), img->getLength(), datalen); + tp.getS().vi_write("\xFF\xD8\xFF\xC0", 4); /* fake-SOI SOF0 */ + tp.getS().vi_write(databeg, datalen); /* DataPart */ + // tp.getS().vi_write("\xFF\xD9", 2); /* fake-EOI */ + /* ^^^ there must be an EOI already */ + + unsigned phot=0; bool inks=false, refe=false; + switch (cs) { + case Image::Sampled::CS_GRAYSCALE: phot=tp.PHOTOMETRIC_MINISBLACK; break; + case Image::Sampled::CS_RGB: phot=tp.PHOTOMETRIC_RGB; break; + case Image::Sampled::CS_YCbCr: phot=tp.PHOTOMETRIC_YCBCR; refe=true; break; /* preferred to RGB */ + case Image::Sampled::CS_CMYK: phot=tp.PHOTOMETRIC_SEPARATED; inks=true; break; /* preferred to RGB */ + default: Error::sev(Error::EERROR) << "TIFF6-JAI: color space " << (unsigned)cs << " not supported in TIFF-JPEG" << (Error*)0; + } + + /* Dat: TIFF tags must appear in increasing numerical order */ + tp.dirSL(tp.ImageWidth, img->getWd()); + tp.dirSL(tp.ImageLength, img->getHt()); + unsigned short eights[]={8,8,8,8}; + tp.dirSHORT(tp.BitsPerSample, img->cs2cpp[cs], eights); + tp.dirSL(tp.Compression, tp.COMPRESSION_JPEG); /* SHORT */ + tp.dirSL(tp.Photometric, phot); /* SHORT */ + tp.dirLONG(tp.StripOffsets, 8); + tp.dirSL(tp.SamplesPerPixel, img->cs2cpp[cs]); /* SHORT */ + tp.dirSL(tp.RowsPerStrip, img->getHt()); + tp.dirLONG(tp.StripByteCounts, datalen+6); + slen_t rats[]={1,1, 0,1, 255,1, 128,1, 255,1, 128,1, 255,1}; + tp.dirRATIONAL(tp.XResolution, 1, rats); + tp.dirRATIONAL(tp.YResolution, 1, rats); + tp.dirSL(tp.PlanarConfig, 1); /* SHORT, PLANARCONFIG_CONTIG */ + tp.dirSL(tp.ResolutionUnit, 1); /* SHORT */ + if (inks) tp.dirSL(tp.InkSet, 1); /* SHORT */ + tp.dirUNDEFINED(tp.JPEGTables, databeg-img->getHeadp()-2, img->getHeadp(), 2, "\xFF\xD9"); + unsigned char hvs=img->end_()[-1]; + if (hvs!=0x22 && cs==Image::Sampled::CS_YCbCr) { + // printf("hvs=0x%02X\n", hvs); + unsigned short horiz_vert[2]={ hvs>>4, hvs&15 }; + tp.dirSHORT(tp.YCbCrSubsampling, 2, horiz_vert); + } + if (refe) tp.dirRATIONAL(tp.ReferenceBlackWhite, 6, rats+2); + tp.dirClose(); + #if 0 + { Files::FILEW f(fopen("t.hea","wb")); + f.vi_write(img->getHeadp(), databeg-img->getHeadp()-2); /* HeadPart */ + f.vi_write("\xFF\xD9", 2); + f.close(); + } + { Files::FILEW f(fopen("t.dat","wb")); + f.vi_write("\xFF\xD8\xFF\xC0", 4); /* fake-SOI SOF0 */ + f.vi_write(databeg, datalen); /* DataPart */ + f.close(); + } + #endif + // out.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); /* HeadPart */ + // out.vi_write(img->getRowbeg(), img->end_()-img->getRowbeg()); /* DataPart */ + return Rule::Applier::OK; + /* SUXX: see compatibility notes in FAQ (README) */ +} + +Rule::Applier out_tiffjai_applier = { "TIFF6-JAI", out_tiffjai_check_rule, out_tiffjai_work, 0 }; + +/* tiff --- Tue Jun 4 16:23:48 CEST 2002 */ + +/** by pts@fazekas.hu at Tue Jun 11 16:56:53 CEST 2002 + * Reads a JPEG Baseline (SOF0) stream on input, and drops everything before + * the first SOF0 marker. Then writes an SOI marker, the SOF0 marker, and + * everything after the SOI marker. The last two bytes read must be an + * EOI marker (/\xFF\xD9/). The first thing to be read must be a SOI marker + * (/\xFF+\xD8/). The getJPEGTables() method can be used to retrieve the + * data read before the SOF0 marker. An SOS marker must be read after SOF0. + * Also retains some information (hvsamples[0]) from the SOF0 marker. + * Suitable for reading the output of cjpeg and Ghostscript /FlateEncode. + * This encoder would be much harder if we were not allowed to read the + * JPEG stream into memory. + */ +class JPEGSOF0Encode: public PSEncoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + JPEGSOF0Encode(GenBuffer::Writable &out_); + virtual void vi_write(char const*buf, slen_t len); + SimBuffer::Flat const& getJPEGTables() const { return buf; } + unsigned char getColorSpace() const { return gi.colorspace; } + unsigned char getHVS() const { return gi.hvs; } + protected: + GenBuffer::Writable &out; + SimBuffer::B buf; + struct jai_gfxinfo gi; +}; + +JPEGSOF0Encode::JPEGSOF0Encode(GenBuffer::Writable &out_): out(out_) {} +void JPEGSOF0Encode::vi_write(char const*bufr, slen_t len) { + if (len==0) { + { Filter::FlatD flatd(buf(), buf.getLength()); + jai_parse_jpeg(&gi, &flatd); + } + slen_t len=buf.getLength(); + if (gi.bad==0 && (len<4 || buf[len-2]!='\xFF' || buf[len-1]!='\xD9')) gi.bad=10; + if (gi.bad!=0) + Error::sev(Error::EERROR) << "JPEGS0F0: invalid JPEG stream: " << jai_errors[gi.bad] << (Error*)0; + out.vi_write("\xFF\xD8", 2); /* extra SOI */ + out.vi_write(buf()+gi.SOF_offs-2, len-gi.SOF_offs+2); /* SOF0 and followers */ + out.vi_write(0,0); + assert(buf[gi.SOF_offs-2]=='\xFF'); /* BUGFIX at 2002.12.02 */ + buf[gi.SOF_offs-1]='\xD9'; /* extra EOI */ + buf.keepLeft(gi.SOF_offs); /* keep only headers */ + } else buf.vi_write(bufr, len); +} + + +Rule::Applier::cons_t out_tiff_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_TIFF + || cache->Compression==Rule::Cache::CO_JAI + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + /* Dat: acroread TIFF predictor2 OK. (examples/fishg_lzw2_pdf.job) */ + /* Dat: /ZIP with /Predictor OK */ + if (cache->Predictor!=cache->PR_None) { + if (cache->Predictor!=cache->PR_TIFF2) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF requires /Predictor 1|2" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_ZIP && cache->Compression!=Rule::Cache::CO_LZW) { + Error::sev(Error::WARNING_DEFER) << "check_rule: real /Predictor requires /ZIP or /LZW" << (Error*)0; + badp=true; + } + } + #if !HAVE_LZW + if (cache->Compression==Rule::Cache::CO_LZW) { + Error::sev(Error::WARNING_DEFER) << "check_rule: `configure --enable-lzw' for /Compression/LZW with /FileFormat/TIFF" << (Error*)0; + badp=true; + } + #endif + if (cache->Compression==Rule::Cache::CO_Fax && !cache->isOneBit()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/Fax requires a 1-bit /SampleFormat" << (Error*)0; + badp=true; + } + if (!cache->isGray() && !cache->isTransparentM() && !cache->isIndexed() && !cache->isRGB()) { + /* Dat: unsupported SampleFormats: /Opaque, /Transparent and /Asis. */ + Error::sev(Error::WARNING_DEFER) << "check_rule: unsupported /SampleFormat for /FileFormat/TIFF" << (Error*)0; + badp=true; + } + if (!cache->isBinSB()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF requires /TransferEncoding/Binary|/?SBFirst" << (Error*)0; + badp=true; + } + if (cache->isDCTE() && cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Indexed8) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /DCTEncode requires /Rgb8 or /Gray8 (or /Indexed8)" << (Error*)0; + badp=true; + } + if (!badp && cache->isTransparentM()) { + cache->origSampleFormat=cache->SampleFormat; + cache->SampleFormat=Image::SF_Transparent8; + } + return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK); + /* ^^^ Dat: 0+: pacify g++-3.1 */ +} + +Rule::Applier::cons_t out_tiff_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + Rule::Cache *cache=&or_->cache; + Image::sf_t origSampleFormat=cache->origSampleFormat; + if (out_tiff_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + + assert(!sf->hasTranspp() || cache->isTransparentM()); + /** Alpha channel or null. */ + Image::Indexed *alpha=(Image::Indexed*)NULLP; + if (cache->isTransparentM()) { + // fprintf(stderr,"sf=%u osf=%u\n", cache->SampleFormat, origSampleFormat); + alpha=PTS_dynamic_cast(Image::Indexed*,sf->getImg())->calcAlpha(); + PTS_dynamic_cast(Image::Indexed*,sf->getImg())->getClearTransp(); + assert((alpha!=NULLP) == (sf->hasTranspp()==true)); + sf->clearTransp(); + static Image::sf_t const graytab[9]={Image::SF_None,Image::SF_Gray1,Image::SF_Gray2,Image::SF_None,Image::SF_Gray4,Image::SF_None,Image::SF_None,Image::SF_None,Image::SF_Gray8}; + static Image::sf_t const rgbtab[9]={Image::SF_None,Image::SF_Rgb1,Image::SF_Rgb2,Image::SF_None,Image::SF_Rgb4,Image::SF_None,Image::SF_None,Image::SF_None,Image::SF_Rgb8}; + static Image::sf_t const indexedtab[9]={Image::SF_None,Image::SF_Indexed1,Image::SF_Indexed2,Image::SF_None,Image::SF_Indexed4,Image::SF_None,Image::SF_None,Image::SF_None,Image::SF_Indexed8}; + unsigned char minbpc=sf->minRGBBpcc(); + // fprintf(stderr,"minbpc=%u\n",minbpc); + if (minbpc<8 && origSampleFormat==Image::SF_Transparent8) minbpc=8; + else if (minbpc<4 && origSampleFormat==Image::SF_Transparent4) minbpc=4; + else if (minbpc<2 && origSampleFormat==Image::SF_Transparent2) minbpc=2; + // fprintf(stderr,"minbpc=%u\n",minbpc); + // cacheHints.EncoderBPL=(slen_t)img->getWd()*img->getCpp()*img->getBpc(); + /* ^^^ Dat: doSampleFormat will do it correctly */ + // assert(saf!=Image::SF_max); + cache->SampleFormat=(alpha==NULLP ? indexedtab : sf->minGrayBpcc()==0 ? rgbtab : graytab)[minbpc]; + } + + or_->doSampleFormat(sf); /* No separations */ + Image::Sampled *img=sf->getImg(); /* call this _after_ doSampleFormat()! */ + + TIFFPrinter tp(out, or_->cache.TransferEncoding==or_->cache.TE_LSBfirst); + /* ^^^ Dat: Binary defaults to MSBfirst, beacuse QuarkXPress 3 can read only + * MSBfirst TIFF files. + */ + unsigned phot= cache->isRGB() ? 0+tp.PHOTOMETRIC_RGB + // : cache->SampleFormat==Image::SF_Mask ? tp.PHOTOMETRIC_MASK + : cache->isGray() ? 0+tp.PHOTOMETRIC_MINISBLACK + // : cache->isIndexed() ? tp.PHOTOMETRIC_PALETTE + : 0+tp.PHOTOMETRIC_PALETTE /* /Indexed*, /Mask, /Transparent+ */; + unsigned compr=tp.COMPRESSION_NONE; + + Filter::VerbatimCountE vc(tp.getS()); + GenBuffer::Writable *cp=&vc; + JPEGSOF0Encode *jp=(JPEGSOF0Encode*)NULLP; + // Dat: g++-3.4: Rule::Cache::CO_None: `cache cannot appear in a constant expression' + switch (cache->Compression) { + case Rule::Cache::CO_None: break; + case Rule::Cache::CO_ZIP: compr=tp.COMPRESSION_DEFLATE; cp=PSEncoder::newFlateEncode(*cp, or_->cacheHints.Effort); break; + case Rule::Cache::CO_LZW: compr=tp.COMPRESSION_LZW; cp=PSEncoder::newLZWEncode(*cp); break; + /* vvv Dat: RunLengthEncode EOD (char 128) is OK and ignored in TIFF PackBits streams */ + case Rule::Cache::CO_RLE: compr=tp.COMPRESSION_PACKBITS; cp=PSEncoder::newRunLengthEncode(*cp, or_->cacheHints.RecordSize); break; + case Rule::Cache::CO_Fax: + if (or_->cacheHints.K<0) compr=tp.COMPRESSION_CCITTFAX4; + else if (or_->cacheHints.K==0) compr=tp.COMPRESSION_CCITTFAX3; + else { compr=tp.COMPRESSION_CCITTFAX3; or_->cacheHints.K=img->getHt(); } + cp=PSEncoder::newCCITTFaxEncode(*cp, or_->cacheHints.K, or_->cacheHints.EncoderBPL, /*EndOfLine:*/ compr==tp.COMPRESSION_CCITTFAX3, /*BlackIs1: !*/ true); + /* Dat: libtiff enforces EndOfLine==(compr==tp.COMPRESSION_CCITTFAX3) */ + break; + case Rule::Cache::CO_IJG: + compr=tp.COMPRESSION_JPEG; + jp=new JPEGSOF0Encode(vc); + cp=PSEncoder::newDCTIJGEncode(*jp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.Quality); + break; + case Rule::Cache::CO_DCT: compr=tp.COMPRESSION_JPEG; { + SimBuffer::B other_parameters; + or_->cacheHints.DCT->dump(other_parameters, 0, false); + jp=new JPEGSOF0Encode(vc); + cp=PSEncoder::newDCTEncode(*jp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.ColorTransform, other_parameters); + break; } + default: assert(0); + } + + GenBuffer::Writable *pp=cp; + if (cache->hasPredictor()) pp=PSEncoder::newPredictor(*cp, cache->Predictor, or_->cacheHints.PredictorBPC, or_->cacheHints.PredictorColumns, or_->cacheHints.PredictorColors); + + slen_t rlenht=img->getRlen()*img->getHt(); + Image::Sampled::dimen_t wd=img->getWd(); + if (rlenht!=0) { + /* Dat: TIFF inserts extra sample bits... */ + /* TIFF images with transparency are really inefficient. That's because + * libtiff doesn't read or write an indexed image with transparency: + * Sorry, can not handle contiguous data with PhotometricInterpretation=3, + * and Samples/pixel=2. + * So Indexed images are converted to RGB* or Gray* first, and then the + * alpha channel is added. The result is a big and inefficiently + * compressible TIFF file. + */ + + if (alpha!=NULLP) { + unsigned char bpc=img->getBpc(); + slen_t rlen=img->getRlen(); + slen_t writelen; + char *buf=(char*)NULLP; + char const*psave=img->getRowbeg(), *p, *ppend=psave+rlenht; + char const*r=alpha->getRowbeg(), *rend; + char *t; + register unsigned u; + Image::Sampled::dimen_t rlena=(wd+7)>>3; + assert(rlena==alpha->getRlen()); + // printf("SF=%u\n", cache->SampleFormat); + if (cache->isGray()) { + /* works at Mon Dec 9 01:25:59 CET 2002 */ + static unsigned char const szor1[16]={2*0,2*1,2*4,2*5,2*16,2*17,2*20,2*21,2*64,2*65,2*68,2*69,2*80,2*81,2*84,2*85}; + static unsigned char const szor2[16]={85,84,81,80,69,68,65,64,21,20,17,16,5,4,1,0}; + // static unsigned char const szor2[8]={0,1,16,17,64,65,80,81}; + buf=new char[(writelen=((slen_t)wd*bpc+3)>>2)+24]; + assert(rlena*8>=rlen); + while (psave!=ppend) { + t=buf; + rend=r+rlena; + p=psave; psave+=rlen; + assert(psave<=ppend); + u=(1<<16); + switch (bpc) { + case 8: + while (p!=psave) { + /* Dat: works at Tue Sep 10 22:45:52 CEST 2002 */ + if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8); + *t++=*p++; *t++=-(0==(u&128)); + u<<=1; + } break; + case 4: + while (p!=psave) { + if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8); + *t++=(p[0]&0xF0)|(0==(u&128)?15:0); + *t++=((p[0]&0xF)<<4)|(0==(u&64)?15:0); + p++; u<<=2; + } break; + case 2: + while (p!=psave) { + if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8); + *t++=(p[0]&0xC0 )|((u&128)!=0?0:48)|((p[0]&0x30)>>2)|((u&64)!=0?0:3); + *t++=((p[0]&0xC)<<4)|((u& 32)!=0?0:48)|((p[0]&0x3 )<<2)|((u&16)!=0?0:3); + p++; u<<=4; + } break; + case 1: + while (p!=psave) { + u=*(unsigned char const*)r++; + *t++=szor1[*(unsigned char const*)p>>4]|szor2[u>>4]; + *t++=szor1[*(unsigned char const*)p&15]|szor2[u&15]; + p++; + } break; + } /* SWITCH Gray bpc */ + // assert(p-psave+0U==rlena*8U); + assert(p>=psave); + pp->vi_write(buf, writelen); + } + } else { + /* works at Sun Dec 8 23:30:17 CET 2002 */ + assert(cache->isRGB()); + buf=new char[(writelen=((slen_t)wd*bpc+1)>>1)+24]; + while (psave!=ppend) { + t=buf; + p=psave; psave+=rlen; + assert(psave<=ppend); + u=(1<<16); + rend=r+rlena; /* superfluous */ + switch (bpc) { + case 8: + while (p<psave) { + if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8); + *t++=*p++; + *t++=*p++; + *t++=*p++; + *t++=-(0==(u&128)); + u<<=1; + } break; + case 4: + while (p<psave) { + if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8); + *t++=p[0]; /* R0 and G0 */ + *t++=(p[1]&0xF0)|((u&128)!=0?0:15); /* B0 and A0 */ + *t++=(p[1]<<4)|((p[2]>>4)&15); /* R1 and G1 */ + *t++=(p[2]<<4)|((u&64)!=0?0:15); /* B1 and A1 */ + p+=3; u<<=2; + } break; + case 2: + while (p<psave) { + if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8); + /* Dat: p[0]==R0G0B0R1 p[1]==G1B1R2G2 p[2]==B2R3G3B3 */ + *t++=(p[0]&0xFC)|((u&128)!=0?0:3); /* R0G0B0 and A0 */ + *t++=(p[0]<<6)|((p[1]>>2)&0x3C)|((u&64)!=0?0:3); /* R1 G1B1 A1 */ + *t++=(p[1]<<4)|((p[2]>>4)&0x0C)|((u&32)!=0?0:3); /* R2G1 B1 A2 */ + *t++=(p[2]<<2)|((u&16)!=0?0:3); /* R3G3B3 and A3 */ + p+=3; u<<=4; + } break; + default: // case 1: + while (p<psave) { + u=*(unsigned char const*)r++; + /* Dat: p[0]==RGBRGBRG p[1]==BRGBRGBR p[2]==GBRGBRGB */ + *t++=(p[0]&0xE0)|((u&128)!=0?0:16) + |((p[0]>>1)&0xE)|((u&64)!=0?0:1); + *t++=(p[0]<<6)|((p[1]>>2)&0x80)|((u&32)!=0?0:16) + |((p[1]>>3)&0xE)|((u&16)!=0?0:1); + *t++=((p[1]<<4)&0xE0)|((u&8)!=0?0:16) + |((p[1]<<3)&0x7)|((p[2]>>5)&0x06)|((u&4)!=0?0:1); + *t++=((p[2]<<2)&0xE0)|((u&2)!=0?0:16) + |((p[2]<<1)&0x0E)|((u&1)!=0?0:1); + p+=3; + } + break; + } /* SWITCH RGB bpc */ + assert(r==rend); // r=rend; + pp->vi_write(buf, writelen); + } + } + delete [] buf; + } else pp->vi_write(img->getRowbeg(), rlenht); + } + pp->vi_write(0,0); /* flush all */ + if (pp!=cp) delete pp; + if (cp!=&vc) delete cp; + + bool refe=false; + if (compr==tp.COMPRESSION_JPEG) switch (jp->getColorSpace()) { + case Image::Sampled::CS_GRAYSCALE: + assert(phot==tp.PHOTOMETRIC_MINISBLACK || phot==tp.PHOTOMETRIC_PALETTE); + /* Dat: we don't change `phot' here, so JPEG compression can be applied + * to the palette indexes of indexed images :-) + */ + break; + case Image::Sampled::CS_RGB: phot=tp.PHOTOMETRIC_RGB; break; + case Image::Sampled::CS_YCbCr: phot=tp.PHOTOMETRIC_YCBCR; refe=true; break; /* preferred to RGB */ + // case Image::Sampled::CS_CMYK: phot=tp.PHOTOMETRIC_SEPARATED; inks=true; break; /* preferred to RGB */ + default: Error::sev(Error::EERROR) << "TIFF6: color space " << (unsigned)jp->getColorSpace() << " not supported in TIFF-JPEG" << (Error*)0; + } + + /* Dat: TIFF tags must appear in increasing numerical order */ + tp.dirSL(tp.ImageWidth, wd); +// tp.dirSL(tp.ImageWidth, img->getWd()/2); + tp.dirSL(tp.ImageLength, img->getHt()); + unsigned short s4[]={img->getBpc(),img->getBpc(),img->getBpc(),img->getBpc()}; + /* ^^^ these values may be different according to the TIFF6 spec, but + * libtiff can read TIFF files only with same BitsPerSamples. + */ + unsigned sppa=img->getCpp()+(alpha!=NULLP ? 1:0); + tp.dirSHORT(tp.BitsPerSample, sppa, s4); + tp.dirSL(tp.Compression, compr); /* SHORT */ + tp.dirSL(tp.Photometric, phot); /* SHORT */ + if (cache->Compression==Rule::Cache::CO_Fax) tp.dirSL(tp.FillOrder, 1); /* byte abcdefgh is (a<<7)+...+h */ + tp.dirLONG(tp.StripOffsets, 8); + if (!cache->isIndexed()) + tp.dirSL(tp.SamplesPerPixel, sppa); /* SHORT */ +// tp.dirSL(tp.SamplesPerPixel, 2); /* SHORT */ + tp.dirSL(tp.RowsPerStrip, img->getHt()); + tp.dirLONG(tp.StripByteCounts, vc.getCount()); + slen_t rats[]={1,1, 0,1, 255,1, 128,1, 255,1, 128,1, 255,1}; + tp.dirRATIONAL(tp.XResolution, 1, rats); + tp.dirRATIONAL(tp.YResolution, 1, rats); + tp.dirSL(tp.PlanarConfig, 1); /* SHORT, PLANARCONFIG_CONTIG */ + if (compr==tp.COMPRESSION_CCITTFAX3) tp.dirLONG(tp.Group3Options, (tp.GROUP3OPT_UNCOMPRESSED)|(or_->cacheHints.K!=0?tp.GROUP3OPT_2DENCODING:0)); + if (compr==tp.COMPRESSION_CCITTFAX4) tp.dirLONG(tp.Group4Options, tp.GROUP4OPT_UNCOMPRESSED); + tp.dirSL(tp.ResolutionUnit, 1); /* SHORT */ + if (cache->Predictor!=cache->PR_None) { + tp.dirSL(tp.Predictor, cache->Predictor); /* 1|2 */ + if (img->getBpc()!=8) + Error::sev(Error::WARNING) << "TIFF6: libtiff supports /Predictor only with bpc=8 and bpc=16" << (Error*)0; + } + + if (cache->isIndexed() || cache->isTransparentM()) { + unsigned colorlen=(1<<img->getBpc()), i=0; + unsigned short *r=new unsigned short[3*colorlen], *g=r+colorlen, *b=g+colorlen; + memset(r, '\0', 3*colorlen); + /** Image palette data */ + char const *p=img->getHeadp(), *pend=img->getRowbeg(); + assert((pend-p)%3==0); + assert(3*colorlen>=(unsigned)(pend-p)); + while (p<pend) { + r[i ]=*(unsigned char const*)p++*257; + g[i ]=*(unsigned char const*)p++*257; + b[i++]=*(unsigned char const*)p++*257; + } + /* ^^^ In a TIFF palette (ColorMap) 0 is black, 65535 is lightest */ + tp.dirSHORT(tp.ColorMap, colorlen*3, r); + delete [] r; + } + if (alpha!=NULLP) { + /* vvv Dat: GIMP 1.0 load fails with tp.EXTRASAMPLE_UNASSALPHA */ + tp.dirSL(tp.ExtraSamples, tp.EXTRASAMPLE_ASSOCALPHA); /* SHORT */ + delete alpha; + } + /* no tp.InkSet, because no CMYK */ + + if (compr==tp.COMPRESSION_JPEG) { + tp.dirUNDEFINED(tp.JPEGTables, jp->getJPEGTables().getLength(), jp->getJPEGTables()() /* , 2, "\xFF\xD9" */); + unsigned char hvs=jp->getHVS(); + if (hvs!=0x22 && phot==tp.PHOTOMETRIC_YCBCR) { + unsigned short horiz_vert[2]={ hvs>>4, hvs&15 }; + tp.dirSHORT(tp.YCbCrSubsampling, 2, horiz_vert); + } + if (refe) tp.dirRATIONAL(tp.ReferenceBlackWhite, 6, rats+2); + delete jp; + } + + tp.dirClose(); + return Rule::Applier::OK; +} + +Rule::Applier out_tiff_applier = { "TIFF6", out_tiff_check_rule, out_tiff_work, 0 }; + + +/* --- Sat Apr 20 11:32:42 CEST 2002 -- Sat Apr 20 16:48:25 CEST 2002 */ + +#if OBJDEP +# warning REQUIRES: crc32.o +# warning REQUIRES: crc32.o +#endif +/** Encodes 32-bit (data.length-minus), data, crc32. */ +class LenCRC32Encode: public PSEncoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + LenCRC32Encode(GenBuffer::Writable &out_, unsigned minus_); + virtual void vi_write(char const*buf, slen_t len); + + protected: + GenBuffer::Writable &out; + unsigned minus; + /** The length is not known in advance, so we have to buffer the whole output + * in memory. + */ + SimBuffer::B sofar; +}; + +LenCRC32Encode::LenCRC32Encode(GenBuffer::Writable &out_, unsigned minus_): out(out_), minus(minus_), sofar("1234") {} +void LenCRC32Encode::vi_write(char const*buf, slen_t len) { + if (len==0) { + char *s=const_cast<char*>(sofar()); + slen_t slen=sofar.getLength(); + unsigned PTS_INT32_T crc=crc32(CRC32_INITIAL, s+4, slen-4); + slen-=minus+4; + s[0]=slen>>24; s[1]=slen>>16; s[2]=slen>>8; s[3]=slen; + s=sofar.vi_mkend(4); + s[0]=crc >>24; s[1]=crc>>16; s[2]=crc>>8; s[3]=crc; + out.vi_write(sofar(), sofar.getLength()); + out.vi_write(0,0); + } else sofar.vi_write(buf, len); +} + +/** PNG output (RFC 2083) */ +Rule::Applier::cons_t out_png_check_rule(Rule::OutputRule* or_) { + /* Supported PNG types: /Gray1, /Gray2, /Gray4, /Gray8, /Rgb8, + * /Indexed1, /Indexed2, /Indexed4, /Indexed8. + * Unsupported PNG types: /Gray16, /Rgb16, /GrayA8, /GrayA16, /RgbA8, + * /RgbA16. + * /Indexed* supports transparency (via PNG chunk tRNS). + */ + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_PNG + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + /* Dat: (by policy) we don't support /Transparent or /Opaque here; the + * user should not specify such SampleFormat in the .job file. + */ + if (!cache->isGray() + && !cache->isTransparentM() + && !cache->isIndexed() + && cache->SampleFormat!=Image::SF_Rgb8) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Gray*, /Indexed*, /Mask, /Transparent+ or /Rgb8" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_Binary) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Binary" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_ZIP) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Compression/None or /ZIP" << (Error*)0; + badp=true; + } + if (cache->Predictor==cache->PR_TIFF2) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Predictor >=10" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + /* Now we are sure about Rule::Applier::OK. */ + or_->cache.WarningOK=true; /* ?? */ + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_png_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + Rule::Cache *cache=&or_->cache; + char tmp[64], colortype; register char*p; + unsigned PTS_INT32_T crc; + + // assert(0); + if (out_png_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf); + Image::Sampled *img=sf->getImg(); + unsigned char bpc=img->getBpc(); /* set _after_ doSampleFormat */ + Image::Sampled::dimen_t wd=img->getWd(), ht=img->getHt(); + + GenBuffer::Writable *rp=new LenCRC32Encode(out,4); + GenBuffer::Writable *cp=PSEncoder::newFlateEncode(*rp, (cache->Compression==Rule::Cache::CO_None) ? 0: or_->cacheHints.Effort); + + /* Dat: PredictorColumns, PredictorBPC and PredictorColors are forced to + * match the image, because PNG requires it. + */ + GenBuffer::Writable *pp=PSEncoder::newPredictor( + *cp, + cache->Predictor==cache->PR_None ? cache->PR_PNGNone : cache->Predictor, + bpc, /*or_->cacheHints.PredictorBPC*/ + wd, /*or_->cacheHints.PredictorColumns*/ + img->getCpp() /*or_->cacheHints.PredictorColors*/ + ); + + /* Critical PNG chunks (capital 1st letter) and ancillary PNG chunks: + * + * -: zero, 1: exactly one, ?: 0 or 1, *: 0 or more, +: 1 or more + * Name Nr sam2p Ordering constraints + * IHDR 1 1 Must be first + * cHRM ? - Before PLTE and IDAT + * gAMA ? - Before PLTE and IDAT + * sBIT ? - Before PLTE and IDAT + * PLTE ? ? Before IDAT + * hIST ? - After PLTE; before IDAT + * tRNS ? ? After PLTE; before IDAT + * bKGD ? ? After PLTE; before IDAT + * pHYs ? - Before IDAT + * tIME ? - None + * tEXt * - None + * zTXt * - None + * IDAT + 1 After IHDR and PLTE, multiple IDATs must be consecutive + * IEND 1 1 Must be last + */ + + /* 0..3: PNG header */ + /* 8..11: IHDR chunk length */ + /* 12..15: IHDR chunk name */ + memcpy(tmp,"\211PNG\r\n\032\n\0\0\0\015IHDR",16); /* ASCII charset is assumed. */ + p=tmp+16; + *p++=wd>>24; *p++=wd>>16; *p++=wd>>8; *p++=wd; /* 16: Width */ + *p++=ht>>24; *p++=ht>>16; *p++=ht>>8; *p++=ht; /* 20: Height */ + *p++=bpc; /* 24: Bit depth */ + colortype=*p++=cache->isGray()?0:cache->isRGB()?2:3; /* 25: Color type */ + *p++=0; /* 26: Compression method: deflate/32K (forced by PNG spec), overcoming with Effort==0 */ + *p++=0; /* 27: Filter type: adaptive filtering with 5 basic PNG filter types */ + *p++=0; /* 28: Non-interlaced */ + crc=crc32(CRC32_INITIAL, tmp+12, 17); + *p++=crc>>24;*p++=crc>>16;*p++=crc>>8;*p++=crc; /* 29: IHDR CRC */ + out.vi_write(tmp, 33); + if (colortype==3) { + bool transp=cache->isTransparentM() && PTS_dynamic_cast(Image::Indexed*,img)->getTransp()>=0; + /* unsigned ncols=PTS_dynamic_cast(Image::Indexed*,img)->getNcols(); */ + unsigned ncols3=img->getRowbeg()-img->getHeadp(); + + p=tmp; + *p++=0; *p++=0; *p++=ncols3>>8; *p++=ncols3; /* 0: PLTE chunk length */ + *p++='P'; *p++='L'; *p++='T'; *p++='E'; /* 4: PLTE chunk name */ + out.vi_write(tmp, 8); + if (transp) { + PTS_dynamic_cast(Image::Indexed*,img)->makeTranspZero(); + p=img->getHeadp(); p[0]=p[1]=p[2]=(char)0; /* force black backround (for consistency) */ + } + out.vi_write(img->getHeadp(), ncols3); + crc=crc32(crc32(CRC32_INITIAL,tmp+4,4), img->getHeadp(), ncols3); + p=tmp; *p++=crc>>24;*p++=crc>>16;*p++=crc>>8;*p++=crc; /* 0: PLTE CRC */ + out.vi_write(tmp, 4); + if (transp) { + out.vi_write("\0\0\0\1tRNS\0@\346\330f", 13); /* color 0 is transparent */ + //fprintf(stderr, "tRNS: 0x%08lx", (unsigned long)crc32(CRC32_INITIAL,"tRNS\0",5)); /* 0x40e6d866 */ + out.vi_write("\0\0\0\1bKGD\0\210\5\35H", 13); /* color 0 is background color */ + //out.vi_write("\0\0\0\1bKGD\2\x66\x0b\x7c\x64", 13); /* color 2 is background color */ + //fprintf(stderr, "bKGD: 0x%08lx", (unsigned long)crc32(CRC32_INITIAL,"bKGD\2",5)); /* 0x88051d48 */ + } + } + + slen_t rlenht=img->getRlen()*img->getHt(); + #if 0 /* Calculates _bad_ CRC (before compression etc.) */ + p=tmp; + *p++=rlenht>>24; *p++=rlenht>>16; *p++=rlenht>>8; *p++=rlenht; /* 0: IDAT chunk length */ + *p++='I'; *p++='D'; *p++='A'; *p++='T'; /* 4: IDAT chunk name */ + out.vi_write(tmp, 8); + if (rlenht!=0) pp->vi_write(img->getRowbeg(), rlenht); + pp->vi_write(0,0); /* flush all, write CRC */ + crc=crc32(crc32(CRC32_INITIAL,tmp+4,4), img->getRowbeg(), rlenht); + p=tmp; *p++=crc>>24;*p++=crc>>16;*p++=crc>>8;*p++=crc; /* 0: IDAT CRC */ + out.vi_write(tmp, 4); + #else + rp->vi_write("IDAT",4); + if (rlenht!=0) pp->vi_write(img->getRowbeg(), rlenht); + pp->vi_write(0,0); /* flush all, write CRC */ + #endif + + out.vi_write("\0\0\0\0IEND\256B`\202",12); /* IEND chunk */ + delete pp; + delete cp; + delete rp; + + return Rule::Applier::OK; +} + +Rule::Applier out_png_applier = { "PNG", out_png_check_rule, out_png_work, 0 }; + +/* --- Sat Jun 15 19:30:41 CEST 2002 */ + +/** BMP RLE compression, type 1. Seems to be optimal. + * @param dst buffer with enough place for compressed data. The caller must + * pre-allocate >=(send-sbeg)+(send-sbeg+128)*2/255. + * @param sbeg first raw data char to compress + * @param send char to finish compression just before + * @return dst+(number of characters occupied by compressed data) + * + * in-memory implementation Sun Jun 23 20:02:41 CEST 2002 + */ + +static char *bmp_compress1_row(char *dst, char const *sbeg, char const *send) { + #if 0 + # define BMP_ASSERT(x) assert(x) + #else + # define BMP_ASSERT(x) + #endif + #undef BUF + #define BUF(x) (*(x)) + #undef PUTCH__ + #define PUTCH__(c) (*dst++=(c)) + char c, c2; + char const *beg, *end, *rend, *q, *r, *best; + signed bestca, rca; /* both must fit into -255..255 */ + slen_t frl, efrl; + int ci; + // bool oddp; + + beg=sbeg; + end=(send-sbeg>255) ? beg+255 : send; + + while (beg!=end) { /* there is still unprocessed data in the buffer */ + c=BUF(beg++); + if (beg==end) { PUTCH__(1); PUTCH__(c); break; } /* last char */ + if (c==BUF(beg)) { /* sure r chunk */ + ci=2; beg++; + rep: + while (beg!=end && c==BUF(beg)) { beg++; ci++; } + PUTCH__(ci); PUTCH__(c); /* r chunk */ + } else { /* possible c chunk */ + rend=end; + BMP_ASSERT(end-beg<=254); + if (end!=send) { /* read an extra char as the terminator of the last run-length of c, buf:0..254 */ + end++; + BMP_ASSERT(end-beg==255); /* buffer is full (255 chars) */ + } + + best=r=beg; + bestca=rca=-1; /* best and current advantage of c over r */ + + while (r!=rend) { /* c chunk should stop only at run-length boundaries */ + BMP_ASSERT(-255<=rca && rca<=255); + BMP_ASSERT(-255<=bestca && bestca<=255); + q=r; r=q+1; ci=1; while (r!=end && BUF(r)==BUF(q)) { r++; ci++; } + if (r==end && end!=rend) break; + if (((r-beg)&1)==0) { /* odd (!) copy length */ + rca+=3-ci; + if (rca<=bestca-1) { r--; break; } /* fix-5 (instead of rule-4): `xyz|bbbbb|xyz|', `abcdef|gggggggg|abababababab|', `abcdef|ggg|hhh|ggg|hhh|ggg|hhh|ggg|hhh|abababababab|' */ + if (bestca<rca) { bestca=rca; best=r-1; } /* make c as short as possible */ + rca--; + } else { /* even copy length */ + rca+=2-ci; + if (rca<=bestca-2) break; /* fix-5 (instead of rule-4): `xyz|bbbbb|xyz|', `abcdef|gggggggg|abababababab|', `abcdef|ggg|hhh|ggg|hhh|ggg|hhh|ggg|hhh|abababababab|' */ + if (bestca<rca) { bestca=rca; best=r; } /* make c as short as possible */ + } + } + BMP_ASSERT(-255<=rca && rca<=255); + BMP_ASSERT(-255<=bestca && bestca<=255); + if (bestca<=0 /* no possible positive advantage */ + || best-beg<=1 /* 1: c is one char, plus 1 char in buf. Imp: ==1?! */ + ) { ci=1; goto rep; } + r=best; /* Imp: get rid of this assignment */ + BMP_ASSERT(beg!=r); + BMP_ASSERT(((r-beg)&1)==1); /* even copy length */ + + if (end==r) { /* no followers, last chunk */ + /* BMP_ASSERT(had_eof); */ + // oddp=(1+(r-beg)&1)==1; + PUTCH__(0); + PUTCH__((r-beg)+1); + PUTCH__(c); + while (beg!=r) { PUTCH__(BUF(beg)); beg++; } /* emit c chunk */ + // if (oddp) PUTCH__(0); /* Imp: padding breaks optimality */ + } else { + BMP_ASSERT(r!=end); + /* BMP_ASSERT(r!=rend); */ /* r==rend is possible here */ + c2=BUF(r); frl=1; q=r+1; + while (q!=end && c2==BUF(q)) { q++; frl++; } /* count follower run length */ + efrl=frl; ci=-2; if (q==end) { /* Imp: get rid of -2 (-2 -> -1) */ + BMP_ASSERT(q==end); + while ((ci=(q==send)?-1:(unsigned char)*q++)!=-1 && (char)ci==c2) efrl++; + } + + /* printf("clen=%u\n", clen); */ + if (1+(r>beg ? r-beg : 256+beg-r)<255 && efrl>=256 && efrl%255==1) { r++; efrl--; } /* make the c chunk one char longer if appropriate */ + + // oddp=(1+(r-beg)&1)==1; + PUTCH__(0); + PUTCH__(1+(r-beg)); + PUTCH__(c); + while (beg!=r) { PUTCH__(BUF(beg)); beg++; } /* emit c chunk */ + // if (oddp) PUTCH__(0); /* Imp: padding breaks optimality */ + + beg=q; /* remove beginning of the r chunk from the buffer */ + if (ci>=0) { beg--; BMP_ASSERT((unsigned char)BUF(beg)==ci); } + + while (efrl>=255) { PUTCH__('\377'); PUTCH__(c2); efrl-=255; } /* emit full r chunks */ + if (efrl>=2) { /* emit last r chunk */ + PUTCH__(efrl); PUTCH__(c2); + } else if (efrl!=0) { + BMP_ASSERT(efrl==1); + beg--; /* leave a single instance of c2 in beginning of the buffer */ + BMP_ASSERT(BUF(beg)==c2); + } + } /* IF c chunk has followers */ + } /* IF r or c chunk */ + end=(send-beg>255) ? beg+255 : send; + } /* WHILE main loop */ + return dst; + #undef BUF + #undef PUTCH__ +} + + +/** Windows Bitmap BMP output */ +Rule::Applier::cons_t out_bmp_check_rule(Rule::OutputRule* or_) { + /* Supported BMP types: /Rgb8, + * /Indexed1, /Indexed4, /Indexed8. + */ + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_BMP + ) return Rule::Applier::DONT_KNOW; + bool badp=false; + /* Dat: (by policy) we don't support /Transparent or /Opaque here; the + * user should not specify such SampleFormat in the .job file. + */ + if (cache->SampleFormat!=Image::SF_Indexed1 + /* Dat: /Indexed2 is not supported by /BMP */ + && cache->SampleFormat!=Image::SF_Indexed4 + && cache->SampleFormat!=Image::SF_Indexed8 + && cache->SampleFormat!=Image::SF_Rgb8) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Indexed1, /Indexed4, /Indexed8 or /Rgb8" << (Error*)0; + badp=true; + } + if (cache->TransferEncoding!=cache->TE_Binary) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Binary" << (Error*)0; + badp=true; + } + if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_RLE) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Compression/None or /RLE" << (Error*)0; + badp=true; + } + if (cache->Compression==Rule::Cache::CO_RLE && cache->SampleFormat!=Image::SF_Indexed8) { + /* !! Imp: Implement compr==2 for /Indexed4 */ + Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP/RLE requires /Indexed8" << (Error*)0; + badp=true; + } + if (cache->hasPredictor()) { + Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Predictor 1" << (Error*)0; + badp=true; + } + if (badp) return Rule::Applier::BAD; + /* Now we are sure about Rule::Applier::OK. */ + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_bmp_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + if (out_bmp_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + or_->doSampleFormat(sf); + Image::Sampled *img=sf->getImg(); + Image::Sampled::dimen_t wd=img->getWd(), ht=img->getHt(), htc=ht; + slen_t rlen=img->getRlen(); + char const*pend=img->getRowbeg()+rlen*ht; + char const*palbeg=img->getHeadp(), *palend=img->getRowbeg(); + slen_t ncols4=(palend-palbeg)/3*4; + unsigned biCompr=or_->cache.Compression!=or_->cache.CO_RLE ? 0 + : or_->cache.SampleFormat==Image::SF_Indexed4 ? 2 : 1; + + SimBuffer::B data; + slen_t crowsize=2+ rlen+(rlen+128)*2/255; /* !! Imp: real upper bound? */ + char *crow=new char[crowsize]; + /* !! GIMP compatibility */ + if (or_->cache.Compression==or_->cache.CO_RLE) { + /* Imp: bmp_compress2_row */ + char *crow2; + while (htc--!=0) { /* BMP stores rows from down */ + crow2=bmp_compress1_row(crow, pend-rlen, pend); +#if 0 + crow2=crow; + *crow2++=10; + *crow2++=1; + *crow2++=10; + *crow2++=2; + *crow2++=10; + *crow2++=3; + *crow2++=10; + *crow2++=4; + *crow2++=10; + *crow2++=5; + *crow2++=10; + *crow2++=6; +#endif + + assert((slen_t)(crow2-crow)<=crowsize-2); + pend-=rlen; + *crow2++='\0'; *crow2++='\0'; /* signal end of compressed data row */ + /* fprintf(stderr, "htc=%u cl=%u\n", htc, crow2-crow); */ + data.vi_write(crow, crow2-crow); + } + data.vi_write("\0\1", 2); /* signal end of bitmap */ + } else { + unsigned pad=(4-(rlen&3))&3; /* Dat: pad rows to 32 bits */ + if (or_->cache.SampleFormat==Image::SF_Rgb8) { /* SWAP RGB values */ + /* BUGFIX at Thu Dec 12 21:36:57 CET 2002 */ + char *buf=new char[rlen]; + while (htc--!=0) { /* BMP stores rows from down */ + char const*pxend=pend, *px=pend-=rlen; + char *q=buf; + while (px!=pxend) { + *q++=px[2]; + *q++=px[1]; + *q++=px[3]; + px+=3; + } + data.vi_write(buf, rlen); + if (pad!=0) data.vi_write("\0\0\0", pad); + } + delete [] buf; + } else { + while (htc--!=0) { /* BMP stores rows from down */ + data.vi_write(pend-=rlen, rlen); + if (pad!=0) data.vi_write("\0\0\0", pad); + } + } + } + assert(pend==img->getRowbeg()); + delete [] crow; + /* Now data is ready. */ + + char *bmphead=new char[54+ncols4+data.getLength()], *p=bmphead; + *p++='B'; *p++='M'; /* magic number header */ + lf32(p, 54+ncols4+data.getLength()); /* bfSize */ + lf32(p, 0); /* zzHotX, zzHotY */ + lf32(p, 54+ncols4); /* bfOffs */ + lf32(p, 40); /* biSize==40 => Windows 3.x style BMP file */ + lf32(p, wd); /* biWidth */ + lf32(p, ht); /* biHeight */ + lf16(p, 1); /* biPlanes, must be 1 */ + lf16(p, img->getBpc()*img->getCpp()); /* biBitCnt: bits per pixel (1, 4, 8: /Indexed*; 24: /Rgb8) */ + lf32(p, biCompr); /* biCompr */ + lf32(p, 0); /* biSizeIm */ + lf32(p, 0); /* biXPels */ + lf32(p, 0); /* biYPels */ + lf32(p, (palend-palbeg)/3); /* biClrUsed */ + lf32(p, (palend-palbeg)/3); /* biClrImp */ + /* vvv Now comes the palette (zero length for /Rgb) */ + while (palbeg!=palend) { + *p++=palbeg[2]; *p++=palbeg[1]; *p++=palbeg[0]; *p++='\0'; + palbeg+=3; + } + assert((slen_t)(p-bmphead)==54+ncols4); + + out.vi_write(bmphead, p-bmphead); delete [] bmphead; +#if 0 + out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 100); + out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 100); + out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 100); + out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 100); + out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + 100); +#endif + out << data; + out.vi_write(0,0); /* signal EOF */ + + return Rule::Applier::OK; +} + +Rule::Applier out_bmp_applier = { "BMP", out_bmp_check_rule, out_bmp_work, 0 }; + +/* --- Sun Mar 24 13:48:57 CET 2002 */ + +/** The Empty applier produces an empty output file. */ +Rule::Applier::cons_t out_empty_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_Empty + ) return Rule::Applier::DONT_KNOW; + return Rule::Applier::OK; +} +Rule::Applier::cons_t out_empty_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + (void)out; + (void)sf; + if (out_empty_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + return Rule::Applier::OK; +} + +Rule::Applier out_empty_applier = { "Empty", out_empty_check_rule, out_empty_work, 0 }; + +/* --- Sun Mar 24 13:48:57 CET 2002 */ + +/** The Meta applier writes some meta-information into the output file */ +Rule::Applier::cons_t out_meta_check_rule(Rule::OutputRule* or_) { + Rule::Cache *cache=&or_->cache; + if (cache->FileFormat!=cache->FF_Meta + ) return Rule::Applier::DONT_KNOW; + // return Rule::Applier::OK; /* Imp: implement the applier */ + return Rule::Applier::BAD; +} +Rule::Applier::cons_t out_meta_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) { + (void)out; + (void)sf; + if (out_meta_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW; + /* Imp: real content here */ + return Rule::Applier::OK; +} + +Rule::Applier out_meta_applier = { "Meta", out_meta_check_rule, out_meta_work, 0 }; + +/* __END__ */ diff --git a/Build/source/utils/sam2p/at_bitmap.h b/Build/source/utils/sam2p/at_bitmap.h new file mode 100644 index 00000000000..72d3c5dad83 --- /dev/null +++ b/Build/source/utils/sam2p/at_bitmap.h @@ -0,0 +1,70 @@ +/* This code is ripped from Autotrace-0.29, but modified by pts. */ + +/* bitmap.h: definition for a bitmap type. No packing is done by + default; each pixel is represented by an entire byte. Among other + things, this means the type can be used for both grayscale and binary + images. */ + +#ifndef AT_BITMAP_H +#define AT_BITMAP_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#define PTS_SAM2P 1 +#define FATALP(m) Error::sev(Error::EERROR) << m << (Error*)0; +#define WARNINGP(m) Error::sev(Error::WARNING) << m << (Error*)0; +#define FATALP1(m,a) Error::sev(Error::EERROR) << m << a << (Error*)0; +#define WARNINGP1(m,a) Error::sev(Error::WARNING) << m << a << (Error*)0; +#define FATALP3(m,a,n,b,o,c,p) Error::sev(Error::EERROR) << m << a << n << b << o << c << p << (Error*)0; +#define WARNINGP3(m,a,n,b,o,c,p) Error::sev(Error::WARNING) << m << n << b << o << c << p << (Error*)0; + +#define XMALLOCT(var,typep,size) var=(typep)new char[size] +#define XMALLOCTU(var,type) var=(type*)new type +#define XFREE(p) delete p +/* ^^^ Imp: arrays?? */ + +/* #include "autotrace.h" */ +typedef char *at_string; +typedef struct _at_bitmap_type { + unsigned short height; + unsigned short width; + unsigned char *bitmap; + unsigned int np; +} at_bitmap_type; + +#include <stdio.h> + +#define xfclose(fd,dummy) fclose(fd) + +/* The basic structure and macros to access it. */ +typedef at_bitmap_type bitmap_type; + +/* The number of color planes of each pixel */ +#define BITMAP_PLANES(b) ((b).np) + +/* The pixels, represented as an array of bytes (in contiguous storage). + Each pixel is represented by np bytes. */ +#define BITMAP_BITS(b) ((b).bitmap) + +/* These are convenient abbreviations for geting inside the members. */ +#define BITMAP_WIDTH(b) ((b).width) +#define BITMAP_HEIGHT(b) ((b).height) + +/* This is the pixel at [ROW,COL]. */ +#define BITMAP_PIXEL(b, row, col) \ + ((BITMAP_BITS (b) + (row) * BITMAP_PLANES (b) * BITMAP_WIDTH (b) \ + + (col) * BITMAP_PLANES(b))) + +#define BITMAP_VALID_PIXEL(b, row, col) \ + ((row) < BITMAP_HEIGHT (b) && (col) < BITMAP_WIDTH (b)) + +/* Allocate storage for the bits, set them all to white, and return an + initialized structure. */ +extern bitmap_type new_bitmap (unsigned short, unsigned short); + +/* Free that storage. */ +extern void free_bitmap (bitmap_type *); + +#endif /* not AT_BITMAP_H */ diff --git a/Build/source/utils/sam2p/bts.ttt b/Build/source/utils/sam2p/bts.ttt new file mode 100644 index 00000000000..a2dadcc8855 --- /dev/null +++ b/Build/source/utils/sam2p/bts.ttt @@ -0,0 +1,1602 @@ +% +% bts.ttt -- Built-in TemplateS, contains most .tte and .ttm files +% by pts@math.bme.hu at Wed Apr 17 10:37:42 CEST 2002 +% Sat Jun 1 18:40:04 CEST 2002 +% ADSC fixups at Sun Jun 23 18:16:29 CEST 2002 +% fixed %%EndComments, bts2.ttt at Sun Sep 22 14:25:45 CEST 2002 +% /l148z, /l1thl at ... +% +% These OutputFile-generation templates will be built in to the sam2p +% executable at compile time. The contents of this file can be referenced as +% `(%bts) run' in .job files. +% + +% _l23_ +/l23 (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: `0 +%%EndComments +%%Page: 1 1 +save`s 9 dict begin +{/T currentfile`T def`1setcolorspace +/F T`F def +<</ImageType 1/Width `w/Height `h/BitsPerComponent +`b/ImageMatrix[1 0 0 -1 0 `h]/Decode +[`D]/DataSource F>> image +`t} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% _l23_ +/l23mask (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: `0 +%%EndComments +%%Page: 1 1 +save`s 9 dict begin +{`r setrgbcolor +/T currentfile`T def +/F T`F def +`w `h false[1 0 0 -1 0 `h]F imagemask +`t} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% _l23_ +/l23ind1 (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: `0 +%%EndComments +%%Page: 1 1 +save`s 9 dict begin +{`R/T currentfile`T def +/F T`F def +`w `h true[1 0 0 -1 0 `h]F imagemask +`t} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% Dat: vvv last color not necessarily transparent +% T `P string readstring pop dup length 0 exch 3 sub getinterval +% Used by /Transparent2, /Transparent4 and /Transparent8. +% This implemetation does: +% rgb-palette imagemask-newcompress-transfer +% Alternative implementation (not this one!): +% ( rgb-transfer imagemask-newcompress-transfer )* +% It would be tedious to flush buffers etc. +% Doesn't work with JPEG compressions, because JPEG requires a bit depth of +% 8. Works with any other /Compression and any /Predictor. +% _l23_ +/l23tran2 (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: `0 +%%EndComments +%%Page: 1 1 +save`s 9 dict begin +{/T currentfile`T def +T `P string readstring pop 0 `p getinterval +/F T`F def +/m 0 def +{255 div m 1 add dup 3 eq{pop setrgbcolor +`w `h false[1 0 0 -1 0 `h]F imagemask +0}if/m exch def}forall +`t} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% _l23_ +% With old (pre-Wed Feb 5 17:46:59 CET 2003) PDF code, /Length was one less, +% because it hasn't counted the last \n newline in the content stream. This +% made a problem with pdfTeX 0.12 shipped with Debian Slink. +% Old code (focus on the \n's) +%[ (3 0 obj\n<</Length ) ] %1 +%-4 %2: length of chunk 4 +%(>>\nstream\n) %3 +%[ (q`s\n`w 0 0 `h 0 0 cm /S Do Q) ] %4.0 +%(\nendstream\nendobj\n) %5 +% At Fri Feb 7 11:56:14 CET 2003 modified all /MediaBox specifications to +% precede the image data, and be in a separate line, to ease parsing. +% vvv tested at Sat Jan 8 12:31:00 CET 2005 +/p02 [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:33:30 CEST 2002 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s\n`w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Length ) ] %8.0 +-11 %9 +(/Interpolate false/Type/XObject/Name/S/Subtype/Image/ColorSpace`1/Width +`w/Height `h/BitsPerComponent `b`F>>stream\n) %10 +[ (`S) ] %11 +(\nendstream\nendobj\n) %12 +[ (5 0 obj\n<</Type/Page/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S +4 0 R>>/ProcSet[/PDF`C]>>/Contents 3 0 R>>\n endobj\n) ] % 13 +(xref\n0 6\n0000000000 65535 f \n) %14 +7 %15 +( 00000 n \n) %16 +1 %17 +( 00000 n \n) %18 +2 %19 +( 00000 n \n) %20 +8 %21 +( 00000 n \n) %22 +13 %23 +( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %24 +14 %25 +(\n%%EOF\n) %26 +] + +% _l23_ +% vvv tested at Sat Jan 8 12:31:00 CET 2005 +/p02mask [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 20:34:35 CEST 2002 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s\n`g rg `w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Length ) ] %8.0 +-11 %9 +(/Interpolate false/Type/XObject/Name/S/Subtype/Image/ImageMask +true/BitsPerComponent 1/Width `w/Height `h`F>>stream\n) %10 +[ (`S) ] %11 +(\nendstream\nendobj\n) %12 +[ (5 0 obj\n<</Type/Page +/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S +4 0 R>>/ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %14 +(xref\n0 6\n0000000000 65535 f \n) %15 +7 %16 +( 00000 n \n) %17 +1 %18 +( 00000 n \n) %19 +2 %20 +( 00000 n \n) %21 +8 %22 +( 00000 n \n) %21 +13 %22 +( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %23 +14 %24 +(\n%%EOF\n) %25 +] + +% _l23_ +% vvv tested at Sat Jan 8 12:31:00 CET 2005 +/p02maskbb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s\n`g rg `w 0 0 `h 0 0 cm\nBI/W `w/H `h/ImageMask true/BPC 1`F ID +`S +EI\nQ\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %15 +8 %16 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% _l23_ +/p02ind1 [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 20:34:35 CEST 2002 +% vvv tested at Sat Jan 8 12:31:00 CET 2005 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +% `G rg 0 0 `w `h re B +[ (q`s +`G rg 0 0 m `w 0 l `w `h l 0 `h l F +`g rg +`w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Length ) ] %8.0 +-11 %9 +(/Interpolate false/Type/XObject/Name/S/Subtype/Image/ImageMask +true/BitsPerComponent 1/Width `w/Height `h`F>>stream\n) %10 +[ (`S) ] %11 +(\nendstream\nendobj\n) %12 +[ (5 0 obj\n<</Type/Page +/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S +4 0 R>>/ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %13 +(xref\n0 6\n0000000000 65535 f \n) %14 +7 %15 +( 00000 n \n) %16 +1 %16 +( 00000 n \n) %17 +2 %18 +( 00000 n \n) %18 +8 %19 +( 00000 n \n) %20 +13 %21 +( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %22 +14 %23 +(\n%%EOF\n) %24 +] + +% _l23_ +% vvv tested at Sat Jan 8 12:31:00 CET 2005 +/p02ind1bb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +% `G rg 0 0 `w `h re B +[ (q`s +`G rg 0 0 m `w 0 l `w `h l 0 `h l F +`g rg `w 0 0 `h 0 0 cm\nBI/W `w/H `h/ImageMask true/BPC 1`F ID +`S +EI\nQ\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page +/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %15 +8 %16 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% _l23_ +% vvv tested at Sat Jan 8 12:31:00 CET 2005 +/p02bb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s\n`w 0 0 `h 0 0 cm\nBI/Interpolate false/W `w/H `h/CS`1/BPC `b`F ID +`S +EI\nQ\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %15 +8 %16 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% Dat: /Kids with direct objects are not valid PDF +% (reported by Sid Steward) +% The PDF Reference 1.5 (and 1.3) actually describes the page Kids array +% as: "An array of indirect references to the immediate children of this +% node. The children may be page objects or other page tree nodes." +%/pd02bb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002 +%(%PDF-1.`0\n`B) %0 +%[ (2 0 obj\n<</Type/Pages/Kids[<</Type/Page +%/MediaBox[`X] +%/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +%3 0 R>>]/Count 1>>\nendobj\n) ] %1 +%[ (3 0 obj\n<</Length ) ] %2 +%-5 %3: length of chunk 5 +%(>>\nstream\n) %4 +%[ (q`s\n`w 0 0 `h 0 0 cm\nBI/Interpolate false/W `w/H `h/CS`1/BPC `b`F ID +%`S +%EI\nQ\n) ] %5.0 +%(endstream\nendobj\n) %6 +%[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +%(xref\n0 4\n0000000000 65535 f \n) %8 +%7 %9: offset of chunk 7, printf("%010u") +%( 00000 n \n) %10 +%1 %11 +%( 00000 n \n) %12 +%2 %13 +%( 00000 n \ntrailer\n<</Size 4/Root 1 0 R>>\nstartxref\n) %14 +%8 %15 +%(\n%%EOF\n) %16 +%] + +% --- + +% _l2jbin_ +/l2jbin (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 2 +%%EndComments +%%Page: 1 1 +save`s 2 dict begin +{/Device`d setcolorspace +/T currentfile`T def +/F T/DCTDecode filter def +<</ImageType 1/Width `w/Height `h/BitsPerComponent +`b/ImageMatrix[1 0 0 -1 0 `h]/Decode +[`D]/DataSource F>> image`t} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% _l2jbin_ +/p0jbin [%sam2p-ttm; by pts@fazekas.hu at Mon Apr 15 21:58:26 CEST 2002 +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s\n`w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Length ) ] %8.0 +-11 %9 +(/Type/XObject/Name/S/Subtype/Image/ColorSpace/Device`d/Width +`w/Height `h/BitsPerComponent `b`F>>stream\n) %10 +[ (`S) ] %11 +(\nendstream\nendobj\n) %12 +[ (5 0 obj\n<</Type/Page +/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S +4 0 R>>/ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %13 +(xref\n0 6\n0000000000 65535 f \n) %14 +7 %15 +( 00000 n \n) %16 +1 %17 +( 00000 n \n) %18 +2 %19 +( 00000 n \n) %20 +8 %21 +( 00000 n \n) %22 +13 %23 +( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %24 +14 %25 +(\n%%EOF\n) %26 +] + +% _l2jbin_ +/p0jbb [%sam2p-ttm; by pts@fazekas.hu at Mon Apr 15 21:58:26 CEST 2002 +% Dat: CropBox is required by buggy gs/gv viewer code +(%PDF-1.`0\n`B) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s\n`w 0 0 `h 0 0 cm\nBI/W `w/H `h/CS/Device`d/BPC `b`F ID +`S +EI\nQ\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %15 +8 %16 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% --- + +% _l1tr_ +/l1tr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +showpage +%%Trailer +%%EOF\n) + +% _l1tr_ +/l1op (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s +`r setrgbcolor +0 0 moveto +`w 0 lineto +0 `h rlineto +-`w 0 rlineto +closepath fill +restore showpage +%%Trailer +%%EOF\n) + +% by pts@fazekas.hu at Sat Jun 15 16:09:25 CEST 2002 +% _l1tr_ +/l1bb (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s +0 0 moveto +`w 0 lineto +0 `h rlineto +-`w 0 rlineto +closepath stroke +restore showpage +%%Trailer +%%EOF\n) + +% _l1tr_ +/p0op [%sam2p-ttm; by pts@fazekas.hu at Wed Apr 17 10:34:36 CEST 2002 +(%PDF-1.0\n) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +% [ (q `g rg 0 0 `w `h re B Q) ] %4.0 +% ^^^ SUXX `re' draws a rectangle with black border in acroread :-( +[ (q `g rg 0 0 m `w 0 l `w `h l 0 `h l F Q\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %15 +8 %16 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% /p0bb: draws the bounding box (./sam2p -s:bbox examples/yellow.gif test.pdf), +% see also /l1bb. Half of the linewidth is cropped by /MediaBox +/p0bb [%sam2p-ttm; by pts@fazekas.hu at Sat Jun 15 16:08:38 CEST 2002 +(%PDF-1.0\n) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ (q`s `g rg 0 0 m `w 0 l `w `h l 0 `h l S Q\n) ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %15 +8 %16 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% _l1tr_ +/p0tr [%sam2p-ttm; by pts@fazekas.hu at Wed Apr 17 10:34:36 CEST 2002 +(%PDF-1.0\n) %0 +[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1 +[ (3 0 obj\n<</Length ) ] %2 +-5 %3: length of chunk 5 +(>>\nstream\n) %4 +[ ] %5.0 +(endstream\nendobj\n) %6 +[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0 +[ (4 0 obj\n<</Type/Page +/MediaBox[`X] +/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents +3 0 R>>\nendobj\n) ] %8 +(xref\n0 5\n0000000000 65535 f \n) %9 +7 %10: offset of chunk 7, printf("%010u") +( 00000 n \n) %11 +1 %12 +( 00000 n \n) %13 +2 %14 +( 00000 n \n) %14 +8 %15 +( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17 +9 %18 +(\n%%EOF\n) %19 +] + +% --- + +% at Sun Jun 2 15:49:39 CEST 2002 +% derived from /l1m8r +% _l1c_ +/l1t8r (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s 36 dict begin +`r setrgbcolor +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +/B `? " E/L 128 " E/Ex()E +`P " u ? 1 - 0 c 1 c{d 3 y put O O}for 0 `p ;/m +0 E{255 div m 1 + u 3 eq{O setrgbcolor +`w `h false[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c +? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? +1 - 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O +c O 0 c ;}i}loop B}imagemask 0}if/m c E}forall d O d O}bind exec}{ +T `P " readstring O 0 `p ;/m 0 E/F T/RunLengthDecode filter E +{255 div m 1 + u 3 eq{O setrgbcolor +`w `h false[1 0 0 -1 0 `h]F imagemask 0}if/m c E}forall +F closefile T closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 15:49:46 CEST 2002 +% derived from /l1mhr +% _l1c_ +/l1thr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s 36 dict begin +`r setrgbcolor +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +/C(.)E/d{A C S O 0 get}E +/B `? " E/L 128 " E/Ex()E +A `P " S O 0 `p ;/m 0 E{255 div m 1 + u 3 eq{O setrgbcolor +`w `h false[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c +? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; +A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O +c O 0 c ;}i}loop B}imagemask 0}if/m c E}forall +d O A read O O}bind exec}{ +T `P " readstring O 0 `p ;/m 0 E/F T/RunLengthDecode filter E +{255 div m 1 + u 3 eq{O setrgbcolor +`w `h false[1 0 0 -1 0 `h]F imagemask 0}if/m c E}forall +F closefile T closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 15:49:59 CEST 2002 +% derived from /l1mbr +% _l1c_ +/l1tbr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s 36 dict begin +`r setrgbcolor +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +/filter where not{{ +/B `? " E/L 128 " E/Ex()E +A `P " S O 0 `p ;/m 0 E{255 div m 1 + u 3 eq{O setrgbcolor +`w `h false[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 + +; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B}imagemask 0}if/m c E}forall A read O O}bind exec}{ +O/F A/RunLengthDecode filter E +A `P " S O 0 `p ;/m 0 E{255 div m 1 + u 3 eq{O setrgbcolor +`w `h false[1 0 0 -1 0 `h]F imagemask 0}if/m c E}forall F closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% PSL1 implementation of /l23tran2 /A85 +% _l1c_ +/l1t8n (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s 16 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/d{{27 S ge{exit}if A read not{511}if dup 122 eq{/S 27 E/D 0 E/C 0 E}{dup 117 +gt{A read{pop}if/S 54 S sub E}{dup 33 ge{S 32 eq{dup/C c E/D -1670420001 E}{dup +117 sub{1 85 7225 614125}S 28 sub get mul D add/D c E}i/S S 1 sub E}if}i}i pop} +loop S 22 eq{511}{C 1868977 mul D add S 24 and neg bitshift 23 S lt{C 3 mul add +}if 255 and/S S 3 eq{32}{S 7 mod 3 eq{22}{S 8 sub}i}i E}i}bind E +/s `? string E +{`P string dup length 1 sub 0 c 1 c{d 3 copy put pop pop}for +0 `p getinterval +/m 0 E +{255 div m 1 add dup 3 eq{pop setrgbcolor +`w `h false[1 0 0 -1 0 `h] +{s dup length 1 sub 0 c 1 c{d 3 copy put pop pop}for}imagemask +0}if/m exch def}forall +d pop}bind +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% PSL1 implementation of /l23tran2 /Hex +% _l1c_ +/l1thn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s 2 dict begin +/s `? string def +{currentfile `P string readhexstring pop +0 `p getinterval +/m 0 def +{255 div m 1 add dup 3 eq{pop setrgbcolor +`w `h false[1 0 0 -1 0 `h] +{currentfile s readhexstring pop}imagemask +0}if/m exch def}forall +currentfile read pop pop}bind +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% PSL1 implementation of /l23tran2 /Binary +% Used by /Transparent2, /Transparent4 and /Transparent8. +% This implemetation does: +% rgb-palette imagemask-newcompress-transfer +% _l1c_ +/l1tbn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +%%EndComments +%%Page: 1 1 +save`s 2 dict begin +/s `? string def +{currentfile `P string readstring pop +0 `p getinterval +/m 0 def +{255 div m 1 add dup 3 eq{pop setrgbcolor +`w `h false[1 0 0 -1 0 `h] +{currentfile s readstring pop}imagemask +0}if/m exch def}forall}bind +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + + +% at Sun Jun 2 15:21:53 CEST 2002 +% derived from /l118r +% l1g8r: /Compression/RLE /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1 +% _l1c_ +/l1g8r (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s `R26 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +/B `? " E/L 128 " E/Ex()E +`w `h `b[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c +? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? +1 - 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O +c O 0 c ;}i}loop B}`i +d O d O}bind exec}{ +/F T/RunLengthDecode filter def +`w `h `b[1 0 0 -1 0 `h]F `i F closefile T closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 15:22:10 CEST 2002 +% derived from /l1ghr +% _l1c_ +/l1ghr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s `R26 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +/C(.)E/d{A C S O 0 get}E +/B `? " E/L 128 " E/Ex()E +`w `h `b[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c +? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; +A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O +c O 0 c ;}i}loop B}`i +d O A read O O}bind exec}{ +/F T/RunLengthDecode filter def +`w `h `b[1 0 0 -1 0 `h]F `i F closefile T closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 15:22:21 CEST 2002 +% derived from /l11br +% _l1c_ +/l1gbr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s `R26 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/RunLengthDecode filter/F exch def}stopped +/B exch def cleartomark B{{ +/B `? " E/L 128 " E/Ex()E +`w `h `b[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 + +; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B}`i A read O O}bind exec}{ +`w `h `b[1 0 0 -1 0 `h]F `i F closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% l1g8n: /Compression/None /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1 +% _l1c_ +/l1g8n (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s `R16 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E{ +{mark A/ASCII85Decode filter/F exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if dup 122 eq{/S 27 E/D 0 E/C 0 E}{dup 117 +gt{A read{pop}if/S 54 S sub E}{dup 33 ge{S 32 eq{dup/C c E/D -1670420001 E}{dup +117 sub{1 85 7225 614125}S 28 sub get mul D add/D c E}i/S S 1 sub E}if}i}i pop} +loop S 22 eq{511}{C 1868977 mul D add S 24 and neg bitshift 23 S lt{C 3 mul add +}if 255 and/S S 3 eq{32}{S 7 mod 3 eq{22}{S 8 sub}i}i E}i}bind E +/s `? string E +`w `h `b[1 0 0 -1 0 `h] +{s dup length 1 sub 0 c 1 c{d 3 copy put pop pop}for}`i +d pop}bind exec}{ +`w `h `b[1 0 0 -1 0 `h]F `i F closefile}i} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% _l1c_ +/l1ghn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s `R1 dict begin +/s `? string def +{`w `h `b[1 0 0 -1 0 `h]{currentfile s readhexstring pop}`i +currentfile read pop pop}bind +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% _l1c_ +/l1gbn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s `R1 dict begin +/s `? string def +{`w `h `b[1 0 0 -1 0 `h]{currentfile s readstring pop}`i}bind +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + + +% at Sat Jun 1 21:19:30 CEST 2002 +% _l1c_ +/l128r (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +12 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 3072 " E/R 0 E +0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E +u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +3 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? 1 +- 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage +d O d O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile T closefile +}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:19:02 CEST 2002 +% derived from /l128r +% _l1c_ +/l12hr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +/C(.)E/d{A C S O 0 get}E +A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E +0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E +u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +3 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; +A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage +d O A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile T closefile +}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:41:59 CEST 2002 +% derived from /l12hr +% _l1c_ +/l12br (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter}stopped +/B exch def cleartomark B{{ +A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E +0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E +u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +3 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 + +; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage +A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace +/F A/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 12:00:13 CEST 2002 +% _l1c_ +/l128n (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +12 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 3072 " E/R 0 E +0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E +u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +3 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B u ? 1 - 0 c 1 c{d 3 y put O O}for +{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage +d O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource T>>image T closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:31:07 CEST 2002 +% derived from /l128n +% _l1c_ +/l12hn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E +0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E +u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +3 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E +`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O +{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage +A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource T>>image T closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + + +% at Sun Jun 2 00:05:36 CEST 2002 +% _l1c_ +/l148r (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +48 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 1536 " E/R 0 E +0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E +15 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? 1 +- 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage +d O d O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile T closefile +}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:26:37 CEST 2002 +% derived from /l148r +% _l1c_ +/l14hr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +/C(.)E/d{A C S O 0 get}E +A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E +0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E +15 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; +A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage +d O A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile T closefile +}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:49:40 CEST 2002 +% derived from /l14hr +% _l1c_ +/l14br (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +/filter where not{{ +A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E +0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E +15 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 + +; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage +A read O O}bind exec}{ +O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace +/F A/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 12:13:50 CEST 2002 +% _l1c_ +/l148n (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +48 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 1536 " E/R 0 E +0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E +15 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E +`w `h 8[1 0 0 -1 0 `h]{B3 0 B u ? 1 - 0 c 1 c{d 3 y put O O}for +{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage +d O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource T>>image T closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:34:26 CEST 2002 +% derived from /l148n +% _l1c_ +/l14hn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E +0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E +15 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E +`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O +{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage +A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource T>>image T closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + + + +% at Sun Jun 2 00:05:36 CEST 2002 +% _l1c_ +/l188r (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +768 " u/H c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O +/B `w " E/R `w 3 * " E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{R 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? 1 +- 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage +d O d O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile T closefile +}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 00:05:36 CEST 2002 +% derived from /l188r +% _l1c_ +/l18hr (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +/C(.)E/d{A C S O 0 get}E +A 768 " u/H c E 0 `p ; S O O/B `w " E/R `w 3 * " E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{R 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; +A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage +d O A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile T closefile +}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 00:05:36 CEST 2002 +% derived from /l18hr +% _l1c_ +/l18br (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +/filter where not{{ +A 768 " u/H c E 0 `p ; S O O/B `w " E/R `w 3 * " E/L 128 " E/Ex()E +`w `h 8[1 0 0 -1 0 `h]{R 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ? +c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 + +; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c +O 0 c ;}i}loop B{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage +A read O O}bind exec}{ +O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace +/F A/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h +/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>> +image F closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 12:14:04 CEST 2002 +% derived from /l188r +% _l1c_ +/l188n (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCII85Decode filter/T exch def}stopped +/B exch def cleartomark B{{ +/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{ +A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85 +7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C +1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3 +eq{22}{S 8 -}i}i E}i}E +768 " u/H c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/B `w " E/R `w 3 * +" E `w `h 8[1 0 0 -1 0 `h]{R 0 B u ? 1 - 0 c 1 c{d 3 y put O O}for +{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage +d O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource T>>image T closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 12:25:13 CEST 2002 +% derived from l188n +% _l1c_ +/l18hn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/d/readhexstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +{mark A/ASCIIHexDecode filter/T exch def}stopped +/B exch def cleartomark B{{ +A 768 " u/H c E 0 `p ; d O O/B `w " E/R `w 3 * +" E `w `h 8[1 0 0 -1 0 `h]{R 0 A B d O +{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage +A read O O}bind exec}{ +[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource T>>image T closefile}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:45:14 CEST 2002 +% derived from /l12hn +% _l1c_ +/l12bn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +/filter where not{{ +A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E +0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E +u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E +3 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E +`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O +{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage}bind exec}{ +O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource A>>image}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 14:47:31 CEST 2002 +% derived from /l14hn +% _l1c_ +/l14bn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +/filter where not{{ +A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E +0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E +15 and B c 3 * 3 ; H c R c p/R R 3 + E +}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E +`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O +{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage}bind exec}{ +O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource A>>image}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% at Sun Jun 2 12:25:13 CEST 2002 +% BUGFIX at Sun Sep 22 20:02:47 CEST 2002 +% derived from l18hn +% _l1c_ +/l18bn (%!PS-Adobe-3.0`E +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +save`s 36 dict begin +/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/d/readstring x +/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x +/-/sub x/"/string x/?/length x/y/copy x{ +/filter where not{{ +A 768 " u/H c E 0 `p ; d O O/B `w " E/R `w 3 * +" E `w `h 8[1 0 0 -1 0 `h]{R 0 A B d O +{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage}bind exec}{ +O[/Indexed/DeviceRGB `# 1 - A `p " d O]setcolorspace +<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 +`h]/Decode[`D]/DataSource A>>image}ifelse} +%%BeginData:; +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF\n) + +% long before Sun Sep 22 13:57:08 CEST 2002 +% /lcrb -> l1gbn +% /lcr8 -> l1g8n +% /lcrh -> l1ghn + +% --- + +% Templates missing from this file: +% l1g8z: /Compression/ZIP /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1 +% (formerly l1fa85g.tte, now: l1zip.psm) +% l1ghz: /Compression/ZIP /TransferEncoding/Hex /SampleFormat/Gray* /FileFormat/PSL1 +% l1gbz: /Compression/ZIP /TransferEncoding/Binary /SampleFormat/Gray* /FileFormat/PSL1 +% l1g8l: /Compression/LZW /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1 +% (formerly l1fa85g.tte, now: l1lzw.psm) +% l1ghl: /Compression/LZW /TransferEncoding/Hex /SampleFormat/Gray* /FileFormat/PSL1 +% l1gbl: /Compression/LZW /TransferEncoding/Binary /SampleFormat/Gray* /FileFormat/PSL1 + +%%EOF diff --git a/Build/source/utils/sam2p/c_lgcc.cpp b/Build/source/utils/sam2p/c_lgcc.cpp new file mode 100644 index 00000000000..b2c8187a7a4 --- /dev/null +++ b/Build/source/utils/sam2p/c_lgcc.cpp @@ -0,0 +1,44 @@ +/* c_lgcc.cpp -- make C++ programs linkable with gcc + * by pts@fazekas.hu at Tue Sep 3 18:31:58 CEST 2002 + * + * This file is not sam2p-specific. See also AC_PTS_GCC_LINKS_CXX in file + * aclocal.m4. + */ + +#include <stdio.h> +#include <stdlib.h> + +/* vvv make these a macro to make them fast */ +#define XMALLOC_CODE() (unsigned len) { \ + void *p=malloc(len); \ + if (p==0) { fputs("out of memory\n",stderr); abort(); } \ + return p; \ +} +#define XFREE_CODE() (void* p) { if (p!=0) free(p); } + +/* Sat Jul 6 16:39:19 CEST 2002 + * empirical checkerg++ helper routines for gcc version 2.95.2 20000220 (Debian GNU/Linux) + */ +#ifdef __CHECKER__ +void* __builtin_vec_new XMALLOC_CODE() +void __builtin_vec_delete XFREE_CODE() +void* __builtin_new XMALLOC_CODE() +void __builtin_delete XFREE_CODE() +void __rtti_user() { abort(); } +void __rtti_si() { abort(); } +void terminate() { abort(); } +/* void* __pure_virtual=0; -- doesn't work */ +extern "C" void __pure_virtual(); void __pure_virtual() { abort(); } + +#else + +/* Tue Sep 3 18:24:26 CEST 2002 + * empirical g++-3.2 helper routines for gcc version 3.2.1 20020830 (Debian prerelease) + */ +void* operator new XMALLOC_CODE() +void* operator new[] XMALLOC_CODE() +void operator delete XFREE_CODE() +void operator delete[] XFREE_CODE() +void* __cxa_pure_virtual=0; + +#endif diff --git a/Build/source/utils/sam2p/c_lgcc3.cpp b/Build/source/utils/sam2p/c_lgcc3.cpp new file mode 100644 index 00000000000..e076ffd74d7 --- /dev/null +++ b/Build/source/utils/sam2p/c_lgcc3.cpp @@ -0,0 +1,31 @@ +/* c_lgcc3.cpp -- make g++-3.2 programs linkable with gcc-2.95 + * by pts@fazekas.hu at Wed Dec 11 16:33:03 CET 2002 + * + * This file is not sam2p-specific. See also AC_PTS_GCC_LINKS_CXX in file + * aclocal.m4. + */ + +#include <stdio.h> +#include <stdlib.h> + +/* vvv make these a macro to make them fast */ +#define XMALLOC_CODE() (unsigned len) { \ + void *p=malloc(len); \ + if (p==0) { fputs("out of memory\n",stderr); abort(); } \ + return p; \ +} +#define XFREE_CODE() (void* p) { if (p!=0) free(p); } + +/* at Wed Dec 11 16:31:42 CET 2002 + * This helper is here for gcc-2.95: c_lgcc3.cpp should be compiled by + * gcc-2.95, remaining files are compiled by g++-3.2 + */ +void* __cxa_pure_virtual=0; +extern "C" void _ZdlPv (void*); +extern "C" void* _Znwj (unsigned); +extern "C" void _ZdaPv (void*); +extern "C" void* _Znaj (unsigned); +void _ZdlPv XFREE_CODE() +void* _Znwj XMALLOC_CODE() +void _ZdaPv XFREE_CODE() +void* _Znaj XMALLOC_CODE() diff --git a/Build/source/utils/sam2p/ccdep.pl b/Build/source/utils/sam2p/ccdep.pl new file mode 100644 index 00000000000..afe684f4aa1 --- /dev/null +++ b/Build/source/utils/sam2p/ccdep.pl @@ -0,0 +1,349 @@ +#! /bin/sh -- +eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \ +;exec perl -T -S -- "$0" ${1+"$@"};#'if 0; +eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q +#!perl -w ++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0; +# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header +# +# ccdep.pl v0.32 -- semiautomatic dependency discovery for C/C++ programs +# by pts@math.bme.hu at Fri May 31 13:36:29 CEST 2002 +# 0.31 by pts@math.bme.hu at Sat Jun 1 15:19:55 CEST 2002 +# 0.32 by pts@math.bme.hu at Tue Sep 3 19:12:20 CEST 2002 +# 0.33 by pts@math.bme.hu at Thu Oct 31 09:47:25 CET 2002 +# +# Dat: no -T (tainting checks) anymore, does bad to our readpipe() +# OK : emit `TARGETS_yes = ...' +# Imp: make #warning etc. in *.h files work as expected +# OK : generated.h +# Imp: add external libraries (-L...) +# Imp: abort if gcc command not found... +# Imp: abort if not all .o are mentioned in gcc output +# Imp: avoid $ etc. in Makefile +# OK : all 8 combinations of PROVIDES|REQUIRES|CONFLICTS +# +BEGIN { eval { require integer; import integer } } +BEGIN { eval { require strict ; import strict } } + +# Typical invocation: ccdep.pl --FAL=assert,no,yes,checker $(CXX) +my @FAL=(); +if (@ARGV and $ARGV[0]=~/\A--FAL=(.*)/s) { @FAL=split/\W+/,$1; shift@ARGV } +my $GCCP; # 'g++' or 'gcc': C/C++ preproc with `-E -MG' switches +$GCCP="@ARGV"; +$GCCP="gcc" if $GCCP!~y/ \t//c; + +# --- + +sub find_ds() { + #** @return a list of .ds file in the current directory + my @L; my $E; + die unless opendir DIR, '.'; + while (defined($E=readdir DIR)) { + push @L, $E if $E=~/\.(c(|c|xx|pp|[+][+])|C)\Z(?!\n)/ and -f $E; + } + @L +} + +sub expand_glob($$ $) { + #** @param $_[0] string containing globs (? and *) + #** @param $_[1] listref of names + #** @param $_[2] dest listref + my $S=quotemeta($_[0]); + if (0==($S=~s@\\([?*])@.$1@g)) { push @{$_[2]}, $_[0]; return } + my $RE=eval"+sub{\$_[0]=~/$S/}"; + die$@if$@; + for my $E (@{$_[1]}) { push @{$_[2]}, $E if $RE->($E) } +} + +sub mustbe_subset_of($$ $$) { + #** A must be a subset (sublist) of B + #** @param $_[0] caption A + #** @param $_[1] ref(array(string)) A + #** @param $_[2] caption B + #** @param $_[3] ref(array(string)) B + my @A=sort @{$_[1]}; + my @B=sort @{$_[3]}; + my($AV,$BV); + while (defined($AV=pop@A)) { + 1 while defined($BV=pop@B) and $BV gt $AV; + if (!defined($BV) or $BV ne $AV) { + print STDERR "$0: $_[0] are: @{$_[1]}\n"; + print STDERR "$0: $_[2] are: @{$_[3]}\n"; + die "$0: $_[0] must be a subset of $_[2]\n"; + } + } +} + +# --- + +print "$0: running.\n"; + +sub unix_shq($) { + my $S=$_[0]; + $S=~s@'@'\\''@g; + "'$S'" +} + +sub shq($) { + my $S=$_[0]; + return $S if $S!~/[^\w.-]/; + if ($^O eq 'MSWin32') { + # assume the called program is CygWin/Ming32; see later + # Arguments are delimited by white space, which is either a space or a tab. + # . A string surrounded by double quotation marks is interpreted as a + # single argument, regardless of white space contained within. A quoted + # string can be embedded in an argument. Note that the caret (^) is not + # recognized as an escape character or delimiter. + # . A double quotation mark preceded by a backslash, \", is interpreted as + # a literal double quotation mark ("). + # . Backslashes are interpreted literally, unless they immediately precede + # a double quotation mark. + # . If an even number of backslashes is followed by a double quotation + # mark, then one backslash (\) is placed in the argv array for every pair + # of backslashes (\\), and the double quotation mark (") is interpreted as + # a string delimiter. + # . If an odd number of backslashes is followed by a double quotation + # mark, then one backslash (\) is placed in the argv array for every pair + # of backslashes (\\) and the double quotation mark is interpreted as an + # escape sequence by the remaining backslash, causing a literal double + # quotation mark (") to be placed in argv. + $S=~s@"@\\"@g; return qq{"$S"} + } else { + $S=~s@'@'\\''@g; return qq{'$S'} + } +} + +sub backtick(@) { + my $S=$_[0]; + if ($^O eq 'MSWin32') { + # assume the called program is CygWin/Ming32; and we have proper /bin/sh + $S="sh -c ".unix_shq($S); # /bin/sh can handle IO-redirections such as `2>&1' right + } else { + # assume UNIX + } + print "+ $S\n"; + #die unless $ENV{PATH}=~/(.*)/s; # Dat: untaint() + #$ENV{PATH}=$1; + #die "$ENV{PATH}"; + # Dat: if `.' is part of $ENV{PATH}, `Insecure directory...' is reported + #die unless $S=~/(.*)/s; # Dat: untaint() + readpipe $S # `` qx`` +} + +my @DS=find_ds(); +my @DSQ=map{shq$_}@DS; +my $R="$GCCP -DOBJDEP -M -MG -E 2>&1 @DSQ"; +$R=backtick($R); + +if ($R!~/: warning: #warning\b/) { + # config2.h:314:4: warning: #warning REQUIRES: c_lgcc3.o + # Dat: g++-3.3 ignores #warning with -M -MG -E + $R.="\n".backtick("$GCCP -DOBJDEP -E 2>&1 >/dev/null @DSQ"); +} + +## die $R; + +#** $pro{"x.ds"} is the list of features provided by "x.ds"; multiplicity +my %pro; +#** $req{"x.ds"} is the list of features required by "x.ds"; multiplicity +my %req; +#** $con{"x.ds"} is the list of features conflicted by "x.ds"; multiplicity +my %con; +#** $repro{"feature"} is a hash=>1 of .ds that provide "feature" +my %repro; +#** $mapro{"executable"} eq "x.ds" if "x.ds" provides main() for "executable" +my %mapro; +#** $idep{"x"} contains the the dependency line for x.ds +my %idep; +#** hash=>1 of "feature"s of NULL-PROVIDES +my %nullpro; +my $included_from; + +my $BS; # undef +while ($R=~/\G(.*)\n?/g) { + my $S=$1; + + if ($S=~/\\\Z/) { if(defined$BS){$BS.="\n$S"}else{$BS=$S} next } + if (defined $BS) { $S="$BS\n$S"; undef $BS } + + if (!length$S) { + } elsif ($S=~/\AIn file included from ([^:]+)/) { + $included_from=$1; + } elsif ($S=~/\A\s{3,}from ([^:]+)/) { + # ^^^ gcc-3.2 + $included_from=$1; + } elsif ($S=~/\A([^:]+):\d+:(\d+:)? warning: #warning (NULL-PROVIDES|PROVIDES|CONFLICTS|REQUIRES):(.*)\Z/) { + # ^^^ (\d+:)? added for gcc-3.1 + # print STDERR "[$S]\n"; + my($DS,$B)=($1,$3); + if (defined $included_from) { $DS=$included_from; undef $included_from } + # print STDERR "[$DS] [$B] [$4]\n"; + if ($B eq 'NULL-PROVIDES') { + for my $FEAT (split' ',$4) { $nullpro{$FEAT}=1 } + } elsif ($B eq 'PROVIDES') { + my @L=split' ',$4; + push @{$pro{$DS}}, @L; + push @{$con{$DS}}, @L; + for my $FEAT (@L) { + $repro{$FEAT}{$DS}=1; + if ($FEAT=~/\A(.*)_main\Z/) { $mapro{$1}=$DS } + } + } elsif ($B eq 'REQUIRES') { + push @{$req{$DS}}, split' ',$4; + } elsif ($B eq 'CONFLICTS') { + push @{$con{$DS}}, split' ',$4; + } else { die } + # print "$1;$2;@L;\n"; + undef $included_from; + } elsif ($S=~/\A([^: ]+)\.o: (([^: ]+?)\.([^ \n]+).*)\Z/s and $1 eq $3) { + # print STDERR "($S)\n"; + my($A,$B,$C)=("$1.o",$2,"$3.$4"); + die "$0: multi gcc output: $A" if exists $idep{$B}; + # ^^^ Dat: maybe both t.c and t.cxx + $B=~s@ /[^ ]+@@g; # remove absolute pathnames + $B=~s@( \\\n)+@ \\\n@g; + $B=~s@ \\\n\Z@@; + $B=~s@^ +\\\n@@gsm; # what was left from absolute pathnames + $B=~s@ *\\\n *\Z(?!\n)@@gsm; # what was left from absolute pathnames + $idep{$C}=$B; + # vvv automatic `t.ds: PROVIDES: t.o' + # print "::: $C $A\n"; + push @{$pro{$C}}, $A; + push @{$con{$C}}, $A; + $repro{$A}{$C}=1; + undef $included_from; + } elsif ($S=~/\A([^:]+):\d+: .*\Z/) { + print "# $S\n"; + undef $included_from; + } elsif ($S=~/\A([^:]+):\d+:(\d+:)? warning: ".*?" redefined\Z/) { + # ^^^ gcc-3.1 + undef $included_from; + } elsif ($S=~/\A([^:]+):\d+:(\d+:)? warning: this is the location of /) { + # ^^^ gcc-3.1 + undef $included_from; + } elsif ($S=~/: No such file or directory$/) { + # ^^^ gcc-3.3 + undef $included_from; + } else { + die "$0: invalid depret: [$S]\n"; + } +} + +mustbe_subset_of "providers"=>[keys(%pro)], "dep_sources"=>[keys(%idep)]; +mustbe_subset_of "dep_sources"=>[keys(%idep)], "sources"=>\@DS; + +{ my @K=keys %repro; + while (my($DS,$L)=each%con) { + my @R=(); + for my $FEAT (@$L) { expand_glob $FEAT, \@K, \@R } + # ^^^ multiplicity remains + $con{$DS}=\@R; + } +} + +die unless open MD, "> Makedep"; +die unless print MD ' +ifndef CCALL +CCALL=$(CC) $(CFLAGS) $(CFLAGSB) $(CPPFLAGS) $(INCLUDES) +endif +ifndef CXXALL +CXXALL=$(CXX) $(CXXFLAGS) $(CXXFLAGSB) $(CPPFLAGS) $(INCLUDES) +endif +ifndef LDALL +LDALL=$(LDY) $(LDFLAGS) $(LIBS) +endif +ifndef CC +CC=gcc +endif +ifndef CXX +CXX=g++ +endif +ifndef LD +LD=$(CC) -s +endif +ifndef LDXX +LDXX=$(CXX) -s +endif +ifndef LDY +LDY=$(LD) +endif +ifndef CFLAGS +CFLAGS=-O2 -W -Wall -fsigned-char +endif +ifndef CXXFLAGS +CXXFLAGS=-O2 -W -Wall -fsigned-char +endif +ifndef GLOBFILES +GLOBFILES=Makefile Makedep +endif +'; + +die unless print MD "ALL +=", join(' ',keys%mapro), "\n"; +die unless print MD "TARGETS =", join(' ',keys%mapro), "\n"; + +# vvv Thu Oct 31 09:49:02 CET 2002 +# (not required) +#my %targets_fal; +#for my $FA (@FAL) { $targets_fal{$FA}="TARGETS_$FA =" } + +while (my($EXE,$MDS)=each%mapro) { + print "exe $EXE\n"; + my @FEA2BA=("${EXE}_main"); + my @DSO=(); # list of .o files required + my @DSL=(); # list of .ds files required + my %CON=(); # hash=>1 of features already conflicted + my %PRO=%nullpro; # hash=>1 of features already provided + my $FEAT; + + while (defined($FEAT=pop@FEA2BA)) { + next if exists $PRO{$FEAT}; + # print " feat $FEAT (@FEA2BA)\n"; ## + # vvv Dat: r.b.e == required by executable + die "$0: feature $FEAT r.b.e $EXE conflicts\n" if exists $CON{$FEAT}; + my @L=keys%{$repro{$FEAT}}; + die "$0: feature $FEAT r.b.e $EXE unprovided\n" if!@L; + die "$0: feature $FEAT r.b.e $EXE overprovided: @L\n" if$#L>=1; + # Now: $L[0] is a .ds providing the feature + push @DSL, $L[0]; + my $O=$L[0]; $O=~s@\.[^.]+\Z@.o@; + push @DSO, $O; + + $PRO{$FEAT}=1; + for my $FEAT2 (@{$pro{$L[0]}}) { + die "$0: extra feature $FEAT2 r.b.e $EXE conflicts\n" if exists $CON{$FEAT2} and not exists $PRO{$FEAT2}; + $PRO{$FEAT2}=1; + } + for my $FEAT2 (@{$req{$L[0]}}) { push @FEA2BA, $FEAT2 if!exists $PRO{$FEAT2} } + for my $FEAT2 (@{$con{$L[0]}}) { $CON{$FEAT2}=1 } + # die if! exists $PRO{$FEAT}; # assert + } + + die unless print MD "${EXE}_DS=@DSL\n". + "$EXE: \$(GLOBFILES) @DSO\n\t\$(LDALL) @DSO -o $EXE\n\t". + q!@echo "Created executable file: !.$EXE. + q! (size: `perl -e 'print -s "!.$EXE.q!"'`)."!. "\n"; + # vvv Sat Jun 1 15:40:19 CEST 2002 + for my $FA (@FAL) { + die unless print MD "$EXE.$FA: \$(GLOBFILES) \$(${EXE}_DS)\n\t". + "\$(CXD_$FA) \$(CXDFAL) \$(${EXE}_DS) -o $EXE.$FA\n"; + # $targets_fal{$FA}.=" $EXE.$FA"; + } +} +print MD "\n"; + +# vvv Thu Oct 31 09:49:02 CET 2002 +# (not required) +# for my $FA (@FAL) { print MD "$targets_fal{$FA}\n" } +# print MD "\n"; + +while (my($K,$V)=each%idep) { + my $O=$K; $O=~s@\.([^.]+)\Z@.o@; + print MD "$O: \$(GLOBFILES) $V\n\t\$(", ($1 eq'c'?"CC":"CXX"), "ALL) -c $K\n" +} +print MD "\n"; + +die unless close MD; + +print "$0: done.\n"; + +__END__ diff --git a/Build/source/utils/sam2p/cgif.c b/Build/source/utils/sam2p/cgif.c new file mode 100644 index 00000000000..45f817b58c3 --- /dev/null +++ b/Build/source/utils/sam2p/cgif.c @@ -0,0 +1,1572 @@ +/* cgif.c -- a merge of some GIF-decoding files from giflib by E.S.Raymond + * by pts@fazekas.hu at Wed Feb 27 13:18:04 CET 2002 + +The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond + +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 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +/*The creators of the GIF format require the following + acknowledgement: + The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated. +*/ + +#ifdef __GNUC__ +#pragma implementation +#endif + +/**** pts: not an ANSI C function */ +#undef EXTERN_C +#ifdef __cplusplus +#define EXTERN_C extern "C" +#define CGIFFF CGIF:: +#else +#define EXTERN_C extern +#define CGIFFF +#endif +#if OBJDEP +# warning PROVIDES: cgif +#endif + +#if 0 +EXTERN_C FILE *fdopen (int fildes, const char *mode); /* GCC 3.0 SUXX */ +#else +#undef _POSIX_SOURCE +#define _POSIX_SOURCE 1 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 2 +#endif + +/* --- gifalloc.c */ + +/***************************************************************************** +* "Gif-Lib" - Yet another gif library. * +* * +* Written by: Gershon Elber Ver 0.1, Jun. 1989 * +* Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 * +****************************************************************************** +* GIF construction tools * +****************************************************************************** +* History: * +* 15 Sep 92 - Version 1.0 by Eric Raymond. * +*****************************************************************************/ + +// #undef __STRICT_ANSI__ /* for MINGW32 open() !! */ +#include <stdio.h> +#include "cgif.h" + +/**** pts ****/ +#include <stdlib.h> /* malloc(), calloc(), free(), realloc() */ +#include <string.h> /* memset() */ + + +//#include <unistd.h> + +#if USE_CGIF_FDOPEN +#include <fcntl.h> /* open() */ +#include <sys/types.h> +#include <sys/stat.h> +# if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER) +# undef __STRICT_ANSI__ +# include <io.h> + /*#define open _open*/ +# endif +#endif + +/* --- gif_err.c */ + +/***************************************************************************** +* "Gif-Lib" - Yet another gif library. * +* * +* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 * +****************************************************************************** +* Handle error reporting for the GIF library. * +****************************************************************************** +* History: * +* 17 Jun 89 - Version 1.0 by Gershon Elber. * +*****************************************************************************/ + +/* #include <stdio.h> already */ +/* #include "gif_lib.h" already */ + +/* --- dgif_lib.c */ + +/****************************************************************************** +* "Gif-Lib" - Yet another gif library. * +* * +* Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 * +******************************************************************************* +* The kernel of the GIF Decoding process can be found here. * +******************************************************************************* +* History: * +* 16 Jun 89 - Version 1.0 by Gershon Elber. * +* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). * +******************************************************************************/ + +#ifdef __MSDOS__ +#include <io.h> +#include <alloc.h> +#include <stdlib.h> +#include <sys\stat.h> +#else +#include <sys/types.h> +#include <sys/stat.h> +#endif /* __MSDOS__ */ + +#include <fcntl.h> +/* #include <stdio.h> already */ +/* #include <string.h> already */ +/* #include "gif_lib.h" already */ + +/* #include <stdlib.h> already */ /* malloc(), free() */ +#include <assert.h> + +/* ---- */ + +/* --- gif_err.c */ + +/* #define PROGRAM_NAME "GIF_LIBRARY" */ + +int CGIFFF _GifError = 0; + +/***************************************************************************** +* Return the last GIF error (0 if none) and reset the error. * +*****************************************************************************/ +int CGIFFF GifLastError(void) +{ + int i = _GifError; + + _GifError = 0; + + return i; +} + +/**** pts ****/ +/** May return NULL. */ +char *CGIFFF GetGifError(void) +{ + char *Err; + + switch(_GifError) { +#if 0 /**** pts ****/ + case E_GIF_ERR_OPEN_FAILED: + Err = "Failed to open given file"; + break; + case E_GIF_ERR_WRITE_FAILED: + Err = "Failed to Write to given file"; + break; + case E_GIF_ERR_HAS_SCRN_DSCR: + Err = "Screen Descriptor already been set"; + break; + case E_GIF_ERR_HAS_IMAG_DSCR: + Err = "Image Descriptor is still active"; + break; + case E_GIF_ERR_NO_COLOR_MAP: + Err = "Neither Global Nor Local color map"; + break; + case E_GIF_ERR_DATA_TOO_BIG: + Err = "#Pixels bigger than Width * Height"; + break; + case E_GIF_ERR_NOT_ENOUGH_MEM: + Err = "Fail to allocate required memory"; + break; + case E_GIF_ERR_DISK_IS_FULL: + Err = "Write failed (disk full?)"; + break; + case E_GIF_ERR_CLOSE_FAILED: + Err = "Failed to close given file"; + break; + case E_GIF_ERR_NOT_WRITEABLE: + Err = "Given file was not opened for write"; + break; +#endif + case D_GIF_ERR_OPEN_FAILED: + Err = "Failed to open given file"; + break; + case D_GIF_ERR_READ_FAILED: + Err = "Failed to Read from given file"; + break; + case D_GIF_ERR_NOT_GIF_FILE: + Err = "Given file is NOT GIF file"; + break; + case D_GIF_ERR_NO_SCRN_DSCR: + Err = "No Screen Descriptor detected"; + break; + case D_GIF_ERR_NO_IMAG_DSCR: + Err = "No Image Descriptor detected"; + break; + case D_GIF_ERR_NO_COLOR_MAP: + Err = "Neither Global Nor Local color map"; + break; + case D_GIF_ERR_WRONG_RECORD: + Err = "Wrong record type detected"; + break; + case D_GIF_ERR_DATA_TOO_BIG: + Err = "#Pixels bigger than Width * Height"; + break; + case D_GIF_ERR_NOT_ENOUGH_MEM: + Err = "Fail to allocate required memory"; + break; + case D_GIF_ERR_CLOSE_FAILED: + Err = "Failed to close given file"; + break; + case D_GIF_ERR_NOT_READABLE: + Err = "Given file was not opened for read"; + break; + case D_GIF_ERR_IMAGE_DEFECT: + Err = "Image is defective, decoding aborted"; + break; + case D_GIF_ERR_EOF_TOO_SOON: + Err = "Image EOF detected, before image complete"; + break; + default: + Err = NULL; + break; + } + return Err; +} + +/***************************************************************************** +* Print the last GIF error to stderr. * +*****************************************************************************/ +void CGIFFF PrintGifError(void) +{ + char *Err=GetGifError(); + if (Err != NULL) + fprintf(stderr, "\nGIF-LIB error: %s.\n", Err); + else + fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError); +} + +/* --- gifalloc.c */ + +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +/****************************************************************************** +* Miscellaneous utility functions * +******************************************************************************/ + +static int BitSize(int n) +/* return smallest bitfield size n will fit in */ +{ + register int i; + + for (i = 1; i <= 8; i++) + if ((1 << i) >= n) + break; + return(i); +} + + +/****************************************************************************** +* Color map object functions * +******************************************************************************/ + +CGIFFF ColorMapObject *CGIFFF MakeMapObject(int ColorCount, GifColorType *ColorMap) +/* + * Allocate a color map of given size; initialize with contents of + * ColorMap if that pointer is non-NULL. + */ +{ + ColorMapObject *Object; + + if (ColorCount != (1 << BitSize(ColorCount))) + return((ColorMapObject *)NULL); + + Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); + if (Object == (ColorMapObject *)NULL) + return((ColorMapObject *)NULL); + + Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); + if (Object->Colors == (GifColorType *)NULL) + return((ColorMapObject *)NULL); + + Object->ColorCount = ColorCount; + Object->BitsPerPixel = BitSize(ColorCount); + + if (ColorMap) + memcpy((char *)Object->Colors, + (char *)ColorMap, ColorCount * sizeof(GifColorType)); + + return(Object); +} + +void CGIFFF FreeMapObject(CGIFFF ColorMapObject *Object) +/* + * Free a color map object + */ +{ + free(Object->Colors); + free(Object); +} + +#if 0 +void DumpColorMap(ColorMapObject *Object, FILE *fp) +{ + if (Object) + { + int i, j, Len = Object->ColorCount; + + for (i = 0; i < Len; i+=4) { + for (j = 0; j < 4 && j < Len; j++) { + fprintf(fp, + "%3d: %02x %02x %02x ", i + j, + Object->Colors[i + j].Red, + Object->Colors[i + j].Green, + Object->Colors[i + j].Blue); + } + fprintf(fp, "\n"); + } + } +} +#endif /* DEBUG */ + +#if 0 +ColorMapObject *CGIFFF UnionColorMap( + ColorMapObject *ColorIn1, + ColorMapObject *ColorIn2, + GifPixelType ColorTransIn2[]) +/* + * Compute the union of two given color maps and return it. If result can't + * fit into 256 colors, NULL is returned, the allocated union otherwise. + * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are + * copied iff they didn't exist before. ColorTransIn2 maps the old + * ColorIn2 into ColorUnion color map table. + */ +{ + int i, j, CrntSlot, RoundUpTo, NewBitSize; + ColorMapObject *ColorUnion; + + /* + * Allocate table which will hold the result for sure. + */ + ColorUnion + = MakeMapObject(MAX(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL); + + if (ColorUnion == NULL) + return(NULL); + + /* Copy ColorIn1 to ColorUnionSize; */ + for (i = 0; i < ColorIn1->ColorCount; i++) + ColorUnion->Colors[i] = ColorIn1->Colors[i]; + CrntSlot = ColorIn1->ColorCount; + + /* + * Potentially obnoxious hack: + * + * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end + * of table 1. This is very useful if your display is limited to + * 16 colors. + */ + while (ColorIn1->Colors[CrntSlot-1].Red == 0 + && ColorIn1->Colors[CrntSlot-1].Green == 0 + && ColorIn1->Colors[CrntSlot-1].Red == 0) + CrntSlot--; + + /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */ + for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++) + { + /* Let's see if this color already exists: */ + for (j = 0; j < ColorIn1->ColorCount; j++) + if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0) + break; + + if (j < ColorIn1->ColorCount) + ColorTransIn2[i] = j; /* color exists in Color1 */ + else + { + /* Color is new - copy it to a new slot: */ + ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; + ColorTransIn2[i] = CrntSlot++; + } + } + + if (CrntSlot > 256) + { + FreeMapObject(ColorUnion); + return((ColorMapObject *)NULL); + } + + NewBitSize = BitSize(CrntSlot); + RoundUpTo = (1 << NewBitSize); + + if (RoundUpTo != ColorUnion->ColorCount) + { + register GifColorType *Map = ColorUnion->Colors; + + /* + * Zero out slots up to next power of 2. + * We know these slots exist because of the way ColorUnion's + * start dimension was computed. + */ + for (j = CrntSlot; j < RoundUpTo; j++) + Map[j].Red = Map[j].Green = Map[j].Blue = 0; + + /* perhaps we can shrink the map? */ + if (RoundUpTo < ColorUnion->ColorCount) + ColorUnion->Colors + = (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo); + } + + ColorUnion->ColorCount = RoundUpTo; + ColorUnion->BitsPerPixel = NewBitSize; + + return(ColorUnion); +} +void ApplyTranslation(SavedImage *Image, GifPixelType Translation[]) +/* + * Apply a given color translation to the raster bits of an image + */ +{ + register int i; + register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width; + + for (i = 0; i < RasterSize; i++) + Image->RasterBits[i] = Translation[Image->RasterBits[i]]; +} +#endif + +/****************************************************************************** +* Extension record functions * +******************************************************************************/ + +#if 0 /**** pts ****/ +void MakeExtension(SavedImage *New, int Function) +{ + New->Function = Function; + /* + * Someday we might have to deal with multiple extensions. + */ +} +#endif + +int CGIFFF AddExtensionBlock(CGIFFF SavedImage *New, int Len, CGIFFF GifByteType ExtData[]) +{ + ExtensionBlock *ep; + + if (New->ExtensionBlocks == NULL) + New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock)); + else + New->ExtensionBlocks = + (ExtensionBlock *)realloc(New->ExtensionBlocks, + sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1)); + + if (New->ExtensionBlocks == NULL) + return(GIF_ERROR); + + ep = &New->ExtensionBlocks[New->ExtensionBlockCount++]; + + if ((ep->Bytes = (GifByteType *)malloc(ep->ByteCount = Len)) == NULL) + return(GIF_ERROR); + + if (ExtData) + memcpy(ep->Bytes, ExtData, Len); + + return(GIF_OK); +} + +void CGIFFF FreeExtension(CGIFFF SavedImage *Image) +{ + ExtensionBlock *ep; + + for (ep = Image->ExtensionBlocks; + ep < Image->ExtensionBlocks + Image->ExtensionBlockCount; + ep++) + (void) free((char *)ep->Bytes); + free((char *)Image->ExtensionBlocks); + Image->ExtensionBlocks = NULL; +} + +/****************************************************************************** +* Image block allocation functions * +******************************************************************************/ +CGIFFF SavedImage *CGIFFF MakeSavedImage(CGIFFF GifFileType *GifFile, CGIFFF SavedImage *CopyFrom) +/* + * Append an image block to the SavedImages array + */ +{ + SavedImage *sp; + + if (GifFile->SavedImages == NULL) + GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); + else + GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, + sizeof(SavedImage) * (GifFile->ImageCount+1)); + + if (GifFile->SavedImages == NULL) + return((SavedImage *)NULL); + else + { + sp = &GifFile->SavedImages[GifFile->ImageCount++]; + memset((char *)sp, '\0', sizeof(SavedImage)); + + if (CopyFrom) + { + memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); + + /* + * Make our own allocated copies of the heap fields in the + * copied record. This guards against potential aliasing + * problems. + */ + + /* first, the local color map */ + if (sp->ImageDesc.ColorMap) + sp->ImageDesc.ColorMap = + MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount, + CopyFrom->ImageDesc.ColorMap->Colors); + + /* next, the raster */ + sp->RasterBits = (GifPixelType *)malloc(sizeof(GifPixelType) + * CopyFrom->ImageDesc.Height + * CopyFrom->ImageDesc.Width); + memcpy(sp->RasterBits, + CopyFrom->RasterBits, + sizeof(GifPixelType) + * CopyFrom->ImageDesc.Height + * CopyFrom->ImageDesc.Width); + + /* finally, the extension blocks */ + if (sp->ExtensionBlocks) + { + sp->ExtensionBlocks + = (ExtensionBlock*)malloc(sizeof(ExtensionBlock) + * CopyFrom->ExtensionBlockCount); + memcpy(sp->ExtensionBlocks, + CopyFrom->ExtensionBlocks, + sizeof(ExtensionBlock) + * CopyFrom->ExtensionBlockCount); + + /* + * For the moment, the actual blocks can take their + * chances with free(). We'll fix this later. + */ + } + } + + return(sp); + } +} + +void CGIFFF FreeSavedImages(CGIFFF GifFileType *GifFile) +{ + SavedImage *sp; + + for (sp = GifFile->SavedImages; + sp < GifFile->SavedImages + GifFile->ImageCount; + sp++) + { + if (sp->ImageDesc.ColorMap) + FreeMapObject(sp->ImageDesc.ColorMap); + + if (sp->RasterBits) + free((char *)sp->RasterBits); + + if (sp->ExtensionBlocks) + FreeExtension(sp); + } + free((char *) GifFile->SavedImages); +} + +/* --- dgif_lib.c */ + +#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */ + +/* #define PROGRAM_NAME "GIFLIB" */ + +#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */ +#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ +#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1 +#define GIF_VERSION_POS 3 /* Version first character in stamp. */ + +#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ +#define LZ_BITS 12 + +#define FILE_STATE_READ 0x01/* 1 write, 0 read - EGIF_LIB compatible.*/ + +#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ +#define FIRST_CODE 4097 /* Impossible code, to signal first. */ +#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ + +#define IS_READABLE(Private) (!(Private->FileState & FILE_STATE_READ)) + +typedef struct GifFilePrivateType { + int FileState, + /*FileHandle,*/ /* Where all this data goes to! */ + BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */ + ClearCode, /* The CLEAR LZ code. */ + EOFCode, /* The EOF LZ code. */ + RunningCode, /* The next code algorithm can generate. */ + RunningBits,/* The number of bits required to represent RunningCode. */ + MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ + LastCode, /* The code before the current code. */ + CrntCode, /* Current algorithm code. */ + StackPtr, /* For character stack (see below). */ + CrntShiftState; /* Number of bits in CrntShiftDWord. */ + unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ + unsigned long PixelCount; /* Number of pixels in image. */ + FILE *File; /* File as stream. */ + CGIFFF GifByteType Buf[256]; /* Compressed input is buffered here. */ + CGIFFF GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ + CGIFFF GifByteType Suffix[LZ_MAX_CODE+1]; /* So we can trace the codes. */ + unsigned int Prefix[LZ_MAX_CODE+1]; +} GifFilePrivateType; + +/* extern int _GifError; */ + +static int DGifGetWord(FILE *File, int *Word); +static int DGifSetupDecompress(CGIFFF GifFileType *GifFile); +static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line, + int LineLen); +static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode); +static int DGifDecompressInput(GifFilePrivateType *Private, int *Code); +static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf, + CGIFFF GifByteType *NextByte); + +/****************************************************************************** +* Open a new gif file for read, given by its name. * +* Returns GifFileType pointer dynamically allocated which serves as the gif * +* info record. _GifError is cleared if succesfull. * +******************************************************************************/ +CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName) { +#if 0 /**** pts ****/ +CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName) +{ + int FileHandle; + + if ((FileHandle = open(FileName, O_RDONLY +#ifdef __MSDOS__ + | O_BINARY +#endif /* __MSDOS__ */ + )) == -1) { + _GifError = D_GIF_ERR_OPEN_FAILED; + return NULL; + } + + return DGifOpenFileHandle(FileHandle); +#else + FILE *f; + if (NULL==(f=fopen(FileName,"rb"))) { _GifError=D_GIF_ERR_OPEN_FAILED; return NULL; } + return DGifOpenFILE(f); +#endif +} + +#if USE_CGIF_FDOPEN + +/****************************************************************************** +* Update a new gif file, given its file handle. * +* Returns GifFileType pointer dynamically allocated which serves as the gif * +* info record. _GifError is cleared if succesfull. * +******************************************************************************/ +CGIFFF GifFileType *CGIFFF DGifOpenFileHandle(int FileHandle) +{ + FILE *f; + +#ifdef __MSDOS__ + setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ + f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ + setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/ +#else + f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ +#endif /* __MSDOS__ */ + return DGifOpenFILE(f); +} +#endif + +/**** pts ****/ +CGIFFF GifFileType *CGIFFF DGifOpenFILE(void/*FILE*/ *f) { + char Buf[GIF_STAMP_LEN+1]; + GifFileType *GifFile; + GifFilePrivateType *Private; + if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) { + _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + return NULL; + } + + memset(GifFile, '\0', sizeof(GifFileType)); + + if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType))) + == NULL) { + _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + free((char *) GifFile); + return NULL; + } + GifFile->Private = (VoidPtr) Private; + /* Private->FileHandle = FileHandle; */ + Private->File = (FILE*)f; + Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */ + + /* Let's see if this is a GIF file: */ + if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) { + _GifError = D_GIF_ERR_READ_FAILED; + free((char *) Private); + free((char *) GifFile); + return NULL; + } + + /* The GIF Version number is ignored at this time. Maybe we should do */ + /* something more useful with it. */ + Buf[GIF_STAMP_LEN] = 0; + if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { + _GifError = D_GIF_ERR_NOT_GIF_FILE; + free((char *) Private); + free((char *) GifFile); + return NULL; + } + + if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { + free((char *) Private); + free((char *) GifFile); + return NULL; + } + + _GifError = 0; + + return GifFile; +} + +/****************************************************************************** +* This routine should be called before any other DGif calls. Note that * +* this routine is called automatically from DGif file open routines. * +******************************************************************************/ +int CGIFFF DGifGetScreenDesc(CGIFFF GifFileType *GifFile) +{ + int i, BitsPerPixel; + GifByteType Buf[3]; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + /* Put the screen descriptor into the file: */ + if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR || + DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR) + return GIF_ERROR; + + if (fread(Buf, 1, 3, Private->File) != 3) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; + BitsPerPixel = (Buf[0] & 0x07) + 1; + GifFile->SBackGroundColor = Buf[1]; + // fprintf(stderr, "colres=%d bpp=%d bgcol=%d\n", GifFile->SColorResolution, BitsPerPixel, GifFile->SBackGroundColor); + if (Buf[0] & 0x80) { /* Do we have global color map? */ + // fprintf(stderr, "have gcolormap\n"); + GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); + + /* Get the global color map: */ + for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { + if (fread(Buf, 1, 3, Private->File) != 3) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + GifFile->SColorMap->Colors[i].Red = Buf[0]; + GifFile->SColorMap->Colors[i].Green = Buf[1]; + GifFile->SColorMap->Colors[i].Blue = Buf[2]; + } + } + + return GIF_OK; +} + +/****************************************************************************** +* This routine should be called before any attemp to read an image. * +******************************************************************************/ +int CGIFFF DGifGetRecordType(CGIFFF GifFileType *GifFile, CGIFFF GifRecordType *Type) +{ + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + if (fread(&Buf, 1, 1, Private->File) != 1) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + + // fprintf(stderr, "record %d at offset %ld\n", Buf&255, ftell(Private->File)); + switch (Buf) { + case ',': *Type = IMAGE_DESC_RECORD_TYPE; break; + case '!': *Type = EXTENSION_RECORD_TYPE; break; + case ';': *Type = TERMINATE_RECORD_TYPE; break; + default: *Type = UNDEFINED_RECORD_TYPE; + // fprintf(stderr, "wrong record %d at offset %ld\n", Buf&255, ftell(Private->File)); + _GifError = D_GIF_ERR_WRONG_RECORD; + return GIF_ERROR; + } + + return GIF_OK; +} + +/****************************************************************************** +* This routine should be called before any attemp to read an image. * +* Note it is assumed the Image desc. header (',') has been read. * +******************************************************************************/ +int CGIFFF DGifGetImageDesc(CGIFFF GifFileType *GifFile) +{ + int i, BitsPerPixel; + GifByteType Buf[3]; + GifImageDesc Image; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + memset(&Image, 0, sizeof(Image)); + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + if (DGifGetWord(Private->File, &Image.Left) == GIF_ERROR || + DGifGetWord(Private->File, &Image.Top) == GIF_ERROR || + DGifGetWord(Private->File, &Image.Width) == GIF_ERROR || + DGifGetWord(Private->File, &Image.Height) == GIF_ERROR) + return GIF_ERROR; + if (fread(Buf, 1, 1, Private->File) != 1) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + BitsPerPixel = (Buf[0] & 0x07) + 1; + Image.Interlace = (Buf[0] & 0x40); + if (Buf[0] & 0x80) { /* Does this image have local color map? */ + + if (Image.ColorMap && GifFile->SavedImages == NULL) + FreeMapObject(Image.ColorMap); + + Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); + + /* Get the image local color map: */ + for (i = 0; i < Image.ColorMap->ColorCount; i++) { + if (fread(Buf, 1, 3, Private->File) != 3) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + Image.ColorMap->Colors[i].Red = Buf[0]; + Image.ColorMap->Colors[i].Green = Buf[1]; + Image.ColorMap->Colors[i].Blue = Buf[2]; + } + } + + /**** pts ****/ + if (NULL!=GifFile->SavedImages) { + GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, + sizeof(SavedImage) * (GifFile->ImageCount + 1)); + } else { + assert(GifFile->ImageCount==0); + GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); + } + if (NULL==GifFile->SavedImages) { + _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + return GIF_ERROR; + } + + { + SavedImage *sp; + sp = &GifFile->SavedImages[GifFile->ImageCount]; + memcpy(&sp->ImageDesc, &Image, sizeof(GifImageDesc)); + sp->RasterBits = (GifPixelType *)NULL; + sp->ExtensionBlockCount = 0; + sp->ExtensionBlocks = (ExtensionBlock *)NULL; + sp->delay=0; + sp->dispose=0; + sp->iter=1; + sp->transp=(-1); + } + + GifFile->ImageCount++; + + Private->PixelCount = (long) Image.Width * + (long) Image.Height; + + DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ + + return GIF_OK; +} + +/****************************************************************************** +* Get one full scanned line (Line) of length LineLen from GIF file. * +******************************************************************************/ +int CGIFFF DGifGetLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line, int LineLen) +{ + GifByteType *Dummy; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + /**** pts ****/ + /* if (!LineLen) LineLen = GifFile->Image.Width; */ + +#if defined(__MSDOS__) || defined(__GNUC__) + if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { +#else + if ((Private->PixelCount -= LineLen) > 0xffff0000) { +#endif /* __MSDOS__ */ + _GifError = D_GIF_ERR_DATA_TOO_BIG; + return GIF_ERROR; + } + + if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { + if (Private->PixelCount == 0) { + /* We probably would not be called any more, so lets clean */ + /* everything before we return: need to flush out all rest of */ + /* image until empty block (size 0) detected. We use GetCodeNext.*/ + do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) + return GIF_ERROR; + while (Dummy != NULL); + } + return GIF_OK; + } + else + return GIF_ERROR; +} + +/****************************************************************************** +* Put one pixel (Pixel) into GIF file. * +******************************************************************************/ +int CGIFFF DGifGetPixel(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType Pixel) +{ + GifByteType *Dummy; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + +#if defined(__MSDOS__) || defined(__GNUC__) + if (--Private->PixelCount > 0xffff0000UL) +#else + if (--Private->PixelCount > 0xffff0000) +#endif /* __MSDOS__ */ + { + _GifError = D_GIF_ERR_DATA_TOO_BIG; + return GIF_ERROR; + } + + if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { + if (Private->PixelCount == 0) { + /* We probably would not be called any more, so lets clean */ + /* everything before we return: need to flush out all rest of */ + /* image until empty block (size 0) detected. We use GetCodeNext.*/ + do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) + return GIF_ERROR; + while (Dummy != NULL); + } + return GIF_OK; + } + else + return GIF_ERROR; +} + +/****************************************************************************** +* Get an extension block (see GIF manual) from gif file. This routine only * +* returns the first data block, and DGifGetExtensionNext shouldbe called * +* after this one until NULL extension is returned. * +* The Extension should NOT be freed by the user (not dynamically allocated).* +* Note it is assumed the Extension desc. header ('!') has been read. * +******************************************************************************/ +int CGIFFF DGifGetExtension(CGIFFF GifFileType *GifFile, int *ExtCode, + CGIFFF GifByteType **Extension) +{ + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + if (fread(&Buf, 1, 1, Private->File) != 1) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + *ExtCode = Buf; + + return DGifGetExtensionNext(GifFile, Extension); +} + +/****************************************************************************** +* Get a following extension block (see GIF manual) from gif file. This * +* routine sould be called until NULL Extension is returned. * +* The Extension should NOT be freed by the user (not dynamically allocated).* +******************************************************************************/ +int CGIFFF DGifGetExtensionNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **Extension) +{ + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (fread(&Buf, 1, 1, Private->File) != 1) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + if (Buf > 0) { + *Extension = Private->Buf; /* Use private unused buffer. */ + (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ + if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + } + else + *Extension = NULL; + + return GIF_OK; +} + +/****************************************************************************** +* This routine should be called last, to close the GIF file. * +******************************************************************************/ +int CGIFFF DGifCloseFile(CGIFFF GifFileType *GifFile) +{ + GifFilePrivateType *Private; + FILE *File; + + if (GifFile == NULL) return GIF_ERROR; + + Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + File = Private->File; + + #if 0 /**** pts ****/ + if (GifFile->Image.ColorMap) + FreeMapObject(GifFile->Image.ColorMap); + #endif + if (GifFile->SColorMap) + FreeMapObject(GifFile->SColorMap); + if (Private) + free((char *) Private); + if (GifFile->SavedImages) + FreeSavedImages(GifFile); + free(GifFile); + +#if 0 /**** pts ****/ + if (fclose(File) != 0) { + _GifError = D_GIF_ERR_CLOSE_FAILED; + return GIF_ERROR; + } +#endif + return GIF_OK; +} + +/****************************************************************************** +* Get 2 bytes (word) from the given file: * +******************************************************************************/ +static int DGifGetWord(FILE *File, int *Word) +{ + unsigned char c[2]; + + if (fread(c, 1, 2, File) != 2) { + CGIFFF _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + + *Word = (((unsigned int) c[1]) << 8) + c[0]; + return GIF_OK; +} + +/****************************************************************************** +* Get the image code in compressed form. his routine can be called if the * +* information needed to be piped out as is. Obviously this is much faster * +* than decoding and encoding again. This routine should be followed by calls * +* to DGifGetCodeNext, until NULL block is returned. * +* The block should NOT be freed by the user (not dynamically allocated). * +******************************************************************************/ +int CGIFFF DGifGetCode(CGIFFF GifFileType *GifFile, int *CodeSize, CGIFFF GifByteType **CodeBlock) +{ + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + *CodeSize = Private->BitsPerPixel; + + return DGifGetCodeNext(GifFile, CodeBlock); +} + +/****************************************************************************** +* Continue to get the image code in compressed form. This routine should be * +* called until NULL block is returned. * +* The block should NOT be freed by the user (not dynamically allocated). * +******************************************************************************/ +int CGIFFF DGifGetCodeNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **CodeBlock) +{ + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (fread(&Buf, 1, 1, Private->File) != 1) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + + if (Buf > 0) { + *CodeBlock = Private->Buf; /* Use private unused buffer. */ + (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ + if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) { + _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + } + else { + *CodeBlock = NULL; + Private->Buf[0] = 0; /* Make sure the buffer is empty! */ + Private->PixelCount = 0; /* And local info. indicate image read. */ + } + + return GIF_OK; +} + +/****************************************************************************** +* Setup the LZ decompression for this image: * +******************************************************************************/ +static int DGifSetupDecompress(CGIFFF GifFileType *GifFile) +{ + int i, BitsPerPixel; + CGIFFF GifByteType CodeSize; + unsigned int *Prefix; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + fread(&CodeSize, 1, 1, Private->File); /* Read Code size from file. */ + BitsPerPixel = CodeSize; + + Private->Buf[0] = 0; /* Input Buffer empty. */ + Private->BitsPerPixel = BitsPerPixel; + Private->ClearCode = (1 << BitsPerPixel); + Private->EOFCode = Private->ClearCode + 1; + Private->RunningCode = Private->EOFCode + 1; + Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ + Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ + Private->StackPtr = 0; /* No pixels on the pixel stack. */ + Private->LastCode = NO_SUCH_CODE; + Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ + Private->CrntShiftDWord = 0; + + Prefix = Private->Prefix; + for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE; + + return GIF_OK; +} + +/****************************************************************************** +* The LZ decompression routine: * +* This version decompress the given gif file into Line of length LineLen. * +* This routine can be called few times (one per scan line, for example), in * +* order the complete the whole image. * +******************************************************************************/ +static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line, + int LineLen) +{ + int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; + CGIFFF GifByteType *Stack, *Suffix; + unsigned int *Prefix; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + StackPtr = Private->StackPtr; + Prefix = Private->Prefix; + Suffix = Private->Suffix; + Stack = Private->Stack; + EOFCode = Private->EOFCode; + ClearCode = Private->ClearCode; + LastCode = Private->LastCode; + + if (StackPtr != 0) { + /* Let pop the stack off before continueing to read the gif file: */ + while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; + } + + while (i < LineLen) { /* Decode LineLen items. */ + if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR) + return GIF_ERROR; + + /*fprintf(stderr,"CrntCode=0x%x\n",CrntCode);*/ + if (CrntCode == EOFCode) { + /* Note however that usually we will not be here as we will stop */ + /* decoding as soon as we got all the pixel, or EOF code will */ + /* not be read at all, and DGifGetLine/Pixel clean everything. */ + if (i != LineLen - 1 || Private->PixelCount != 0) { + CGIFFF _GifError = D_GIF_ERR_EOF_TOO_SOON; + return GIF_ERROR; + } + i++; + } + else if (CrntCode == ClearCode) { + /* We need to start over again: */ + for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE; + Private->RunningCode = Private->EOFCode + 1; + Private->RunningBits = Private->BitsPerPixel + 1; + Private->MaxCode1 = 1 << Private->RunningBits; + LastCode = Private->LastCode = NO_SUCH_CODE; + } + else { + /* Its regular code - if in pixel range simply add it to output */ + /* stream, otherwise trace to codes linked list until the prefix */ + /* is in pixel range: */ + if (CrntCode < ClearCode) { + /* This is simple - its pixel scalar, so add it to output: */ + Line[i++] = CrntCode; + } + else { + /* Its a code to needed to be traced: trace the linked list */ + /* until the prefix is a pixel, while pushing the suffix */ + /* pixels on our stack. If we done, pop the stack in reverse */ + /* (thats what stack is good for!) order to output. */ + if (Prefix[CrntCode] == NO_SUCH_CODE) { + /* Only allowed if CrntCode is exactly the running code: */ + /* In that case CrntCode = XXXCode, CrntCode or the */ + /* prefix code is last code and the suffix char is */ + /* exactly the prefix of last code! */ + if (CrntCode == Private->RunningCode - 2) { + CrntPrefix = LastCode; + Suffix[Private->RunningCode - 2] = + Stack[StackPtr++] = DGifGetPrefixChar(Prefix, + LastCode, ClearCode); + } + else { + CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; + } + } + else + CrntPrefix = CrntCode; + + /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */ + /* During the trace. As we might loop forever, in case of */ + /* defective image, we count the number of loops we trace */ + /* and stop if we got LZ_MAX_CODE. obviously we can not */ + /* loop more than that. */ + j = 0; + while (j++ <= LZ_MAX_CODE && + CrntPrefix > ClearCode && + CrntPrefix <= LZ_MAX_CODE) { + Stack[StackPtr++] = Suffix[CrntPrefix]; + CrntPrefix = Prefix[CrntPrefix]; + } + if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { + CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; + } + /* Push the last character on stack: */ + Stack[StackPtr++] = CrntPrefix; + + /* Now lets pop all the stack into output: */ + while (StackPtr != 0 && i < LineLen) + Line[i++] = Stack[--StackPtr]; + } + if (LastCode != NO_SUCH_CODE) { + Prefix[Private->RunningCode - 2] = LastCode; + + if (CrntCode == Private->RunningCode - 2) { + /* Only allowed if CrntCode is exactly the running code: */ + /* In that case CrntCode = XXXCode, CrntCode or the */ + /* prefix code is last code and the suffix char is */ + /* exactly the prefix of last code! */ + Suffix[Private->RunningCode - 2] = + DGifGetPrefixChar(Prefix, LastCode, ClearCode); + } + else { + Suffix[Private->RunningCode - 2] = + DGifGetPrefixChar(Prefix, CrntCode, ClearCode); + } + } + LastCode = CrntCode; + } + } + + Private->LastCode = LastCode; + Private->StackPtr = StackPtr; + + return GIF_OK; +} + +/****************************************************************************** +* Routine to trace the Prefixes linked list until we get a prefix which is * +* not code, but a pixel value (less than ClearCode). Returns that pixel value.* +* If image is defective, we might loop here forever, so we limit the loops to * +* the maximum possible if image O.k. - LZ_MAX_CODE times. * +******************************************************************************/ +static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode) +{ + int i = 0; + + while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code]; + return Code; +} + +/****************************************************************************** +* Interface for accessing the LZ codes directly. Set Code to the real code * +* (12bits), or to -1 if EOF code is returned. * +******************************************************************************/ +int CGIFFF DGifGetLZCodes(CGIFFF GifFileType *GifFile, int *Code) +{ + GifByteType *CodeBlock; + GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + _GifError = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + if (DGifDecompressInput(Private, Code) == GIF_ERROR) + return GIF_ERROR; + + if (*Code == Private->EOFCode) { + /* Skip rest of codes (hopefully only NULL terminating block): */ + do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) + return GIF_ERROR; + while (CodeBlock != NULL); + + *Code = -1; + } + else if (*Code == Private->ClearCode) { + /* We need to start over again: */ + Private->RunningCode = Private->EOFCode + 1; + Private->RunningBits = Private->BitsPerPixel + 1; + Private->MaxCode1 = 1 << Private->RunningBits; + } + + return GIF_OK; +} + +/****************************************************************************** +* The LZ decompression input routine: * +* This routine is responsable for the decompression of the bit stream from * +* 8 bits (bytes) packets, into the real codes. * +* Returns GIF_OK if read succesfully. * +******************************************************************************/ +static int DGifDecompressInput(GifFilePrivateType *Private, int *Code) +{ + CGIFFF GifByteType NextByte; + static unsigned int CodeMasks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000f, 0x001f, 0x003f, 0x007f, + 0x00ff, 0x01ff, 0x03ff, 0x07ff, + 0x0fff + }; + + while (Private->CrntShiftState < Private->RunningBits) { + /* Needs to get more bytes from input stream for next code: */ + if (DGifBufferedInput(Private->File, Private->Buf, &NextByte) + == GIF_ERROR) { + return GIF_ERROR; + } + Private->CrntShiftDWord |= + ((unsigned long) NextByte) << Private->CrntShiftState; + Private->CrntShiftState += 8; + } + *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; + + Private->CrntShiftDWord >>= Private->RunningBits; + Private->CrntShiftState -= Private->RunningBits; + + /* If code cannt fit into RunningBits bits, must raise its size. Note */ + /* however that codes above 4095 are used for special signaling. */ + if (++Private->RunningCode > Private->MaxCode1 && + Private->RunningBits < LZ_BITS) { + Private->MaxCode1 <<= 1; + Private->RunningBits++; + } + return GIF_OK; +} + +/****************************************************************************** +* This routines read one gif data block at a time and buffers it internally * +* so that the decompression routine could access it. * +* The routine returns the next byte from its internal buffer (or read next * +* block in if buffer empty) and returns GIF_OK if succesful. * +******************************************************************************/ +static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf, + CGIFFF GifByteType *NextByte) +{ + if (Buf[0] == 0) { + /* Needs to read the next buffer - this one is empty: */ + if (fread(Buf, 1, 1, File) != 1) + { + CGIFFF _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + if (fread(&Buf[1], 1, Buf[0], File) != Buf[0]) + { + CGIFFF _GifError = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + *NextByte = Buf[1]; + Buf[1] = 2; /* We use now the second place as last char read! */ + Buf[0]--; + } + else { + *NextByte = Buf[Buf[1]++]; + Buf[0]--; + } + + return GIF_OK; +} + +/****************************************************************************** +* This routine reads an entire GIF into core, hanging all its state info off * +* the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() * +* first to initialize I/O. Its inverse is EGifSpew(). * +******************************************************************************/ +int CGIFFF DGifSlurp(CGIFFF GifFileType *GifFile) +{ + static unsigned InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */ + InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */ + /**** pts: unused vars ****/ + /* int i, j, Error, ImageSize; */ + char eatit; + int ext_code; + + GifRecordType RecordType; + /**** pts ****/ + SavedImage *sp=0; /**** pts: avoid gcc warning */ + /** Extension info of next SavedImage */ + SavedImage ext; + /** No-extension info */ + SavedImage noext; + + GifByteType *ExtData; + + /**** pts ****/ + memset(&noext, 0, sizeof(noext)); + noext.delay=0; + noext.dispose=0; + noext.iter=1; + noext.transp=(-1); + noext.ExtensionBlocks=NULL; + noext.ExtensionBlockCount=0; + ext=noext; + + /**** pts ****/ + GifFile->SavedImages=0; + + do { + if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) + return(GIF_ERROR); + + switch (RecordType) { + case IMAGE_DESC_RECORD_TYPE: + if (DGifGetImageDesc(GifFile) == GIF_ERROR) + return(GIF_ERROR); + + /**** pts: DGifGetImageDesc has already allocated the mem ****/ + sp = &GifFile->SavedImages[GifFile->ImageCount-1]; + /**** pts: apply extensions to the image just read */ + ext.RasterBits=sp->RasterBits; + ext.ImageDesc=sp->ImageDesc; + *sp=ext; + ext=noext; + + /**** pts ****/ + sp->RasterBits = (GifPixelType*) malloc((0L+sp->ImageDesc.Width) * sp->ImageDesc.Height * sizeof(GifPixelType)); + if (sp->RasterBits==NULL) { _GifError=D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } + if (sp->ImageDesc.Interlace) { + unsigned i, j, Height=sp->ImageDesc.Height, Width=sp->ImageDesc.Width; + /* Need to perform 4 passes on the images: */ + for (i = 0; i < 4; i++) + for (j = InterlacedOffset[i]; j < Height; j += InterlacedJumps[i]) + if (DGifGetLine(GifFile, sp->RasterBits+Width*j, Width) != GIF_OK) return GIF_ERROR; + } else { + if (DGifGetLine(GifFile, sp->RasterBits, (0L+sp->ImageDesc.Width) * sp->ImageDesc.Height) + == GIF_ERROR) + return(GIF_ERROR); + } + break; + + case EXTENSION_RECORD_TYPE: + + if (DGifGetExtension(GifFile,&ext_code,&ExtData)==GIF_ERROR) + return(GIF_ERROR); + if (ExtData!=NULL) { + #if 0 /**** pts ****/ + ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++]; + ep->ByteCount = ExtData[0]; + ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType)); + memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char)); + #else + /**** pts ****/ + eatit=0; + if (0xf9==(unsigned char)(ext_code)) { + assert(ExtData[0]>=4); + ext.dispose=ExtData[1]>>2; + ext.delay=(ExtData[3] << 8) | ExtData[2]; + if ((ExtData[1] & 0x01) == 1) ext.transp=ExtData[4]; + eatit=1; /* Eat this extension. */ + } else if (0xff==(unsigned char)(ext_code)) { + assert(ExtData[0]>=3); + ext.iter=(ExtData[3] << 8) | ExtData[2]; + eatit=1; /* Eat this extension. */ + } else { + AddExtensionBlock(&ext, ExtData[0], ExtData+1); + ext.ExtensionBlocks[ext.ExtensionBlockCount-1].code=ext_code; + } + #endif + while (1) { + if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) + return(GIF_ERROR); + #if 0 /**** pts ****/ + ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++]; + ep->ByteCount = ExtData[0]; + ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType)); + memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char)); + #else + if (ExtData==NULL) break; + AddExtensionBlock(sp, ExtData[0], ExtData+1); + #endif + } + } + break; + + case TERMINATE_RECORD_TYPE: + break; + + default: /* Should be trapped by DGifGetRecordType */ + break; + } + } + while + (RecordType != TERMINATE_RECORD_TYPE); + + return(GIF_OK); +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/cgif.h b/Build/source/utils/sam2p/cgif.h new file mode 100644 index 00000000000..619601f2155 --- /dev/null +++ b/Build/source/utils/sam2p/cgif.h @@ -0,0 +1,253 @@ +/* cgif.h -- a merge of some GIF-decoding files from giflib by E.S.Raymond + * by pts@fazekas.hu at Wed Feb 27 13:18:04 CET 2002 + +The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond + +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 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +/****************************************************************************** +* In order to make life a little bit easier when using the GIF file format, * +* this library was written, and which does all the dirty work... * +* * +* Written by Gershon Elber, Jun. 1989 * +* Hacks by Eric S. Raymond, Sep. 1992 * +******************************************************************************* +* History: * +* 14 Jun 89 - Version 1.0 by Gershon Elber. * +* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). * +* 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to suoport GIF slurp) * +* 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support) +******************************************************************************/ + +#ifndef CGIF_H +#define CGIF_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#define GIF_LIB_VERSION " Version 3.0, " + +#define GIF_ERROR 0 +#define GIF_OK 1 + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif /* NULL */ + +#if _MSC_VER > 1000 +# undef __PROTOTYPES__ +# define __PROTOTYPES__ 1 +# pragma warning(disable: 4127) /* conditional expression is constant */ +# pragma warning(disable: 4244) /* =' : conversion from 'int ' to 'unsigned char ', possible loss of data */ +#endif + +/* at Wed Dec 11 15:33:22 CET 2002 */ +/* #define USE_CGIF_FDOPEN 1 */ +#undef USE_CGIF_FDOPEN + +#ifdef __cplusplus +class CGIF { public: +#define EXTERN static +#else +#define EXTERN extern +#endif + +typedef int GifBooleanType; +typedef unsigned char GifPixelType; +typedef unsigned char * GifRowType; +typedef unsigned char GifByteType; + +#define GIF_MESSAGE(Msg) fprintf(stderr, "\n%s: %s\n", PROGRAM_NAME, Msg) +#define GIF_EXIT(Msg) { GIF_MESSAGE(Msg); exit(-3); } + +#ifdef SYSV +#define VoidPtr char * +#else +#define VoidPtr void * +#endif /* SYSV */ + +typedef struct GifColorType { + GifByteType Red, Green, Blue; +} GifColorType; + +typedef struct ColorMapObject +{ + int ColorCount; + int BitsPerPixel; + GifColorType *Colors; /* on malloc(3) heap */ +} +ColorMapObject; + +typedef struct GifImageDesc { + int Left, Top, Width, Height, /* Current image dimensions. */ + Interlace; /* Sequential/Interlaced lines. */ + ColorMapObject *ColorMap; /* The local color map */ +} GifImageDesc; + +struct SavedImage; +typedef struct GifFileType { + int SWidth, SHeight, /* Screen dimensions. */ + SColorResolution, /* How many colors can we generate? */ + SBackGroundColor; /* I hope you understand this one... */ + ColorMapObject *SColorMap; /* NULL if not exists. */ + int ImageCount; /* Number of current image */ + /*GifImageDesc Image; */ /* Block describing current image */ + struct SavedImage *SavedImages; /* Use this to accumulate file state */ + VoidPtr Private; /* Don't mess with this! */ +} GifFileType; + +typedef enum { + UNDEFINED_RECORD_TYPE, + SCREEN_DESC_RECORD_TYPE, + IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */ + EXTENSION_RECORD_TYPE, /* Begin with '!' */ + TERMINATE_RECORD_TYPE /* Begin with ';' */ +} GifRecordType; + +/****************************************************************************** +* GIF89 extension function codes * +******************************************************************************/ + +#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ +#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control */ +#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ +#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */ + +/****************************************************************************** +* O.K., here are the routines one can access in order to decode GIF file: * +* (GIF_LIB file DGIF_LIB.C). * +******************************************************************************/ + +EXTERN GifFileType *DGifOpenFileName(const char *GifFileName); +#if USE_CGIF_FDOPEN +EXTERN GifFileType *DGifOpenFileHandle(int GifFileHandle); +#endif +EXTERN GifFileType *DGifOpenFILE(void/*FILE*/ *f); +EXTERN int DGifSlurp(GifFileType *GifFile); +EXTERN int DGifGetScreenDesc(GifFileType *GifFile); +EXTERN int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType); +EXTERN int DGifGetImageDesc(GifFileType *GifFile); +EXTERN int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen); +EXTERN int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel); +EXTERN int DGifGetComment(GifFileType *GifFile, char *GifComment); +EXTERN int DGifGetExtension(GifFileType *GifFile, int *GifExtCode, + GifByteType **GifExtension); +EXTERN int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension); +EXTERN int DGifGetCode(GifFileType *GifFile, int *GifCodeSize, + GifByteType **GifCodeBlock); +EXTERN int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock); +EXTERN int DGifGetLZCodes(GifFileType *GifFile, int *GifCode); +EXTERN int DGifCloseFile(GifFileType *GifFile); + +#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ +#define D_GIF_ERR_READ_FAILED 102 +#define D_GIF_ERR_NOT_GIF_FILE 103 +#define D_GIF_ERR_NO_SCRN_DSCR 104 +#define D_GIF_ERR_NO_IMAG_DSCR 105 +#define D_GIF_ERR_NO_COLOR_MAP 106 +#define D_GIF_ERR_WRONG_RECORD 107 +#define D_GIF_ERR_DATA_TOO_BIG 108 +#define D_GIF_ERR_NOT_ENOUGH_MEM 109 +#define D_GIF_ERR_CLOSE_FAILED 110 +#define D_GIF_ERR_NOT_READABLE 111 +#define D_GIF_ERR_IMAGE_DEFECT 112 +#define D_GIF_ERR_EOF_TOO_SOON 113 + + +/****************************************************************************** +* O.K., here are the routines from GIF_LIB file GIF_ERR.C. * +******************************************************************************/ +EXTERN void PrintGifError(void); +EXTERN char *GetGifError(void); +EXTERN int GifLastError(void); + +/***************************************************************************** + * + * Everything below this point is new after version 1.2, supporting `slurp + * mode' for doing I/O in two big belts with all the image-bashing in core. + * + *****************************************************************************/ + +/****************************************************************************** +* Color Map handling from ALLOCGIF.C * +******************************************************************************/ + +EXTERN ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap); +EXTERN void FreeMapObject(ColorMapObject *Object); + +/****************************************************************************** +* Support for the in-core structures allocation (slurp mode). * +******************************************************************************/ + +/* This is the in-core version of an extension record */ +typedef struct { + /** Extension code: + * 0xf9 Graphics Control extension (not stored!) + * 0xfe Comment extension + * 0xff Netscape Loop extension (not stored!) + * .... ??? + */ + int code; + int ByteCount; + /**** pts ****/ + GifByteType *Bytes; /* on malloc(3) heap */ +} ExtensionBlock; + +/* This holds an image header, its unpacked raster bits, and extensions */ +typedef struct SavedImage { + GifImageDesc ImageDesc; + + /**** pts ****/ + GifPixelType *RasterBits; /* on malloc(3) heap */ + int ExtensionBlockCount; + ExtensionBlock *ExtensionBlocks; /* on malloc(3) heap */ + + /**** pts ****/ + /** from Graphics Control extension: 0..63 */ + unsigned char dispose; + /** from Graphics Control extension: 0..65535 */ + unsigned short delay; + /** from Graphics Control extension: transparency index: -1 or 0..255 */ + signed short transp; + /** from Netscape Loop extension: iteration count: 0..65535 */ + unsigned short iter; +} SavedImage; + +EXTERN void MakeExtension(SavedImage *New, int Function); +EXTERN int AddExtensionBlock(SavedImage *New, int Len, GifByteType ExtData[]); +EXTERN void FreeExtension(SavedImage *Image); + +EXTERN SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom); +EXTERN void FreeSavedImages(GifFileType *GifFile); + +#ifdef __cplusplus + static int _GifError; +}; +#else + extern int _GifError; +#endif + +#endif /* CGIF_H */ diff --git a/Build/source/utils/sam2p/cols2.pl b/Build/source/utils/sam2p/cols2.pl new file mode 100644 index 00000000000..b1a343a653f --- /dev/null +++ b/Build/source/utils/sam2p/cols2.pl @@ -0,0 +1,311 @@ +#! /bin/sh -- +eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \ +;exec perl -x -S -- "$0" ${1+"$@"};#'if 0; +eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q +#!perl -w ++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0; +# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header + +# +# cols2.pl -- create a read-only C hash table from hash function +# by pts@fazekas.hu at Fri Mar 1 09:24:46 CET 2002 +# minor VC6.0 updates at Thu Dec 12 19:01:06 CET 2002 +# +BEGIN{$^W=1} +BEGIN { eval { require integer; import integer } } +BEGIN { eval { require strict ; import strict } } + +my @L=( # imagemagick's ColorList.h + [ "None", 3, 2, 1 ], + [ "AliceBlue", 240, 248, 255 ], + [ "AntiqueWhite", 250, 235, 215 ], + [ "Aquamarine", 50, 191, 193 ], + [ "Azure", 240, 255, 255 ], + [ "Beige", 245, 245, 220 ], + [ "Bisque", 255, 228, 196 ], + [ "Black", 0, 0, 0 ], + [ "BlanchedAlmond", 255, 235, 205 ], + [ "Blue", 0, 0, 255 ], + [ "BlueViolet", 138, 43, 226 ], + [ "Brown", 165, 42, 42 ], + [ "burlywood", 222, 184, 135 ], + [ "CadetBlue", 95, 146, 158 ], + [ "chartreuse", 127, 255, 0 ], + [ "chocolate", 210, 105, 30 ], + [ "Coral", 255, 114, 86 ], + [ "CornflowerBlue", 34, 34, 152 ], + [ "cornsilk", 255, 248, 220 ], + [ "Cyan", 0, 255, 255 ], + [ "DarkGoldenrod", 184, 134, 11 ], + [ "DarkGreen", 0, 86, 45 ], + [ "DarkKhaki", 189, 183, 107 ], + [ "DarkOliveGreen", 85, 86, 47 ], + [ "DarkOrange", 255, 140, 0 ], + [ "DarkOrchid", 139, 32, 139 ], + [ "DarkSalmon", 233, 150, 122 ], + [ "DarkSeaGreen", 143, 188, 143 ], + [ "DarkSlateBlue", 56, 75, 102 ], + [ "DarkSlateGray", 47, 79, 79 ], + [ "DarkTurquoise", 0, 166, 166 ], + [ "DarkViolet", 148, 0, 211 ], + [ "DeepPink", 255, 20, 147 ], + [ "DeepSkyBlue", 0, 191, 255 ], + [ "DimGray", 84, 84, 84 ], + [ "DodgerBlue", 30, 144, 255 ], + [ "Firebrick", 142, 35, 35 ], + [ "FloralWhite", 255, 250, 240 ], + [ "ForestGreen", 80, 159, 105 ], + [ "gainsboro", 220, 220, 220 ], + [ "GhostWhite", 248, 248, 255 ], + [ "Gold", 218, 170, 0 ], + [ "Goldenrod", 239, 223, 132 ], + [ "Gray", 126, 126, 126 ], + [ "Green", 0, 255, 0 ], + [ "GreenYellow", 173, 255, 47 ], + [ "honeydew", 240, 255, 240 ], + [ "HotPink", 255, 105, 180 ], + [ "IndianRed", 107, 57, 57 ], + [ "ivory", 255, 255, 240 ], + [ "Khaki", 179, 179, 126 ], + [ "lavender", 230, 230, 250 ], + [ "LavenderBlush", 255, 240, 245 ], + [ "LawnGreen", 124, 252, 0 ], + [ "LemonChiffon", 255, 250, 205 ], + [ "LightBlue", 176, 226, 255 ], + [ "LightCoral", 240, 128, 128 ], + [ "LightCyan", 224, 255, 255 ], + [ "LightGoldenrod", 238, 221, 130 ], + [ "LightGoldenrodYellow", 250, 250, 210 ], + [ "LightGray", 168, 168, 168 ], + [ "LightPink", 255, 182, 193 ], + [ "LightSalmon", 255, 160, 122 ], + [ "LightSeaGreen", 32, 178, 170 ], + [ "LightSkyBlue", 135, 206, 250 ], + [ "LightSlateBlue", 132, 112, 255 ], + [ "LightSlateGray", 119, 136, 153 ], + [ "LightSteelBlue", 124, 152, 211 ], + [ "LightYellow", 255, 255, 224 ], + [ "LimeGreen", 0, 175, 20 ], + [ "linen", 250, 240, 230 ], + [ "Magenta", 255, 0, 255 ], + [ "Maroon", 143, 0, 82 ], + [ "MediumAquamarine", 0, 147, 143 ], + [ "MediumBlue", 50, 50, 204 ], + [ "MediumForestGreen", 50, 129, 75 ], + [ "MediumGoldenrod", 209, 193, 102 ], + [ "MediumOrchid", 189, 82, 189 ], + [ "MediumPurple", 147, 112, 219 ], + [ "MediumSeaGreen", 52, 119, 102 ], + [ "MediumSlateBlue", 106, 106, 141 ], + [ "MediumSpringGreen", 35, 142, 35 ], + [ "MediumTurquoise", 0, 210, 210 ], + [ "MediumVioletRed", 213, 32, 121 ], + [ "MidnightBlue", 47, 47, 100 ], + [ "MintCream", 245, 255, 250 ], + [ "MistyRose", 255, 228, 225 ], + [ "moccasin", 255, 228, 181 ], + [ "NavajoWhite", 255, 222, 173 ], + [ "Navy", 35, 35, 117 ], + [ "NavyBlue", 35, 35, 117 ], + [ "OldLace", 253, 245, 230 ], + [ "OliveDrab", 107, 142, 35 ], + [ "Orange", 255, 135, 0 ], + [ "OrangeRed", 255, 69, 0 ], + [ "Orchid", 239, 132, 239 ], + [ "PaleGoldenrod", 238, 232, 170 ], + [ "PaleGreen", 115, 222, 120 ], + [ "PaleTurquoise", 175, 238, 238 ], + [ "PaleVioletRed", 219, 112, 147 ], + [ "PapayaWhip", 255, 239, 213 ], + [ "PeachPuff", 255, 218, 185 ], + [ "peru", 205, 133, 63 ], + [ "Pink", 255, 181, 197 ], + [ "Plum", 197, 72, 155 ], + [ "PowderBlue", 176, 224, 230 ], + [ "purple", 160, 32, 240 ], + [ "Red", 255, 0, 0 ], + [ "RosyBrown", 188, 143, 143 ], + [ "RoyalBlue", 65, 105, 225 ], + [ "SaddleBrown", 139, 69, 19 ], + [ "Salmon", 233, 150, 122 ], + [ "SandyBrown", 244, 164, 96 ], + [ "SeaGreen", 82, 149, 132 ], + [ "seashell", 255, 245, 238 ], + [ "Sienna", 150, 82, 45 ], + [ "SkyBlue", 114, 159, 255 ], + [ "SlateBlue", 126, 136, 171 ], + [ "SlateGray", 112, 128, 144 ], + [ "snow", 255, 250, 250 ], + [ "SpringGreen", 65, 172, 65 ], + [ "SteelBlue", 84, 112, 170 ], + [ "Tan", 222, 184, 135 ], + [ "Thistle", 216, 191, 216 ], + [ "tomato", 255, 99, 71 ], + [ "Transparent", 0, 0, 1 ], + [ "Turquoise", 25, 204, 223 ], + [ "Violet", 156, 62, 206 ], + [ "VioletRed", 243, 62, 150 ], + [ "Wheat", 245, 222, 179 ], + [ "White", 255, 255, 255 ], + [ "WhiteSmoke", 245, 245, 245 ], + [ "Yellow", 255, 255, 0 ], + [ "YellowGreen", 50, 216, 56 ], + [ "Gray0", 0, 0, 0 ], + [ "Gray1", 3, 3, 3 ], + [ "Gray10", 26, 26, 26 ], + [ "Gray100", 255, 255, 255 ], + [ "Gray11", 28, 28, 28 ], + [ "Gray12", 31, 31, 31 ], + [ "Gray13", 33, 33, 33 ], + [ "Gray14", 36, 36, 36 ], + [ "Gray15", 38, 38, 38 ], + [ "Gray16", 41, 41, 41 ], + [ "Gray17", 43, 43, 43 ], + [ "Gray18", 46, 46, 46 ], + [ "Gray19", 48, 48, 48 ], + [ "Gray2", 5, 5, 5 ], + [ "Gray20", 51, 51, 51 ], + [ "Gray21", 54, 54, 54 ], + [ "Gray22", 56, 56, 56 ], + [ "Gray23", 59, 59, 59 ], + [ "Gray24", 61, 61, 61 ], + [ "Gray25", 64, 64, 64 ], + [ "Gray26", 66, 66, 66 ], + [ "Gray27", 69, 69, 69 ], + [ "Gray28", 71, 71, 71 ], + [ "Gray29", 74, 74, 74 ], + [ "Gray3", 8, 8, 8 ], + [ "Gray30", 77, 77, 77 ], + [ "Gray31", 79, 79, 79 ], + [ "Gray32", 82, 82, 82 ], + [ "Gray33", 84, 84, 84 ], + [ "Gray34", 87, 87, 87 ], + [ "Gray35", 89, 89, 89 ], + [ "Gray36", 92, 92, 92 ], + [ "Gray37", 94, 94, 94 ], + [ "Gray38", 97, 97, 97 ], + [ "Gray39", 99, 99, 99 ], + [ "Gray4", 10, 10, 10 ], + [ "Gray40", 102, 102, 102 ], + [ "Gray41", 105, 105, 105 ], + [ "Gray42", 107, 107, 107 ], + [ "Gray43", 110, 110, 110 ], + [ "Gray44", 112, 112, 112 ], + [ "Gray45", 115, 115, 115 ], + [ "Gray46", 117, 117, 117 ], + [ "Gray47", 120, 120, 120 ], + [ "Gray48", 122, 122, 122 ], + [ "Gray49", 125, 125, 125 ], + [ "Gray5", 13, 13, 13 ], + [ "Gray50", 127, 127, 127 ], + [ "Gray51", 130, 130, 130 ], + [ "Gray52", 133, 133, 133 ], + [ "Gray53", 135, 135, 135 ], + [ "Gray54", 138, 138, 138 ], + [ "Gray55", 140, 140, 140 ], + [ "Gray56", 143, 143, 143 ], + [ "Gray57", 145, 145, 145 ], + [ "Gray58", 148, 148, 148 ], + [ "Gray59", 150, 150, 150 ], + [ "Gray6", 15, 15, 15 ], + [ "Gray60", 153, 153, 153 ], + [ "Gray61", 156, 156, 156 ], + [ "Gray62", 158, 158, 158 ], + [ "Gray63", 161, 161, 161 ], + [ "Gray64", 163, 163, 163 ], + [ "Gray65", 166, 166, 166 ], + [ "Gray66", 168, 168, 168 ], + [ "Gray67", 171, 171, 171 ], + [ "Gray68", 173, 173, 173 ], + [ "Gray69", 176, 176, 176 ], + [ "Gray7", 18, 18, 18 ], + [ "Gray70", 179, 179, 179 ], + [ "Gray71", 181, 181, 181 ], + [ "Gray72", 184, 184, 184 ], + [ "Gray73", 186, 186, 186 ], + [ "Gray74", 189, 189, 189 ], + [ "Gray75", 191, 191, 191 ], + [ "Gray76", 194, 194, 194 ], + [ "Gray77", 196, 196, 196 ], + [ "Gray78", 199, 199, 199 ], + [ "Gray79", 201, 201, 201 ], + [ "Gray8", 20, 20, 20 ], + [ "Gray80", 204, 204, 204 ], + [ "Gray81", 207, 207, 207 ], + [ "Gray82", 209, 209, 209 ], + [ "Gray83", 212, 212, 212 ], + [ "Gray84", 214, 214, 214 ], + [ "Gray85", 217, 217, 217 ], + [ "Gray86", 219, 219, 219 ], + [ "Gray87", 222, 222, 222 ], + [ "Gray88", 224, 224, 224 ], + [ "Gray89", 227, 227, 227 ], + [ "Gray9", 23, 23, 23 ], + [ "Gray90", 229, 229, 229 ], + [ "Gray91", 232, 232, 232 ], + [ "Gray92", 235, 235, 235 ], + [ "Gray93", 237, 237, 237 ], + [ "Gray94", 240, 240, 240 ], + [ "Gray95", 242, 242, 242 ], + [ "Gray96", 245, 245, 245 ], + [ "Gray97", 247, 247, 247 ], + [ "Gray98", 250, 250, 250 ], + [ "Gray99", 252, 252, 252 ], +); + +# quote all [^!-~]|[^\\ +sub cq($) { + # @return param octal-quoted as a C source string + my $S=$_[0]; + $S=~s@([\\"])@\\$1@g; + $S=~s@([^!-~])@sprintf"\\%03o",ord$1@ge; + $S=~s@\\([0-7][0-7][0-7])(?=[0-9])@\\$1""@g; # pacify VC6.0 warning + $S +} + +my @P; +sub hash0($) { + my $N=0; + for(split'',$_[0][0]) { $N=$N*95+(223&ord); } + $N&=65535; + $N%=1109; + push @{$P[$N]}, $_[0]; +} + +@P=(); +for (@L) { hash0($_); } +# my $S=""; +# die @P; +print STDERR "Collisions:\n"; +for (@P) { print STDERR "X@$_.\n" if defined($_) and $#$_>=1 } +print STDERR "---\n"; + +my $S="\000"; # contains strings +my $H=""; # contains the hash table indices, offsets to $S +for (@P) { + if (defined($_)) { + $H.=length($S).","; + for (@$_) { + # $S.=$_->[0]."#".$_->[1].",".$_->[2].",".$_->[3].";" + $S.=$_->[0]."\000".chr($_->[1]).chr($_->[2]).chr($_->[3]); + } + # substr($S,-1,1)="\000"; + $S.="\000"; + } else { $H.="0,"; } +# print STDERR "X@$_.\n" if defined($_) and $#$_>=1 } +} +$S=~s@\000\Z(?!\n)@@; +print "#define xpmColors_mul 95\n"; +print "#define xpmColors_mod 1109\n"; +print "unsigned short xpmColors_ofs[]={$H};\n"; +print "char xpmColors_dat[]=\"".cq($S)."\";\n"; + +# 357, 2048 +# 189, 3457 +# 175, 3823 +# 973 (222), 1993 +# 751 (22), 1997 +# 439 (2), 2053 +# 79 (222222), 1229 +# 539 (22222), 1201 +# 287 (222), 1163 diff --git a/Build/source/utils/sam2p/config-vc6.h b/Build/source/utils/sam2p/config-vc6.h new file mode 100644 index 00000000000..ae59ea039c1 --- /dev/null +++ b/Build/source/utils/sam2p/config-vc6.h @@ -0,0 +1,197 @@ +/* config-vc6.h. config.h replacement for MS Visual C++ 6.0 */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* #undef __CHAR_UNSIGNED__ */ +#endif + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +/* #undef HAVE_ALLOCA_H */ + +/* Define if you have the ANSI # stringizing operator in cpp. */ +/* #undef HAVE_STRINGIZE */ + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ + +/* Define if you have the ANSI C header files. */ +/* #undef STDC_HEADERS */ + +/* A type name of a signed integral type of exactly 16 bits. Always defined. + */ +#define PTS_INT16_T short + +/* A type name of a signed integral type of exactly 32 bits. Always defined. + */ +#define PTS_INT32_T int + +/* A type name of a signed integral type of exactly 64 bits. Maybe left + * 0-defined. + */ +#define PTS_INT64_T long long + +/* A type name of a signed integral type of exactly 128 bits. Maybe left + * 0-defined. + */ +#define PTS_INT128_T 0 + +/* A type name of a signed integral type which has space to hold a pointer. + * Always defined. + */ +#define PTS_INTP_T int + +/* Imp: document this + */ +#define PTS_INTP_OK 1 + +/* Imp: document this + */ +/* #undef PTS_mode_t */ + +/* Imp: document this + */ +/* #undef PTS_off_t */ + +/* Imp: document this + */ +/* #undef PTS_pid_t */ + +/* Imp: document this + */ +#define PTS_size_t unsigned int + +/* Just a dummy, non-existent type. + */ +/* #undef PTS_size_tt */ + +/* Imp: document this + */ +/* #undef PTS_uid_t */ + +/* Imp: document this + */ +/* #undef PTS_gid_t */ + +/* Imp: document this + */ +/* #undef PTS_dev_t */ + +/* Does the C compiler support prototypes? + */ +#define HAVE_PROTOTYPES 1 + +/* Define to empty if the keyword does not work. + */ +/* #undef volatile */ + +/* Imp: document this + */ +#define HAVE_strcpy_in_string 1 + +/* Imp: document this + */ +/* #undef HAVE_strcpy_in_strings */ + +/* Imp: document these + */ +/* #undef HAVE_MEMCMPY_BUILTIN */ +#define HAVE_getc_in_stdio 1 +#define HAVE_fgetc_in_stdio 1 +#define HAVE_putc_in_stdio 1 +#define HAVE_fputc_in_stdio 1 +#define HAVE_atoi_in_stdlib 1 +/* #undef HAVE_malloc_in_malloc */ +#define HAVE_malloc_in_stdlib 1 +#define HAVE_memcpy_in_stringxs 1 +#define HAVE_sprintf_in_stdio 1 +#define HAVE_write_in_unistd 1 +#define HAVE_system_in_stdlib 1 +/* #undef HAVE_lstat_in_sys_stat */ +#define HAVE_PTS_STDC 1 +/* #undef HAVE_SWITCH_ENUM_BUG */ +#define HAVE_ASCII_SYSTEM 1 +#define PTS_CFG_P_TMPDIR 0 + +/* Is the file c_gcc.cpp required for gcc when linking C++ programs? */ +#define HAVE_PTS_C_LGCC_CPP_REQUIRED 1 +/* #undef HAVE_PTS_C_LGCC3_CPP_REQUIRED */ + +/** Does the C library have a working vsnprintf()? */ +/* #undef HAVE_PTS_VSNPRINTF */ +/* #undef HAVE_PTS_VSNPRINTF_OLD */ +/* #undef HAVE_PTS_VSNPRINTF_C99 */ + +/** What shell does the C library system(3) function call? */ +#define HAVE_PTS_SYSTEMF 1 +#define HAVE_PTS_SYSTEMF_WIN32 1 +/* #undef HAVE_PTS_SYSTEMF_UNIX */ +/* #undef HAVE_PTS_SYSTEMF_OTHER */ + +/** popen("...","wb") and "rb" works binary */ +/* #undef HAVE_PTS_POPEN_B */ + +/** popen("...","w") and "r" works binary */ +/* #undef HAVE_PTS_POPEN_ */ + +/* The number of bytes in a __int64. */ +#define SIZEOF___INT64 0 + +/* The number of bytes in a bool. */ +#define SIZEOF_BOOL 1 + +/* The number of bytes in a char. */ +#define SIZEOF_CHAR 1 + +/* The number of bytes in a char *. */ +#define SIZEOF_CHAR_P 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a long long. */ +#define SIZEOF_LONG_LONG 8 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +/* The number of bytes in a very long. */ +#define SIZEOF_VERY_LONG 0 + +/* The number of bytes in a void *. */ +#define SIZEOF_VOID_P 4 + +/* Can have static const int VARNAME=1; inside a class { ... } ? */ +/* #undef HAVE_STATIC_CONST */ + +/* sam2p-specific */ +#define USE_BUILTIN_ZIP 1 +#define USE_BUILTIN_FAXE 1 +#define USE_BUILTIN_LZW 1 +#define USE_IN_GIF 1 +#define USE_OUT_GIF 1 diff --git a/Build/source/utils/sam2p/config.h.in b/Build/source/utils/sam2p/config.h.in new file mode 100644 index 00000000000..9322e64c19a --- /dev/null +++ b/Build/source/utils/sam2p/config.h.in @@ -0,0 +1,201 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +#undef __CHAR_UNSIGNED__ +#endif + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have the ANSI # stringizing operator in cpp. */ +#undef HAVE_STRINGIZE + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* A type name of a signed integral type of exactly 16 bits. Always defined. + */ +#undef PTS_INT16_T + +/* A type name of a signed integral type of exactly 32 bits. Always defined. + */ +#undef PTS_INT32_T + +/* A type name of a signed integral type of exactly 64 bits. Maybe left + * 0-defined. + */ +#undef PTS_INT64_T + +/* A type name of a signed integral type of exactly 128 bits. Maybe left + * 0-defined. + */ +#undef PTS_INT128_T + +/* A type name of a signed integral type which has space to hold a pointer. + * Always defined. + */ +#undef PTS_INTP_T + +/* Imp: document this + */ +#undef PTS_INTP_OK + +/* Imp: document this + */ +#undef PTS_mode_t + +/* Imp: document this + */ +#undef PTS_off_t + +/* Imp: document this + */ +#undef PTS_pid_t + +/* Imp: document this + */ +#undef PTS_size_t + +/* Just a dummy, non-existent type. + */ +#undef PTS_size_tt + +/* Imp: document this + */ +#undef PTS_uid_t + +/* Imp: document this + */ +#undef PTS_gid_t + +/* Imp: document this + */ +#undef PTS_dev_t + +/* Does the C compiler support prototypes? + */ +#undef HAVE_PROTOTYPES + +/* Define to empty if the keyword does not work. + */ +#undef volatile + +/* Imp: document this + */ +#undef HAVE_strcpy_in_string + +/* Imp: document this + */ +#undef HAVE_strcpy_in_strings + +/* Imp: document these + */ +#undef HAVE_MEMCMPY_BUILTIN +#undef HAVE_getc_in_stdio +#undef HAVE_fgetc_in_stdio +#undef HAVE_putc_in_stdio +#undef HAVE_fputc_in_stdio +#undef HAVE_atoi_in_stdlib +#undef HAVE_malloc_in_malloc +#undef HAVE_malloc_in_stdlib +#undef HAVE_memcpy_in_stringxs +#undef HAVE_sprintf_in_stdio +#undef HAVE_write_in_unistd +#undef HAVE_system_in_stdlib +#undef HAVE_lstat_in_sys_stat +#undef HAVE_PTS_STDC +#undef HAVE_SWITCH_ENUM_BUG +#undef HAVE_ASCII_SYSTEM +#undef PTS_CFG_P_TMPDIR + +/** "" or ".16", so composing "%.16g" for printing doubles with printf(3) + * will just print enough digits + */ +#define PTS_CFG_PRINTFGLEN ".16" + +/* Is the file c_gcc.cpp required for gcc when linking C++ programs? */ +#undef HAVE_PTS_C_LGCC_CPP_REQUIRED +#undef HAVE_PTS_C_LGCC3_CPP_REQUIRED + +/** Does the C library have a working vsnprintf()? */ +#undef HAVE_PTS_VSNPRINTF +#undef HAVE_PTS_VSNPRINTF_OLD +#undef HAVE_PTS_VSNPRINTF_C99 + +/** What shell does the C library system(3) function call? */ +#undef HAVE_PTS_SYSTEMF +#undef HAVE_PTS_SYSTEMF_WIN32 +#undef HAVE_PTS_SYSTEMF_UNIX +#undef HAVE_PTS_SYSTEMF_OTHER + +/** popen("...","wb") and "rb" works binary */ +#undef HAVE_PTS_POPEN_B + +/** popen("...","w") and "r" works binary */ +#undef HAVE_PTS_POPEN_ + +/* The number of bytes in a __int64. */ +#undef SIZEOF___INT64 + +/* The number of bytes in a bool. */ +#undef SIZEOF_BOOL + +/* The number of bytes in a char. */ +#undef SIZEOF_CHAR + +/* The number of bytes in a char *. */ +#undef SIZEOF_CHAR_P + +/* The number of bytes in a int. */ +#undef SIZEOF_INT + +/* The number of bytes in a long. */ +#undef SIZEOF_LONG + +/* The number of bytes in a long long. */ +#undef SIZEOF_LONG_LONG + +/* The number of bytes in a short. */ +#undef SIZEOF_SHORT + +/* The number of bytes in a very long. */ +#undef SIZEOF_VERY_LONG + +/* The number of bytes in a void *. */ +#undef SIZEOF_VOID_P + +/* Can have static const int VARNAME=1; inside a class { ... } ? */ +#undef HAVE_STATIC_CONST + +/* sam2p-specific */ +#undef USE_BUILTIN_ZIP +#undef USE_BUILTIN_FAXE +#undef USE_BUILTIN_LZW +#undef USE_IN_GIF +#undef USE_OUT_GIF diff --git a/Build/source/utils/sam2p/config2.h b/Build/source/utils/sam2p/config2.h new file mode 100644 index 00000000000..ae0a76804db --- /dev/null +++ b/Build/source/utils/sam2p/config2.h @@ -0,0 +1,343 @@ +#ifndef CONFIG2_H +#define CONFIG2_H 1 + +#include <assert.h> /* NDEBUG==1 means: no assertions */ +#if NDEBUG +# define ASSERT_SIDE(x) x /* assert with side effect */ +# define ASSERT_SIDE2(x,y) x /* assert with side effect */ +#else +# define ASSERT_SIDE(x) assert(x) +# define ASSERT_SIDE2(x,y) assert(x y) +#endif + +#if _MSC_VER > 1000 +# include "config-vc6.h" +#else +# include "config.h" +#endif + +#if 0 +/* vvv i386 Debian slink gcc */ +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_LONG_LONG 8 +#endif + +#if SIZEOF_CHAR_P!=SIZEOF_LONG && SIZEOF_INT>=4 + typedef unsigned slen_t; + typedef signed slendiff_t; +# define SIZEOF_SLEN_T SIZEOF_INT +# define SLEN_P "" +#else + typedef unsigned long slen_t; + typedef signed long slendiff_t; +# define SIZEOF_SLEN_T SIZEOF_LONG +# define SLEN_P "l" +#endif + +#if SIZEOF___INT64>SIZEOF_LONG +# define HAVE_LONG_LONG 1 +# define PTS_CFG_LONGEST __int64 /* may be used as signed CFG_LONGEST */ +# define SIZEOF_CFG_LONGEST SIZEOF___INT64 +#elif SIZEOF_LONG_LONG>SIZEOF_LONG +# define HAVE_LONG_LONG 1 +# define PTS_CFG_LONGEST long long /* may be used as signed CFG_LONGEST */ +# define SIZEOF_CFG_LONGEST SIZEOF_LONG_LONG +#elif SIZEOF_VERY_LONG>SIZEOF_LONG +# define HAVE_LONG_LONG 1 +# define PTS_CFG_LONGEST very long /* may be used as signed CFG_LONGEST */ +# define SIZEOF_CFG_LONGEST SIZEOF_VERY_LONG +#else +# undef HAVE_LONG_LONG +# define PTS_CFG_LONGEST long +# define SIZEOF_CFG_LONGEST SIZEOF_LONG +#endif + +#define NULLP ((void*)0) + +#define USE_IN_TIFF 1 +#define USE_IN_JPEG 1 +#define USE_IN_PNG 1 +#define USE_IN_PCX 1 +#define USE_IN_XPM 1 +/* #define USE_IN_GIF 1 -- defined in */ +#define USE_IN_PNM 1 +#define USE_IN_BMP 1 +#define USE_IN_PIP 1 /* simple paletted format defined by pts, but not implemented */ +#define USE_IN_TGA 1 +#define USE_IN_LBM 1 +#define USE_IN_JAI 1 +#define USE_IN_PDF 1 +#define USE_IN_PS 1 +/* #define USE_OUT_GIF 1 -- moved to config.h */ +#define USE_IN_XPM_MAPPING 1 +#define USE_BIG_MEMORY 1 +#define USE_DICT_MAPPING 1 +/* at Tue Jan 18 16:18:34 CET 2005 */ +#define USE_ZLIB_MEM 1 + +/** Quotes a filename to be displayed in error messages */ +/* #define FNQ(str) (str) */ +#define FNQ(filename) SimBuffer::B().appendFnq(SimBuffer::Static(filename)) +#define FNQ2(beg,len) SimBuffer::B().appendFnq(SimBuffer::Static(beg,len),true) +#define FNQ2STDOK(beg,len) SimBuffer::B().appendFnq(SimBuffer::Static(beg,len),false) + + +#define param_assert assert + +#undef __VA_START_STDC__ +#ifdef __STDC__ +# define __VA_START_STDC__ 1 +#endif +#if _MSC_VER > 1000 +# undef __PROTOTYPES__ +# define __PROTOTYPES__ 1 +# undef __VA_START_STDC__ +# define __VA_START_STDC__ 1 +# pragma warning(disable: 4127) /* conditional expression is constant */ +# pragma warning(disable: 4244) /* =' : conversion from 'int ' to 'unsigned char ', possible loss of data */ +# pragma warning(disable: 4250) /* 'SimBuffer::B' : inherits 'SimBuffer::Flat::getLength' via dominance */ +# pragma warning(disable: 4514) /* 'each_char' : unreferenced inline function has been removed */ +# pragma warning(disable: 4512) /* 'PipeE' : assignment operator could not be generated */ +# pragma warning(disable: 4310) /* cast truncates constant value */ +# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */ +#endif + +#if __VA_START_STDC__ +# define PTS_va_start(ap, fmt) va_start(ap, fmt) +#else +# define PTS_va_start(ap, fmt) va_start(ap) +#endif + +#if HAVE_STATIC_CONST +# define BEGIN_STATIC_ENUM(basetype,type) typedef basetype type; static const type +# define BEGIN_STATIC_ENUM1(type) static const type +# define END_STATIC_ENUM() ; +#else /* VC6.0 */ +# define BEGIN_STATIC_ENUM(basetype,type) enum type { +# define BEGIN_STATIC_ENUM1(type) enum { +# define END_STATIC_ENUM() }; +#endif + +#if ((defined(__STDC__) || defined(__PROTOTYPES__)) && !defined(NO_PROTO)) || defined(__cplusplus) +# define _(args) args +# define OF(args) args +# define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */ +#else +# define _(args) () +# define OF(args) () +# define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */ +#endif + +#if SIZEOF_BOOL!=1 +#define bool PTS_bool +#define true 1 +#define false 0 +typedef unsigned char bool; +#endif + +#ifdef const +# undef const +# define PTS_const +# undef HAVE_CONST +#else +# define PTS_const const +# define HAVE_CONST 1 +#endif + +#ifdef volatile +# undef volatile +# define PTS_volatile +# undef HAVE_VOLATILE +#else +# define PTS_volatile volatile +# define HAVE_VOLATILE 1 +#endif + +#ifdef NEED_STRING_H +/* We use: memset(), memmove(), strncpy(), memcpy(), memcmp() */ +#if HAVE_MEMCMPY_BUILTIN +# undef memcpy +# define memcpy dummy_memcpy +# undef memcmp +# define memcmp dummy_memcmp +#endif +#ifdef HAVE_strcpy_in_string +# include <string.h> +#elif HAVE_strcpy_in_strings +# include <strings.h> +#else +# error no strcpy +#endif +#if HAVE_MEMCMPY_BUILTIN +# undef memcmp +# undef memcpy +#endif +#endif + +#ifdef NEED_MALLOC +#if HAVE_malloc_in_stdlib +# include <stdlib.h> +#elif HAVE_PTS_STDC && HAVE_malloc_in_malloc +# include <malloc.h> +#elif HAVE_PTS_STDC +# error malloc() not found +#elif HAVE_PROTOTYPES + void *malloc(PTS_size_t size); + void *realloc(void *ptr, PTS_size_t size); + void free(void *ptr); +#else + void *malloc(); + void *realloc(); + void free(); +#endif +#endif + +#ifdef NEED_ALLOCA +/* Make alloca work the best possible way. + * Imp: AIX requires this to be the 1st thing in the file?? + */ +#ifdef __GNUC__ +# ifndef atarist +# ifndef alloca +# define alloca __builtin_alloca +# endif +# endif /* atarist */ +#elif defined(__BORLANDC__) +# include <malloc.h> +#elif HAVE_ALLOCA_H +# include <alloca.h> +#elif defined(_AIX) + #pragma alloca /* indented to avoid choking of pre-ANSI compilers */ +#elif !defined alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +#endif +#endif /* NEED_ALLOCA */ + +#ifdef NEED_SIGN_EXTEND_CHAR +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if HAVE_PTS_STDC +# define SIGN_EXTEND_CHAR(c) ((signed char)(c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128) +#endif +#endif + +/* by pts@fazekas.hu at Fri Mar 22 17:01:27 CET 2002 */ +#if defined(HAVE_PTS_POPEN_) +# define HAVE_PTS_POPEN 1 +# define CFG_PTS_POPEN_B "" +#elif defined(HAVE_PTS_POPEN_B) +# define HAVE_PTS_POPEN 1 +# define CFG_PTS_POPEN_B "b" +#else +# undef HAVE_PTS_POPEN +#endif + +#undef NEED_LONG_LONG +#undef NEED_LONG_DOUBLE + +/** Filename, directory and quoting conventions for the host OS. + * 0: UNIX + * 1: DOS/Win3.1 + * 2: WinNT + * 3: Win9X + * 4: VMS + * 5: Mac + * 6... + * + * Imp: implement other than UNIX + */ +#define COTY_UNIX 0 +#define COTY_DOS 1 +#define COTY_WINNT 2 +#define COTY_WIN9X 3 +#define COTY_VMS 4 +#define COTY_MAC 5 +#define COTY_OTHER 6 + +#if HAVE_PTS_SYSTEMF_UNIX +# define OS_COTY COTY_UNIX +#else +# if HAVE_PTS_SYSTEMF_WIN32 +# define OS_COTY COTY_WIN9X +# else +# define OS_COTY COTY_OTHER +# endif +#endif + +/* vvv Imp: autodetect this */ +#if defined(__MSDOS__) || defined(__CYGWIN__) || defined(__MINGW32__) || _MSC_VER > 1000 +# define HAVE_DOS_BINARY 1 +#else +# undef HAVE_DOS_BINARY +#endif + +/* #define PTS_dynamic_cast(ptrtype,ptr) dynamic_cast<ptrtype>(ptr) -- would include special G++ symbols into .o */ +#define PTS_dynamic_cast(ptrtype,ptr) ((ptrtype)(ptr)) + +/** Suppress effect of -Wcast-align warning */ +#define PTS_align_cast(ptrtype,ptr) ((ptrtype)(void*)(ptr)) +/** Suppress effect of -Wcast-align warning */ +#define PTS_calign_cast(ptrtype,ptr) ((ptrtype)(void const*)(ptr)) + + +#undef HAVE_LZW +#if USE_BUILTIN_LZW +# define HAVE_LZW 1 +#else +# define HAVE_LZW 1 /* try to use external lzw_codec */ +#endif +/* #define USE_BUILTIN_FAXE 1 */ /* in config.h */ +#undef USE_BUILTIN_FAXD /* sure */ +/* #define USE_BUILTIN_FAXD 1 */ /* in config.h */ + +#ifndef __cplusplus +#undef true +#undef false +#ifdef __BEOS__ +typedef unsigned char bool; +#else +typedef int bool; +#endif +#define true ((bool)1) +#define false ((bool)0) +#endif + +/* by pts@fazekas.hu at Tue Sep 3 18:47:47 CEST 2002 */ +#if OBJDEP && defined(__cplusplus) && HAVE_PTS_C_LGCC_CPP_REQUIRED +# warning REQUIRES: c_lgcc.o +#endif +#if OBJDEP && defined(__cplusplus) && HAVE_PTS_C_LGCC3_CPP_REQUIRED +# warning REQUIRES: c_lgcc3.o +#endif + +/* at Wed Aug 21 18:28:24 CEST 2002 */ +#if HAVE_getc_in_stdio +# define MACRO_GETC getc +#else +# if HAVE_fgetc_in_stdio +# define MACRO_GETC fgetc +# else +# error getc() or fgetc() is required +# endif +#endif +#if HAVE_putc_in_stdio +# define MACRO_PUTC putc +#else +# if HAVE_fputc_in_stdio +# define MACRO_PUTC fputc +# else +# error putc() or fputc() is required +# endif +#endif + + + +#endif /* config2.h */ diff --git a/Build/source/utils/sam2p/configure b/Build/source/utils/sam2p/configure new file mode 100755 index 00000000000..fc4ae328057 --- /dev/null +++ b/Build/source/utils/sam2p/configure @@ -0,0 +1,7520 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.57. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="gensi.cpp" +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS ENABLE_DEBUG CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT GFLAG CXXFLAGSB LDXX pts_cjpeg pts_djpeg pts_tif22pnm pts_tifftopnm pts_pngtopnm pts_gs pts_lzw_codec pts_gzip pts_zip pts_bash pts_make pts_perl CXXCPP EGREP ALLOCA LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug=val val: no, assert(default), yes, checker + --enable-lzw enable built-in LZW (de)compression (def: no) + --enable-zip enable built-in ZIP compression (def: yes) + --enable-fax enable built-in Fax compression (def: yes) + --enable-gif enable reading and writing GIF images (def: no) + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +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 || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + ac_config_headers="$ac_config_headers config.h" + + + echo "$as_me:$LINENO: checking for --enable-debug" >&5 +echo $ECHO_N "checking for --enable-debug... $ECHO_C" >&6 + + # Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + +fi; + ENABLE_DEBUG="$enable_debug" + if test x"$enable_debug" = xno; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + elif test x"$enable_debug" = x || test x"$enable_debug" = xassert; then + echo "$as_me:$LINENO: result: assert" >&5 +echo "${ECHO_T}assert" >&6 + ENABLE_DEBUG=assert + elif test x"$enable_debug" = xyes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + elif test x"$enable_debug" = xchecker; then + echo "$as_me:$LINENO: result: checker" >&5 +echo "${ECHO_T}checker" >&6 + else + echo "$as_me:$LINENO: result: \"?? $enable_debug\"" >&5 +echo "${ECHO_T}\"?? $enable_debug\"" >&6 + { { echo "$as_me:$LINENO: error: Invalid --enable--debug option specified." >&5 +echo "$as_me: error: Invalid --enable--debug option specified." >&2;} + { (exit 1); exit 1; }; } + fi + + +echo "$as_me:$LINENO: checking for --enable-lzw" >&5 +echo $ECHO_N "checking for --enable-lzw... $ECHO_C" >&6 +# Check whether --enable-lzw or --disable-lzw was given. +if test "${enable_lzw+set}" = set; then + enableval="$enable_lzw" + +fi; +if test x1 = x"`perl -e 'print time>1056165811'`"; then + # After 19 June 2003: default: yes + if test x"$enable_lzw" = x"no"; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + else + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define USE_BUILTIN_LZW 1 +_ACEOF + + fi +else + if test x"$enable_lzw" = x"yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define USE_BUILTIN_LZW 1 +_ACEOF + + { echo "$as_me:$LINENO: WARNING: LZW is patented till 19 June 2003; ask permission from Unisys to use it!" >&5 +echo "$as_me: WARNING: LZW is patented till 19 June 2003; ask permission from Unisys to use it!" >&2;} + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi +fi + +echo "$as_me:$LINENO: checking for --enable-zip" >&5 +echo $ECHO_N "checking for --enable-zip... $ECHO_C" >&6 +# Check whether --enable-zip or --disable-zip was given. +if test "${enable_zip+set}" = set; then + enableval="$enable_zip" + +fi; +if test x"$enable_zip" = x"no"; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define USE_BUILTIN_ZIP 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for --enable-fax" >&5 +echo $ECHO_N "checking for --enable-fax... $ECHO_C" >&6 +# Check whether --enable-fax or --disable-fax was given. +if test "${enable_fax+set}" = set; then + enableval="$enable_fax" + +fi; +if test x"$enable_fax" = x"no"; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define USE_BUILTIN_FAXE 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for --enable-gif" >&5 +echo $ECHO_N "checking for --enable-gif... $ECHO_C" >&6 +# Check whether --enable-gif or --disable-gif was given. +if test "${enable_gif+set}" = set; then + enableval="$enable_gif" + +fi; +if test x"$enable_gif" = x"yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define USE_IN_GIF 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define USE_OUT_GIF 1 +_ACEOF + + { echo "$as_me:$LINENO: WARNING: GIF is a resistered trademark of Compuserve; ask permission from them to use it!" >&5 +echo "$as_me: WARNING: GIF is a resistered trademark of Compuserve; ask permission from them to use it!" >&2;} +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +CXXFLAGS=" " +CCC="$CCC g++" +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C++ compiler default output" >&5 +echo $ECHO_N "checking for C++ compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 +echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +: +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +if test x"$ac_cv_prog_cxx_g" = xyes; then GFLAG=-g; else GFLAG=""; fi + + +echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -fsigned-char" >&5 +echo $ECHO_N "checking whether ${CXX-g++} accepts -fsigned-char... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_fs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} -fsigned-char -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_fs=yes; +else ac_cv_prog_cxx_fs=no; fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_fs" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_fs" >&6 +if test $ac_cv_prog_cxx_fs = yes; then CXXFLAGS="$CXXFLAGS -fsigned-char"; fi + + +echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking whether ${CXX-g++} accepts -fno-rtti -fno-exceptions... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_nrne+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} -fno-rtti -fno-exceptions -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_nrne=yes; +else ac_cv_prog_cxx_nrne=no; fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_nrne" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_nrne" >&6 +if test $ac_cv_prog_cxx_nrne = yes; then CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"; fi + + + +echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -ansi -pedantic -Wall -W" >&5 +echo $ECHO_N "checking whether ${CXX-g++} accepts -ansi -pedantic -Wall -W... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_apwaw+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} -ansi -pedantic -Wall -W -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_apwaw=yes; +else ac_cv_prog_cxx_apwaw=no; fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_apwaw" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_apwaw" >&6 +if test $ac_cv_prog_cxx_apwaw = yes; then CXXFLAGSB="$CXXFLAGSB -ansi -pedantic -Wall -W"; fi + + + +echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes" >&5 +echo $ECHO_N "checking whether ${CXX-g++} accepts -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_ptscxxopts+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_ptscxxopts=yes; +else ac_cv_prog_cxx_ptscxxopts=no; fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_ptscxxopts" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_ptscxxopts" >&6 +if test $ac_cv_prog_cxx_ptscxxopts = yes; then CXXFLAGSB="$CXXFLAGSB -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes"; fi + + + + XTRA="-W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations" + CC_bak="$CC" CC="${CC:-cc} -Werror -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations" + CXX_bak="$CXX" CXX="${CXX:-c++} -Werror -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations" + echo "$as_me:$LINENO: checking for ignored -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations" >&5 +echo $ECHO_N "checking for ignored -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations... $ECHO_C" >&6 +if test "${ac_cv_pts_ignoring_nebfcmd+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_ignoring_nebfcmd=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_pts_ignoring_nebfcmd=yes +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_ignoring_nebfcmd" >&5 +echo "${ECHO_T}$ac_cv_pts_ignoring_nebfcmd" >&6 + CC="$CC_bak" + CXX="$CXX_bak" + +if test x"$ac_cv_pts_ignoring_nebfcmd" = xyes +then ac_cv_prog_cxx_nebfcmd=no +fi + + +echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -Wnested-externs -Wbad-function-cast -Wmissing-declarations" >&5 +echo $ECHO_N "checking whether ${CXX-g++} accepts -Wnested-externs -Wbad-function-cast -Wmissing-declarations... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_nebfcmd+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + echo 'void f(void);void f(void){}' > conftest.cc +if test -z "`${CXX-g++} -Wnested-externs -Wbad-function-cast -Wmissing-declarations -c conftest.cc 2>&1`" +then ac_cv_prog_cxx_nebfcmd=yes; +else ac_cv_prog_cxx_nebfcmd=no; fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_nebfcmd" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_nebfcmd" >&6 +if test $ac_cv_prog_cxx_nebfcmd = yes; then CXXFLAGSB="$CXXFLAGSB -Wnested-externs -Wbad-function-cast -Wmissing-declarations"; fi + + + + + echo "$as_me:$LINENO: checking whether gcc can link C++ code" >&5 +echo $ECHO_N "checking whether gcc can link C++ code... $ECHO_C" >&6 +if test "${ac_cv_pts_gcc_links_cxx+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + CXX_saved="$CXX" + LIBS_saved="$LIBS" + CXX_new="$CXX" + ac_ext_saved="$ac_ext" + cat > conftest.$ac_ext <<EOF +#line 1964 "configure" +#include "confdefs.h" + + #include <stdio.h> + struct B { virtual int f()=0; int x() { return f(); } }; + struct C1: public B { virtual int f() {return 1;}}; + struct C2: public B { virtual int f() {return 2;}}; + C1 global; /* global.x() will cause segfault in i386-uclibc-gcc */ + +int main() { + + /* vvv (B*) cast added for gcc-3.1 */ + B *p=(ferror(stderr))?(B*)new C1():(B*)new C2(); /* Imp: argc... */ + /* if (p==0) throw long(42); */ /* doesn't work with -fno-rtti */ + int ok2=p->x()==2; + delete p; + return !(ok2 && global.x()==1); + +; return 0; } +EOF +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + + + case x"$CC" in + xgcc-*) CXX="$CC" ;; # gcc-3.2 + x*-gcc-*) CXX="$CC" ;; # + x*-gcc) CXX="$CC" ;; # i386-uclibc-gcc + *) CXX=gcc ;; + esac + CXX_new="$CXX" + ac_ext="$ac_objext" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} && ./conftest${ac_exeext} + then ac_cv_pts_gcc_links_cxx=yes + else + LIBS="$LIBS_saved c_lgcc.cpp" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} && ./conftest${ac_exeext} + then ac_cv_pts_gcc_links_cxx=yes-with-help + else + LIBS="$LIBS_saved c_lgcc3.cpp" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} && ./conftest${ac_exeext} + then ac_cv_pts_gcc_links_cxx=yes-with-help3 + else ac_cv_pts_gcc_links_cxx=no; CXX_new="$CXX_saved"; fi + fi + fi + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + + ac_cv_pts_gcc_links_cxx=compilation-failed +fi +rm -f conftest* + CXX="$CXX_saved" + LIBS="$LIBS_saved" + ac_ext="$ac_ext_saved" + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_gcc_links_cxx" >&5 +echo "${ECHO_T}$ac_cv_pts_gcc_links_cxx" >&6 + + case x"$ac_cv_pts_gcc_links_cxx" in + xyes-with-help) LDXX="$CXX_new"; cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_C_LGCC_CPP_REQUIRED 1 +_ACEOF + ;; + xyes-with-help3) LDXX="$CXX_new"; cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_C_LGCC3_CPP_REQUIRED 1 +_ACEOF + ;; + xyes) LDXX="$CXX_new" ;; + xno) LDXX="$CXX_new" ;; + *) { { echo "$as_me:$LINENO: error: Compilation failed, aborting." >&5 +echo "$as_me: error: Compilation failed, aborting." >&2;} + { (exit 1); exit 1; }; } ;; + esac + + +# Extract the first word of "cjpeg", so it can be a program name with args. +set dummy cjpeg; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_cjpeg+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_cjpeg" in + /*) + ac_cv_path_pts_cjpeg="$pts_cjpeg" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_cjpeg="$pts_cjpeg" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_cjpeg="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_cjpeg="$ac_cv_path_pts_cjpeg" +if test -n "$pts_cjpeg"; then + echo "$as_me:$LINENO: result: $pts_cjpeg" >&5 +echo "${ECHO_T}$pts_cjpeg" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_cjpeg" = x; then + { echo "$as_me:$LINENO: WARNING: cjpeg would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: cjpeg would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: cjpeg is required for /Compression/IJG" >&5 +echo "$as_me: WARNING: cjpeg is required for /Compression/IJG" >&2;} +fi + +# Extract the first word of "djpeg", so it can be a program name with args. +set dummy djpeg; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_djpeg+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_djpeg" in + /*) + ac_cv_path_pts_djpeg="$pts_djpeg" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_djpeg="$pts_djpeg" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_djpeg="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_djpeg="$ac_cv_path_pts_djpeg" +if test -n "$pts_djpeg"; then + echo "$as_me:$LINENO: result: $pts_djpeg" >&5 +echo "${ECHO_T}$pts_djpeg" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_djpeg" = x; then + { echo "$as_me:$LINENO: WARNING: djpeg would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: djpeg would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: djpeg is required for loading JPEG files" >&5 +echo "$as_me: WARNING: djpeg is required for loading JPEG files" >&2;} +fi + +# Extract the first word of "tif22pnm", so it can be a program name with args. +set dummy tif22pnm; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_tif22pnm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_tif22pnm" in + /*) + ac_cv_path_pts_tif22pnm="$pts_tif22pnm" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_tif22pnm="$pts_tif22pnm" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_tif22pnm="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_tif22pnm="$ac_cv_path_pts_tif22pnm" +if test -n "$pts_tif22pnm"; then + echo "$as_me:$LINENO: result: $pts_tif22pnm" >&5 +echo "${ECHO_T}$pts_tif22pnm" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_tif22pnm" = x; then + { echo "$as_me:$LINENO: WARNING: tif22pnm would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: tif22pnm would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: tif22pnm is required for loading TIFF files" >&5 +echo "$as_me: WARNING: tif22pnm is required for loading TIFF files" >&2;} +fi + +# Extract the first word of "tifftopnm", so it can be a program name with args. +set dummy tifftopnm; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_tifftopnm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_tifftopnm" in + /*) + ac_cv_path_pts_tifftopnm="$pts_tifftopnm" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_tifftopnm="$pts_tifftopnm" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_tifftopnm="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_tifftopnm="$ac_cv_path_pts_tifftopnm" +if test -n "$pts_tifftopnm"; then + echo "$as_me:$LINENO: result: $pts_tifftopnm" >&5 +echo "${ECHO_T}$pts_tifftopnm" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_tifftopnm" = x; then + { echo "$as_me:$LINENO: WARNING: tifftopnm would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: tifftopnm would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: tifftopnm might become useful for loading TIFF files" >&5 +echo "$as_me: WARNING: tifftopnm might become useful for loading TIFF files" >&2;} +fi + +# Extract the first word of "pngtopnm", so it can be a program name with args. +set dummy pngtopnm; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_pngtopnm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_pngtopnm" in + /*) + ac_cv_path_pts_pngtopnm="$pts_pngtopnm" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_pngtopnm="$pts_pngtopnm" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_pngtopnm="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_pngtopnm="$ac_cv_path_pts_pngtopnm" +if test -n "$pts_pngtopnm"; then + echo "$as_me:$LINENO: result: $pts_pngtopnm" >&5 +echo "${ECHO_T}$pts_pngtopnm" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_pngtopnm" = x; then + { echo "$as_me:$LINENO: WARNING: pngtopnm would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: pngtopnm would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: pngtopnm might become useful for loading PNG files" >&5 +echo "$as_me: WARNING: pngtopnm might become useful for loading PNG files" >&2;} +fi + +# Extract the first word of "gs", so it can be a program name with args. +set dummy gs; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_gs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_gs" in + /*) + ac_cv_path_pts_gs="$pts_gs" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_gs="$pts_gs" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_gs="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_gs="$ac_cv_path_pts_gs" +if test -n "$pts_gs"; then + echo "$as_me:$LINENO: result: $pts_gs" >&5 +echo "${ECHO_T}$pts_gs" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_gs" = x; then + { echo "$as_me:$LINENO: WARNING: gs would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: gs would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: gs is recommended for viewing PS files, and might become recommended for /Compression/ZIP" >&5 +echo "$as_me: WARNING: gs is recommended for viewing PS files, and might become recommended for /Compression/ZIP" >&2;} +fi + +# Extract the first word of "lzw_codec", so it can be a program name with args. +set dummy lzw_codec; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_lzw_codec+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_lzw_codec" in + /*) + ac_cv_path_pts_lzw_codec="$pts_lzw_codec" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_lzw_codec="$pts_lzw_codec" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_lzw_codec="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_lzw_codec="$ac_cv_path_pts_lzw_codec" +if test -n "$pts_lzw_codec"; then + echo "$as_me:$LINENO: result: $pts_lzw_codec" >&5 +echo "${ECHO_T}$pts_lzw_codec" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_lzw_codec" = x; then + { echo "$as_me:$LINENO: WARNING: lzw_codec would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: lzw_codec would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: lzw_codec might become recommended for /Compression/LZW" >&5 +echo "$as_me: WARNING: lzw_codec might become recommended for /Compression/LZW" >&2;} +fi + +# Extract the first word of "gzip", so it can be a program name with args. +set dummy gzip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_gzip+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_gzip" in + /*) + ac_cv_path_pts_gzip="$pts_gzip" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_gzip="$pts_gzip" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_gzip="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_gzip="$ac_cv_path_pts_gzip" +if test -n "$pts_gzip"; then + echo "$as_me:$LINENO: result: $pts_gzip" >&5 +echo "${ECHO_T}$pts_gzip" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_gzip" = x; then + { echo "$as_me:$LINENO: WARNING: gzip would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: gzip would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: gzip might become useful for /Compression/ZIP" >&5 +echo "$as_me: WARNING: gzip might become useful for /Compression/ZIP" >&2;} +fi + +# Extract the first word of "zip", so it can be a program name with args. +set dummy zip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_zip+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_zip" in + /*) + ac_cv_path_pts_zip="$pts_zip" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_zip="$pts_zip" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_zip="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_zip="$ac_cv_path_pts_zip" +if test -n "$pts_zip"; then + echo "$as_me:$LINENO: result: $pts_zip" >&5 +echo "${ECHO_T}$pts_zip" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_zip" = x; then + { echo "$as_me:$LINENO: WARNING: zip would provide increased functionality to this program:" >&5 +echo "$as_me: WARNING: zip would provide increased functionality to this program:" >&2;} + { echo "$as_me:$LINENO: WARNING: zip might become useful for /Compression/ZIP" >&5 +echo "$as_me: WARNING: zip might become useful for /Compression/ZIP" >&2;} +fi + +# Extract the first word of "bash", so it can be a program name with args. +set dummy bash; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_bash+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_bash" in + /*) + ac_cv_path_pts_bash="$pts_bash" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_bash="$pts_bash" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_bash="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_bash="$ac_cv_path_pts_bash" +if test -n "$pts_bash"; then + echo "$as_me:$LINENO: result: $pts_bash" >&5 +echo "${ECHO_T}$pts_bash" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_bash" = x; then + { echo "$as_me:$LINENO: WARNING: bash is required:" >&5 +echo "$as_me: WARNING: bash is required:" >&2;} + { { echo "$as_me:$LINENO: error: bash is required for compiling this program" >&5 +echo "$as_me: error: bash is required for compiling this program" >&2;} + { (exit 1); exit 1; }; } +fi + +# Extract the first word of "make", so it can be a program name with args. +set dummy make; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_make+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_make" in + /*) + ac_cv_path_pts_make="$pts_make" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_make="$pts_make" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_make="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_make="$ac_cv_path_pts_make" +if test -n "$pts_make"; then + echo "$as_me:$LINENO: result: $pts_make" >&5 +echo "${ECHO_T}$pts_make" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_make" = x; then + { echo "$as_me:$LINENO: WARNING: make is required:" >&5 +echo "$as_me: WARNING: make is required:" >&2;} + { { echo "$as_me:$LINENO: error: make is required for compiling this program" >&5 +echo "$as_me: error: make is required for compiling this program" >&2;} + { (exit 1); exit 1; }; } +fi + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_pts_perl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case "$pts_perl" in + /*) + ac_cv_path_pts_perl="$pts_perl" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_pts_perl="$pts_perl" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -x $ac_dir/$ac_word; then + ac_cv_path_pts_perl="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +pts_perl="$ac_cv_path_pts_perl" +if test -n "$pts_perl"; then + echo "$as_me:$LINENO: result: $pts_perl" >&5 +echo "${ECHO_T}$pts_perl" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x"$ac_cv_path_pts_perl" = x; then + { echo "$as_me:$LINENO: WARNING: perl is required:" >&5 +echo "$as_me: WARNING: perl is required:" >&2;} + { { echo "$as_me:$LINENO: error: perl is required for compiling this program" >&5 +echo "$as_me: error: perl is required for compiling this program" >&2;} + { (exit 1); exit 1; }; } +fi + + +#AC_CHECK_PROG(ac_pts_cjpeg, cjpeg, yes) + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + 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 +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + + echo "$as_me:$LINENO: checking whether cc supports prototypes" >&5 +echo $ECHO_N "checking whether cc supports prototypes... $ECHO_C" >&6 +if test "${ac_cv_pts_have_prototypes+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int foo(int x) { return 0; } +int +main () +{ +return foo(10); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_prototypes=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_pts_have_prototypes=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_prototypes" >&5 +echo "${ECHO_T}$ac_cv_pts_have_prototypes" >&6 + if test x"$ac_cv_pts_have_prototypes" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PROTOTYPES 1 +_ACEOF + + fi + + + + + echo "$as_me:$LINENO: checking whether cc compiles standard C" >&5 +echo $ECHO_N "checking whether cc compiles standard C... $ECHO_C" >&6 +if test "${ac_cv_pts_have_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#if defined(__STDC__) && __STDC__ + /* note: the starting spaces are deliberate in the next line */ + #if 0 + nope + #endif +#else +#if defined(__cplusplus) && __cplusplus + #if 0 + nope + #endif +#else + nope +#endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "nope" >/dev/null 2>&1; then + ac_cv_pts_have_stdc=no +else + + if test x"$ac_cv_pts_have_prototypes" = xyes; then + ac_cv_pts_have_stdc=yes + else + ac_cv_pts_have_stdc=no + fi + +fi +rm -f conftest* + + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_stdc" >&5 +echo "${ECHO_T}$ac_cv_pts_have_stdc" >&6 + if test x"$ac_cv_pts_have_stdc" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_STDC 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for switch(enum) bug" >&5 +echo $ECHO_N "checking for switch(enum) bug... $ECHO_C" >&6 +if test "${ac_cv_pts_have_switch_enum_bug+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_SWITCH_ENUM_BUG" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_SWITCH_ENUM_BUG" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +enum what { foo, bar }; +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + switch ((enum what)1) { + case foo: return 1; + case bar: return 0; + } + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_switch_enum_bug=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_have_switch_enum_bug=yes +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_switch_enum_bug" >&5 +echo "${ECHO_T}$ac_cv_pts_have_switch_enum_bug" >&6 + if test x"$ac_cv_pts_have_switch_enum_bug" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_SWITCH_ENUM_BUG 1 +_ACEOF + + fi + + + + echo "$as_me:$LINENO: checking for ASCII system" >&5 +echo $ECHO_N "checking for ASCII system... $ECHO_C" >&6 +if test "${ac_cv_pts_have_ascii_system+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#if 'a'!=97 || '!'!=33 +#error You need an ASCII system to compile this. +#else +ascii_yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "ascii_yes" >/dev/null 2>&1; then + ac_cv_pts_have_ascii_system=yes +else + ac_cv_pts_have_ascii_system=no + +fi +rm -f conftest* + + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_ascii_system" >&5 +echo "${ECHO_T}$ac_cv_pts_have_ascii_system" >&6 + if test x"$ac_cv_pts_have_ascii_system" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ASCII_SYSTEM 1 +_ACEOF + + fi + + if test x"$ac_cv_pts_have_ascii_system" != xyes; then + { { echo "$as_me:$LINENO: error: you need an ASCII system" >&5 +echo "$as_me: error: you need an ASCII system" >&2;} + { (exit 1); exit 1; }; } + fi + +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_const=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + + echo "$as_me:$LINENO: checking for C keyword volatile" >&5 +echo $ECHO_N "checking for C keyword volatile... $ECHO_C" >&6 +if test "${ac_cv_pts_have_volatile+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +volatile int i; +int +main () +{ +i=5; i++; return i-6; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_volatile=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_pts_have_volatile=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_volatile" >&5 +echo "${ECHO_T}$ac_cv_pts_have_volatile" >&6 + if test x"$ac_cv_pts_have_volatile" = xno; then + cat >>confdefs.h <<\_ACEOF +#define volatile +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking whether c++ supports static const" >&5 +echo $ECHO_N "checking whether c++ supports static const... $ECHO_C" >&6 +if test "${ac_cv_pts_have_static_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#undef const +class A { public: static const int i=1; }; +int +main () +{ +return A::i==0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_static_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_pts_have_static_const=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_static_const" >&5 +echo "${ECHO_T}$ac_cv_pts_have_static_const" >&6 + if test x"$ac_cv_pts_have_static_const" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STATIC_CONST 1 +_ACEOF + + fi + + + + +CXXFLAGS_save="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS -ansi" + + echo "$as_me:$LINENO: checking for working getc in stdio.h" >&5 +echo $ECHO_N "checking for working getc in stdio.h... $ECHO_C" >&6 +if test "${ac_cv_pts_getc_in_stdio+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdio.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + return argc>42? getc(stdin)*0+1:0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_getc_in_stdio=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_getc_in_stdio=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_getc_in_stdio" >&5 +echo "${ECHO_T}$ac_cv_pts_getc_in_stdio" >&6 + if test x"$ac_cv_pts_getc_in_stdio" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_getc_in_stdio 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working fgetc in stdio.h" >&5 +echo $ECHO_N "checking for working fgetc in stdio.h... $ECHO_C" >&6 +if test "${ac_cv_pts_fgetc_in_stdio+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdio.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + return argc>42?fgetc(stdin)*0+1:0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_fgetc_in_stdio=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_fgetc_in_stdio=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_fgetc_in_stdio" >&5 +echo "${ECHO_T}$ac_cv_pts_fgetc_in_stdio" >&6 + if test x"$ac_cv_pts_fgetc_in_stdio" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_fgetc_in_stdio 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working putc in stdio.h" >&5 +echo $ECHO_N "checking for working putc in stdio.h... $ECHO_C" >&6 +if test "${ac_cv_pts_putc_in_stdio+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdio.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + return argc>42? putc(' ',stdout)*0+1:0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_putc_in_stdio=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_putc_in_stdio=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_putc_in_stdio" >&5 +echo "${ECHO_T}$ac_cv_pts_putc_in_stdio" >&6 + if test x"$ac_cv_pts_putc_in_stdio" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_putc_in_stdio 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working fputc in stdio.h" >&5 +echo $ECHO_N "checking for working fputc in stdio.h... $ECHO_C" >&6 +if test "${ac_cv_pts_fputc_in_stdio+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdio.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + return argc>42?fputc(' ',stdout)*0+1:0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_fputc_in_stdio=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_fputc_in_stdio=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_fputc_in_stdio" >&5 +echo "${ECHO_T}$ac_cv_pts_fputc_in_stdio" >&6 + if test x"$ac_cv_pts_fputc_in_stdio" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_fputc_in_stdio 1 +_ACEOF + + fi + +CXXFLAGS="$CXXFLAGS_save" + + + echo "$as_me:$LINENO: checking for working sprintf in stdio.h" >&5 +echo $ECHO_N "checking for working sprintf in stdio.h... $ECHO_C" >&6 +if test "${ac_cv_pts_sprintf_in_stdio+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdio.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char s[42]="X"; sprintf(s, "Hello, World!"); return *s!='H'; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_sprintf_in_stdio=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_sprintf_in_stdio=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_sprintf_in_stdio" >&5 +echo "${ECHO_T}$ac_cv_pts_sprintf_in_stdio" >&6 + if test x"$ac_cv_pts_sprintf_in_stdio" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_sprintf_in_stdio 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working atoi in stdlib.h" >&5 +echo $ECHO_N "checking for working atoi in stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_pts_atoi_in_stdlib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdlib.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + return atoi("42")!=42; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_atoi_in_stdlib=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_atoi_in_stdlib=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_atoi_in_stdlib" >&5 +echo "${ECHO_T}$ac_cv_pts_atoi_in_stdlib" >&6 + if test x"$ac_cv_pts_atoi_in_stdlib" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_atoi_in_stdlib 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working write in unistd.h" >&5 +echo $ECHO_N "checking for working write in unistd.h... $ECHO_C" >&6 +if test "${ac_cv_pts_write_in_unistd+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <unistd.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + return write(1,"what",0)!=0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_write_in_unistd=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_write_in_unistd=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_write_in_unistd" >&5 +echo "${ECHO_T}$ac_cv_pts_write_in_unistd" >&6 + if test x"$ac_cv_pts_write_in_unistd" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_write_in_unistd 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working system in stdlib.h" >&5 +echo $ECHO_N "checking for working system in stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_pts_system_in_stdlib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdlib.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + /*>255 OK*/return system("true")!=0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_system_in_stdlib=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_system_in_stdlib=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_system_in_stdlib" >&5 +echo "${ECHO_T}$ac_cv_pts_system_in_stdlib" >&6 + if test x"$ac_cv_pts_system_in_stdlib" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_system_in_stdlib 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working lstat in sys/stat.h" >&5 +echo $ECHO_N "checking for working lstat in sys/stat.h... $ECHO_C" >&6 +if test "${ac_cv_pts_lstat_in_sys_stat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <sys/stat.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + struct stat st; return 0!=lstat("/",&st); + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_lstat_in_sys_stat=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_lstat_in_sys_stat=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_lstat_in_sys_stat" >&5 +echo "${ECHO_T}$ac_cv_pts_lstat_in_sys_stat" >&6 + if test x"$ac_cv_pts_lstat_in_sys_stat" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_lstat_in_sys_stat 1 +_ACEOF + + fi + + + + echo "$as_me:$LINENO: checking for working strcpy in string.h" >&5 +echo $ECHO_N "checking for working strcpy in string.h... $ECHO_C" >&6 +if test "${ac_cv_pts_strcpy_in_string+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <string.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H'; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_strcpy_in_string=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_strcpy_in_string=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_strcpy_in_string" >&5 +echo "${ECHO_T}$ac_cv_pts_strcpy_in_string" >&6 + if test x"$ac_cv_pts_strcpy_in_string" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_strcpy_in_string 1 +_ACEOF + + fi + + ac_cv_pts_have_string=no + if test x"$ac_cv_pts_strcpy_in_string" = xyes; then + ac_cv_pts_have_string=yes + ac_cv_pts_string_header=string + else + + echo "$as_me:$LINENO: checking for working strcpy in strings.h" >&5 +echo $ECHO_N "checking for working strcpy in strings.h... $ECHO_C" >&6 +if test "${ac_cv_pts_strcpy_in_strings+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <strings.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H'; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_strcpy_in_strings=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_strcpy_in_strings=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_strcpy_in_strings" >&5 +echo "${ECHO_T}$ac_cv_pts_strcpy_in_strings" >&6 + if test x"$ac_cv_pts_strcpy_in_strings" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_strcpy_in_strings 1 +_ACEOF + + fi + + if test x"$ac_cv_pts_strcpy_in_strings" = xyes; then + ac_cv_pts_have_string=yes + ac_cv_pts_string_header=strings + fi + fi + if test x"$ac_cv_pts_have_string" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_STRING 1 +_ACEOF + + fi + CC_bak="$CC" + CC="${CC:-cc} -Werror" + + echo "$as_me:$LINENO: checking for working memcpy in $ac_cv_pts_string_header.h" >&5 +echo $ECHO_N "checking for working memcpy in $ac_cv_pts_string_header.h... $ECHO_C" >&6 +if test "${ac_cv_pts_memcpy_in_stringxs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <$ac_cv_pts_string_header.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char s[42]="X"; memcpy(s, "Hello, World!", 2); return *s!='H'; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_memcpy_in_stringxs=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_memcpy_in_stringxs=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_memcpy_in_stringxs" >&5 +echo "${ECHO_T}$ac_cv_pts_memcpy_in_stringxs" >&6 + if test x"$ac_cv_pts_memcpy_in_stringxs" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_memcpy_in_stringxs 1 +_ACEOF + + fi + + CC="$CC_bak" + + echo "$as_me:$LINENO: checking whether memcmp and memcpy are built-in" >&5 +echo $ECHO_N "checking whether memcmp and memcpy are built-in... $ECHO_C" >&6 +if test "${ac_cv_pts_have_memcmpy_builtin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_cv_pts_have_memcmpy_builtin=no + if test x"$ac_cv_pts_have_string" = xyes; then + if test x"$ac_cv_pts_memcpy_in_stringxs" = xno; then + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_STRING" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_STRING" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char s[42]="X"; memcpy(s, "Hello, World!", 2); return memcmp(s, "H", 1)!=0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_memcmpy_builtin=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: missing memcmp and memcpy" >&5 +echo "$as_me: error: missing memcmp and memcpy" >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + fi + fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_memcmpy_builtin" >&5 +echo "${ECHO_T}$ac_cv_pts_have_memcmpy_builtin" >&6 + if test x"$ac_cv_pts_have_memcmpy_builtin" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_MEMCMPY_BUILTIN 1 +_ACEOF + + fi + + + + echo "$as_me:$LINENO: checking for working malloc in stdlib.h" >&5 +echo $ECHO_N "checking for working malloc in stdlib.h... $ECHO_C" >&6 +if test "${ac_cv_pts_malloc_in_stdlib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <stdlib.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char *p=(char*)malloc(42); if (p!=0) free((void*)p); return p==0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_malloc_in_stdlib=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_malloc_in_stdlib=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_malloc_in_stdlib" >&5 +echo "${ECHO_T}$ac_cv_pts_malloc_in_stdlib" >&6 + if test x"$ac_cv_pts_malloc_in_stdlib" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_malloc_in_stdlib 1 +_ACEOF + + fi + + if test x"$ac_cv_pts_malloc_in_stdlib" != xyes; then + + echo "$as_me:$LINENO: checking for working malloc in malloc.h" >&5 +echo $ECHO_N "checking for working malloc in malloc.h... $ECHO_C" >&6 +if test "${ac_cv_pts_malloc_in_malloc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +#undef const +#undef volatile +#undef inline +#include <malloc.h> +#include "confdefs.h" +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + char *p=malloc(42); if (p!=0) free(p); return p==0; + return 1; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_malloc_in_malloc=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_malloc_in_malloc=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_malloc_in_malloc" >&5 +echo "${ECHO_T}$ac_cv_pts_malloc_in_malloc" >&6 + if test x"$ac_cv_pts_malloc_in_malloc" = xyes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_malloc_in_malloc 1 +_ACEOF + + fi + + fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo "$as_me:$LINENO: checking for working alloca.h" >&5 +echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6 +if test "${ac_cv_working_alloca_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <alloca.h> +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_working_alloca_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_working_alloca_h=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 +echo "${ECHO_T}$ac_cv_working_alloca_h" >&6 +if test $ac_cv_working_alloca_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for alloca" >&5 +echo $ECHO_N "checking for alloca... $ECHO_C" >&6 +if test "${ac_cv_func_alloca_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_alloca_works=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_alloca_works=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 +echo "${ECHO_T}$ac_cv_func_alloca_works" >&6 + +if test $ac_cv_func_alloca_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA 1 +_ACEOF + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=alloca.$ac_objext + +cat >>confdefs.h <<\_ACEOF +#define C_ALLOCA 1 +_ACEOF + + +echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 +echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6 +if test "${ac_cv_os_cray+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 +echo "${ECHO_T}$ac_cv_os_cray" >&6 +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 +echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6 +if test "${ac_cv_c_stack_direction+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} + +int +main () +{ + exit (find_stack_direction () < 0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_stack_direction=1 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_stack_direction=-1 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 +echo "${ECHO_T}$ac_cv_c_stack_direction" >&6 + +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + + + echo "$as_me:$LINENO: checking for width of printf .g" >&5 +echo $ECHO_N "checking for width of printf .g... $ECHO_C" >&6 +if test "${ac_cv_pts_cfg_printfglen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CFG_PRINTFGLEN" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CFG_PRINTFGLEN" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#define __USE_SVID 1 +#define __USE_GNU 1 +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + unsigned i; + char tmp[64], pat[10], *p; + FILE *f=fopen("conftestval","w"); + if (!f) return 1; + for (i=1;i<61;i++) { + sprintf(pat, "%%.%ug", i); + sprintf(tmp, pat, 1.0/3); + if (tmp[0]=='0' && tmp[1]=='.') { + p=tmp+2; while (*p=='3') p++; + if (*p!='\0') break; + } + } + if (i>1) fprintf(f,".%u",i-1); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_cfg_printfglen=\""`cat conftestval`"\" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_cfg_printfglen="" +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + test x"$ac_cv_pts_cfg_printfglen" = x && ac_cv_pts_cfg_printfglen=no + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_cfg_printfglen" >&5 +echo "${ECHO_T}$ac_cv_pts_cfg_printfglen" >&6 + if test x"$ac_cv_pts_cfg_printfglen" = xno; then :; else + cat >>confdefs.h <<_ACEOF +#define PTS_CFG_PRINTFGLEN $ac_cv_pts_cfg_printfglen +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for tmpdir" >&5 +echo $ECHO_N "checking for tmpdir... $ECHO_C" >&6 +if test "${ac_cv_pts_cfg_p_tmpdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CFG_P_TMPDIR" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CFG_P_TMPDIR" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#define __USE_SVID 1 +#define __USE_GNU 1 +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + FILE *f=fopen("conftestval","w"); + if (!f) return 1; + fputs(P_tmpdir,f); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_cfg_p_tmpdir=\""`cat conftestval`"\" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_cfg_p_tmpdir=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_cfg_p_tmpdir" >&5 +echo "${ECHO_T}$ac_cv_pts_cfg_p_tmpdir" >&6 + cat >>confdefs.h <<_ACEOF +#define PTS_CFG_P_TMPDIR $ac_cv_pts_cfg_p_tmpdir +_ACEOF + + + + echo "$as_me:$LINENO: checking for binary popen_" >&5 +echo $ECHO_N "checking for binary popen_... $ECHO_C" >&6 +if test "${ac_cv_pts_have_popen_+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_POPEN_" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_POPEN_" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */ +#define _POSIX_SOURCE 1 /* popen() */ +#define _POSIX_C_SOURCE 2 /* popen() */ +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ FILE *p=popen("echo Ko rt5","r"); + int i; + (void)argc; (void)argv; + if (p==0) return 1; + if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2; + if (getc(p)!='r' || getc(p)!='t') return 3; + if (getc(p)!='f'-'a'+'0') return 4; + if (getc(p)!='\n') return 5; + if (getc(p)!=-1) return 6; + if (0!=pclose(p)) return 7; + + p=popen("cat >conftestval","w"); + if (p==0) return 31; + for (i=0;i<666;i++) putc(i,p); + if (ferror(p)) return 32; + if (0!=pclose(p)) return 33; + p=fopen("conftestval","rb"); + if (p==0) return 34; + for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35; + if (fclose(p)!=0) return 36; + + return 0; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_popen_=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_have_popen_=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_popen_" >&5 +echo "${ECHO_T}$ac_cv_pts_have_popen_" >&6 + if test x"$ac_cv_pts_have_popen_" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_POPEN_ 1 +_ACEOF + + fi + +if test $ac_cv_pts_have_popen_ = yes; then + ac_cv_pts_have_popen_b=no +fi + + echo "$as_me:$LINENO: checking for binary popen_b" >&5 +echo $ECHO_N "checking for binary popen_b... $ECHO_C" >&6 +if test "${ac_cv_pts_have_popen_b+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_POPEN_B" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_POPEN_B" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */ +#define _POSIX_SOURCE 1 /* popen() */ +#define _POSIX_C_SOURCE 2 /* popen() */ +#include <stdio.h> + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ FILE *p=popen("echo Ko rt5","rb"); + int i; + (void)argc; (void)argv; + if (p==0) return 1; + if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2; + if (getc(p)!='r' || getc(p)!='t') return 3; + if (getc(p)!='f'-'a'+'0') return 4; + if (getc(p)!='\n') return 5; + if (getc(p)!=-1) return 6; + if (0!=pclose(p)) return 7; + + p=popen("cat >conftestval","wb"); + if (p==0) return 31; + for (i=0;i<666;i++) putc(i,p); + if (ferror(p)) return 32; + if (0!=pclose(p)) return 33; + p=fopen("conftestval","rb"); + if (p==0) return 34; + for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35; + if (fclose(p)!=0) return 36; + + return 0; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_have_popen_b=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_have_popen_b=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_have_popen_b" >&5 +echo "${ECHO_T}$ac_cv_pts_have_popen_b" >&6 + if test x"$ac_cv_pts_have_popen_b" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_POPEN_B 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for working vsnprintf" >&5 +echo $ECHO_N "checking for working vsnprintf... $ECHO_C" >&6 +if test "${ac_cv_pts_vsnprintf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#if 0 /* autoconf-2.54 */ + extern "C" void std::exit (int) throw (); using std::exit; + extern "C" void std::exit (int); using std::exit; + extern "C" void exit (int) throw (); + extern "C" void exit (int); + void exit (int); +#endif +#ifdef __cplusplus +extern "C" void exit(int); +#endif +#define _BSD_SOURCE 1 /* vsnprintf */ +#define _POSIX_SOURCE 1 +#define _POSIX_C_SOURCE 2 +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +static int myprintf(int max, char *dstr, char *fmt, ...) { + int i; + va_list ap; + #if defined(__STDC__) + va_start(ap, fmt); + #else + va_start(ap); + #endif + i=vsnprintf(dstr, max, fmt, ap); + va_end(ap); + return i; +} + +int c99t[]={13,9,10,10,10}, oldt[]={-1,9,-1,0,-1}, sun99t[]={13,9,10,-1,10}; +/* wincrtt[]={-1,9,10,-1,-1}, but it modifies the string in a completely + * bogus way (passes 1 test of 5) + */ + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ char buf[40]; + int i; + int g[5], gg; + int *t=oldt; + FILE *f=fopen("conftestval","w"); + (void)argc; + (void)argv; + + if (f) { + for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='X'; buf[i]='\0'; + i=myprintf(10, buf, "%s-%ld", "Alma", -1234567L); + if (i==c99t[0]) t=c99t; /* oldt[0]!=c99t[0] */ + g[0]=(i==t[0] && 0==memcmp(buf, "Alma--123\0X", 11)); + /* printf("(%s) %d %d\n", buf, i, g[0]); */ + + for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Y'; buf[i]='\0'; + i=myprintf(10, buf, "%s-%ld", "Alma", -123L); + g[1]=(i==t[1] && 0==memcmp(buf, "Alma--123\0Y", 11)); + /* printf("(%s) %d %d\n", buf, i, g[1]); */ + + for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Z'; buf[i]='\0'; + i=myprintf(10, buf, "%s-%ld", "Alma", -1234L); + g[2]=(i==t[2] && 0==memcmp(buf, "Alma--123\0Z", 11)); + /* printf("(%s) %d %d\n", buf, i, g[2]); */ + + buf[0]='#'; + i=myprintf(0, buf, "%s-%ld", "Alma", -1234L); + if (t==c99t && i==sun99t[3]) t=sun99t; + g[3]=(i==t[3] && buf[0]=='#'); + /* printf("(%s) %d %d\n", buf, i, g[3]); */ + + buf[0]=buf[1]='$'; + i=myprintf(1, buf, "%s-%ld", "Alma", -1234L); + g[4]=(i==t[4] && buf[0]=='\0' && buf[1]=='$'); + /* printf("(%s) %d %d\n", buf, i, g[4]); */ + + gg=g[0] && g[1] && g[2] && g[3] && g[4]; + fputs(!gg ? "bad\n" : t==oldt ? "old\n" : t==sun99t ? "sun99\n" : "c99\n", f); + fclose(f); + } + return 0; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_vsnprintf="`cat conftestval`"; ac_cv_pts_vsnprintf="${ac_cv_pts_vsnprintf:-invalid}" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_vsnprintf=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_vsnprintf" >&5 +echo "${ECHO_T}$ac_cv_pts_vsnprintf" >&6 + if test x"$ac_cv_pts_vsnprintf" = xold; then + ac_cv_pts_have_vsnprintf=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_VSNPRINTF 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_VSNPRINTF_OLD 1 +_ACEOF + + elif test x"$ac_cv_pts_have_vsnprintf" = xc99; then + ac_cv_pts_have_vsnprintf=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_VSNPRINTF 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_VSNPRINTF_C99 1 +_ACEOF + + else + ac_cv_pts_have_vsnprintf=no + ac_cv_pts_vsnprintf=no + fi + + + echo no-original >conftestval + echo "$as_me:$LINENO: checking for working system(3)" >&5 +echo $ECHO_N "checking for working system(3)... $ECHO_C" >&6 +if test "${ac_cv_pts_systemf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <stdio.h> +#include <stdlib.h> /* system() */ + +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + (void)argc; + (void)argv; + if (0!=system("echo t >conftestval && echo \"let it\" be e >conftestval")) { + FILE *f=fopen("conftestval","w"); + if (f) { + fprintf(f,"runtime-error\n"); + fclose(f); + } + } + return 0; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_systemf="`cat conftestval`"; ac_cv_pts_systemf="${ac_cv_pts_systemf:-invalid}" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_systemf=compile-error +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + # echo "($ac_cv_pts_systemf)" + # if test x"$ac_cv_pts_systemf" = x'"let it" be e '; then + if test x"$ac_cv_pts_systemf" = x't && echo "let it" be e '; then + # Win32 COMMAND.COM + ac_cv_pts_systemf=win32 + elif test x"$ac_cv_pts_systemf" = x"let it be e"; then + # UNIX /bin/sh + ac_cv_pts_systemf=unix + fi + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_systemf" >&5 +echo "${ECHO_T}$ac_cv_pts_systemf" >&6 + if test x"$ac_cv_pts_systemf" = xwin32; then + ac_cv_pts_have_systemf=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_SYSTEMF 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_SYSTEMF_WIN32 1 +_ACEOF + + elif test x"$ac_cv_pts_systemf" = xunix; then + ac_cv_pts_have_systemf=yes + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_SYSTEMF 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_SYSTEMF_UNIX 1 +_ACEOF + + elif test x"$ac_cv_pts_systemf" = x"invalid"; then + ac_cv_pts_have_systemf=no + elif test x"$ac_cv_pts_systemf" = x"compile-error"; then + ac_cv_pts_have_systemf=no + elif test x"$ac_cv_pts_systemf" = x"runtime-error"; then + ac_cv_pts_have_systemf=no + elif test x"$ac_cv_pts_systemf" = x"no-original"; then + ac_cv_pts_have_systemf=no + else + ac_cv_pts_have_systemf=yes + # ac_cv_pts_systemf=other + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_SYSTEMF 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define HAVE_PTS_SYSTEMF_OTHER 1 +_ACEOF + + fi + + + + + + +echo "$as_me:$LINENO: checking whether char is unsigned" >&5 +echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6 +if test "${ac_cv_c_char_unsigned+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$GCC" = yes; then + # GCC predefines this symbol on systems where it applies. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __CHAR_UNSIGNED__ + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then + ac_cv_c_char_unsigned=yes +else + ac_cv_c_char_unsigned=no +fi +rm -f conftest* + +else +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_C_CHAR_UNSIGNED" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_C_CHAR_UNSIGNED" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +int main() { + volatile char c = 255; return(c < 0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_char_unsigned=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_char_unsigned=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_c_char_unsigned" >&5 +echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6 +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + cat >>confdefs.h <<\_ACEOF +#define __CHAR_UNSIGNED__ 1 +_ACEOF + +fi + + +if test x"$ac_cv_sizeof_char" = x; then +echo "$as_me:$LINENO: checking size of char" >&5 +echo $ECHO_N "checking size of char... $ECHO_C" >&6 +if test "${ac_cv_sizeof_char+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sizeof_char_p=-1;ac_cv_sizeof_short=-1;ac_cv_sizeof_int=-1 +ac_cv_sizeof_long=-1 +if test "$cross_compiling" = yes; then + ac_cv_sizeof_char=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#undef const +#undef volatile +#undef inline +#include <stdio.h> +int main(){FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "ac_cv_sizeof_char=%d\n", sizeof(char)); + fprintf(f, "ac_cv_sizeof_char_p=%d\n", sizeof(char*)); + fprintf(f, "ac_cv_sizeof_short=%d\n", sizeof(short)); + fprintf(f, "ac_cv_sizeof_int=%d\n", sizeof(int)); + fprintf(f, "ac_cv_sizeof_long=%d\n", sizeof(long)); + return 0; /* exit(0); -- return is more portable */ +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "`cat conftestval`" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi + +echo "$as_me:$LINENO: result: $ac_cv_sizeof_char" >&5 +echo "${ECHO_T}$ac_cv_sizeof_char" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR $ac_cv_sizeof_char +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR_P $ac_cv_sizeof_char_p +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + +fi + +if test $ac_cv_sizeof_char = -1; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_INTEGRALS" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_INTEGRALS" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: checking size of short" >&5 +echo $ECHO_N "checking size of short... $ECHO_C" >&6 +if test "${ac_cv_sizeof_short+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_short=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(short)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_short=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_short=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5 +echo "${ECHO_T}$ac_cv_sizeof_short" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +echo "$as_me:$LINENO: checking size of int" >&5 +echo $ECHO_N "checking size of int... $ECHO_C" >&6 +if test "${ac_cv_sizeof_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_int=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(int)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_int=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_int=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 +echo "${ECHO_T}$ac_cv_sizeof_int" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +echo "$as_me:$LINENO: checking size of long" >&5 +echo $ECHO_N "checking size of long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_long=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(long)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_long=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_long=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +echo "$as_me:$LINENO: checking size of long long" >&5 +echo $ECHO_N "checking size of long long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_long_long=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(long long)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_long_long=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_long_long=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + +if test $ac_cv_sizeof_long_long = 8 +then ac_cv_sizeof___int64=0; ac_cv_sizeof_very_long=0; fi +echo "$as_me:$LINENO: checking size of very long" >&5 +echo $ECHO_N "checking size of very long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_very_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_very_long=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(very long)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_very_long=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_very_long=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_very_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_very_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VERY_LONG $ac_cv_sizeof_very_long +_ACEOF + + +if test $ac_cv_sizeof_very_long = 8; then ac_cv_sizeof___int64=0; fi +echo "$as_me:$LINENO: checking size of __int64" >&5 +echo $ECHO_N "checking size of __int64... $ECHO_C" >&6 +if test "${ac_cv_sizeof___int64+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof___int64=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(__int64)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof___int64=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof___int64=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof___int64" >&5 +echo "${ECHO_T}$ac_cv_sizeof___int64" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF___INT64 $ac_cv_sizeof___int64 +_ACEOF + + + +# echo $ac_cv_sizeof_long_long +if test $ac_cv_sizeof_char != 1; then + { { echo "$as_me:$LINENO: error: sizeof(char)!=1" >&5 +echo "$as_me: error: sizeof(char)!=1" >&2;} + { (exit 1); exit 1; }; } +fi +if test $ac_cv_sizeof_short = 2; then + ac_cv_pts_int16_t=short +elif test $ac_cv_sizeof_int = 2; then + ac_cv_pts_int16_t=int +else + { { echo "$as_me:$LINENO: error: cannot find inttype: sizeof(inttype)==2" >&5 +echo "$as_me: error: cannot find inttype: sizeof(inttype)==2" >&2;} + { (exit 1); exit 1; }; } +fi +cat >>confdefs.h <<_ACEOF +#define PTS_INT16_T $ac_cv_pts_int16_t +_ACEOF + +if test $ac_cv_sizeof_int = 4; then + ac_cv_pts_int32_t=int +elif test $ac_cv_sizeof_long = 4; then + ac_cv_pts_int32_t=long +elif test $ac_cv_sizeof_long -lt 4; then + { { echo "$as_me:$LINENO: error: sizeof(long)<4" >&5 +echo "$as_me: error: sizeof(long)<4" >&2;} + { (exit 1); exit 1; }; } +else + { { echo "$as_me:$LINENO: error: cannot find inttype: sizeof(inttype)==4" >&5 +echo "$as_me: error: cannot find inttype: sizeof(inttype)==4" >&2;} + { (exit 1); exit 1; }; } +fi +cat >>confdefs.h <<_ACEOF +#define PTS_INT32_T $ac_cv_pts_int32_t +_ACEOF + +if test $ac_cv_sizeof_long = 8; then + ac_cv_pts_int64_t=long +elif test $ac_cv_sizeof_long_long = 8; then + ac_cv_pts_int64_t="long long" +elif test $ac_cv_sizeof_very_long = 8; then + ac_cv_pts_int64_t="very long" +elif test $ac_cv_sizeof___int64 = 8; then + ac_cv_pts_int64_t="__int64" +else + ac_cv_pts_int64_t=0 + { echo "$as_me:$LINENO: WARNING: cannot find inttype: sizeof(inttype)==8" >&5 +echo "$as_me: WARNING: cannot find inttype: sizeof(inttype)==8" >&2;} +fi +cat >>confdefs.h <<_ACEOF +#define PTS_INT64_T $ac_cv_pts_int64_t +_ACEOF + +if test $ac_cv_sizeof_long = 16; then + ac_cv_pts_int128_t=long +elif test $ac_cv_sizeof_long_long = 16; then + ac_cv_pts_int128_t="long long" +elif test $ac_cv_sizeof_very_long = 16; then + ac_cv_pts_int128_t="very long" +else + ac_cv_pts_int128_t=0 + { echo "$as_me:$LINENO: WARNING: cannot find inttype: sizeof(inttype)==16" >&5 +echo "$as_me: WARNING: cannot find inttype: sizeof(inttype)==16" >&2;} +fi +cat >>confdefs.h <<_ACEOF +#define PTS_INT128_T $ac_cv_pts_int128_t +_ACEOF + + + + +echo "$as_me:$LINENO: checking size of char *" >&5 +echo $ECHO_N "checking size of char *... $ECHO_C" >&6 +if test "${ac_cv_sizeof_char_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_char_p=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(char *)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_char_p=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_char_p=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_char_p" >&5 +echo "${ECHO_T}$ac_cv_sizeof_char_p" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR_P $ac_cv_sizeof_char_p +_ACEOF + + +echo "$as_me:$LINENO: checking size of void *" >&5 +echo $ECHO_N "checking size of void *... $ECHO_C" >&6 +if test "${ac_cv_sizeof_void_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_void_p=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(void *)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_void_p=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_void_p=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5 +echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + +echo "$as_me:$LINENO: checking for an integral type to hold a ptr" >&5 +echo $ECHO_N "checking for an integral type to hold a ptr... $ECHO_C" >&6 +if test "${ac_cv_pts_intp_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +if test $ac_cv_sizeof_char_p != $ac_cv_sizeof_void_p; then + { { echo "$as_me:$LINENO: error: $ac_cv_sizeof_char_p==sizeof(char*)!=sizeof(void*)" >&5 +echo "$as_me: error: $ac_cv_sizeof_char_p==sizeof(char*)!=sizeof(void*)" >&2;} + { (exit 1); exit 1; }; } +fi +if test $ac_cv_sizeof_char_p -le 2; then + ac_cv_pts_intp_t=$ac_cv_pts_int16_t +elif test $ac_cv_sizeof_char_p -le 4; then + ac_cv_pts_intp_t=$ac_cv_pts_int32_t +elif test $ac_cv_sizeof_char_p -le 8; then + ac_cv_pts_intp_t=$ac_cv_pts_int64_t +elif test $ac_cv_sizeof_char_p -le 16; then + ac_cv_pts_intp_t=$ac_cv_pts_int128_t +else + # :; fi; if true; then + echo "$as_me:$LINENO: result: not found!" >&5 +echo "${ECHO_T}not found!" >&6 + { { echo "$as_me:$LINENO: error: no integral type for sizeof(char*)==$ac_cv_sizeof_char_p" >&5 +echo "$as_me: error: no integral type for sizeof(char*)==$ac_cv_sizeof_char_p" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +cat >>confdefs.h <<_ACEOF +#define PTS_INTP_T $ac_cv_pts_intp_t +_ACEOF + +echo "$as_me:$LINENO: result: $ac_cv_pts_intp_t" >&5 +echo "${ECHO_T}$ac_cv_pts_intp_t" >&6 +echo "$as_me:$LINENO: checking for ptr <-> integral conversion" >&5 +echo $ECHO_N "checking for ptr <-> integral conversion... $ECHO_C" >&6 +if test "${ac_cv_pts_intp_ok+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_POINTERS" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_POINTERS" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* #include "confdefs.h" -- automatic */ +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +/* #ifndef __cplusplus; #define const; #endif -- automatic config.h */ + {char const*p="The quick brown fox."+5; + PTS_INTP_T i; + while (*p!='r') p++; /* prevent compiler optimisations */ + i=(PTS_INTP_T)p; + while (*p!='w') p++; /* prevent compiler optimisations */ + return p!=(char*)(i+2); } + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_pts_intp_ok=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_pts_intp_ok=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +if test x"$ac_cv_pts_intp_ok" = xyes; then + cat >>confdefs.h <<\_ACEOF +#define PTS_INTP_OK 1 +_ACEOF + +fi +echo "$as_me:$LINENO: result: $ac_cv_pts_intp_ok" >&5 +echo "${ECHO_T}$ac_cv_pts_intp_ok" >&6 + + + + + + + +echo "$as_me:$LINENO: checking for integral type size_t" >&5 +echo $ECHO_N "checking for integral type size_t... $ECHO_C" >&6 +if test "${ac_cv_integral_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPEX" >&5 +echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPEX" >&2;} + { (exit 1); exit 1; }; } + +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <stdio.h> +/* #include "confdefs.h" -- automatic */ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <stdio.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#define MY_TYPE size_t +int main +#ifdef __STDC__ +(int argc, char **argv) +#else +(argc, argv) int argc; char **argv; +#endif +{ + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, 0<(MY_TYPE)-1 ? "unsigned " : "signed "); + if (sizeof(MY_TYPE)==1) fprintf(f, "char"); + else if (sizeof(MY_TYPE)==sizeof(char)) fprintf(f, "char"); + else if (sizeof(MY_TYPE)==sizeof(short)) fprintf(f, "short"); + else if (sizeof(MY_TYPE)==sizeof(int)) fprintf(f, "int"); + else if (sizeof(MY_TYPE)==sizeof(long)) fprintf(f, "long"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT16_T)) fprintf(f, "PTS_INT16_T"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT32_T)) fprintf(f, "PTS_INT32_T"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT64_T)) fprintf(f, "PTS_INT64_T"); + else if (sizeof(MY_TYPE)==sizeof(PTS_INT128_T)) fprintf(f, "PTS_INT128_T"); + else return 3; /* fprintf(f, "???"); */ + if (ferror(f)) return 2; /* printf("\n"); */ + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_integral_type_size_t="`cat conftestval`"; + +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) + if test x"unsigned" = x; then echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; { { echo "$as_me:$LINENO: error: This is fatal." >&5 +echo "$as_me: error: This is fatal." >&2;} + { (exit 1); exit 1; }; }; fi + ac_cv_integral_type_size_t="unsigned" + echo -n "substituting " + +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +cat >>confdefs.h <<_ACEOF +#define PTS_size_t $ac_cv_integral_type_size_t +_ACEOF + +echo "$as_me:$LINENO: result: $ac_cv_integral_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_integral_type_size_t" >&6 + + +echo "$as_me:$LINENO: checking size of bool" >&5 +echo $ECHO_N "checking size of bool... $ECHO_C" >&6 +if test "${ac_cv_sizeof_bool+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_bool=-1 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdio.h> +#include <sys/types.h> +int main() { + FILE *f=fopen("conftestval", "w"); + if (!f) return 1; + fprintf(f, "%d\n", sizeof(bool)); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_bool=`cat conftestval` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_sizeof_bool=0 +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_bool" >&5 +echo "${ECHO_T}$ac_cv_sizeof_bool" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_BOOL $ac_cv_sizeof_bool +_ACEOF + + + + + + ac_config_files="$ac_config_files Makehelp" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makehelp" ) CONFIG_FILES="$CONFIG_FILES Makehelp" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@ENABLE_DEBUG@,$ENABLE_DEBUG,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@GFLAG@,$GFLAG,;t t +s,@CXXFLAGSB@,$CXXFLAGSB,;t t +s,@LDXX@,$LDXX,;t t +s,@pts_cjpeg@,$pts_cjpeg,;t t +s,@pts_djpeg@,$pts_djpeg,;t t +s,@pts_tif22pnm@,$pts_tif22pnm,;t t +s,@pts_tifftopnm@,$pts_tifftopnm,;t t +s,@pts_pngtopnm@,$pts_pngtopnm,;t t +s,@pts_gs@,$pts_gs,;t t +s,@pts_lzw_codec@,$pts_lzw_codec,;t t +s,@pts_gzip@,$pts_gzip,;t t +s,@pts_zip@,$pts_zip,;t t +s,@pts_bash@,$pts_bash,;t t +s,@pts_make@,$pts_make,;t t +s,@pts_perl@,$pts_perl,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@EGREP@,$EGREP,;t t +s,@ALLOCA@,$ALLOCA,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +rm -f Makedep +ac_n="${ac_n:-$ECHO_N}" +echo $ac_n "running make Makedep""... $ac_c" 1>&6 +echo "configure:7504: running make Makedep" >&5 +if >&5 2>&5 make Makedep; then : + echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + +else + echo "$as_me:$LINENO: result: error" >&5 +echo "${ECHO_T}error" >&6 + { { echo "$as_me:$LINENO: error: cannot compute depends" >&5 +echo "$as_me: error: cannot compute depends" >&2;} + { (exit 1); exit 1; }; } +fi + +echo "configure:7517: all OK" >&5 + +echo "configure done. Now you should run: make; make install" + diff --git a/Build/source/utils/sam2p/configure.in b/Build/source/utils/sam2p/configure.in new file mode 100644 index 00000000000..0bcb8cbc330 --- /dev/null +++ b/Build/source/utils/sam2p/configure.in @@ -0,0 +1,222 @@ +dnl +dnl configure.in -- for sam2p +dnl by pts@fazekas.hu at Thu Nov 1 22:46:51 CET 2001 +dnl Mon Mar 4 08:56:35 CET 2002 +dnl +dnl Dat: autoheader stops reading the file at the 1st error +dnl Imp: concat (TCL, Ruby) +dnl Imp: stringify +dnl Imp: C and C++ +dnl Imp: warnings +dnl OK : traditional C +dnl Imp: ctype +dnl Imp: check for socklen_t + +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(gensi.cpp) +AC_CONFIG_HEADER(config.h) +AC_PTS_ENABLE_DEBUG + +AC_MSG_CHECKING([for --enable-lzw]) +AC_ARG_ENABLE(lzw, + [ --enable-lzw enable built-in LZW (de)compression (def: no)], + [], []) +if test x1 = x"`perl -e 'print time>1056165811'`"; then + # After 19 June 2003: default: yes + if test x"$enable_lzw" = x"no"; then + AC_MSG_RESULT(no) + else + AC_MSG_RESULT(yes) + AC_DEFINE(USE_BUILTIN_LZW) + dnl AC_MSG_WARN(LZW was patented till 19 June 2003; ask permission from Unisys to use it!) + fi +else + if test x"$enable_lzw" = x"yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(USE_BUILTIN_LZW) + AC_MSG_WARN(LZW is patented till 19 June 2003; ask permission from Unisys to use it!) + else + AC_MSG_RESULT(no) + fi +fi + +dnl Sun Jul 7 23:58:11 CEST 2002 +AC_MSG_CHECKING([for --enable-zip]) +AC_ARG_ENABLE(zip, + [ --enable-zip enable built-in ZIP compression (def: yes)], + [], []) +if test x"$enable_zip" = x"no"; then + AC_MSG_RESULT(no) +else + AC_MSG_RESULT(yes) + AC_DEFINE(USE_BUILTIN_ZIP) +fi + +dnl Sun Jul 7 23:58:11 CEST 2002 +AC_MSG_CHECKING([for --enable-fax]) +AC_ARG_ENABLE(fax, + [ --enable-fax enable built-in Fax compression (def: yes)], + [], []) +if test x"$enable_fax" = x"no"; then + AC_MSG_RESULT(no) +else + AC_MSG_RESULT(yes) + AC_DEFINE(USE_BUILTIN_FAXE) +fi + +AC_MSG_CHECKING([for --enable-gif]) +AC_ARG_ENABLE(gif, + [ --enable-gif enable reading and writing GIF images (def: no)], + [], []) +if test x"$enable_gif" = x"yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(USE_IN_GIF) + AC_DEFINE(USE_OUT_GIF) + AC_MSG_WARN(GIF is a resistered trademark of Compuserve; ask permission from them to use it!) +else + AC_MSG_RESULT(no) +fi + +dnl Checks for programs. +dnl AC_PROG_CC +AC_LANG_CPLUSPLUS +CXXFLAGS=" " +dnl ^^^ set it to non-empty, so AC_PROG_CXX won't include `-g' +CCC="$CCC g++" +dnl ^^^ check g++ before c++ (see acspecific.m4, grep AC_PROG_CXX) +AC_PROG_CXX + +AC_SUBST(GFLAG) +if test x"$ac_cv_prog_cxx_g" = xyes; then GFLAG=-g; else GFLAG=""; fi +dnl ac_cv_prog_cc_g also + +AC_PTS_PROG_CXXFLAGS(fs, -fsigned-char) +AC_PTS_PROG_CXXFLAGS(nrne, -fno-rtti -fno-exceptions) +dnl ^^^ `g++ -fno-rtti': disables `typeinfo' (??) and run-time type identification +dnl ^^^ `g++ -fno-exceptions': disables catch and throw +AC_PTS_PROG_CXXFLAGSB(apwaw, -ansi -pedantic -Wall -W) +dnl vvv gcc-3.2 gives too many stupid warnings with -Wtraditional +dnl AC_PTS_PROG_CXXFLAGSB(-Wtraditional) +AC_PTS_PROG_CXXFLAGSB(ptscxxopts, -felide-constructors -Wstrict-prototypes dnl +-Wpointer-arith -Wcast-align -Winline dnl +-Wcast-qual -Wmissing-prototypes) +AC_PTS_CHECK_IGNORING(nebfcmd,-W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations) +if test x"$ac_cv_pts_ignoring_nebfcmd" = xyes +then ac_cv_prog_cxx_nebfcmd=no +fi +AC_PTS_PROG_CXXFLAGSB(nebfcmd,-Wnested-externs -Wbad-function-cast -Wmissing-declarations) +dnl vvv g++ version egcs-2.91.60 + gcc version 2.7.2.3 requires +dnl `g++ -fno-rtti -fno-exceptions' for AC_PTS_GCC_LINKS_CXX to be `yes' +AC_PTS_GCC_LINKS_CXX + +AC_PTS_WARN_PROG(cjpeg, [cjpeg is required for /Compression/IJG]) +AC_PTS_WARN_PROG(djpeg, [djpeg is required for loading JPEG files]) +AC_PTS_WARN_PROG(tif22pnm, [tif22pnm is required for loading TIFF files]) +AC_PTS_WARN_PROG(tifftopnm, [tifftopnm might become useful for loading TIFF files]) +AC_PTS_WARN_PROG(pngtopnm, [pngtopnm might become useful for loading PNG files]) +dnl AC_PTS_WARN_PROG(gs, [gs is required for /Compression/Fax, and might become recommended for /Compression/ZIP]) +AC_PTS_WARN_PROG(gs, [gs is recommended for viewing PS files[,] and might become recommended for /Compression/ZIP]) +AC_PTS_WARN_PROG(lzw_codec, [lzw_codec might become recommended for /Compression/LZW]) +AC_PTS_WARN_PROG(gzip, [gzip might become useful for /Compression/ZIP]) +AC_PTS_WARN_PROG(zip, [zip might become useful for /Compression/ZIP]) +AC_PTS_ERR_PROG(bash, [bash is required for compiling this program]) +AC_PTS_ERR_PROG(make, [make is required for compiling this program]) +AC_PTS_ERR_PROG(perl, [perl is required for compiling this program]) +dnl AC_PTS_ERR_PROG(touch, [touch is required for compiling this program]) +dnl ^^^ as of 0.37, touch is not required + +#AC_CHECK_PROG(ac_pts_cjpeg, cjpeg, yes) + +dnl Checks for C/C++ language features +AC_PTS_HAVE_STDC +AC_PTS_HAVE_SWITCH_ENUM_BUG +AC_PTS_ENSURE_ASCII_SYSTEM +AC_C_CONST +AC_PTS_C_VOLATILE +AC_PTS_HAVE_STATIC_CONST + +dnl Checks for libraries. + +dnl Checks for header files. +dnl AC_CHECK_HEADERS(stdio.h); exit 42 +dnl AC_CHECK_HEADERS(stdio.h stdlib.h unistd.h string.h strings.h) + +dnl Dat: getc_in_stdio fails for uClibc-0.9.14 _and_ `i386-uclibc-gcc -ansi' +CXXFLAGS_save="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS -ansi" +AC_PTS_CHECK_HEADER(stdio.h, getc, getc_in_stdio, [return argc>42? getc(stdin)*0+1:0;]) +AC_PTS_CHECK_HEADER(stdio.h, fgetc, fgetc_in_stdio, [return argc>42?fgetc(stdin)*0+1:0;]) +AC_PTS_CHECK_HEADER(stdio.h, putc, putc_in_stdio, [return argc>42? putc(' ',stdout)*0+1:0;]) +AC_PTS_CHECK_HEADER(stdio.h, fputc, fputc_in_stdio, [return argc>42?fputc(' ',stdout)*0+1:0;]) +CXXFLAGS="$CXXFLAGS_save" + +AC_PTS_CHECK_HEADER(stdio.h, sprintf, sprintf_in_stdio, [char s[42]="X"; sprintf(s, "Hello, World!"); return *s!='H';] ) +AC_PTS_CHECK_HEADER(stdlib.h, atoi, atoi_in_stdlib, [return atoi("42")!=42;]) +AC_PTS_CHECK_HEADER(unistd.h, write, write_in_unistd, [return write(1,"what",0)!=0;]) +AC_PTS_CHECK_HEADER(stdlib.h, system, system_in_stdlib, [/*>255 OK*/return system("true")!=0;]) +AC_PTS_CHECK_HEADER(sys/stat.h, lstat, lstat_in_sys_stat,[struct stat st; return 0!=lstat("/",&st);]) +AC_PTS_CHECK_STRING +AC_PTS_CHECK_MALLOC +AC_FUNC_ALLOCA +AC_PTS_CFG_PRINTFGLEN +AC_PTS_CFG_P_TMPDIR +AC_PTS_HAVE_POPEN_ +if test $ac_cv_pts_have_popen_ = yes; then + ac_cv_pts_have_popen_b=no +fi +AC_PTS_HAVE_POPEN_B +AC_PTS_HAVE_VSNPRINTF +AC_PTS_HAVE_SYSTEMF + +dnl Checks for integral/pointer sizes. + +dnl AC_C_CHAR_UNSIGNED + +AC_PTS_CHECK_POINTERS +dnl AC_PTS_CHECK_INTEGRALS -- alread in AC_PTS_CHECK_POINTERS +dnl AC_REQUIRE([AC_PTS_CHECK_POINTERS]) +dnl AC_REQUIRE([AC_PTS_CHECK_INTEGRALS]) +dnl Dat: POINTERS, INTEGRALS order would result in `(cached)' without AC_REQUIRE +dnl DAT: newer autoconfs disallow AC_REQUIRE(...) outside macros + +dnl ac_cv_alma=korte # Dat: automagically inserted into config.cache +dnl AC_DEFINE(PTS_INT128_T, 42) # Dat: includes to conftest.h, config.h + +dnl cat confdefs.h # Dat: contains already AC_DEFINE()d symbols + +dnl Checks for typedefs, structures, and compiler characteristics. +dnl AC_TYPE_SIZE_T +AC_PTS_CHECK_INTEGRAL_TYPE(size_t, unsigned) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(time_t, unsigned) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(mode_t, int) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(off_t, long) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(pid_t, int) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(dev_t, unsigned long) +dnl dnl ^^^ Dat: unsigned PTS_INT64_T on Linux i386 +dnl AC_PTS_CHECK_INTEGRAL_TYPE(uid_t, unsigned) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(gid_t, unsigned) +dnl AC_PTS_CHECK_INTEGRAL_TYPE(size_tt, signed) +dnl Dat: AC_TYPE_SIGNAL is OK, there should be no AC_PTS_CHECK_* substitute +dnl AC_PTS_TYPE_GETGROUPS +dnl ^^^ doesn't work wth CPPFLAGS=-traditional +AC_PTS_CHECK_SIZEOF(bool, -1) +dnl ^^^ Dat: 0 #if (PC: 1, Digital Unix: 8, Solaris: 4) +dnl ^^^ Dat: autoconf-2.54 AC_CHECK_SIZEOF checks sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h inttypes.h stdint.h unistd.h + +dnl Checks for library functions. +dnl (None!) + +dnl Finishing. + +dnl AC_OUTPUT(config.h) -- bad!! +dnl skipping AC_OUTPUT -- bad!! +AC_OUTPUT(Makehelp) + +dnl AC_PTS_RUN_OK([perl -x -S ./ccdep.pl $CXX], [], [AC_MSG_ERROR(cannot compute depends)]) +rm -f Makedep +AC_PTS_RUN_OK([make Makedep], [], [AC_MSG_ERROR(cannot compute depends)]) +AC_PTS_OK +echo "configure done. Now you should run: make; make install" + +dnl end of configure.in diff --git a/Build/source/utils/sam2p/contrib/aprea.ps b/Build/source/utils/sam2p/contrib/aprea.ps new file mode 100644 index 00000000000..6d8ab0b2973 --- /dev/null +++ b/Build/source/utils/sam2p/contrib/aprea.ps @@ -0,0 +1,22 @@ +% anti-setpagedevice preamble by pts@inf.bme.hu in 2002.03.15 +userdict begin +1 dict dup /ImagingBBox null put +/setpagedevice where{ + pop setpagedevice + /setpagedevice{% -dict:pagedevice- sp - + dup length dict copy + dup /PageSize undef dup /ImagingBBox undef + dup /HWResolution undef + 0}% changed to //setpagedevice in next line + dup dup length 1 sub 3 index load put bind 1 index + where{dup wcheck{3 1 roll put}{pop def}ifelse}{def}ifelse + % ^^^ instead of ef' -- redef at the appropriate place + }if +[/11x17/a3/a4/a4small/b5/ledger/legal/letter/lettersmall/note +/a0/a1/a2/a5/a6/a7/a8/a9/a10/b0/b1/b2/b3/b4/b5/c0/c1/c2/c3/c4 +/c5/c6/archE/archD/archC/archB/archA/flsa/flse/halfletter +/tabloid/csheet/dsheet/esheet/executivepage/com10envelope +/monarchenvelope/c5envelope/dlenvelope/folio/quarto]{ +dup where{dup wcheck{exch{}put}{pop{}def}ifelse}{pop}ifelse +% ^^^ make these ops a no-op ({}) if they exist +}forall end% userdict
\ No newline at end of file diff --git a/Build/source/utils/sam2p/contrib/sam2p.tk b/Build/source/utils/sam2p/contrib/sam2p.tk new file mode 100644 index 00000000000..b1af4bf1306 --- /dev/null +++ b/Build/source/utils/sam2p/contrib/sam2p.tk @@ -0,0 +1,1450 @@ +#!/usr/bin/wish -f +# +# sam2p.tk +# by pts@fazekas.hu at Sat Apr 6 13:14:37 CEST 2002 +# +# OK: confirm quit +# Imp: don't update widgets when error in job file +# Imp: newline mangling when loading/saving files +# Imp: /DCT, ability to type literal MiniPS code to an `entry' +# Imp: Perl parser should signal error on <hex123> etc. +# Imp: B2Press + Move + B2Release; inserts twice +# Imp: initial `focus' +# Imp: default values +# Imp: tk-start with sh +# Imp: to center of the resized window +# Imp: tooltips (mouse button 2, 3) +# Imp: less vertical padding +# Imp: really detect what kind of -*-fixed fonts we have +# Dat: TCL 8.0 doesn't have `string equal' +# Dat: never do `.text mark set sel.first 1.5', beacuse this will override tag `sel' +# Dat: `entry' widgets don't accept "insert + 1 chars" as a character index +# Dat: tag-parser treats comments as legal tokens +# Dat: <Insert> matches <Shift-Insert>, <Key-Insert> does not. +# Dat: <Motion> is mouse motion event over the sub-window +# Dat: <Enter> and <Leave> is an event sent when +# SUXX: Tcl: 8.0 doesn't have [string map ...] +# SUXX: Tk: radio and checkbuttons cannot be made smaller or larger +# SUXX: Tk: color for -relief cannot be specified +# SUXX: Tk: on UNIX, Tk converts "Times New Roman" to "times" unless specified as "-*-times new roman-*-*-*-*-*-*-*-*-*-*-iso8859-1" +# SUXX: Tk: .text cursor width cannot be extended to the right only (not to the left) +# SUXX: Tk: .text cannot show the last line on the top unless first==last +# SUXX: Tk bug: echo `bind . <ButtonRelease-2> {put got}' | wish +# Test: 1. press button2 2. move mouse 3. release button 4. move mouse +# `got' is printed twice. Strange: works fine with button 1 and 3. +# Even the following doesn't help: +# echo `bind . <B2-ButtonRelease-2> {put got}' | wish +# Even event parameters are useless to distinguish normal and duplicate +# events. This is a bug even on all other X11 clients. May be a GPM bug +# or an xlib bug?? + +# puts [file type alma] + +proc pts_PATH_sep {} { + global tcl_platform + if {0==[string compare windows $tcl_platform(platform)]} {return ;} + return : + # Imp: `macintosh' +} + +proc pts_read_ok {filename} { + if {0==[string length $filename]} {return 0} + if {[catch {set t [file type $filename]}]} { + if {[catch {set t [file type [file dirname $filename]]}]} {return !d} + return !e + } + if {0!=[string compare $t file]} {return !f} + if {![file readable $filename]} {return !r} + return OK +} + +proc pts_write_ok {filename} { + if {0==[string length $filename]} {return 0} + if {[catch {set t [file type $filename]}]} { + if {[catch {set t [file type [set dir [file dirname $filename]]]}]} {return !d} + if {0==[string compare $t directory] && [file writable $dir]} {return ++} + return !dw + } + if {0!=[string compare $t file]} {return !f} + if {![file writable $filename]} {return !w} + return OK +} + +proc pts_direct_bindtags {w} { + #** Moves all binds associated with widget $w to directly widget itself. + ## Half idea: bindtags $w "$w [bindtags $w]" + # Dat: this assumes [lindex [bindtags $w] 0] == $w + foreach tag [bindtags $w] { + if {0!=[string compare $tag $w]} { + foreach evtseq [bind $tag] { + bind $w $evtseq [bind $w $evtseq]\n[bind $tag $evtseq] + } + } + } + bindtags $w $w +} + +proc pts_readonly {w} { + #** @param $w text or entry + #** Makes the specified widget read-only. [$w configure -state disabled] + #** is not OK, because it makes the insertion cursor invisible. + pts_direct_bindtags $w + # SUXX: cannot be avoided. Example: we must disable <Key> (typing letters), + # but allow <Key-Left> + bind $w <Meta-Key-d> break + bind $w <Meta-Key-f> break + bind $w <Meta-Key-Delete> break + bind $w <Meta-Key-BackSpace> break + bind $w <Control-Key-d> break + bind $w <Control-Key-i> break + bind $w <Control-Key-k> break + bind $w <Control-Key-h> break + bind $w <Control-Key-t> break + bind $w <Key-BackSpace> break + bind $w <Key-Delete> break + bind $w <Key-Return> break + bind $w <Key-KP_Enter> break + bind $w <Key> break + bind $w <<PasteSelection>> break + bind $w <<Paste>> break + bind $w <<Cut>> break + bind $w <<Clear>> break +} + +proc pts_readonly_color {w} { + #** Calls [pts_readonly $w], and sets widget colors etc. to make the user + #** see that it's a read-only widget. + pts_readonly $w + $w configure -background [[winfo toplevel $w] cget -background] -relief sunken +} + +proc pts_listrev {list} { + # by pts@fazekas.hu at Sun Apr 21 21:08:20 CEST 2002 + set i [llength $list] + set ret {} + while {$i>0} {incr i -1; lappend ret [lindex $list $i]} + return $ret +} + +proc pts_listrev1 {list} { + #** Chops the 1st element of list, and returns the reverse of the rest. + # by pts@fazekas.hu at Sun Apr 21 21:08:20 CEST 2002 + set i [llength $list] + set ret {} + while {$i>1} {incr i -1; lappend ret [lindex $list $i]} + return $ret +} + +## puts [pts_listrev {1 2 {3 4}}]; exit + +set pts_unknown_font [font actual ..unknown..] +proc pts_has_font {f} { + # by pts@fazekas.hu at Sat Apr 6 16:26:24 CEST 2002 + # This is rather dirty, because there is no clean way to test whether a font + # exists in Tk. + #** return 1 or 0 + global pts_unknown_font + if {0==[string compare fixed $f]} {return 1} + if {[string match -*-fixed-* $f]} {return 1} ;# Imp: first `*' shouldn't contain `-' + # Dat: pts_unknown_font is `fixed' on UNIX systems... + if {0==[string compare $pts_unknown_font [font actual $f]]} {return 0} + return 1 +} + +proc pts_last_font {first args} { + #** @param first,args list of font names (suitable arg for `-font' of widgets) + #** @return the last font name that is available + for {set i [llength $args]} {$i>0} {} { + incr i -1 + if {[pts_has_font [set f [lindex $args $i]]]} {return $f} + } + return $first +} + +proc pts_fix_shift_tab {} { + # by pts@fazekas.hu at Sat Apr 6 15:22:58 CEST 2002 + set tmp [bind all <Shift-Key-Tab>] + ## puts $tmp + if {[string length $tmp]==0} {set tmp {tkTabToWindow [tk_focusPrev %]}} + bind all <Shift-Key-Tab> $tmp + catch {bind all <Key-ISO_Left_Tab> $tmp} + # ^^^ Dat: catch is here because some systems don't have ISO_Left_Tab +} + +proc pts_fix_one_tab {wPath} { + # by pts@fazekas.hu at Sat Apr 6 15:38:43 CEST 2002 + # pts_fix_shift_tab() should be called. + bind $wPath <Key-Tab> "[bind all <Key-Tab>]; break" + bind $wPath <Shift-Key-Tab> "[bind all <Shift-Key-Tab>]; break" + bind $wPath <Key-ISO_Left_Tab> "[bind all <Shift-Key-Tab>]; break" +} + +proc pts_tag_set_first {w tagName index} { + if {[$w tag nextrange $tagName 1.0 end] != ""} { + if {[$w compare $index < $tagName.last]} { + if {[$w compare $index < $tagName.first]} \ + {$w tag add $tagName $index $tagName.first} \ + {$w tag remove $tagName $tagName.first $index} + } { + set tmp [$w index $tagName.last] + $w tag remove $tagName 1.0 end + $w tag add $tagName $tmp $index + } + } +} +proc pts_tag_set_last {w tagName index} { + if {[$w tag nextrange $tagName 1.0 end] != ""} { + if {[$w compare $index > $tagName.first]} { + if {[$w compare $index > $tagName.last]} \ + {$w tag add $tagName $tagName.last $index} \ + {$w tag remove $tagName $index $tagName.last} + } { + set tmp [$w index $tagName.first] + $w tag remove $tagName 1.0 end + $w tag add $tagName $index $tmp + } + } +} + +proc pts_paste {w} {catch { + set tmp [$w index insert] + $w insert insert [selection get -displayof $w -selection CLIPBOARD] + $w tag remove sel 0.1 end + $w tag add sel $tmp insert +}} + +proc pts_text_insert_newline {w autoindent} { + #** Doesn't respect overstrike mode (neither does Turbo Pascal). + #** Does auto-indenting of spaces and tabs. + if {[$w cget -state] == "disabled"} {return} + if $autoindent { + if {![string length [set tmp [$w search -regexp "\[^ \t]" {insert linestart} {insert lineend}]]]} {set tmp "insert lineend"} + $w insert insert \n[$w get {insert linestart} $tmp] + } {$w insert insert \n} + $w see insert +} +proc pts_text_autoindent {w bool} { + if $bool {} ;# early error message if bool is malformed + bind $w <Return> "pts_text_insert_newline %W $bool; break" +} + +# vvv Overriding text.tcl, so we won't clobber the visible selection. +proc tkTextInsert {w s} { + if {($s == "") || ([$w cget -state] == "disabled")} {return} + if {[string match "* 1" [bind $w <Insert>]]} { + # vvv in overstrike mode, overstrike only in the middle of the line + if {[$w compare insert != "insert lineend"]} {$w delete insert} + } + $w insert insert $s; $w see insert +} + +#proc pts_text_insert {w s overstrike} { +# if {($s == "") || ([$w cget -state] == "disabled")} {return} +# set tmp [$w index insert] +# # vvv in overstrike mode, overstrike only in the middle of the line +# if {$overstrike && [$w compare insert != "insert lineend"]} {$w delete insert} +# $w insert insert $s; $w see insert +#} +proc pts_text_overstrike {w bool} { + #puts [$w configure -insertontime] + #puts [$w configure -insertofftime] + if {$bool} {$w configure -insertofftime 0} \ + {$w configure -insertofftime [lindex [$w configure -insertofftime] 3]} + # Dat: we cannot override the widget's <KeyPress> method here, because then + # we won't be able to receive cursor movement etc. events, see docs in + # bindtags(n) and bind(n). So support must be built into tkTextInsert, + # since `bind Text <KeyPress> {tkTextInsert %W %A}' is the default. + # bind Text <KeyPress> "pts_text_insert %W %A $bool; break ;#alma" + focus .; focus $w ;# trick to avoid non-reblinking bug in Tk8.0 Linux. +} +proc pts_text_toggle_overstrike {w bool} { + if {$bool} {set bool 0} {set bool 1} + pts_text_overstrike $w $bool + bind $w <Insert> "pts_text_toggle_overstrike %W $bool" +} +proc pts_text_auto_overstrike {w bool} { + #** Sets overstrike mode, and binds Insert to do the switching. A + #** non-blinking cursor indicates overstrike mode. (Tk is too stupid to draw + #** a block cursor.) + #** @param w a text widget + pts_text_overstrike $w $bool + bind $w <Key-Insert> "pts_text_toggle_overstrike %W $bool" +} + +# redefine tkScrollButtonDown, so it won't `sunken' the slider +# (se tcl8.2/scrlbar.tcl) +proc tkScrollButtonDown {w x y} { + global tkPriv + set tkPriv(relief) [$w cget -activerelief] + if {0==[string compare slider [set element [$w identify $x $y]]]} { + tkScrollStartDrag $w $x $y + } else { + $w configure -activerelief sunken + tkScrollSelect $w $element initial + } +} +proc tkScrollButton2Down {w x y} { + global tkPriv + set element [$w identify $x $y] + if {0==[string compare $element arrow1]||0==[string compare $element arrow2]} { + tkScrollButtonDown $w $x $y + return + } + tkScrollToPos $w [$w fraction $x $y] + set tkPriv(relief) [$w cget -activerelief] + update idletasks + # $w configure -activerelief sunken + $w activate slider + tkScrollStartDrag $w $x $y +} + +option add *Dialog.msg.wrapLength 3i widgetDefault +proc pts_message_box {args} { + global sa_normfont + #** similar to tkMessageBox; ignores platform's native MessageBox support. + global tkPriv tcl_platform + + set w tkPrivMsgBox + upvar #0 $w data + + # + # The default value of the title is space (" ") not the empty string + # because for some window managers, a + # wm title .foo "" + # causes the window title to be "foo" instead of the empty string. + # + set specs { + {-default "" "" ""} + {-icon "" "" "info"} + {-message "" "" ""} + {-parent "" "" .} + {-title "" "" " "} + {-type "" "" "ok"} + } + + tclParseConfigSpec $w $specs "" $args + + if {[lsearch {info warning error question} $data(-icon)] == -1} { + error "invalid icon \"$data(-icon)\", must be error, info, question or warning" + } + if {$tcl_platform(platform) == "macintosh"} { + if {$data(-icon) == "error"} { + set data(-icon) "stop" + } elseif {$data(-icon) == "warning"} { + set data(-icon) "caution" + } elseif {$data(-icon) == "info"} { + set data(-icon) "note" + } + } + + if {![winfo exists $data(-parent)]} { + error "bad window path name \"$data(-parent)\"" + } + + switch -- $data(-type) { + abortretryignore { + set buttons { + {abort -width 6 -text Abort -under 0} + {retry -width 6 -text Retry -under 0} + {ignore -width 6 -text Ignore -under 0} + } + } + ok { + set buttons { + {ok -width 6 -text OK -under 0} + } + if {$data(-default) == ""} { + set data(-default) "ok" + } + } + okcancel { + set buttons { + {ok -width 6 -text OK -under 0} + {cancel -width 6 -text Cancel -under 0} + } + } + retrycancel { + set buttons { + {retry -width 6 -text Retry -under 0} + {cancel -width 6 -text Cancel -under 0} + } + } + yesno { + set buttons { + {yes -width 6 -text Yes -under 0} + {no -width 6 -text No -under 0} + } + } + yesnocancel { + set buttons { + {yes -width 6 -text Yes -under 0} + {no -width 6 -text No -under 0} + {cancel -width 6 -text Cancel -under 0} + } + } + default { + error "invalid message box type \"$data(-type)\", must be abortretryignore, ok, okcancel, retrycancel, yesno or yesnocancel" + } + } + + if {[string compare $data(-default) ""]} { + set valid 0 + foreach btn $buttons { + if {![string compare [lindex $btn 0] $data(-default)]} { + set valid 1 + break + } + } + if {!$valid} { + error "invalid default button \"$data(-default)\"" + } + } + + # 2. Set the dialog to be a child window of $parent + # + # + if {[string compare $data(-parent) .]} { + set w $data(-parent).__tk__messagebox + } else { + set w .__tk__messagebox + } + + # 3. Create the top-level window and divide it into top + # and bottom parts. + + catch {destroy $w} + toplevel $w -class Dialog + wm title $w $data(-title) + wm iconname $w Dialog + wm protocol $w WM_DELETE_WINDOW { } + wm transient $w $data(-parent) + if {$tcl_platform(platform) == "macintosh"} { + unsupported1 style $w dBoxProc + } + + frame $w.bot + pack $w.bot -side bottom -fill both + frame $w.top + pack $w.top -side top -fill both -expand 1 + if {$tcl_platform(platform) != "macintosh"} { + $w.bot configure -relief raised -bd 1 + $w.top configure -relief raised -bd 1 + } + + # 4. Fill the top part with bitmap and message (use the option + # database for -wraplength so that it can be overridden by + # the caller). + + label $w.msg -justify left -text $data(-message) + #catch {$w.msg configure -font \ + # -Adobe-Times-Medium-R-Normal--*-180-*-*-*-*-*-* + #} + pack $w.msg -in $w.top -side right -expand 1 -fill both -padx 3m -pady 3m + if {$data(-icon) != ""} { + label $w.bitmap -bitmap $data(-icon) + pack $w.bitmap -in $w.top -side left -padx 3m -pady 3m + } + + # 5. Create a row of buttons at the bottom of the dialog. + + set i 0 + foreach but $buttons { + set name [lindex $but 0] + set opts [lrange $but 1 end] + if {![string compare $opts {}]} { + # Capitalize the first letter of $name + set capName \ + [string toupper \ + [string index $name 0]][string range $name 1 end] + set opts [list -text $capName] + } + + eval button $w.$name $opts -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 -command [list "set tkPriv(button) $name"] + + if {![string compare $name $data(-default)]} { + $w.$name configure -default active + } + pack $w.$name -in $w.bot -side left -expand 1 \ + -padx 3m -pady 2m + + # create the binding for the key accelerator, based on the underline + # + set underIdx [$w.$name cget -under] + if {$underIdx >= 0} { + set key [string index [$w.$name cget -text] $underIdx] + bind $w <Alt-[string tolower $key]> "$w.$name invoke" + bind $w <Alt-[string toupper $key]> "$w.$name invoke" + } + incr i + } + + # 6. Create a binding for <Return> on the dialog if there is a + # default button. + + if {[string compare $data(-default) ""]} { + bind $w <Return> "tkButtonInvoke $w.$data(-default)" + } + + # 7. Withdraw the window, then update all the geometry information + # so we know how big it wants to be, then center the window in the + # display and de-iconify it. + + wm withdraw $w + update idletasks + set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \ + - [winfo vrootx [winfo parent $w]]}] + set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \ + - [winfo vrooty [winfo parent $w]]}] + wm geom $w +$x+$y + wm deiconify $w + + # 8. Set a grab and claim the focus too. + + set oldFocus [focus] + set oldGrab [grab current $w] + if {$oldGrab != ""} { + set grabStatus [grab status $oldGrab] + } + grab $w + if {[string compare $data(-default) ""]} { + focus $w.$data(-default) + } else { + focus $w + } + + # 9. Wait for the user to respond, then restore the focus and + # return the index of the selected button. Restore the focus + # before deleting the window, since otherwise the window manager + # may take the focus away so we can't redirect it. Finally, + # restore any grab that was in effect. + + tkwait variable tkPriv(button) + catch {focus $oldFocus} + destroy $w + if {$oldGrab != ""} { + if {$grabStatus == "global"} { + grab -global $oldGrab + } else { + grab $oldGrab + } + } + return $tkPriv(button) +} + + +# --- + +proc sa_radio {framePath variable value labelCaption args} { + global $variable sa_normfont + # Imp: use -text + set $variable "" + frame $framePath + lappend args -variable $variable -value $value -indicatoron true -borderwidth 1 + # lappend args -value $value -indicatoron true -borderwidth 1 + eval "radiobutton $framePath.r $args" + + $framePath.r configure -activebackground [$framePath.r cget -background] + label $framePath.l -text $labelCaption -font $sa_normfont ;# Imp: Why doesn't -anchor work?? + bind $framePath.l <ButtonRelease-1> "$framePath.r invoke" + pack $framePath.r $framePath.l -side left + # bind $framePath.r <Key-ISO_Left_Tab> {tkTabToWindow [tk_focusPrev %W]} +} +#proc sa_radio_pack {framePath} {} +proc sa_check {wPath variable labelCaption args} { + global sa_boldfont + # Imp: clicking to the right from the caption shouldn't have effect + lappend args -font $sa_boldfont -text $labelCaption -anchor w -borderwidth 1 -variable $variable + eval "checkbutton $wPath $args" + $wPath configure -activebackground [$wPath cget -background] +} + +proc sa_check_update {wPath variable labelCaption} { + sa_check $wPath $variable $labelCaption -command "update_check $variable $wPath" +} + +proc sa_int {framePath variable labelCaption entryWidth args} { + # Imp: clicking to the right from the caption shouldn't have effect + # Imp: check for int... + global sa_normfont sa_boldfont + frame $framePath ;# may already exist?? + label $framePath.l -text $labelCaption -font $sa_boldfont + lappend args -relief sunken -width $entryWidth -font $sa_normfont \ + -borderwidth 1 -foreground black -background white \ + -selectbackground yellow -selectforeground black -selectborderwidth 0 + eval "entry $framePath.i $args" + pack $framePath.l $framePath.i -side left + # $framePath configure -activebackground [$framePath cget -background] +} + +proc sa_w_text {args} { + lappend args -relief solid -highlightcolor gray30 \ + -borderwidth 1 -foreground black -background white \ + -selectbackground gray85 -selectforeground black -selectborderwidth 0 + eval "text $args" +} + +proc sa_w_entry {args} { + lappend args -relief sunken -borderwidth 1 -foreground black -background white \ + -selectbackground yellow -selectforeground black -selectborderwidth 0 + eval "entry $args" +} + +set sa_frame 0 +proc sa_vframe {parentPath} { + #** Creates and packs vertical frame, which is 5 pixel high + global sa_frame + set w $parentPath.saf[incr sa_frame] + frame $w -height 5 -width 1 + pack $w -fill x +} + +# vvv The mouse must be used to insert visible selection (of other apps) +bind Text <Insert> {} + +bind Text <B2-Motion> {} +bind Text <Button-2> {} +# puts T[bind Text]T + + +# vvv allow the well-known (almost indrustry standard) Windows/Borland/GTK +# cliboard key bindings on all platforms +event add <<Cut>> <Control-Key-x> <Shift-Key-Delete> +event add <<Copy>> <Control-Key-c> <Control-Key-Insert> +event add <<Paste>> <Control-Key-v> <Shift-Key-Insert> +# event add <<PasteSelection>> <ButtonRelease-2> +# Dat: <<Paste>> is normal, <Control-Key-v> paste, which requires prior +# <Control-Key-c>. Works across applications. +# Dat: <<PasteSelection>> is xterm/netscape-like paste, which does not +# require <Control-Key-c>. Also works across applications. + +# vvv this <<Paste>> deletes current selection even on UNIX; but we don't like that +# bind Text <<Paste>> {catch {%W delete sel.first sel.last}; catch {%W insert insert [selection get -displayof %W -selection CLIPBOARD]}} +# vvv this <<Paste>> leaves visible selection intact +# bind Text <<Paste>> {catch {%W insert insert [selection get -displayof %W -selection CLIPBOARD]}} +# vvv this <<Paste>> sets visible selection to the newly pasted data +bind Text <<Paste>> {pts_paste %W} + +# vvv our <<PasteSelection>> doesn't move the cursor (like xterm, unlike Motif) +bind Text <<PasteSelection>> {pts_text_paste_selection %W %x %y} + +bind Text <B2-Motion> {} +bind Text <Button-2> {} + +# bind Text <ButtonRelease-2> {puts evt; pts_text_paste_selection %W %x %y} +#catch { +#event delete <<PasteSelection>> <ButtonRelease-2> +#} +#catch { +#event add <<PasteSelection>> <B2-ButtonRelease-2> +#event add <<PasteSelection>> <Button-2> +#} + +# puts EI[event info <<PasteSelection>>] +# puts A[event info <<PasteSelection>>]BN + +proc pts_text_paste_selection {w x y} { + #** If has focus, than pastes visible selection to the unchanged cursor + #** position; otherwise claims focus and sets cursor position to mouse. + if {0==[string compare $w [focus -displayof $w]]} { + catch {$w insert insert [selection get -displayof $w]} + if {0==[string compare normal [$w cget -state]]} {focus $w} + } {$w mark set insert [tkTextClosestGap $w $x $y]; focus $w} +} + + +# vvv overrides text.tcl, doesn't clobber the selection. +bind Text <1> {tkTextButton1 %W %x %y} + +proc ptsTextDelLn W { + # puts [%W index {insert linestart}]..[%W index {insert lineend + 1 chars}] + if {[$W compare {insert lineend + 1 chars} == end]} { + # <Control-y> in the last line must not move the cursor + $W delete {insert linestart} {insert lineend} + } { + $W delete {insert linestart} {insert lineend + 1 chars} + } +} + +# vvv Overriding text.tcl, so we won't clobber the visible selection when moving +# the cursor or just inserting +proc tkTextSetCursor {w pos} { + if {[$w compare $pos == end]} {set pos {end - 1 chars}} + $w mark set insert $pos + # $w tag remove sel 1.0 end + $w see insert +} + +# vvv Overriding text.tcl, so PageUp and PageDown will jump within the page. +proc tkTextScrollPages {w count} { + set tmp [expr {([$w cget -height]-1)*$count}] + $w yview scroll $tmp units + return "insert + $tmp lines" +} + +# vvv Overrides text.tcl with Turbo Pascal-style Shift+Arrow selection: +# Shift+Movement-key, when moved _from_ either end of the selection, +# updates that end appropriately. Otherwise, it clobbers the selection, +# and creates a new selection from the current `insert' position to the +# position the cursor is moved to. +proc tkTextKeySelect {w newIndex} { + # puts "[$w index insert] -> [$w index $newIndex] ([$w index end])" + if {[$w compare end == $newIndex]} {set newIndex "end - 1 char"} + $w mark set anchor insert + if {[$w tag nextrange sel 1.0 end] == ""} { + if {[$w compare $newIndex < insert]} {$w tag add sel $newIndex insert} {$w tag add sel insert $newIndex} + } { # already have a selection + # puts "a=[$w index sel.first]-[$w index sel.last] i=[$w index insert]" + if {[$w compare insert == sel.first]} {pts_tag_set_first $w sel $newIndex} \ + elseif {[$w compare insert == sel.last]} {pts_tag_set_last $w sel $newIndex} \ + { $w tag remove sel 1.0 end + if {[$w compare $newIndex < insert]} {$w tag add sel $newIndex insert} {$w tag add sel insert $newIndex} + } + } + $w mark set insert $newIndex; $w see insert + update idletasks + # puts "[$w tag ranges sel]" + # puts "b=[$w index sel.first]-[$w index sel.last] i=[$w index insert]" +} + +# Imp: ^K B: Control-Space, ^K K: Control-Shift-Space + +bind Text <Control-Key-y> {ptsTextDelLn %W} +bind Text <Control-Key-Y> [bind Text <Control-Key-y>] +bind Text <Control-Key-d> {if {[%W compare {insert + 1 chars} != end]} {%W delete insert}} +# ^^^ ensures that pressing `Delete' on the last empty line is a no-op +bind Text <Key-Delete> [bind Text <Control-Key-d>] +# ^^^ don't clobber visible selection +bind Text <Key-BackSpace> {if {[%W compare insert != 1.0]} {%W delete insert-1c; %W see insert}} +# ^^^ don't clobber visible selection + +proc pts_entry_Delete {w} { + set i 0 + set j -1 + set k -1 + set i [$w index insert] + catch {set j [$w index sel.first]} + catch {set k [$w index sel.last]} + if {0==[string compare $i $j] || 0==[string compare $i $k]} \ + {$w delete sel.first sel.last} \ + {$w delete insert} +} + +bind Entry <B2-Motion> {} +bind Entry <Button-2> {} + +# vvv Overrides entry.tcl, so it won't clobber the selection. +bind Entry <Key-Delete> {pts_entry_Delete %W} +# vvv Overrides entry.tcl, so it won't clobber the selection. +bind Entry <Control-Key-d> {pts_entry_Delete %W} +bind Entry <Control-Key-i> {%W insert insert \t} + +# vvv Overrides entry.tcl, so it won't clobber the selection. +proc tkEntrySetCursor {w pos} {$w icursor $pos; tkEntrySeeInsert $w} +# vvv Overrides entry.tcl, so it won't clobber the selection. +proc tkEntryInsert {w s} {if {[string length $s]} { + $w insert insert $s + tkEntrySeeInsert $w +}} +# vvv Overrides entry.tcl with Turbo Pascal look and feel. +proc tkEntryKeySelect {w new} { + if {[$w selection present]} { + set i [$w index insert] + if {[$w index sel.first]==$i} {$w selection from sel.last} \ + elseif {[$w index sel.last]==$i} {$w selection from sel.first} \ + {$w selection from insert} + } {$w selection from insert} + $w selection to $new + $w icursor $new + # tkEntrySeeInsert will be called by our caller. +} +# vvv Overrides entry.tcl, so it won't clobber the selection. +proc tkEntryBackspace w { + set x [expr {[$w index insert] - 1}] + if {$x >= 0} {$w delete $x} + if {[$w index @0] >= [$w index insert]} { + set range [$w xview] + set left [lindex $range 0] + set right [lindex $range 1] + $w xview moveto [expr {$left - ($right - $left)/2.0}] + } +} + +proc pts_entry_paste_selection {w x y} { + #** If has focus, than pastes visible selection to the unchanged cursor + #** position; otherwise claims focus and sets cursor position to mouse. + if {0==[string compare $w [focus -displayof $w]]} { + catch {$w insert insert [selection get -displayof $w]} + if {0==[string compare normal [$w cget -state]]} {focus $w} + } {$w icursor [tkEntryClosestGap $w $x]; focus $w} +} +bind Entry <<PasteSelection>> {pts_entry_paste_selection %W %x %y} +bind Entry <Insert> {} ;# <Shift-Insert> already OK. + + +# vvv override tk.tcl, so it won't select the whole Entry when tab is pressed} +proc tkTabToWindow w {focus $w} + +# --- + +# vvv Imp: improve this on Windows +set sa_normfont [pts_last_font \ + system variable helvetica \ + arial {arial -12 normal} \ + -adobe-helvetica-medium-r-normal--11-*-100-100-*-*-iso8859-* \ + -adobe-helvetica-medium-r-normal--12-*-75-75-*-*-iso8859-* \ + sansserif dialog}] +set sa_boldfont [pts_last_font \ + sansserif system variable helvetica \ + arial {arial -12 bold} \ + -adobe-helvetica-bold-r-normal--12-*-75-75-*-*-iso8859-1 \ + -adobe-helvetica-bold-r-normal--11-80-100-100-p-60-iso8859-1 \ + dialogb] +set sa_fixfont [pts_last_font \ + fixed systemfixed fixsedsys monospaced monospace \ + -*-fixed-*-*-*--13-*-*-*-*-*-iso8859-1 \ + -misc-fixed-medium-r-semicondensed--13-*-75-75-*-*-iso8859-1 \ + 6x13] +# puts sa_normfont=$sa_normfont; puts sa_boldfont=$sa_boldfont +# Dat: 100 DPI, 14-point Helvetica is too large, 11-point is somewhat small + +option add *Dialog.msg.font $sa_normfont ;# respected +option add *Dialog.Button*font $sa_boldfont ;# respected + +wm title . {sam2p Job Editor} +set tk_StrictMotif 0 +pts_fix_shift_tab +# . configure -bg red + + +frame .gtop + +set g .gtop.g0 +frame $g + +label $g.lFileFormat -text FileFormat -anchor w -font $sa_boldfont +sa_radio $g.fPSL1 FileFormat PSL1 "PS L1" -command {update_radio FileFormat PSL1} +sa_radio $g.fPSLC FileFormat PSLC "PS LC" -command {update_radio FileFormat PSLC} +sa_radio $g.fPSL2 FileFormat PSL2 "PS L2" -command {update_radio FileFormat PSL2} +sa_radio $g.fPSL3 FileFormat PSL3 "PS L3" -command {update_radio FileFormat PSL3} +sa_radio $g.fPDFB10 FileFormat PDFB1.0 "PDF B 1.0" -command {update_radio FileFormat PDFB1.0} +sa_radio $g.fPDFB12 FileFormat PDFB1.2 "PDF B 1.2" -command {update_radio FileFormat PDFB1.2} +sa_radio $g.fPDF10 FileFormat PDF1.0 "PDF 1.0" -command {update_radio FileFormat PDF1.0} +sa_radio $g.fPDF12 FileFormat PDF1.2 "PDF 1.2" -command {update_radio FileFormat PDF1.2} +sa_radio $g.fGIF89a FileFormat GIF89a "GIF 89a" -command {update_radio FileFormat GIF89a} +sa_radio $g.fEmpty FileFormat Empty Empty -command {update_radio FileFormat Empty} +sa_radio $g.fMeta FileFormat Meta Meta -command {update_radio FileFormat Meta} +sa_radio $g.fPNM FileFormat PNM PNM -command {update_radio FileFormat PNM} +sa_radio $g.fPAM FileFormat PAM PAM -command {update_radio FileFormat PAM} +sa_radio $g.fPIP FileFormat PIP PIP -command {update_radio FileFormat PIP} +sa_radio $g.fJPEG FileFormat JPEG JPEG -command {update_radio FileFormat JPEG} +sa_radio $g.fTIFF FileFormat TIFF TIFF -command {update_radio FileFormat TIFF} +sa_radio $g.fPNG FileFormat PNG PNG -command {update_radio FileFormat PNG} + +pack $g.lFileFormat -fill x +pack $g.fPSL1 $g.fPSLC $g.fPSL2 $g.fPSL3 $g.fPDFB10 $g.fPDFB12 $g.fPDF10 $g.fPDF12 $g.fGIF89a \ + $g.fEmpty $g.fMeta $g.fPNM $g.fPAM $g.fPIP $g.fJPEG $g.fTIFF $g.fPNG -fill x +frame $g.pFileFormat -height 5 -width 1 +pack $g.pFileFormat -fill x + + +set g .gtop.g1 +frame $g + +label $g.lSampleFormat -text SampleFormat -anchor w -font $sa_boldfont +sa_radio $g.fOpaque SampleFormat Opaque Opaque -command {update_radio SampleFormat Opaque} +sa_radio $g.fTransparent SampleFormat Transparent Transparent -command {update_radio SampleFormat Transparent} +sa_radio $g.fGray1 SampleFormat Gray1 "Gray 1" -command {update_radio SampleFormat Gray1} +sa_radio $g.fIndexed1 SampleFormat Indexed1 "Indexed 1" -command {update_radio SampleFormat Indexed1} +sa_radio $g.fMask SampleFormat Mask Mask -command {update_radio SampleFormat Mask} +sa_radio $g.fTransparent2 SampleFormat Transparent2 "Transparent 2" -command {update_radio SampleFormat Transparent2} +sa_radio $g.fGray2 SampleFormat Gray2 "Gray 2" -command {update_radio SampleFormat Gray2} +sa_radio $g.fIndexed2 SampleFormat Indexed2 "Indexed 2" -command {update_radio SampleFormat Indexed2} +sa_radio $g.fTransparent4 SampleFormat Transparent4 "Transparent 4" -command {update_radio SampleFormat Transparent4} +sa_radio $g.fRGB1 SampleFormat RGB1 "RGB 1" -command {update_radio SampleFormat Rgb1} +sa_radio $g.fGray4 SampleFormat Gray4 "Gray 4" -command {update_radio SampleFormat Gray4} +sa_radio $g.fIndexed4 SampleFormat Indexed4 "Indexed 4" -command {update_radio SampleFormat Indexed4} +sa_radio $g.fTransparent8 SampleFormat Transparent8 "Transparent 8" -command {update_radio SampleFormat Transparent8} +sa_radio $g.fRgb2 SampleFormat Rgb2 "RGB 2" -command {update_radio SampleFormat Rgb2} +sa_radio $g.fGray8 SampleFormat Gray8 "Gray 8" -command {update_radio SampleFormat Gray8} +sa_radio $g.fIndexed8 SampleFormat Indexed8 "Indexed 8" -command {update_radio SampleFormat Indexed8} +sa_radio $g.fRgb4 SampleFormat Rgb4 "RGB 4" -command {update_radio SampleFormat Rgb4} +sa_radio $g.fRgb8 SampleFormat Rgb8 "RGB 8" -command {update_radio SampleFormat Rgb8} +pack $g.lSampleFormat -fill x +pack $g.fOpaque $g.fTransparent $g.fGray1 $g.fIndexed1 $g.fMask $g.fTransparent2 $g.fGray2 $g.fIndexed2 $g.fTransparent4 \ + $g.fRGB1 $g.fGray4 $g.fIndexed4 $g.fTransparent8 $g.fRgb2 $g.fGray8 \ + $g.fIndexed8 $g.fRgb4 $g.fRgb8 -fill x +frame $g.pSampleFormat -height 5 -width 1 +pack $g.pSampleFormat -fill x + +set g .gtop.g2 +frame $g + +proc find_val_range {key} { + #** @param key for example "/Compression", "/InputFile", of type tKey + #** @return "" or [beg end] abs.index of the value associated with that key + #** (may span multiple tokens) + global jtw ;# text widget containing the tagged job file + set end 1.0 + while {[llength [set lst [$jtw tag nextrange tKey $end]]]} { + set beg [lindex $lst 0] + set end [lindex $lst 1] + ##puts "key=<[$jtw get $beg $end]>" + set ikey [$jtw get $beg $end] + if {0==[string compare $ikey $key]} { + + ## puts prev=[$jtw tag prevrange tAny $end] + set lst [$jtw tag prevrange tAny $end] + if {0!=[llength $lst] && [$jtw compare [lindex $lst 0] < $end] + && [$jtw compare $end < [lindex $lst 1]]} { + set lst [list $end [lindex $lst 1]] + } { + if {![llength [set lst [$jtw tag nextrange tAny $end]]]} return "" + # ^^^ Imp: show error: found, but no value + } + ##puts "lst=$lst end=$end." + ##eval "puts \[$jtw get $lst\]" + if {2!=[llength [set tns [$jtw tag names [lindex $lst 0]]]]} return "" + # ^^^ Imp: show error: found, but untagged value + ##puts LT=[lindex $tns 1]:$tns: + if {![llength [set lst [$jtw tag nextrange [lindex $tns 1] $end]]]} return "" + # ^^^ This trick is used to find only a single tag. A single tag often + # means a single PostScript token, but -- for example `(a)(b)' and + # `[]' contain a single tag, but two tokens. + # Imp: show better error message + set white [$jtw get $end [lindex $lst 0]] + ##puts aaa($white) + if {[regexp "\[^\\000\011-\015 ]" $white]} return "" + # ^^^ Imp: show error: key and value separated by non-whitespace + ##puts bbb + set beg [lindex $lst 0] + set end [lindex $lst 1] + set val [$jtw get $beg $end] + set openc [expr {2*[string match <<* $val]+[string match \\\[* $val]}] ;# ] + ## puts "openc=$openc; val=<$val>" + if {$openc} { + set end "$beg + $openc chars" + set openc 1 + while {1} { + if {![llength [set lst [$jtw tag nextrange tBrac $end]]]} return "" + # ^^^ Imp: show error: unclosed >> + set val [$jtw get [lindex $lst 0] [lindex $lst 1]] + if {[string match <<* $val]} {incr openc; set end 2} \ + elseif {[string match \\\[* $val]} {incr openc; set end 1} \ + elseif {[string match >>* $val]} {incr openc -1; set end 2} \ + elseif {[string match \]* $val]} {incr openc -1; set end 1} \ + {return ""} + # ^^^ Imp: show error: invalid tBrac + set end "[lindex $lst 0] + $end chars" + if {!$openc} {return "$beg [$jtw index $end]"} + } + } + # puts "val=<$val>" + # return [$jtw get $beg $end] + return $lst + } + } + return "" +} + +proc update_psval {key newval} { + #** return oldval or "" + global jtw + if {![llength [set found [find_val_range $key]]]} {return ""} + set oldval [eval "$jtw get $found"] + eval "$jtw delete $found" + set found [lindex $found 0] + if {[string match /* $newval]} {$jtw insert $found $newval {tAny tNameval}} \ + elseif {[string match (* $newval]} {$jtw insert $found $newval {tAny tString}} \ + elseif {[string match \[-0-9\]* $newval]} {$jtw insert $found $newval {tAny tInt}} \ + {$jtw insert $found $newval {tAny tSing}} + $jtw mark set insert "$found + 1 chars"; $jtw see insert + return $oldval +} + +proc update_radio {key newval} { + global jtw + # puts "got=([find_val_range /Compression])" + #set found [find_val_range /Hints] + # set found [find_val_range /Profile] + #puts "found=$found." + #puts "is=([$jtw get [lindex $found 0] [lindex $found 1]])." + if {![string length [update_psval /$key /$newval]]} { + bell + pts_message_box -title Warning -message "Cannot find key /$key. Please verify that the .job file is correct." + } +} + +proc update_check {key wPath} { + set varname [$wPath cget -variable] + global $varname + if {[set $varname]} {update_psval /$key true} {update_psval /$key false} +} + +#set psstr_map "" +#proc psstr_map_init {} { +# for {set i 0} {$i<32} {incr i} {lappend psstr_map [format %c $i] [format \\%02o $i]} +# for {set i 127} {$i<256} {incr i} {lappend psstr_map [format %c $i] [format \\%02o $i]} +#} +#(\\)' +#psstr_map_init +#regexp {^[] -'+-[^]+} str + +proc pts_psstr_q {str} { + #** This would be <60 chars in Perl. TCL is stupid, lame and sloow. + set ret "" + while {1} { + regexp {^[] -'+-[^-~]*} $str head + # ^^^ rejects low-unprintable, >=127, backslash, lparen and rparen + set ret $ret$head + if {[string length $str]==[set headlen [string length $head]]} break + scan [string index $str $headlen] %c charcode + set ret $ret[format \\%03o [expr {$charcode&255}]] + set str [string range $str [expr {1+$headlen}] end] + } + return $ret +} + +proc update_str {key newval empty} { + # Imp: regsub... + # set newval [string map $psstr_map $newval] + if {[string length $newval]} {set newval ([pts_psstr_q $newval])} {set newval $empty} + if {![string length [update_psval /$key $newval]]} { + bell + pts_message_box -title Warning -message "Cannot find key /$key. Please verify that the .job file is correct." + } +} + +proc update_int {key newval empty} { + if {[catch {set intval [expr {0+$newval}]}] || [string compare $intval $newval]} {set intval $empty} + if {![string length [update_psval /$key $intval]]} { + bell + pts_message_box -title Warning -message "Cannot find key /$key. Please verify that the .job file is correct." + } +} + +proc but_save {} { + global jtw jfn + set f [open [$jfn get] w] + catch {fconfigure $f -encoding binary} ;# TCL 8.2 + fconfigure $f -translation binary + puts -nonewline $f [$jtw get 1.0 end] + close $f + # bell +} + +set tmpfnb "sam2p_tmp_[pid]" + +proc but_relight {} { + # Imp: error checks + # Imp: \n transl + # set f [open |[list tr a-z A-Z >tmp.tmp] w] + global jtw tmpfnb + set f [open "|perl -I. -Msam2ptol -e sam2ptol::highlight $jtw >$tmpfnb.tjb" w] + catch {fconfigure $f -encoding binary} ;# TCL 8.2 + fconfigure $f -translation binary + puts -nonewline $f [$jtw get 1.0 end] + close $f + set f [open $tmpfnb.tjb r] + catch {fconfigure $f -encoding binary} ;# TCL 8.2 + fconfigure $f -translation binary + # puts [read $f] + eval [read $f] + close $f + file delete -- $tmpfnb.tjb +} + +proc but_load {} { + global jtw jfn tmpfnb + if {[catch {set f [open [$jfn get] r]} err]} { + pts_message_box -message "Load failed: $err" + } { + catch {fconfigure $f -encoding binary} ;# TCL 8.2 + fconfigure $f -translation binary + $jtw delete 1.0 end + $jtw insert end [read $f] + close $f + but_relight + # bell + + global InputFile InputFileOK + set InputFile "" + if {[llength [set found [find_val_range /InputFile]]]} { + set val [eval "$jtw get $found"] + if {[string match (*) $val]} { + # vvv Imp: real PS backslash interpolation, not TCL + set InputFile [subst -nocommands -novariables [string range $val 1 [expr {[string length $val]-2}]]] + } + } + set InputFileOK [pts_read_ok $InputFile] + + global OutputFile OutputFileOK + set OutputFile "" + if {[llength [set found [find_val_range /OutputFile]]]} { + set val [eval "$jtw get $found"] + if {[string match (*) $val]} { + # vvv Imp: real PS backslash interpolation, not TCL + set OutputFile [subst -nocommands -novariables [string range $val 1 [expr {[string length $val]-2}]]] + } + } + set OutputFileOK [pts_write_ok $OutputFile] + + global FileFormat + set FileFormat "" + if {[llength [set found [find_val_range /FileFormat]]]} { + set FileFormat [string range [eval "$jtw get $found"] 1 end] + } + + global SampleFormat + set SampleFormat "" + if {[llength [set found [find_val_range /SampleFormat]]]} { + set SampleFormat [string range [eval "$jtw get $found"] 1 end] + } + + global Compression + set Compression "" + if {[llength [set found [find_val_range /Compression]]]} { + set Compression [string range [eval "$jtw get $found"] 1 end] + } + + global TransferEncoding + set TransferEncoding "" + if {[llength [set found [find_val_range /TransferEncoding]]]} { + set TransferEncoding [string range [eval "$jtw get $found"] 1 end] + } + + global Predictor + set Predictor "" + if {[llength [set found [find_val_range /Predictor]]]} { + set Predictor [eval "$jtw get $found"] + } + + global TransferCPL + set TransferCPL "" + if {[llength [set found [find_val_range /TransferCPL]]]} { + set TransferCPL [eval "$jtw get $found"] + } + + global Effort + set Effort "" + if {[llength [set found [find_val_range /Effort]]]} { + set Effort [eval "$jtw get $found"] + } + + global RecordSize + set RecordSize "" + if {[llength [set found [find_val_range /RecordSize]]]} { + set RecordSize [eval "$jtw get $found"] + } + + global K + set K "" + if {[llength [set found [find_val_range /K]]]} { + set K [eval "$jtw get $found"] + } + + global Quality + set Quality "" + if {[llength [set found [find_val_range /Quality]]]} { + set Quality [eval "$jtw get $found"] + } + + global WarningOK + set WarningOK "" + if {[llength [set found [find_val_range /WarningOK]]]} { + if {[string compare true [eval "$jtw get $found"]]} {set WarningOK 1} {set WarningOK 1} + } + + global TmpRemove + set TmpRemove "" + if {[llength [set found [find_val_range /TmpRemove]]]} { + if {[string compare true [eval "$jtw get $found"]]} {set TmpRemove 1} {set TmpRemove 1} + } + + } +} + +proc but_quit {} { + if {0==[string compare yes [pts_message_box -type yesno -title {Confirm quit} -message "Quit now, without saving?"]]} exit +} + +proc but_run {} { + # by pts@fazekas.hu at Fri Apr 26 23:43:17 CEST 2002 + global JobFile + sa_debug_append "exec sam2p $JobFile:\n" + # if {[catch {set ret [exec sam2p $JobFile 2>@ stdout]} ret]} {} + if {[catch {set ret [exec sh -c {exec sam2p $1 2>&1} sam2p. $JobFile]} ret]} { + set ret "Error running sam2p:\n$ret" + } + # puts ($ret) + sa_debug_append $ret\n\n +} + +# option add *Dialog*Label*font fixed +# option add *Label*Font times +#option add *font times +#option add *$g*font times +#option add *Dialog.msg.background red + +label $g.lCompression -text Compression -anchor w -font $sa_boldfont +sa_radio $g.fNone Compression None None -command {update_radio Compression None} +sa_radio $g.fLZW Compression LZW LZW -command {update_radio Compression LZW} +sa_radio $g.fZIP Compression ZIP ZIP -command {update_radio Compression ZIP} +sa_int $g.fZIP.fEffort Effort Effort 2 -textvariable Effort +bind $g.fZIP.fEffort.i <FocusOut> {update_int Effort [%W get] pop} +pack $g.fZIP.fEffort -side left +sa_radio $g.fRLE Compression RLE RLE -command {update_radio Compression RLE} +sa_int $g.fRLE.fRecordSize RecordSize R.S 3 -textvariable RecordSize +bind $g.fRLE.fRecordSize.i <FocusOut> {update_int RecordSize [%W get] pop} +pack $g.fRLE.fRecordSize -side left +sa_radio $g.fFax Compression Fax Fax -command {update_radio Compression Fax} +sa_int $g.fFax.fK K K 5 -textvariable K +bind $g.fFax.fK.i <FocusOut> {update_int K [%W get] pop} +pack $g.fFax.fK -side left +sa_radio $g.fDCT Compression DCT DCT -command {update_radio Compression DCT} +sa_radio $g.fIJG Compression IJG IJG -command {update_radio Compression IJG} +sa_int $g.fIJG.fQuality Quality Q'lty 3 -textvariable Quality +bind $g.fIJG.fQuality.i <FocusOut> {update_int Quality [%W get] pop} +pack $g.fIJG.fQuality -side left +sa_radio $g.fJAI Compression JAI JAI -command {update_radio Compression JAI} +#label $g.fJAI.haha -text haha +#pack $g.fJAI.haha -side left +pack $g.lCompression -fill x +pack $g.fNone $g.fLZW $g.fZIP $g.fRLE $g.fFax $g.fDCT $g.fIJG $g.fJAI -fill x +sa_vframe $g + +sa_int $g.lPredictor Predictor Predictor 3 -textvariable Predictor +bind $g.lPredictor.i <FocusOut> {update_int Predictor [%W get] pop} +pack $g.lPredictor -fill x +sa_vframe $g + +sa_check_update $g.cWarningOK WarningOK WarningOK +# -textvariable WarningOK +pack $g.cWarningOK -fill x +sa_vframe $g + +label $g.lTransferEncoding -text TransferEncoding -anchor w -font $sa_boldfont +sa_radio $g.fBinary TransferEncoding Binary Binary -command {update_radio TransferEncoding Binary} +sa_radio $g.fASCII TransferEncoding ASCII ASCII -command {update_radio TransferEncoding ASCII} +sa_radio $g.fHex TransferEncoding Hex Hex -command {update_radio TransferEncoding Hex} +sa_radio $g.fA85 TransferEncoding A85 A85 -command {update_radio TransferEncoding A85} +pack $g.lTransferEncoding -fill x +pack $g.fBinary $g.fASCII $g.fHex $g.fA85 -fill x +frame $g.pTransferEncoding -height 5 -width 1 +pack $g.pTransferEncoding -fill x + +sa_int $g.fTransferCPL TransferCPL TransferCPL 3 -textvariable TransferCPL +bind $g.fTransferCPL.i <FocusOut> {update_int TransferCPL [%W get] pop} + +pack $g.fTransferCPL -fill x +sa_vframe $g + +sa_check_update $g.cTmpRemove TmpRemove {Tmp Remove} +pack $g.cTmpRemove -fill x +sa_vframe $g + + +set g .gtop.g3 +frame $g + +sa_w_text $g.t -width 58 -height 18 -wrap none -font $sa_fixfont +pts_fix_one_tab $g.t +pts_text_autoindent $g.t 1 +pts_text_auto_overstrike $g.t 0 +# $g.t insert end "<<%sam2p job file\n /InputFile (alma)\n /OutputFile (korte)\n /Profile \[\n /Compression /LZW/Predictor 13\n /Hints<</DCT <</a true /b (>>)>> >>\n ]\n>>\n" +# $g.t insert end [read [open template.job r]] +# Imp: close file... +$g.t mark set insert 1.0; $g.t see insert +$g.t tag configure tAny; $g.t tag lower tAny sel +$g.t tag configure tSing -foreground "#003f7f"; $g.t tag raise tSing sel +$g.t tag configure tString -foreground "#007f7f"; $g.t tag raise tString sel +$g.t tag configure tKey -foreground "#00007f"; $g.t tag raise tKey sel +$g.t tag configure tNameval -foreground "#0000ff"; $g.t tag raise tNameval sel +$g.t tag configure tBrac -foreground "#ff0000"; $g.t tag raise tBrac sel +$g.t tag configure tComment -foreground "#007f00"; $g.t tag raise tComment sel +$g.t tag configure tInt -foreground "#3f0000"; $g.t tag raise tInt sel +$g.t tag configure tError -background "#ffdddd"; $g.t tag lower tError sel + +# puts X[bindtags $g.t]X +# puts X[bind $g.t]X +# puts XZ[bind all]X + +set jtw $g.t + +# Imp: delete tmp.tmp + +# -font sansserif +# puts [$g.t tag ranges tSing] +# reground blue + +# update idletasks; puts [winfo geometry $g.t] ;# not ready, has to be packed first + +frame $g.f +sa_w_text $g.f.td -width 1 -height 13 -wrap char -font $sa_fixfont \ + -yscrollcommand "$g.f.sd set" -spacing3 2 +$g.f.td configure -selectbackground yellow ;# override +scrollbar $g.f.sd -command "$g.f.td yview" -width 11 -elementborderwidth 2 \ + -relief flat -borderwidth 1 -takefocus 0 -troughcolor gray65 +$g.f.sd configure -activebackground [$g.f.sd cget -background] + +# OK: non-editable, but not disabled (we need the cursor!) +# $g.f.td configure -background [lindex [$g.f.td configure -background] 3] +pts_readonly_color $g.f.td +# puts $g.f.td +# puts TD:[bind .gtop.g3.f.td <Key-Return>] + +pts_fix_one_tab $g.f.td +$g.f.td insert end "Debug messages, sam2p output:\n\n" +# $g.f.td insert end "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n" +# $g.f.td insert end "21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n" +$g.f.td mark set insert 1.0; $g.f.td see insert +set debugtext $g.f.td + +pack $g.t -expand 0 -fill x +pack $g.f.td -expand 1 -fill both -side left +pack $g.f.sd -fill both -side left +pack $g.f -expand 1 -fill both + +pack .gtop.g0 .gtop.g1 .gtop.g2 -side left +pack .gtop.g3 -expand 1 -fill both -side left + +frame .gbot +frame .gbot.gbl + +set g .gbot.gbl.fCurdir +frame $g +label $g.l -text "Current dir" -font $sa_boldfont +sa_w_entry $g.e -font $sa_normfont +# bind $g.e <FocusOut> {update_str e [%W get] pop} +pack $g.l -side left +pack $g.e -expand 1 -fill x -side left +$g.e insert 0 [pwd] + +# puts [bind .gbot.gbl.fCurdir.e] + +bind Text <B2-Motion> {} +bind Text <Button-2> {} +# puts T[bind Text]T +# puts [bind Text <Button-2>] +#puts ([bind Entry <Tab>]) + +#foreach evtseq [bind Entry] { +# if {[string match <Key-*> $evtseq] +# || [string match <*-Key-*> $evtseq] +# || [string match <*-Key> $evtseq] +# } { +# bind $g.e $evtseq {break} +# puts +:$evtseq +# } { +# #puts -:$evtseq +# } +#} + +# Dat: this assumes [lindex [bindtags $g.e] 0] == $g.e +#foreach tag [bindtags $g.e] { +# foreach evtseq [bind $tag] { +# # if {0==[string length [bind $g.e $evtseq]]} {bind $g.e $evtseq [bind $tag $evtseq]} +# } +#} + +pts_readonly_color $g.e + + +# event info <<Clear>> +#bind $g.e <Key-Tab> {# nothing} +#bind $g.e <Key-ISO_Left_Tab> {# nothing} +# puts /[bind $g.e] +# puts :[bind $g.e <Key-Return>] + +set g .gbot.gbl.fJobFile +frame $g +label $g.l -text JobFile -font $sa_boldfont +sa_w_entry $g.e -font $sa_normfont -textvariable JobFile +label $g.r -text OK -font $sa_normfont -textvariable JobFileOK -width 2 +bind $g.e <FocusOut> {set JobFileOK [pts_write_ok $JobFile]} +set jfn $g.e +pack $g.l -side left +pack $g.e -expand 1 -fill x -side left +pack $g.r -side left + + +set g .gbot.gbl.fInputFile +frame $g +label $g.l -text InputFile -font $sa_boldfont +sa_w_entry $g.e -font $sa_normfont -textvariable InputFile +label $g.r -text OK -font $sa_normfont -textvariable InputFileOK -width 2 +bind $g.e <FocusOut> {update_str InputFile [%W get] pop; set InputFileOK [pts_read_ok $InputFile]} +pack $g.l -side left +pack $g.e -expand 1 -fill x -side left +pack $g.r -side left +set InputFileOK [pts_read_ok $InputFile] + +set g .gbot.gbl.fOutputFile +frame $g +label $g.l -text OutputFile -font $sa_boldfont +sa_w_entry $g.e -font $sa_normfont -textvariable OutputFile +label $g.r -text OK -font $sa_normfont -textvariable OutputFileOK -width 2 +bind $g.e <FocusOut> {update_str OutputFile [%W get] pop; set OutputFileOK [pts_write_ok $OutputFile]} +pack $g.l -side left +pack $g.e -expand 1 -fill x -side left +pack $g.r -side left + +pack .gbot.gbl.fCurdir .gbot.gbl.fJobFile .gbot.gbl.fInputFile .gbot.gbl.fOutputFile -expand 1 -fill x + +frame .gbot.ha +button .gbot.ha.bLoad -text {Load Job} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \ + -command but_load +bind . <Alt-Key-l> but_load +button .gbot.ha.bSave -text {Save Job} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \ + -command but_save +bind . <Alt-Key-s> but_save + +frame .gbot.hb +button .gbot.hb.bRun -text {Run} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \ + -command but_run +bind . <Alt-Key-r> but_run +button .gbot.hb.bQuit -text {Quit} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \ + -command but_quit +bind . <Alt-Key-q> but_quit +pack .gbot.gbl -expand 1 -fill x -side left +pack .gbot.ha.bLoad .gbot.ha.bSave +pack .gbot.hb.bRun .gbot.hb.bQuit +pack .gbot.ha .gbot.hb -side left + +pack .gtop -expand 1 -fill both +pack .gbot -expand 0 -fill x +update idletasks ;# a sima [update] helyett, hogy a "geometry" jó legyen +scan [wm geometry .] "%dx%d%s" width height tmp +wm minsize . $width $height + + +set env(PATH) $env(PATH)[pts_PATH_sep]. +#if {[catch {set ret [exec sam2p --help 2>&1]} ret]} {} +if {[catch {set ret [exec sh -c {exec sam2p --help 2>&1}]} ret]} { + set ret "Error:\n$ret" +} + +proc sa_debug_append msg { + global debugtext + $debugtext insert end $msg + $debugtext mark set insert end + $debugtext see insert +} + +sa_debug_append $ret\n\n +# puts ($ret) + + +$jfn delete 0 end +if {[llength $argv]} {$jfn insert 0 [lindex $argv 0]; but_load} { + $jfn insert 0 template.job; but_load; $jfn delete 0 end + set InputFileOK 0 + set OutputFileOK 0 + set JobFileOK 0 +} +# set InputFile hello +# but_load +# puts $argv +# puts TD:[bind .gtop.g3.f.td <Key-Return>] + + +#__END__ diff --git a/Build/source/utils/sam2p/contrib/sam2ptol.pm b/Build/source/utils/sam2p/contrib/sam2ptol.pm new file mode 100644 index 00000000000..8c73da50fce --- /dev/null +++ b/Build/source/utils/sam2p/contrib/sam2ptol.pm @@ -0,0 +1,77 @@ +# sam2ptol.pm by pts@math.bme.hu at Sun Apr 7 14:48:27 CEST 2002 +package sam2ptol; +BEGIN{$^W=1} +use integer; +use strict; + +my %keys=qw{/InputFile 1 /OutputFile 1 /TmpRemove 1 /Profile 1 + /FileFormat 1 /SampleFormat 1 /WarningOK 1 /TransferEncoding 1 /Compression 1 + /Predictor 1 /Transparent 1 /Hints 1 + /Effort 1 /RecordSize 1 /K 1 /Quality 1 /ColorTransform 1 /TransferCPL 1 + /EncoderColumns 1 /EncoderRows 1 /EncoderColors 1 + /PredictorColumns 1 /PredictorBPC 1 /PredictorColors 1 + /Comment 1 /Title 1 /Subject 1 /Author 1 /Creator 1 /Producer 1 + /Created 1 /Produced 1 /LoadHints 1 /Templates 1}; +# Dat: DCT is not key! +my %values=qw{ + /PSL1 1 /PSLC 1 /PSL2 1 /PSL3 1 /PDFB1.0 1 /PDFB1.2 1 /PDF1.0 1 /PDF1.2 1 + /GIF89a 1 /Empty 1 /Meta 1 /PNM 1 /PAM 1 /PIP 1 /Opaque 1 /Transparent 1 + /Transparent2 1 /Transparent4 1 /Transparent8 1 /Gray1 1 /Gray2 1 /Gray4 1 + /Gray8 1 /Indexed1 1 /Indexed2 1 /Indexed4 1 /Indexed8 1 /Mask 1 /Rgb1 1 + /Rgb2 1 /Rgb4 1 /Rgb8 1 /RGB1 1 /RGB2 1 /RGB4 1 /RGB8 1 /Asis 1 /Binary 1 + /ASCII 1 /Hex 1 /AHx 1 /ASCIIHex 1 /A85 1 /ASCII85 1 /None 1 /LZW 1 /ZIP 1 + /Flate 1 /Fl 1 /RLE 1 /RunLength 1 /RunLengthEncoded 1 /RL 1 /PackBits 1 + /Fax 1 /CCITTFax 1 /CCF 1 /DCT 1 /JPEG 1 /JPG 1 /JFIF 1 /IJG 1 /JAI 1 +}; + +sub highlight { + #** Example: perl -I. -Msam2ptol -e sam2ptol::highlight alma <examples/a_jpg.job + die "$0: 1arg, tclPath expected\n" if @ARGV!=1; + my $w=$ARGV[0]; # name of the widget + $_=join'',<STDIN>; + my($beg,$end,$c,$ta,$tb); + for (qw{tError tInt tComment tString tSing tKey tNameval tBrac}) { print "$w tag remove tString 1.0 end\n" } + while (m@( + \((\\.|[^\\()]+)*\) # String. Imp: nesting?? + |/([^\000-\040/\%{}<>\[\]()\177-\377]*) # Sname + |[_A-Za-z_]([^\000-\040/\%{}<>\[\]()\177-\377]*) # Ename + |<<|>>|\[|\] + |true|false|pop|null + |%[^\r\n]* + |-?\d+ + )@gsx) { + my $e=$1; + $beg=($end=pos())-length($e); + $c=substr($e,0,1); + $ta="$w tag add"; $tb=" {1.0 + $beg chars} {1.0 + $end chars}\n"; + if ($c eq'/') { + if (exists $keys{$e}) { + print "$ta tKey$tb"; + # print STDERR "($e)\n"; + } elsif (exists $values{$e}) { + print "$ta tNameval$tb"; + } else { + print "$ta tError$tb"; + } + } elsif ($c eq'(') { + print "$ta tString$tb"; + print "$w tag add tString {1.0 + $beg chars} {1.0 + $end chars}\n" + } elsif ($e eq'true' or $e eq'false' or $e eq'pop' or $e eq'null') { + print "$ta tSing$tb"; + } elsif ($e=~/\A[_A-Za-z]/) { + # } elsif ($e=~/\A\w/) { + # print STDERR "($e)\n"; + print "$ta tError$tb"; + } elsif ($c eq'%') { + print "$ta tComment$tb"; + } elsif ($c eq'-' or ord($c)>=ord('0') and ord($c)<=ord('9')) { + print "$ta tInt$tb"; + } else { + print "$ta tBrac$tb"; + } + print "$ta tAny$tb"; + # print "[".pos()."]\n"; + } +} + +1; diff --git a/Build/source/utils/sam2p/contrib/template.job b/Build/source/utils/sam2p/contrib/template.job new file mode 100644 index 00000000000..751846d499f --- /dev/null +++ b/Build/source/utils/sam2p/contrib/template.job @@ -0,0 +1,33 @@ +<<%sam2p job file template (.cpp code is _not_ generated from this) + /InputFile pop + /OutputFile pop + /TmpRemove true /LoadHints pop /Templates pop + /Profile [<< + /FileFormat pop + /SampleFormat pop + /WarningOK true + /TransferEncoding pop + /Compression /None + /Predictor 1 + /Transparent null + /Hints << + /Effort -1 + /RecordSize 0 + /K 0 + /Quality 75 + /ColorTransform pop + /TransferCPL 78 + /DCT <<>> + /EncoderColumns 0 /EncoderRows 0 /EncoderColors 0 + /PredictorColumns 0 /PredictorBPC 0 /PredictorColors 0 + /Comment pop + /Title pop + /Subject pop + /Author pop + /Creator pop + /Producer pop + /Created pop + /Produced pop + >> + >>] +>>% __EOF__ diff --git a/Build/source/utils/sam2p/crc32.c b/Build/source/utils/sam2p/crc32.c new file mode 100644 index 00000000000..9ad826b9a58 --- /dev/null +++ b/Build/source/utils/sam2p/crc32.c @@ -0,0 +1,142 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Ripped from the zip sources: + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* $Id: crc32.c,v 1.2 2002/12/11 14:01:52 pts Exp $ */ + +#ifdef __GNUC__ +#pragma implementation +#endif +#if OBJDEP +# warning PROVIDES: crc32 +#endif + +/*#include "zip.h"*/ +/* #ifndef USE_ZLIB */ +#include "crc32.h" + +#define ZCONST PTS_const + +#ifdef CRC32 +# undef CRC32 +#endif +#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) +#define DO1(buf) crc = CRC32(crc, *(unsigned char ZCONST*)buf++) +#define DO2(buf) DO1(buf); DO1(buf) +#define DO4(buf) DO2(buf); DO2(buf) +#define DO8(buf) DO4(buf); DO4(buf) + +#undef NO_UNROLLED_LOOPS +#define local static +#define ulg unsigned PTS_INT32_T +#define uch unsigned char +#define extent slen_t +#ifndef NULL +#define NULL ((void*)0) +#endif +#ifndef near +#define near +#endif +#ifndef ___ +/**** pts ****/ +#if defined(__STDC__) || defined(__cplusplus) +# define _(args) args +# define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */ +#else +# define _(args) () +# define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */ +#endif +#endif + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local ZCONST ulg near crc_table[] = { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +}; + + +/* ========================================================================= */ +ulg crc32 ___((register ulg crc, register ZCONST char *buf, extent len),(crc, buf, len),( + register ulg crc; /* crc shift register */ + register ZCONST char *buf; /* pointer to bytes to pump through */ + extent len; /* number of bytes in buf[] */ +/* Run a set of bytes through the crc shift register. If buf is a NULL + pointer, then initialize the crc shift register contents instead. + Return the current crc in either case. */ +)) { + /* register ulg near *crc_table; */ + + if (buf == NULLP) return crc /*0L*/; + + /* crc_table = get_crc_table(); */ + + crc = crc ^ 0xffffffffUL; +#ifndef NO_UNROLLED_LOOPS + while (len >= 8) { + DO8(buf); + len -= 8; + } +#endif + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffUL; /* (instead of ~c for 64-bit machines) */ +} + +/* #endif */ /* !USE_ZLIB */ + +/* __EOF__ */ diff --git a/Build/source/utils/sam2p/crc32.h b/Build/source/utils/sam2p/crc32.h new file mode 100644 index 00000000000..0059919ab91 --- /dev/null +++ b/Build/source/utils/sam2p/crc32.h @@ -0,0 +1,30 @@ +/* crc32.c -- Calculate CRC-32 for GZIP + PNG + */ + +#ifndef CRC32_H +#define CRC32_H 1 + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "config2.h" + +#define CRC32_INITIAL ((unsigned PTS_INT32_T)0) +/** Usage: + * unsigned PTS_INT32_T crc=CRC32_INITIAL; + * crc=crc32(crc, "alma", 4); + * crc=crc32(crc, "korte", 5); + * ... + * putchar( (char)(crc & 0xff) ); + * putchar( (char)((crc >> 8) & 0xff) ); + * putchar( (char)((crc >> 16) & 0xff) ); + * putchar( (char)((crc >> 24) & 0xff) ); + */ +extern +#ifdef __cplusplus +"C" +#endif +unsigned PTS_INT32_T crc32 _((unsigned PTS_INT32_T oldcrc, char PTS_const *s, slen_t slen)); + +#endif /* CRC32_H */ diff --git a/Build/source/utils/sam2p/debian/README.debian b/Build/source/utils/sam2p/debian/README.debian new file mode 100644 index 00000000000..99058a15076 --- /dev/null +++ b/Build/source/utils/sam2p/debian/README.debian @@ -0,0 +1,6 @@ +The Debian Package sam2p +---------------------------- + +Comments regarding the Package + +Szabó Péter <pts@winter>, Fri, 7 Feb 2003 12:16:40 +0100 diff --git a/Build/source/utils/sam2p/debian/changelog b/Build/source/utils/sam2p/debian/changelog new file mode 100644 index 00000000000..b5a524be674 --- /dev/null +++ b/Build/source/utils/sam2p/debian/changelog @@ -0,0 +1,192 @@ +sam2p (0.45-2) unstable; urgency=low + + * cgif.c is indicated to be free software. + + -- Szabó Péter <pts@math.bme.hu> Sun, 2 Jul 2006 23:04:21 +0200 + +sam2p (0.45-1) unstable; urgency=low + + * Small docs changes. + * Little bugfixes. + + -- Szabó Péter <pts@math.bme.hu> Sun, 2 Jul 2006 17:19:29 +0200 + +sam2p (0.44-14) unstable; urgency=low + + * assertion BUGFIX in image.cpp:1480 Image::SampledInfo::setSampleFormat() + + -- Szabo Peter <pts@math.bme.hu> Thu, 6 Apr 2006 15:13:11 +0200 + +sam2p (0.44-13) unstable; urgency=low + + * Added -j:quiet + * No >/dev/null on png22pnm and tif22pnm + + -- Szabó Péter <pts@math.bme.hu> Fri, 26 Aug 2005 08:29:56 +0200 + +sam2p (0.44-12) unstable; urgency=low + + * Fixed non-(0,0)-based EPS loading by putting `translate' after + `setpagedevice' in in_ps.cpp + + -- Szabó Péter <pts@math.bme.hu> Fri, 12 Aug 2005 23:13:38 +0200 + +sam2p (0.44-11) unstable; urgency=low + + * %%BeginData:; hack for GSView, as reported by Zoltán Petres + + -- Szabó Péter <pts@math.bme.hu> Tue, 17 May 2005 14:39:20 +0200 + +sam2p (0.44-10) unstable; urgency=low + + * encoder.cpp slen_t -> int fixes for 64-bit. Thanks to Stefan Fritsch. + + -- Szabó Péter <pts@math.bme.hu> Thu, 14 Apr 2005 09:23:01 +0200 + +sam2p (0.44-9) unstable; urgency=low + + * 64-bit fix (slen_t and slendiff_t), in reply to the + report by Stefan Fritsch. + + -- Szabó Péter <pts@math.bme.hu> Tue, 12 Apr 2005 20:51:40 +0200 + +sam2p (0.44-8) unstable; urgency=low + + * Added /ImageDPI and -m:dpi:, see README. + * Fixed a couple of bugs. + + -- Szabó Péter <pts@winter> Mon, 21 Feb 2005 23:53:51 +0100 + +sam2p (0.44-7) unstable; urgency=low + + * Updated copyright of pts_fax.c + * Updated copyright of cgif.c + * BUGFIX of JPEG -> EPS `delete tp' buf in appliers.cpp + + -- Szabó Péter <pts@math.bme.hu> Thu, 20 Jan 2005 15:11:23 +0100 + +sam2p (0.44-6) unstable; urgency=low + + * Re-ripped pts_defl.c from linux-2.6.8.1 (ZLIB 1.1.3), + formerly it was Info-ZIP 2.2 + * BUGFIX in image.cpp + * Documentation fixes + + -- Szabó Péter <pts@winter> Tue, 18 Jan 2005 17:04:28 +0100 + +sam2p (0.44-5) unstable; urgency=low + + * Added -pdf:x (generate PDF with /XObject{}s). + * Changed PDF output so elements of /Kids are indirect references + (see the PDF Reference 1.5 for details). + * Added option: -transparent "#abcdef" + + -- Szabó Péter <pts@winter> Sat, 8 Jan 2005 12:29:10 +0100 + +sam2p (0.44-4) unstable; urgency=low + + * Some glitches of g++-3.4 avoided. Now sam2p compiles fine. + * -l:gs=-r216 support for PDF. + + -- Szabó Péter <pts@math.bme.hu> Thu, 6 Jan 2005 10:59:50 +0100 + +sam2p (0.44-3) unstable; urgency=low + + * minor fixes, documentation addons + + -- Szabó Péter <pts@math.bme.hu> Tue, 1 Jun 2004 18:50:15 +0200 + +sam2p (0.44-2) unstable; urgency=low + + * Added answers to FAQ in README. + + -- Szabó Péter <pts@math.bme.hu> Fri, 5 Mar 2004 19:54:44 +0100 + +sam2p (0.44-1) unstable; urgency=low + + * bugfixes + * PDF, PS and EPS import + * compressed bts2.ttt, so target sam2p is smaller (ps_tiny --copy) + * printf("%.16g") in configure + + -- Szabó Péter <pts@math.bme.hu> Wed, 1 Oct 2003 19:49:32 +0200 + +sam2p (0.43-4) unstable; urgency=low + + * Allow to read stdin from a pipe + * Recognize SOF2 (progressive) JPEG and other non-baseline types + * Fixed SimBuffer::Flat::copyRange + + -- Szabó Péter <pts@math.bme.hu> Tue, 11 Mar 2003 14:10:37 +0100 + +sam2p (0.43-3) unstable; urgency=low + + * Merged with CVS, created Debian source packages. + + -- Szabó Péter <pts@math.bme.hu> Wed, 12 Feb 2003 20:51:58 +0100 + +sam2p (0.43-2) unstable; urgency=low + + * Added proper Description:, Depends: and Build-Depends: to + debian/changelog, modified the Makefile to respect $(DESTDIR) etc. + + -- Szabó Péter <pts@winter> Fri, 7 Feb 2003 14:16:56 +0100 + +sam2p (0.43-1) unstable; urgency=low + + * Initial Debian release. + * PDF generation bugfixes + * PDF /MediaBox is output into a separate line near the beginning of file + (graphicP compatibility) + +sam2p (0.41) unstable; urgency=low + + * vcsam2p.exe (graphic .exe with Visual Studio 6.0), merged + * added Below feature -m:lower:5 + * png22pnm support + * Debian Slink pdfTeX integration + + -- Szabó Péter <pts@winter> Wed, 5 Feb 2003 18:40:12 +0100 + +sam2p (0.41) unstable; urgency=low + + * All earlier versions listed here: + * 0.29 Apr 4 2002 + sam2p_article.tex preliminary version + * 0.30 Sat Apr 6 09:19:23 CEST 2002 + * 0.31 -- Fri Apr 12 23:54:57 CEST 2002 + not working TCL/TK GUI, sam2p_article corrected + * 0.32 Sat Apr 13 12:55:09 CEST 2002 -- + PCX input, class Encoder, class Decoder + * 0.33 JPEG, TIFF, PNG input. JPEG output. + * 0.34 PDF output, PNG output. + * 0.35 Fri Apr 26 08:28:41 CEST 2002 + transparency, gui, sam2p_talk, EuroBachoTeX 2002 + * 0.36 Sat May 26 14:06:09 CEST 2002 + Blanca bugfixes + * 0.37 Sat Jun 1 14:06:43 CEST 2002 + ccdep.pl, --enable-debug, XPM output, opaque TIFF output, + more PS output, BMP output, transparent PNM output, one-liner mode, + XWD output, PS output with margins, autoconf consts, + built-in CCITTFaxEncode + * 0.38 Tue Sep 3 20:16:59 CEST 2002 + Many portability bugfixes. Now more versions of GNU C++ compilers and + more achitectures are tested and supported. + gcc-3.1 or gcc-3.2 compliance (AC_C_CONST working const; with autoconf + 2.53) + * 0.39 -j:warn, allow /OutputFile(-) (stdout) in one-liner mode, + one-liner mode with src == dst filename `--', EPS margins, PDF margins, + -m, scaling PS output command line, PSL1 Gray ZIP&LZW in all + TransferEncodings + * 0.40 Wed Dec 11 19:24:31 CET 2002 + builds out-of-the box (./configure ...; make -> sam2p.exe) on Win32 with MinGW32 + Perl + * 0.41 GIF and XPM load bugfixes + synchronized to GIMP tif22pnm + transparent(+?) TIFF output, really + better tif22pnm support + + -- Szabó Péter <pts@winter> Wed, 5 Feb 2003 11:40:12 +0100 + +Local variables: +mode: debian-changelog +End: diff --git a/Build/source/utils/sam2p/debian/control b/Build/source/utils/sam2p/debian/control new file mode 100644 index 00000000000..0eb0ddd1293 --- /dev/null +++ b/Build/source/utils/sam2p/debian/control @@ -0,0 +1,24 @@ +Source: sam2p +Section: unknown +Priority: optional +Maintainer: Szabó Péter <pts@fazekas.hu> +Standards-Version: 3.2.1 +Build-Depends: g++, perl + +Package: sam2p +Architecture: any +Depends: ${shlibs:Depends} +Recommends: tif22pnm | netpbm, png22pnm | netpbm, libjpeg-progs +Description: convert raster images to EPS and PDF and others + sam2p is a UNIX command line utility written in ANSI C++ that converts many + raster (bitmap) image formats into Adobe PostScript or PDF files. The images + are not vectorized. sam2p gives full control to the user to specify + standards-compliance, compression, and bit depths. In some cases sam2p can + compress an image 100 times smaller than the PostScript output of many other + common image converters. sam2p provides ZIP, RLE and LZW (de)compression + filters even on Level1 devices. + . + Recommendations: package netpbm provides the tifftopnm and pngtopnm utilities. + Please use tif22pnm and png22pnm (by the author of sam2p) instead of these, + because *22* provides a much richer functionality with less bugs. package + libjpeg-prog provides the excellent cjpeg and djpeg utilities. diff --git a/Build/source/utils/sam2p/debian/copyright b/Build/source/utils/sam2p/debian/copyright new file mode 100644 index 00000000000..28c5b7b6aab --- /dev/null +++ b/Build/source/utils/sam2p/debian/copyright @@ -0,0 +1,4 @@ +This package was written by Szabó Péter pts@winter on Fri, 7 Feb 2003 12:16:40 +0100. + +Copyright: GPL (see /usr/share/common-licenses/GPL) + diff --git a/Build/source/utils/sam2p/debian/dirs b/Build/source/utils/sam2p/debian/dirs new file mode 100644 index 00000000000..3c52b973eae --- /dev/null +++ b/Build/source/utils/sam2p/debian/dirs @@ -0,0 +1,3 @@ +usr/bin +usr/sbin +usr/share/man/man1 diff --git a/Build/source/utils/sam2p/debian/rules b/Build/source/utils/sam2p/debian/rules new file mode 100755 index 00000000000..71ddf1a626b --- /dev/null +++ b/Build/source/utils/sam2p/debian/rules @@ -0,0 +1,69 @@ +#!/usr/bin/make -f +# Made with the aid of debmake, by Christoph Lameter, +# based on the sample debian/rules file for GNU hello by Ian Jackson. + +package=sam2p + +build: + $(checkdir) + ./configure --enable-gif --enable-lzw --prefix=/usr + $(MAKE) + touch build + +clean: + $(checkdir) + -rm -f build + -$(MAKE) MAKE_DIST=1 clean + -rm -f `find . -name "*~"` + -rm -rf debian/tmp debian/files* core debian/substvars +# Dat: make distclean would remove the `configure' script + +binary-indep: checkroot build + $(checkdir) +# There are no architecture-independent files to be uploaded +# generated by this package. If there were any they would be +# made here. + +binary-arch: checkroot build + $(checkdir) + -rm -rf debian/tmp + install -d debian/tmp + cd debian/tmp && install -d `cat ../dirs` + $(MAKE) install prefix=`pwd`/debian/tmp/usr DESTDIR=`pwd`/debian/tmp/usr +# Must have debmake installed for this to work. Otherwise please copy +# /usr/bin/debstd into the debian directory and change debstd to debian/debstd + debstd README README.1 README.2 README.3 README.4 README.5 README.6 README~ + dpkg-gencontrol -isp + chown -R root.root debian/tmp + chmod -R go=rX debian/tmp + dpkg --build debian/tmp .. + +define checkdir + test -f debian/rules +endef + +binary: + $(checkdir) + if test root = "`whoami`"; then $(MAKE) -f debian/rules binary-indep binary-arch; \ + else fakeroot $(MAKE) -f debian/rules binary-indep binary-arch; fi + +checkroot: + $(checkdir) + test root = "`whoami`" + +.PHONY: binary binary-arch binary-indep clean checkroot + +.PHONY: source source-here +source-here: + rm -rf debsrc + mkdir -p debsrc/debian + cp -a $(wildcard $(addprefix debian/,README.debian docs changelog control copyright dirs rules prerm postrm postinst preinst)) debsrc/debian + $(MAKEF) install-debsrc + DIR="`<debian/changelog perl -ne 'print if s@^(\S+) [(]([^)]+?)(?:-\d+)?[)].*@$$1-$$2@;last'`" && \ + test ! -d "$$DIR" && \ + mv debsrc "$$DIR" && \ + (dpkg-source -b "$$DIR";true) && \ + rm -rf "$$DIR" + +source: source-here + mv $(package)_*-*.tar.gz $(package)_*-*.dsc .. diff --git a/Build/source/utils/sam2p/encoder.cpp b/Build/source/utils/sam2p/encoder.cpp new file mode 100644 index 00000000000..8369fdc4c8e --- /dev/null +++ b/Build/source/utils/sam2p/encoder.cpp @@ -0,0 +1,1649 @@ +/* encoder.cpp -- various PostScript and PDF encoding filter implementations + * by pts@fazekas.hu at Sun Mar 3 14:16:00 CET 2002 + * --- Mon Mar 4 00:00:20 CET 2002 + */ + +/* Imp: make built-in FlateEncode DYNALLOC */ +/* Imp: add lzw_codec */ +/* Imp: add gzip */ +/* Imp: add zlib */ + +#ifdef __GNUC__ +#pragma implementation +#endif + + +#include "encoder.hpp" +#include "error.hpp" +#include "gensio.hpp" +#include <stdlib.h> /* getenv() */ +#include <string.h> + +/* --- */ + +/** Does output EOD (end-of-data) marker `>' */ +class ASCIIHexEncode: public PSEncoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + ASCIIHexEncode(GenBuffer::Writable &out_, unsigned maxcpl_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned maxcpl; + /** Number of hex digits already printed. */ + unsigned curcpl; + GenBuffer::Writable &out; +}; + +/** Does output EOD (end-of-data) marker `~>' */ +class ASCII85Encode: public PSEncoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + ASCII85Encode(GenBuffer::Writable &out_, unsigned maxcpl_); + virtual void vi_write(char const*buf, slen_t len); + + protected: + void wout(unsigned PTS_INT32_T buf_); + unsigned maxcpl; + /** Number of digits available in this line */ + GenBuffer::Writable &out; + unsigned ascii85breaklen; + unsigned ascii85left; + unsigned PTS_INT32_T ascii85buf; + char *obuf, *obufend, *op; +}; + +/** Doesn't output EOD (end-of-data) marker `>' */ +class RunLengthEncode: public PSEncoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + RunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize_); + virtual void vi_write(char const*buf, slen_t len); + + protected: + slen_t recordsize; + GenBuffer::Writable &out; + // char *obuf, *obufend, *op; + slen_t record_left; + unsigned saved_c, saved_rep; + /** size == header+buffer+EOD */ + char saved[130]; +}; + +static int gen_write(char *block, unsigned len, void *zfile); + +#if USE_BUILTIN_ZIP +#include "pts_defl.h" /* Imp: because pts_defl_interface :-( */ +#if OBJDEP +# warning REQUIRES: pts_defl +#endif +class FlateEncode: public PSEncoder { +#if PTS_DEFL_RIPPED_ZLIB /* Dat: defined in pts_defl.h */ + public: + /** @param level: 1..9: 9==highest compression */ + FlateEncode(GenBuffer::Writable &out_, unsigned level_); + virtual ~FlateEncode() { zlib_deflateEnd(&zs); } /* Dat: ==Z_OK check (for unflushed buffers) omitted */ + virtual void vi_write(char const*buf, slen_t len); + protected: + /** Formerly only one instance of FlateEncode was allowed. + * It exists <=> loced==true + */ + // static bool locked; + /** Writable that this filter writes to */ + GenBuffer::Writable &out; + char workspace[ZLIB_DEFLATE_WORKSPACESIZE_MIN]; /* big, about 300k */ + char obuf[4096]; + /*struct*/ z_stream zs; +#else /* old, ripped from Info-ZIP 2.2 */ + public: + /** @param level: 1..9: 9==highest compression */ + FlateEncode(GenBuffer::Writable &out_, unsigned level_); + virtual ~FlateEncode() { if (fs!=NULLP) fs->delete2(fs); } + virtual void vi_write(char const*buf, slen_t len); + static void *gen_malloc(unsigned n); + static void gen_free(void *p); + protected: + /** Formerly only one instance of FlateEncode was allowed. + * It exists <=> loced==true + */ + // static bool locked; + /** Writable that this filter writes to */ + GenBuffer::Writable &out; + #if SIZEOF_INT>2 + typedef unsigned s_t; + #else + typedef unsigned short s_t; + #endif + /** Adler32 checksum */ + s_t s1, s2; + bool had_header; + struct pts_defl_interface* fs; +#endif /* else PTS_DEFL_RIPPED_ZLIB */ +}; +#endif + +/** Just store the data in Flate (ZLIB) format, no real compression. Adds + * about 3 bytes of overhead per 65535 bytes (compression ratio: + * 100.004578%) + */ +class FlateStoreEncode: public PSEncoder { + public: + /** @param level: 1..9: 9==highest compression */ + FlateStoreEncode(GenBuffer::Writable &out_); + inline virtual ~FlateStoreEncode() {} + virtual void vi_write(char const*buf, slen_t len); + protected: + GenBuffer::Writable &out; + #if SIZEOF_INT>2 + typedef unsigned s_t; + #else + typedef unsigned short s_t; + #endif + /** Adler32 checksum */ + s_t s1, s2; + bool had_header; + /** Number of bytes already in buf */ + unsigned abuflen; + /** Max: 65535 */ + #if HAVE_STATIC_CONST + static const unsigned ABUFSIZE=65535; + #else + #define ABUFSIZE 65535 + #endif + /** Should really not allocate a FlateStoreEncode on the stack. */ + char abuf[ABUFSIZE+5]; +}; + +#if USE_BUILTIN_FAXE + +#include "pts_fax.h" +#if OBJDEP +# warning REQUIRES: pts_faxe +#endif +class CCITTFaxEncode: public PSEncoder { + public: + CCITTFaxEncode(GenBuffer::Writable &out_, slendiff_t K, slen_t Columns, bool EndOfLine, bool BlackIs1); + virtual void vi_write(char const*buf, slen_t len); + protected: + GenBuffer::Writable &out; + stream_CFE_state sCFEs; + unsigned char rbuf[4096]; + unsigned char wbuf[4096]; + stream_cursor_read r; + stream_cursor_write w; + unsigned char *hard, *rlimit; + + static void*gen_xalloc(unsigned n); + static void gen_free(void *ptr); + static void gen_memset(void *s, int c, unsigned n); + static void gen_memcpy(void *dest, const void *src, unsigned n); +}; +#endif + +#if USE_BUILTIN_LZW +#include "pts_lzw.h" /* Imp: because pts_lzw_state :-( */ +#if OBJDEP +# warning REQUIRES: pts_lzw +#endif +class LZWEncode: public PSEncoder { + public: + LZWEncode(GenBuffer::Writable &out_); + virtual void vi_write(char const*buf, slen_t len); + protected: + GenBuffer::Writable &out; + struct pts_lzw_state fs; +}; +#endif + +/** + * Reporting of GS errors is somewhat dump: the actual message isn't reported, + * only the fact that something went wrong. + * Imp: force a no-error trailer output by gs, and check that + */ +class GSEncode: public PSEncoder { + public: + /** @param filter_psname is a full-featured PostScript *Encode filter + * specification string, for example: "<</Effort 5>>/FlateEncode" or + * "0/RunLengthEncode" or "72 pop/ASCIIHexEncode"; will be surrounded as + * `currentfile ... filter' + */ + GSEncode(GenBuffer::Writable &out_, char const*filter_psname); + inline virtual ~GSEncode() {} + /* vvv Imp: correct these */ + virtual void vi_write(char const*buf, slen_t len); + protected: + class P: public Filter::PipeE { + protected: virtual void vi_check(); + public: P(GenBuffer::Writable &out_, char const*filter_psname); + }; + /** We need this delegator because `delete ...' won't work with multiple + * inheritance. (?? ) + */ + P p; +}; + +class CjpegEncode: public PSEncoder { + public: + /** @param filter_psname is a full-featured PostScript *Encode filter + * specification string, for example: "<</Effort 5>>/FlateEncode" or + * "0/RunLengthEncode" or "72 pop/ASCIIHexEncode"; will be surrounded as + * `currentfile ... filter' + */ + CjpegEncode(GenBuffer::Writable &out_, char const*filter_psname, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality); + inline virtual ~CjpegEncode() {} + virtual void vi_write(char const*buf, slen_t len); + protected: + class P: public Filter::PipeE { public: + // protected: virtual void vi_check(); + P(GenBuffer::Writable &out_, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality); + protected: /* Not needed: protected -> public: pacify VC6.0 */ + virtual void vi_copy(FILE *f); + bool rgbp; + }; + /** We need this delegator because `delete ...' won't work with multiple + * inheritance. (?? ) + */ + P p; +}; + +#if !USE_BUILTIN_LZW +class Lzw_codecEncode: public PSEncoder { + public: + /** @param filter_psname is a full-featured PostScript *Encode filter + * specification string, for example: "<</Effort 5>>/FlateEncode" or + * "0/RunLengthEncode" or "72 pop/ASCIIHexEncode"; will be surrounded as + * `currentfile ... filter' + */ + Lzw_codecEncode(GenBuffer::Writable &out_, char const*filter_psname); + inline virtual ~Lzw_codecEncode() {} + virtual void vi_write(char const*buf, slen_t len); + protected: + class P: public Filter::PipeE { public: + // protected: virtual void vi_check(); + P(GenBuffer::Writable &out_); + protected: + // virtual void vi_copy(FILE *f); + }; + /** We need this delegator because `delete ...' won't work with multiple + * inheritance. (?? ) + */ + P p; +}; +#endif + +class TIFFPredictor2: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + TIFFPredictor2(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned PTS_INT32_T h; + unsigned char *obuf, *op, bpc, cpp; + slen_t rlen; + GenBuffer::Writable &out; +}; + +class PNGPredictorNone: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorNone(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + slen_t rlen, opleft; + GenBuffer::Writable &out; +}; + +class PNGPredictorSub: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorSub(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned PTS_INT32_T h; + unsigned char *obuf, *op; + slen_t rlen; + GenBuffer::Writable &out; + unsigned char bpccpp; +}; + +class PNGPredictorUp: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorUp(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned char *obuf, *op, *oq; + slen_t rlen; + GenBuffer::Writable &out; +}; + +class PNGPredictorAverage: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorAverage(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned PTS_INT32_T h/*, g*/; + unsigned char *obuf, *op, *oq; + slen_t rlen; + GenBuffer::Writable &out; + unsigned char bpccpp; +}; + +class PNGPredictorPaeth: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorPaeth(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned PTS_INT32_T h, g; + unsigned char *obuf, *op, *oq; + slen_t rlen; + GenBuffer::Writable &out; + unsigned char bpccpp; +}; + +class PNGPredictorAuto: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorAuto(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned PTS_INT32_T h, g; + unsigned char *obuf, *o_prior, *o_0, *o_1, *o_2, *o_3, *o_4, *oo[5]; + slen_t rlen; + GenBuffer::Writable &out; + unsigned char bpccpp; + slen_t opleft; +}; + +/* Imp: code reuse with PNGPredictorAuto */ +class PNGPredictorAutoUnsigned: public Encoder { + public: + /** @param maxcpl_: maximum # hex digits per line, should be even */ + PNGPredictorAutoUnsigned(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + virtual void vi_write(char const*buf, slen_t len); + protected: + unsigned PTS_INT32_T h, g; + unsigned char *obuf, *o_prior, *o_0, *o_1, *o_2, *o_3, *o_4, *oo[5]; + slen_t rlen; + GenBuffer::Writable &out; + unsigned char bpccpp; + slen_t opleft; +}; + +/* --- */ + +FlateStoreEncode::FlateStoreEncode(GenBuffer::Writable &out_) + :out(out_) + ,s1(1) + ,s2(0) + ,had_header(false) + ,abuflen(0) + {} + +#if 0 +/** 0x7801: ZLIB header signaling fastest compression + * 0: 2 bits: DEFLATE block header signaling stored (uncompressed) block + + * 6 bits of padding. + */ +char FlateStoreEncode::header[3]= { 0x78, 1, 0 }; +#endif + +void FlateStoreEncode::vi_write(char const*buf, slen_t len) { + register s_t sold; + register char const*p=buf; char const*pend=p+len; + (void)sold; + if (len==0) { /* EOF: flush and send trailer */ + /* Dat: Last block has to be written even if it's empty. */ + if (!had_header) { out.vi_write("\x78\x01", 2); had_header=true; } + abuf[0]=(char)1; /* Last, stored block with padding */ + abuf[1]=abuflen; abuf[2]=abuflen>>8; + abuf[3]=~(abuflen); abuf[4]=~(abuflen>>8); + out.vi_write(abuf, abuflen+5); + if (s1>=65521) s1-=65521; + if (s2>=65521) s2-=65521; + unsigned char trailer[4]; + trailer[0]=s2>>8; trailer[1]=s2&255; trailer[2]=s1>>8; trailer[3]=s1&255; + out.vi_write((char const*)trailer,4); + out.vi_write(0,0); /* Signal EOF */ + return; + } + /* From rfc1950.txt: + Adler-32 is composed of two sums accumulated per byte: s1 is + the sum of all bytes, s2 is the sum of all s1 values. Both sums + are done modulo 65521. s1 is initialized to 1, s2 to zero. The + Adler-32 checksum is stored as s2*65536 + s1 in most- + significant-byte first (network) order. + */ + /* Update Adler-32 checksum */ + while (p!=pend) { + #if SIZEOF_INT>2 + if ((s1+=*(unsigned char const*)p)>=65521) s1-=65521; + if ((s2+=s1)>=65521) s2-=65521; + #elif SIZEOF_SHORT==2 + sold=s1; + if ((s1+=*(unsigned char const*)p))<sold) s1+=15; /* 15==65536-21 */ + sold=s2; + s2=(s2+s1)&0xffff; + if ((s2+=s1)<sold) s2+=15; + #else + /* vvv 0xffff is needed since unsigned short may be > 0..65535 */ + sold=s1; + s1=(s1+*(unsigned char const*)p)&0xffff; + if (s1<sold) s1+=15; /* 15==65536-21 */ + sold=s2; + s2=(s2+s1)&0xffff; + if (s2<sold) s2+=15; + #endif + p++; + } + // fprintf(stderr, "len=%u\n", len); + unsigned abufleft; + while ((abufleft=ABUFSIZE-abuflen)<len) { + // putchar('.'); + // fprintf(stderr, "ABUFSIZE=%u abuflen=%u\n", ABUFSIZE, abuflen); + memcpy(abuf+abuflen+5, buf, abufleft); + abuf[0]=0; /* Stored block with padding */ + abuf[1]=(char)ABUFSIZE; abuf[2]=(char)(ABUFSIZE>>8); + abuf[3]=(char)~(ABUFSIZE); abuf[4]=(char)~(ABUFSIZE>>8); + if (!had_header) { out.vi_write("\x78\x01", 2); had_header=true; } + /* fprintf(stderr,"%02x %02x", abuf[1], abuf[2]); */ + out.vi_write(abuf, ABUFSIZE+5); /* emit next stored block with header */ + abuflen=0; + len-=abufleft; + buf+=abufleft; + } + // putchar('X'); + memcpy(abuf+abuflen+5, buf, len); + abuflen+=len; + /* Now abuf is possibly full. That is intentional, so we will be able to + * emit a full last block instead of an empty one. + */ +} + +/* --- */ + +ASCIIHexEncode::ASCIIHexEncode(GenBuffer::Writable &out_, unsigned maxcpl_) + :maxcpl(maxcpl_) + ,curcpl(0) + ,out(out_) {} + +void ASCIIHexEncode::vi_write(char const*buf, slen_t len) { + /* Imp: buffering (1K etc.) */ + static char const hextable []="0123456789abcdef"; + char obuf[3]; + obuf[0]='\n'; + if (len==0) { out.vi_write(">",1); out.vi_write(0,0); } + else while (len--!=0) { + obuf[1]=hextable[(*(unsigned char const*)buf)>>4]; + obuf[2]=hextable[(*(unsigned char const*)buf)&15]; + if (curcpl>=maxcpl) { curcpl=2; out.vi_write(obuf, 3); } + else { curcpl+=2; out.vi_write(obuf+1, 2); } + buf++; + } +} + +/* --- */ + +ASCII85Encode::ASCII85Encode(GenBuffer::Writable &out_, unsigned maxcpl_) + :maxcpl(maxcpl_) + ,out(out_) + ,ascii85breaklen(maxcpl_) + ,ascii85left(4) { + obufend=(op=obuf=new char[4096])+4096; +} + +void ASCII85Encode::vi_write(char const*buf, slen_t len) { + if (len==0) { + char encoded[6]; + assert(ascii85left<=4); + if (ascii85left!=4) { + unsigned PTS_INT32_T buf_=ascii85buf<<8*ascii85left; + unsigned PTS_INT32_T q; + unsigned w1; + + q = buf_ / ((unsigned PTS_INT32_T)85*85*85*85); /* actually only a byte */ + assert(q<=85); + encoded[0] = q + '!'; + + buf_ -= q * ((unsigned PTS_INT32_T)85*85*85*85); q = buf_ / ((unsigned PTS_INT32_T)85*85*85); + encoded[1] = q + '!'; + + buf_ -= q * ((unsigned PTS_INT32_T)85*85*85); q = buf_ / (85*85); + encoded[2] = q + '!'; + + w1 = (unsigned) (buf_ - q*(unsigned PTS_INT32_T)(85*85)); + assert(w1/85<85); + encoded[3] = (w1 / 85) + '!'; + encoded[4] = (w1 % 85) + '!'; + encoded[5-ascii85left] = '\0'; + char* cp; + for (cp = encoded; *cp!='\0'; ) { + if (op==obufend) out.vi_write(op=obuf, obufend-obuf); + // if (*cp<='!') { fprintf(stderr, "e=%d.\n", cp-encoded); } + assert(*cp>='!'); + assert(*cp<='~'); + *op++=*cp++; + if (--ascii85breaklen == 0) { + if (op==obufend) out.vi_write(op=obuf, obufend-obuf); + *op++='\n'; + ascii85breaklen = maxcpl; + } + } /* NEXT */ + } /* IF */ + if (op!=obuf) out.vi_write(obuf, op-obuf); /* flush buffer cache */ + out.vi_write("~>",2); out.vi_write(0,0); + delete [] obuf; + obuf=(char*)NULLP; + } else { + assert(obuf!=NULLP); + register unsigned PTS_INT32_T abuf=ascii85buf; + register unsigned aleft=ascii85left; + assert(aleft>=1 && aleft<=4); + do { + while (len!=0 && aleft!=0) { + abuf=(abuf<<8)+*(unsigned char const*)buf++; len--; aleft--; + } + if (aleft!=0) break; + wout(abuf); + aleft=4; + } while (len!=0); + ascii85buf=abuf; ascii85left=aleft; + } +} + +void ASCII85Encode::wout(unsigned PTS_INT32_T buf_) { + char encoded[6]; + if (buf_ != (unsigned PTS_INT32_T)0) { + unsigned PTS_INT32_T q; + unsigned w1; + + q = buf_ / ((unsigned PTS_INT32_T)85*85*85*85); /* actually only a byte */ + encoded[0] = q + '!'; + + buf_ -= q * ((unsigned PTS_INT32_T)85*85*85*85); q = buf_ / ((unsigned PTS_INT32_T)85*85*85); + encoded[1] = q + '!'; + + buf_ -= q * ((unsigned PTS_INT32_T)85*85*85); q = buf_ / (85*85); + encoded[2] = q + '!'; + + w1 = (unsigned) (buf_ - q*(unsigned PTS_INT32_T)(85*85)); + encoded[3] = (w1 / 85) + '!'; + encoded[4] = (w1 % 85) + '!'; + encoded[5] = '\0'; + } else { + encoded[0] = 'z', encoded[1] = '\0'; + } + char* cp; + for (cp = encoded; *cp!='\0'; ) { + if (op==obufend) out.vi_write(op=obuf, obufend-obuf); + assert(*cp>='!'); + assert(*cp<='~'); + *op++=*cp++; + if (--ascii85breaklen == 0) { + if (op==obufend) out.vi_write(op=obuf, obufend-obuf); + *op++='\n'; + ascii85breaklen = maxcpl; + } + } +} + +/* --- */ + +RunLengthEncode::RunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize_) + :recordsize(RecordSize_==0?(slen_t)-1:RecordSize_) + ,out(out_) { + record_left=recordsize; + // obufend=(op=obuf=new char[4096])+4096; /* Imp: implement write buffering */ + saved_c=saved_rep=0; +} + +void RunLengthEncode::vi_write(char const*buf, slen_t len) { + unsigned j, umax; + char b; + if (len==0) { /* handle EOF */ + if (saved_rep!=0) { + assert(saved_rep>=2); + (saved+1)[-1]=257-saved_rep; + (saved+1)[1]=(char)128; /* EOD */ + out.vi_write((saved+1)-1,3); + // fprintf(stderr,"rd=%u\n",saved_rep); + } else if (saved_c!=0) { + (saved+1)[-1]=saved_c-1; + (saved+1)[saved_c]=(char)128; /* EOD */ + out.vi_write((saved+1)-1, saved_c+2); + // fprintf(stderr,"re=%u\n",saved_c); + } else { + (saved+1)[-1]=(char)128; + out.vi_write((saved+1)-1, 1); + } + out.vi_write(0,0); /* propagate EOF */ + record_left=0; /* signal that no further data will be accepted */ + return; + } + again: + assert(record_left>=1); + assert(len>=1); + /* Imp: locally cache vars saved* */ + j=0; + if (saved_c==0) { + saved_rep=0; saved_c=1; b=(saved+1)[0]=*buf++; len--; + if (0==--record_left) goto put_norep; + if (0==len) return; + goto yes; + } + if (saved_c==1 && saved_rep==0) { yes: + if (*buf++==(saved+1)[0]) { + saved_rep=2; len--; + if (0==--record_left) goto put_rep; + } else { + (saved+1)[1]=buf[-1]; saved_c=2; len--; + if (0==--record_left) goto put_norep; + } + if (0==len) return; + } + assert(record_left>=1); + assert(len>=1); + assert((saved_rep==0 && saved_c>=2) || (saved_rep>=2 && saved_c==1)); + if (saved_rep!=0) { /* Try to increase the repeating sequence */ + assert(saved_rep>=2); + assert(saved_c==1); + assert(len>=1); + b=(saved+1)[0]; + umax=len>128?128:len; if (umax>record_left) umax=record_left; + /* fprintf(stderr,"um1=%u\n", umax); */ + if (umax>128-saved_rep) umax=128-saved_rep; + assert(umax>=1); + j=0; while (j!=umax && buf[j]==b) { j++; saved_rep++; } + if (j!=len || saved_rep==128) { + put_rep: /* Found a maximal repeat width */ + (saved+1)[-1]=257-saved_rep; + out.vi_write((saved+1)-1,2); + /* fprintf(stderr,"ra=%u\n",saved_rep); */ + if ((record_left-=j)==0) record_left=recordsize; + buf+=j; + saved_c=saved_rep=0; + if (0==(len-=j)) return; + goto again; + } /* Current repeat width can be further increased */ + } else { /* Try to increase the non-repeating sequence */ + assert(saved_c>=2); + if (buf[0]==(saved+1)[saved_c-1]) { /* this decision might be sub-optimal */ + saved_c--; + /* Now: saved_c: non-repeat length, >=1 */ + (saved+1)[-1]=saved_c-1; + out.vi_write((saved+1)-1, saved_c+1); + /* fprintf(stderr,"rb=%u\n",saved_c); */ + // record_left++; /* because of saved_c--; but we would increase it later anyway */ + // buf+=saved_c; + (saved+1)[0]=buf[0]; /* first matching char-pair data */ + saved_c=1; saved_rep=2; /* make the new block a >=2 repeat */ + record_left--; buf++; + if (0==--len) return; + goto again; + } + (saved+1)[saved_c++]=buf[0]; + //record_left--; + //buf++; + //len--; + //if (saved_c==128) goto put_norep; + //if (0==len) return; + umax=len>128?128:len; if (umax>record_left) umax=record_left; + if (umax>128-saved_c) umax=128-saved_c; + /* fprintf(stderr,"um2=%u\n", umax); */ + assert(umax>=1); + j=1; while (j!=umax && buf[j]!=buf[j-1]) (saved+1)[saved_c++]=buf[j++]; + if (j!=len || saved_c==128) { + put_norep: /* Found a maximal non-repeat width */ + (saved+1)[-1]=saved_c-1; + out.vi_write((saved+1)-1, saved_c+1); + /* fprintf(stderr,"rc=%u\n",saved_c); */ + if ((record_left-=j)==0) record_left=recordsize; + buf+=j; + saved_c=saved_rep=0; + if (0==(len-=j)) return; + goto again; + } /* Current non-repeat width can be further increased */ + } + assert(j==len); + record_left-=j; + assert(saved_rep<128); + assert(saved_c<128); +} + +/* --- */ + +#if USE_BUILTIN_ZIP +// bool FlateEncode::locked=false; + +#if PTS_DEFL_RIPPED_ZLIB +FlateEncode::FlateEncode(GenBuffer::Writable &out_, unsigned level_) + :out(out_) { + // assert(!locked); locked /* locking is not necessary anymore */ + // pts_deflate_init(&fs); /* obsolete */ + zs.total_in=0; + zs.total_out=0; + zs.workspace=workspace; + zs.msg=(char*)0; + zs.state=(struct zlib_internal_state*)0; + zs.data_type=Z_UNKNOWN; /* Imp: do we have to initialize it? */ + assert(zlib_deflate_workspacesize()+(unsigned)0<sizeof(workspace) && "Flate workspace too small"); + if (Z_OK!=zlib_deflateInit(&zs, level_)) + Error::sev(Error::EERROR) << "Flate init error (out of memory?)" << (Error*)0; +} + +void FlateEncode::vi_write(char const*buf, slen_t len) { + slen_t got, zgot; + /* fprintf(stderr,"wcall\n"); */ + zs.next_in=(unsigned char*)const_cast<char*>(buf); zs.avail_in=len; + if (len==0) { /* flush all output */ + do { /* SUXX: C compiler should emit a warning: while (1) { ... } while(...); */ + zs.next_out=(unsigned char*)obuf; zs.avail_out=sizeof(obuf); + /* fprintf(stderr,"wdone zai=%d zao=%d\n", zs.avail_in, zs.avail_out); */ + if (Z_STREAM_END!=(zgot=zlib_deflate(&zs, Z_FINISH)) && Z_OK!=zgot) + Error::sev(Error::EERROR) << "Flate close error: " << zs.msg << (Error*)0; + got=sizeof(obuf)-zs.avail_out; + /* fprintf(stderr, "got=%u zgot=%d Z_OK=%d\n", got, zgot, Z_OK); */ + if (got>0) out.vi_write(obuf, got); + } while (zgot==Z_OK); + /* Dat: zlib_deflateEnd() will be called in the destructur */ + out.vi_write(0,0); /* Signal EOF */ + /* Dat: zlib_deflate() adds RFC 1950 header and adler32 checksum automatically */ + } else { + do { + /* fprintf(stderr,"writ\n"); */ + zs.next_out=(unsigned char*)obuf; zs.avail_out=sizeof(obuf); + if (Z_OK!=zlib_deflate(&zs, 0)) + Error::sev(Error::EERROR) << "Flate write error: " << zs.msg << (Error*)0; + if (0<(got=sizeof(obuf)-zs.avail_out)) out.vi_write(obuf, got); + } while (0!=zs.avail_in); + } +} +#else +FlateEncode::FlateEncode(GenBuffer::Writable &out_, unsigned level_) + :out(out_) + ,s1(1) + ,s2(0) + ,had_header(false) { + // assert(!locked); locked /* locking is not necessary anymore */ + // pts_deflate_init(&fs); /* obsolete */ + fs=pts_defl_new( + /*zpfwrite=*/ gen_write, + /*zpfmalloc=*/ gen_malloc, + /*zpffree=*/ gen_free, + /*pack_level=*/ level_, + /*zfile=*/ (void*)&out_ + ); + if (fs==NULL) Error::sev(Error::EERROR) << "Flate init error (out of memory?)" << (Error*)0; +} +void *FlateEncode::gen_malloc(unsigned n) { + return operator new(n); + // return new char[n]; +} +void FlateEncode::gen_free(void *p) { + /*return*/ operator delete(p); + // delete [] (char*)p; +} + +void FlateEncode::vi_write(char const*buf, slen_t len) { + register s_t sold; + register char const*p=buf; char const*pend=p+len; + (void)sold; + if (!had_header) { + out.vi_write("\x78\xda",2); /* ZLIB (RFC 1950): max compression header */ + had_header=true; + } + if (len==0) { /* EOF: send trailer */ + fs->deflate2(0,0,fs); /* Let the compressor flush its buffers. */ + if (fs->err!=0) Error::sev(Error::EERROR) << "Flate compression error" << (Error*)0; + fs->delete2(fs); + fs=(struct pts_defl_interface*)NULL; + if (s1>=65521) s1-=65521; + if (s2>=65521) s2-=65521; + unsigned char trailer[4]; + trailer[0]=s2>>8; trailer[1]=s2&255; trailer[2]=s1>>8; trailer[3]=s1&255; + out.vi_write((char const*)trailer,4); + out.vi_write(0,0); /* Signal EOF */ + return; + } + assert(fs!=NULL); + + /* From rfc1950.txt: + Adler-32 is composed of two sums accumulated per byte: s1 is + the sum of all bytes, s2 is the sum of all s1 values. Both sums + are done modulo 65521. s1 is initialized to 1, s2 to zero. The + Adler-32 checksum is stored as s2*65536 + s1 in most- + significant-byte first (network) order. + */ + /* Update Adler-32 checksum */ + while (p!=pend) { + #if SIZEOF_INT>2 + if ((s1+=*(unsigned char const*)p)>=65521) s1-=65521; + if ((s2+=s1)>=65521) s2-=65521; + #elif SIZEOF_SHORT==2 + sold=s1; + if ((s1+=*(unsigned char const*)p))<sold) s1+=15; /* 15==65536-21 */ + sold=s2; + s2=(s2+s1)&0xffff; + if ((s2+=s1)<sold) s2+=15; + #else + /* vvv 0xffff is needed since unsigned short may be > 0..65535 */ + sold=s1; + s1=(s1+*(unsigned char const*)p)&0xffff; + if (s1<sold) s1+=15; /* 15==65536-21 */ + sold=s2; + s2=(s2+s1)&0xffff; + if (s2<sold) s2+=15; + #endif + p++; + } + while (len>=0x8000) { fs->deflate2(const_cast<char*>(buf),0x8000, fs); len-=0x8000; buf+=0x8000; } + if (len!=0) fs->deflate2(const_cast<char*>(buf),len, fs); +} +#endif /* PTS_DEFL_RIPPED_ZLIB */ +#endif /* USE_BUILTIN_ZIP */ + +int /*FlateEncode::*/gen_write(char *block, unsigned len, void *zfile) { + static_cast<GenBuffer::Writable*>(zfile)->vi_write(block, len); + return 0; +} + + +/* --- */ + +#if USE_BUILTIN_FAXE +void* CCITTFaxEncode::gen_xalloc(unsigned n) { + return operator new(n); + // void *ret; if ((ret=malloc(n))==0) abort(); return ret; +} +void CCITTFaxEncode::gen_free(void *ptr) { + /*return*/ operator delete(ptr); + // free(ptr); +} +void CCITTFaxEncode::gen_memset(void *s, int c, unsigned n) { + /*return*/ memset(s,c,n); +} +void CCITTFaxEncode::gen_memcpy(void *dest, const void *src, unsigned n) { + /*return*/ memcpy(dest, src, n); +} +CCITTFaxEncode::CCITTFaxEncode(GenBuffer::Writable &out_, slendiff_t K, slen_t Columns, bool EndOfLine, bool BlackIs1): out(out_) { + sCFEs.memset_=gen_memset; + sCFEs.xalloc_=gen_xalloc; + sCFEs.free_=gen_free; + sCFEs.memcpy_=gen_memcpy; + s_CFE_template.set_defaults((stream_state*)&sCFEs); + sCFEs.K=K; + sCFEs.Columns=Columns; + sCFEs.EndOfLine=EndOfLine; + sCFEs.BlackIs1=BlackIs1; + const int cf_max_height=(unsigned)-1/2-100; /* Dat: was slen_t */ + if (sCFEs.K < -cf_max_height || sCFEs.K > cf_max_height /* Dat: .K is an int */ + || sCFEs.Columns < 0 || sCFEs.Columns > cfe_max_width /* Dat: .Columns is an int */ + || sCFEs.Rows < 0 || sCFEs.Rows > cf_max_height /* Dat: .Rows is an int */ + || sCFEs.DamagedRowsBeforeError < 0 + || sCFEs.DamagedRowsBeforeError > cf_max_height /* Dat: .DamagedRowsBeforeError is an int */ + || sCFEs.DecodedByteAlign < 1 || sCFEs.DecodedByteAlign > 16 + || (sCFEs.DecodedByteAlign & (sCFEs.DecodedByteAlign - 1)) != 0 + ) Error::sev(Error::EERROR) << "pts_fax: invalid params" << (Error*)0; + if (0!=s_CFE_template.init((stream_state*)&sCFEs)) + Error::sev(Error::EERROR) << "pts_fax: init failed" << (Error*)0; + #if __CHECKER__ + memset(&r, 0, sizeof(r)); + memset(&w, 0, sizeof(w)); + #endif + r.ptr=rlimit=rbuf-1; + hard=rbuf+sizeof(rbuf)-1; + assert(hard-r.ptr>=(int)s_CFE_template.min_in_size); +} + +void CCITTFaxEncode::vi_write(char const*buf, slen_t len) { + int pog; + // unsigned char *save_wptr; + if (len==0) { + r.limit=rlimit; + do { + w.ptr=wbuf-1; + w.limit=wbuf+sizeof(wbuf)-1; + assert(w.limit-w.ptr>=(int)s_CFE_template.min_out_size); + pog=s_CFE_template.process((stream_state*)&sCFEs, &r, &w, /*last:*/ true); + // fprintf(stderr, "pog=%d write=%d last=%d\n", pog, w.ptr-(wbuf-1), true); + assert(pog!=PTSFAX_ERRC); /* /CCITTFaxEncode filter must accept any input */ + assert(pog!=PTSFAX_EOFC); /* /CCITTFaxEncode filter doesn't have EOD markers */ + if (w.ptr!=wbuf-1) out.vi_write((char const*)wbuf, w.ptr-(wbuf-1)); + } while (pog==1); + s_CFE_template.release((stream_state*)&sCFEs); + out.vi_write(0,0); /* propagate EOF */ + return; + } + + while (len!=0) { + assert(r.ptr==rbuf-1); + assert(hard>rlimit); + unsigned clen=hard-rlimit; + if (clen>len) clen=len; + assert(clen>0); + // fprintf(stderr, "clen=%u\n", clen); + memcpy(rlimit+1, buf, clen); + rlimit+=clen; + buf+=clen; + len-=clen; + /* if (r.ptr==rlimit) break; */ + r.limit=rlimit; + do { + w.ptr=wbuf-1; + w.limit=wbuf+sizeof(wbuf)-1; + assert(w.limit-w.ptr>=(int)s_CFE_template.min_out_size); + pog=s_CFE_template.process((stream_state*)&sCFEs, &r, &w, /*last:*/ false); + // fprintf(stderr, "len=%d pog=%d write=%d last=%d\n", len, pog, w.ptr-(wbuf-1), false); + assert(pog!=PTSFAX_ERRC); /* /CCITTFaxEncode filter must accept any input */ + assert(pog!=PTSFAX_EOFC); /* /CCITTFaxEncode filter doesn't have EOD markers */ + if (w.ptr!=wbuf-1) out.vi_write((char const*)wbuf, w.ptr-(wbuf-1)); + } while (pog==1); + // assert(pog!=1); /* not true: output space is enough (sizeof(wbuf)>min_out_size) */ + assert(pog==0); /* more input is needed */ + if (r.ptr!=rbuf-1) { + // fprintf(stderr, "limit=%d\n", rlimit-r.ptr); + memmove(rbuf, r.ptr+1, rlimit-r.ptr); + rlimit=rbuf-1+(rlimit-r.ptr); + r.ptr=rbuf-1; + } + } + // fprintf(stderr, "done\n"); +} +#endif /* USE_BUILTIN_FAXE */ + +/* --- */ + +#if USE_BUILTIN_LZW +LZWEncode::LZWEncode(GenBuffer::Writable &out_): out(out_) { + fs.tif_writer=/*FlateEncode::*/gen_write; + fs.tif_sout=(void*)&out_; + if (0==pts_lzw_init(&fs)) Error::sev(Error::EERROR) << "LZW init error" << (Error*)0; +} + +void LZWEncode::vi_write(char const*buf, slen_t len) { + /* Imp: report real error _reason_ (if appropriate?? ) */ + if (len==0) { + if (0==fs.tif_feeder(0,0,&fs)) goto we; + out.vi_write(0,0); /* propagate EOF */ + return; + } + while (len>=0x8000) { + if (0==fs.tif_feeder(const_cast<char*>(buf),0x8000,&fs)) we: + Error::sev(Error::EERROR) << "LZW write error" << (Error*)0; + len-=0x8000; buf+=0x8000; + } + if (len!=0 && 0==fs.tif_feeder(const_cast<char*>(buf),len,&fs)) goto we; +} +#endif /* USE_BUILTIN_LZW */ + +/* --- */ + +#if !USE_BUILTIN_LZW +Lzw_codecEncode::Lzw_codecEncode(GenBuffer::Writable &out_, char const*filter_psname) + :p(out_) { + (void)filter_psname; +} +void Lzw_codecEncode::vi_write(char const*buf, slen_t len) { p.vi_write(buf,len); } + +/* Imp: figure out path-to-gs: gs or gswin32c */ +Lzw_codecEncode::P::P(GenBuffer::Writable &out_) + // :PipeEncoder(out_, ">/tmp/t cat - cjpeg quality %i", quality), rgbp(rgbp_) { + // :Filter::PipeE(out_, "cjpeg -quality %i >%D", quality), rgbp(rgbp_) { + :Filter::PipeE(out_, "lzw_codec encode >%D") {} +#endif + +/* --- */ + +CjpegEncode::CjpegEncode(GenBuffer::Writable &out_, char const*filter_psname, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality) + :p(out_, Columns, Rows, rgbp_, quality) { + (void)filter_psname; +} +void CjpegEncode::vi_write(char const*buf, slen_t len) { p.vi_write(buf,len); } + +/* Imp: figure out path-to-gs: gs or gswin32c */ +CjpegEncode::P::P(GenBuffer::Writable &out_, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality) + // :PipeEncoder(out_, ">/tmp/t cat - cjpeg quality %i", quality), rgbp(rgbp_) { + :Filter::PipeE(out_, "cjpeg -quality %i >%D", quality), rgbp(rgbp_) { + /* Dat: we're extremely lucky that cjpeg can read PGM or PPM files from stdin */ + // operator<<("P5 width height 255\n"); /* RAWBITS PGM */ + // operator<<("P6 width height 255\n"); /* RAWBITS PPM */ + *this << (rgbp_?"P6 ":"P5 ") << Columns << ' ' << Rows << " 255\n"; +} +void CjpegEncode::P::vi_copy(FILE *f) { + char r[9]; + static char jfif[9]="\377\340\000\020JFIF"; + static unsigned char adobe[16]= { + 0xff, /* marker */ + 0xee, /* APP14 */ + 0, /* length-hi */ + 14, /* length-lo */ + 'A', 'd', 'o', 'b', 'e', /* ID */ + 1, /* version-hi */ + 0, /* version-lo */ + 0, 0, /* flags0 */ + 0, 0, /* flags1 */ + 0, /* ColorTransform */ + }; + if (MACRO_GETC(f)!=0xff || MACRO_GETC(f)!=0xd8 || fread(r, 1, 8, f)!=8) { + bad: Error::sev(Error::EERROR) << "CjpegEncode: cjpeg created bad JPEG" << (Error*)0; + } + out.vi_putcc((char)0xff); + out.vi_putcc((char)0xd8); + r[9]=r[3]; r[3]='\020'; + if ((unsigned char)r[9]>=6 && 0==memcmp(r, jfif, 8)) { /* JFIF marker */ + r[3]=r[9]; unsigned skip=r[9]-6; + out.vi_write(r, 8); + while (skip--!=0) out.vi_putcc(MACRO_GETC(f)); + } + if (ferror(f) || feof(f)) goto bad; + /* Now we can emit the Adobe marker. */ + adobe[sizeof(adobe)-1]=rgbp==true; /* ColorTransform value 0 for Gray, 1 for RGB->YCbCr */ + out.vi_write((char*)adobe, sizeof(adobe)); + /* vvv Dat: pacify VC6.0: Filter::PipeE::vi_copy(f); doesn't work */ + PipeE::vi_copy(f); + /* ^^^ copy rest of file verbatim */ + // ((Filter::PipeE)*this).vi_copy(f); +} + +/* --- */ + +GSEncode::GSEncode(GenBuffer::Writable &out_, char const*filter_psname) + :p(out_, filter_psname) {} +void GSEncode::vi_write(char const*buf, slen_t len) { p.vi_write(buf,len); } + +/* Imp: figure out path-to-gs: gs or gswin32c */ +GSEncode::P::P(GenBuffer::Writable &out_, char const*filter_psname) + :Filter::PipeE(out_, "gs -s_OFN=%D -dNODISPLAY -q - >%E") + { + operator<<("{/o _OFN(w)file "); + operator<<(filter_psname); + operator<<(" filter def/s 4096 string def" + "{currentfile s readstring exch o exch writestring not{exit}if}loop " + "o closefile quit}bind exec\n"); +} +void GSEncode::P::vi_check() { + /* If STDOUT of gs is not empty, then it is very probably an error message. */ + // tmpename.term0(); /* already is */ + assert(tmpename.end_()[0]=='\0'); + if (0!=Files::statSize(tmpename())) Error::sev(Error::EERROR) << "GSEncode: GS runtime error" << (Error*)0; + /* Imp: display a meaningful error message */ +} + +/* --- */ + +PSEncoder* PSEncoder::newASCIIHexEncode(GenBuffer::Writable &out_,unsigned maxcpl_) { + // SimBuffer::B fp; (fp << maxcpl_ << " pop/ASCIIHexEncode").term0(); + // PSEncoder *ret=new GSEncode(out_, fp()); + PSEncoder *ret=new ASCIIHexEncode(out_,maxcpl_); + // ret->shortname="AHx"; ret->longname="ASCIIHex"; + // ret->filter_psname << fp; + return ret; +} +PSEncoder* PSEncoder::newASCII85Encode(GenBuffer::Writable &out_,unsigned maxcpl_) { + // SimBuffer::B fp; (fp << maxcpl_ << " pop/ASCII85Encode").term0(); + PSEncoder *ret=new ASCII85Encode(out_,maxcpl_); + // PSEncoder *ret=new GSEncode(out_, fp()); + // ret->shortname="A85"; ret->longname="ASCII85"; + // ret->filter_psname << fp; + return ret; +} +PSEncoder* PSEncoder::newCCITTFaxEncode(GenBuffer::Writable &out_,slendiff_t K, slen_t Columns, bool EndOfLine, bool BlackIs1) { + #if USE_BUILTIN_FAXE + return new CCITTFaxEncode(out_, K, Columns, EndOfLine, BlackIs1); + #else + // (void)out_; (void)K; (void)Columns; + // assert(0 && "unimplemented"); + SimBuffer::B fp("<< /K "); + fp << K << "/Columns " << Columns; + if (EndOfLine) fp << "/EndOfLine true"; /* PS default: false */ + if (BlackIs1) fp << "/BlackIs1 true"; + (fp << ">>/CCITTFaxEncode").term0(); + // fprintf(stderr, "fp=(%s)\n", fp()); + PSEncoder *ret=new GSEncode(out_, fp()); + // ret->shortname="CCF"; ret->longname="CCITTFax"; + // ret->filter_psname << fp; /* Dat: this could be made faster */ + return ret; + #endif +} +PSEncoder* PSEncoder::newLZWEncode(GenBuffer::Writable &out_) { +#if USE_BUILTIN_LZW + SimBuffer::B fp("/LZWEncode"); + PSEncoder *ret=new LZWEncode(out_); + // PSEncoder *ret=new GSEncode(out_, fp()); + // ret->shortname="LZW"; ret->longname="LZW"; + // ret->filter_psname << fp; + return ret; +#else + (void)out_; + #if 0 + Error::sev(Error::EERROR) << "LZW not supported in this compilation of sam2p" << (Error*)0; + #endif + Error::sev(Error::WARNING) << "LZW: please `configure --enable-lzw' for builtin /Compression/LZW support" << (Error*)0; + #if 0 + /* This is useless, because gs 5.50--7.04 have dummy LZW compressor: + * it emits a correct LZW stream, but does no real compression, and + * the file size is often increased. + */ + PSEncoder *ret=new GSEncode(out_, "/LZWEncode"); + // ret->shortname="LZW"; ret->longname="LZW"; + // ret->filter_psname << "/LZWEncode"; + return ret; + #endif + #if 1 /* ask lzw_codec from the author of sam2p */ + return new Lzw_codecEncode(out_, "/LZWEncode"); + #endif + return 0; +#endif +} +PSEncoder* PSEncoder::newFlateEncode(GenBuffer::Writable &out_, signed Effort) { + // (void)out_; (void)K; (void)Columns; + // assert(0 && "unimplemented"); + if (Effort==0) { + PSEncoder *ret=new FlateStoreEncode(out_); + // ret->shortname="Fla"; ret->longname="Flate"; + // ret->filter_psname << fp; + return ret; + } + if (Effort<1 || Effort>9) Effort=5; + #if USE_BUILTIN_ZIP + PSEncoder *ret=new FlateEncode(out_, Effort); + #else + SimBuffer::B fp("<</Effort "); (fp << Effort << ">>/FlateEncode").term0(); + PSEncoder *ret=new GSEncode(out_, fp()); + #endif + // ret->shortname="Fla"; ret->longname="Flate"; + // ret->filter_psname << fp; + return ret; +} +PSEncoder* PSEncoder::newRunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize) { + SimBuffer::B fp; (fp << RecordSize << "/RunLengthEncode").term0(); + PSEncoder *ret=new RunLengthEncode(out_, RecordSize); + // PSEncoder *ret=new GSEncode(out_, fp()); + // ret->shortname="RL"; ret->longname="RunLength"; + // ret->filter_psname << fp; + return ret; +} + +PSEncoder* PSEncoder::newDCTIJGEncode(GenBuffer::Writable &out_, + slen_t Columns, + slen_t Rows, + unsigned char Colors, /*1..4*/ + unsigned char quality /*libJPEG quality: 0..100 */ +) { + /* Dat: this supports only the Gray and RGB color spaces of JPEG */ + param_assert(Colors==1 || Colors==3); + param_assert(/* quality>=0 && */ quality <=100); + SimBuffer::B fp("<<IJG "); + (fp<< "/Columns " << Columns + << "/Rows " << Rows + << "/Colors " << (unsigned)Colors + << ">>/DCTEncode").term0(); + /* Dat: the default of /ColorTransform (defined in DCTEncode in + subsubsection 3.13.3 in PLRM.pdf) is just perfect. */ + PSEncoder *ret=new CjpegEncode(out_, fp(), Columns, Rows, Colors==3, quality); + // ret->longname=ret->shortname="DCT"; ret->filter_psname << fp; + return ret; +} + +PSEncoder* PSEncoder::newDCTEncode(GenBuffer::Writable &out_, + slen_t Columns, + slen_t Rows, + unsigned char Colors, /*1..4*/ + unsigned char quality, /*libJPEG quality: 0..100 */ + unsigned char const*HSamples, /*all 1..4, NULLP OK*/ + unsigned char const*VSamples, /*all 1..4, NULLP OK*/ + unsigned char (*QuantTables)[64], /*NULLP OK*/ + double QFactor, /*0..1000000*/ + unsigned numHuffTables, + unsigned char **HuffTables, /*NULLP OK*/ + unsigned char ColorTransform /*0,1,2 3=default*/ +) { + (void)quality; + (void)QuantTables; + (void)QFactor; + (void)numHuffTables; + (void)HuffTables; + SimBuffer::B tmp; + /* Imp: respect quality */ + /* Imp: respect QFactor (double) */ + /* Imp: respect QuantTables */ + /* Imp: respect numHuffTables, HuffTables */ + + SimBuffer::B fp("<<"); + fp << "/Columns " << Columns + << "/Rows " << Rows + << "/Colors " << (unsigned)Colors; + if (HSamples!=(unsigned char const*)NULLP) { + tmp.clear(); tmp.vi_write((char const*)HSamples, (unsigned)Colors); + fp << "/HSamples "; fp.appendDumpPS(tmp,true); + } + if (VSamples!=(unsigned char const*)NULLP) { + tmp.clear(); tmp.vi_write((char const*)VSamples, (unsigned)Colors); + fp << "/VSamples "; fp.appendDumpPS(tmp,true); + } + if (ColorTransform!=3) fp << "/ColorTransform " << (unsigned)ColorTransform; + (fp << ">>/DCTEncode").term0(); + + // PSEncoder *ret=new DCTEncode(out_,? ? ?); + PSEncoder *ret=new GSEncode(out_, fp()); + // ret->shortname="DCT"; ret->longname="DCT"; + // ret->filter_psname << fp; + return ret; +} + +PSEncoder* PSEncoder::newDCTEncode(GenBuffer::Writable &out_, + slen_t Columns, + slen_t Rows, + unsigned char Colors, /*1..4*/ + unsigned char ColorTransform, /*0,1,2 3=default*/ + SimBuffer::Flat const& other_parameters +) { + SimBuffer::B fp("<<"); + fp << "/Columns " << Columns + << "/Rows " << Rows + << "/Colors " << (unsigned)Colors; + if (ColorTransform!=3) fp << "/ColorTransform " << (unsigned)ColorTransform; + (fp << other_parameters << ">>/DCTEncode").term0(); + PSEncoder *ret=new GSEncode(out_, fp()); + // ret->shortname="DCT"; ret->longname="DCT"; + // ret->filter_psname << fp; + return ret; +} + +/* --- */ + +TIFFPredictor2::TIFFPredictor2(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : h(0), bpc(bpc_), cpp(cpp_), out(out_) { + param_assert(cpp_*bpc_<=32); + rlen=(columns_*cpp_*bpc_+7)>>3; /* BUGFIX at Tue Mar 12 12:09:51 CET 2002 */ + op=obuf=new unsigned char[rlen]; +} + +void TIFFPredictor2::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + slen_t opleft=rlen-(op-obuf); + register unsigned int i, d, o, bpccpp; + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] obuf; + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + bpccpp=(cpp-1)*bpc; + if (bpc==1) { + while (p!=pend0) { + i=*p++; + d=(i>>7); o =((d-((h>>bpccpp)))&1)<<7; h=(h<<1)|d; + d=(i>>6); o|=((d-((h>>bpccpp)))&1)<<6; h=(h<<1)|d; + d=(i>>5); o|=((d-((h>>bpccpp)))&1)<<5; h=(h<<1)|d; + d=(i>>4); o|=((d-((h>>bpccpp)))&1)<<4; h=(h<<1)|d; + d=(i>>3); o|=((d-((h>>bpccpp)))&1)<<3; h=(h<<1)|d; + d=(i>>2); o|=((d-((h>>bpccpp)))&1)<<2; h=(h<<1)|d; + d=(i>>1); o|=((d-((h>>bpccpp)))&1)<<1; h=(h<<1)|d; + d=(i ); o|=((d-((h>>bpccpp)))&1) ; h=(h<<1)|d; + *op++=o; + if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; } + } + } else if (bpc==2) { + while (p!=pend0) { + i=*p++; + d=(i>>6); o =((d-((h>>bpccpp)))&3)<<6; h=(h<<2)|d; // fprintf(stderr,"d=%#x\n", d); + d=(i>>4); o|=((d-((h>>bpccpp)))&3)<<4; h=(h<<2)|d; + d=(i>>2); o|=((d-((h>>bpccpp)))&3)<<2; h=(h<<2)|d; + d=(i ); o|=((d-((h>>bpccpp)))&3) ; h=(h<<2)|d; + *op++=o; + if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; } + } + } else if (bpc==4) { + while (p!=pend0) { + i=*p++; + d=(i>>4); o =((d-((h>>bpccpp)))&15)<<4; h=(h<<4)|d; + d=(i ); o|=((d-((h>>bpccpp)))&15) ; h=(h<<4)|d; + *op++=o; + if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; } + } + } else if (bpc==8) { + while (p!=pend0) { + i=*p++; *op++=((i-((h>>bpccpp)))/*&255*/); h=(h<<8)|i; + if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; } + } + } else assert(0); +} + +/* --- */ + +PNGPredictorNone::PNGPredictorNone(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : opleft(0), out(out_) { + rlen=(columns_*cpp_*bpc_+7)>>3; +} + +void PNGPredictorNone::vi_write(char const*buf, slen_t len) { + if (len==0) { + assert(opleft==0); /* unflushed (half-ready) row disallowed */ + out.vi_write(0,0); + return; + } + /* The following code just inserts a '\0' in front of each scanline */ + /* Imp: make it faster by collapsing vi_writes */ + if (opleft==0) { opleft=rlen; out.vi_write("\0",1); } /* Scanline (row) header: describes predictor used */ + while (len>opleft) { + out.vi_write(buf,opleft); + buf+=opleft; len-=opleft; + opleft=rlen; out.vi_write("\0",1); /* Scanline (row) header: describes predictor used */ + } + if (len!=0) out.vi_write(buf,len); + opleft-=len; +} + +/* --- */ + +PNGPredictorSub::PNGPredictorSub(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : h(0), out(out_) { + param_assert(cpp_*bpc_<=32); + rlen=(columns_*cpp_*bpc_+7)>>3; + op=obuf=1+new unsigned char[rlen+1]; + obuf[-1]='\1'; /* Scanline (row) header: describes predictor used */ + bpccpp=((cpp_*bpc_+7)&~7)-8; +} + +void PNGPredictorSub::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + slen_t opleft=rlen-(op-obuf); + register unsigned int i; + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] (obuf-1); + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + while (p!=pend0) { + i=*p++; *op++=((i-((h>>bpccpp)))/*&255*/); h=(h<<8)|i; + if (--opleft==0) { h=0; + out.vi_write((char*)obuf-1,rlen+1); op=obuf; opleft=rlen; + } + } +} + +/* --- */ + +PNGPredictorUp::PNGPredictorUp(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : out(out_) { + rlen=(columns_*cpp_*bpc_+7)>>3; + // fprintf(stderr, "rUp.rlen=%u cpp=%u bpc=%u\n", rlen, cpp_, bpc_); + op=obuf=1+new unsigned char[2*rlen+1]; + oq=op+rlen; /* prev scanline */ + memset(oq, '\0', rlen); + obuf[-1]='\2'; /* Scanline (row) header: describes predictor used */ +} + +void PNGPredictorUp::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + slen_t opleft=rlen-(op-obuf); + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] (obuf-1); + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + while (p!=pend0) { + *op++=((*p-*oq)/*&255*/); *oq++=*p++; + if (--opleft==0) { + out.vi_write((char*)obuf-1,rlen+1); opleft=rlen; + op=obuf; oq=obuf+rlen; + } + } +} + +/* --- */ + +PNGPredictorAverage::PNGPredictorAverage(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : h(0), /*g(0),*/ out(out_) { + param_assert(cpp_*bpc_<=32); + rlen=(columns_*cpp_*bpc_+7)>>3; + op=obuf=1+new unsigned char[2*rlen+1]; + oq=op+rlen; /* prev scanline */ + memset(oq, '\0', rlen); + obuf[-1]='\3'; /* Scanline (row) header: describes predictor used */ + bpccpp=((cpp_*bpc_+7)&~7)-8; +} + +void PNGPredictorAverage::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + slen_t opleft=rlen-(op-obuf); + register unsigned int i; + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] (obuf-1); + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + while (p!=pend0) { + /* vvv Data: *og+h can be 0..510 */ + i=*p; *op++=i-((((h>>bpccpp)&255)+*oq)>>1); h=(h<<8)|i; *oq++=*p++; + // i=*p; *op++=(*p-((*oq+h)>>1)/*&255*/); h=i; *oq++=*p++; + if (--opleft==0) { + out.vi_write((char*)obuf-1,rlen+1); opleft=rlen; + op=obuf; oq=obuf+rlen; h=0; + } + } +} + +/* --- */ + +/* Dat: egcs-2.91.60 is buggy */ +// static inline unsigned abs_(unsigned i) { return ((signed)i)<0 ? -i : i; } +static inline unsigned abs_(unsigned i) { return ((signed)i)<0 ? (i*-1) : i; } + +static inline unsigned paeth_predictor(unsigned a, unsigned b, unsigned c) { + /* Code ripped from RFC 2083 (PNG specification), which also says: + * The calculations within the PaethPredictor function must be + * performed exactly, without overflow. Arithmetic modulo 256 is to + * be used only for the final step of subtracting the function result + * from the target byte value. + */ + /* a = left, b = above, c = upper left */ + unsigned p = a + b - c; /* initial estimate */ + unsigned pa = abs_(p - a); /* distances to a, b, c */ + unsigned pb = abs_(p - b); + unsigned pc = abs_(p - c); + // assert(abs_(3*(-1))==3); + // fprintf(stderr, "b=%u c=%u %d %d\n", b, c, p-b, ((signed)(p-b))<0 ? (b-p) : (p-b) ); + // fprintf(stderr, "pa=%u pb=%u pc=%u\n", pa, pb, pc); + assert(pa<=255); + assert(pb<=255); + assert(pc<=255*2); + /* return nearest of a,b,c, breaking ties in order a,b,c. */ + return (pa <= pb && pa <= pc) ? a + : pb <= pc ? b + : c; +} + +PNGPredictorPaeth::PNGPredictorPaeth(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : h(0), g(0), out(out_) { + param_assert(cpp_*bpc_<=32); + rlen=(columns_*cpp_*bpc_+7)>>3; + op=obuf=1+new unsigned char[2*rlen+2]; + oq=obuf+rlen+1; /* prev scanline */ + memset(obuf+rlen, '\0', rlen+1); + obuf[-1]='\4'; /* Scanline (row) header: describes predictor used */ + bpccpp=((cpp_*bpc_+7)&~7)-8; +} + +void PNGPredictorPaeth::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + slen_t opleft=rlen-(op-obuf); + register unsigned int i; + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] (obuf-1); + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + while (p!=pend0) { + // assert(0==obuf[rlen] && 4==obuf[-1]); + i=*p; *op++=i-paeth_predictor((h>>bpccpp)&255, *oq, (g>>bpccpp)&255); + h=(h<<8)|i; g=(g<<8)|*oq; *oq++=*p++; + // i=*p; *op++=i-h; h=i; *oq++=*p++; + if (--opleft==0) { + out.vi_write((char*)obuf-1,rlen+1); opleft=rlen; + op=obuf; oq=obuf+rlen+1; h=0; g=0; + } + } +} + +/* --- */ + +PNGPredictorAuto::PNGPredictorAuto(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : h(0), g(0), out(out_) { + param_assert(cpp_*bpc_<=32); + opleft=rlen=(columns_*cpp_*bpc_+7)>>3; + obuf=new unsigned char[6*rlen+6]; + o_prior=obuf+rlen+1; /* Prior(x): ooprior[-opleft] */ + obuf[rlen*1+1]='\0'; o_0=obuf+2*rlen+2; + obuf[rlen*2+2]='\1'; o_1=obuf+3*rlen+3; + obuf[rlen*3+3]='\2'; o_2=obuf+4*rlen+4; + obuf[rlen*4+4]='\3'; o_3=obuf+5*rlen+5; + obuf[rlen*5+5]='\4'; o_4=obuf+6*rlen+6; + oo[0]=o_0; oo[1]=o_1; oo[2]=o_2; oo[3]=o_3; oo[4]=o_4; + memset(obuf, '\0', rlen+1); + bpccpp=((cpp_*bpc_+7)&~7)-8; +} + +void PNGPredictorAuto::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + register unsigned int i; + register unsigned raw_x_bpp, prior_x, prior_x_bpp; + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] obuf; + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + while (p!=pend0) { + raw_x_bpp=(h>>bpccpp) &255; + prior_x=*(o_prior-opleft); + prior_x_bpp=(g>>bpccpp) &255; + i=*p; + *(o_0-opleft)=i; + *(o_1-opleft)=i-raw_x_bpp; + *(o_2-opleft)=i-prior_x; + *(o_3-opleft)=i-((raw_x_bpp+prior_x)>>1); + *(o_4-opleft)=i-paeth_predictor(raw_x_bpp, prior_x, prior_x_bpp); + h=(h<<8)|i; g=(g<<8)|*(o_prior-opleft); *(o_prior-opleft)=*p++; + if (--opleft==0) { + /* Select the predictor having the smallest signed sum of values. */ + slendiff_t min_weight, cur_weight; + unsigned min_pred=0, cur_pred; + register signed char *beg, *end; + min_weight=0; beg=(end=(signed char*)o_0)-rlen; while (beg!=end) min_weight+=*beg++; + if (min_weight<0) min_weight*=-1; + for (cur_pred=1; cur_pred<=4; cur_pred++) { + cur_weight=0; beg=(end=(signed char*)oo[cur_pred])-rlen; while (beg!=end) cur_weight+=*beg++; + if (cur_weight<0) cur_weight*=-1; + if (cur_weight<min_weight) { min_weight=cur_weight; min_pred=cur_pred; } + } + // fprintf(stderr, "cp=%u\n", min_pred); + + out.vi_write((char*)(oo[min_pred]-rlen-1),rlen+1); + opleft=rlen; h=0; g=0; + } + } +} + +/* --- */ + +PNGPredictorAutoUnsigned::PNGPredictorAutoUnsigned(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_) + : h(0), g(0), out(out_) { + param_assert(cpp_*bpc_<=32); + opleft=rlen=(columns_*cpp_*bpc_+7)>>3; + obuf=new unsigned char[6*rlen+6]; + o_prior=obuf+rlen+1; /* Prior(x): ooprior[-opleft] */ + obuf[rlen*1+1]='\0'; o_0=obuf+2*rlen+2; + obuf[rlen*2+2]='\1'; o_1=obuf+3*rlen+3; + obuf[rlen*3+3]='\2'; o_2=obuf+4*rlen+4; + obuf[rlen*4+4]='\3'; o_3=obuf+5*rlen+5; + obuf[rlen*5+5]='\4'; o_4=obuf+6*rlen+6; + oo[0]=o_0; oo[1]=o_1; oo[2]=o_2; oo[3]=o_3; oo[4]=o_4; + memset(obuf, '\0', rlen+1); + bpccpp=((cpp_*bpc_+7)&~7)-8; +} + +void PNGPredictorAutoUnsigned::vi_write(char const*buf, slen_t len) { + unsigned char const *p=(unsigned char const*)buf, *pend0=p+len; + register unsigned int i; + register unsigned raw_x_bpp, prior_x, prior_x_bpp; + // unsigned lines=0; + if (len==0) { + assert(opleft==rlen); /* unflushed (half-ready) row disallowed */ + assert(obuf!=NULLP); + delete [] obuf; + obuf=(unsigned char*)NULLP; + out.vi_write(0,0); + return; + } + // fprintf(stderr, "rlen=%u len=%u opleft=%u\n", rlen, len, opleft); + while (p!=pend0) { + raw_x_bpp=(h>>bpccpp) &255; + prior_x=*(o_prior-opleft); + prior_x_bpp=(g>>bpccpp) &255; + i=*p; + *(o_0-opleft)=i; + *(o_1-opleft)=i-raw_x_bpp; + *(o_2-opleft)=i-prior_x; + *(o_3-opleft)=i-((raw_x_bpp+prior_x)>>1); + *(o_4-opleft)=i-paeth_predictor(raw_x_bpp, prior_x, prior_x_bpp); + h=(h<<8)|i; g=(g<<8)|*(o_prior-opleft); *(o_prior-opleft)=*p++; + if (--opleft==0) { + /* Select the predictor having the smallest unsigned sum of values. */ + slen_t min_weight, cur_weight; + unsigned min_pred=0, cur_pred; + register unsigned char *beg, *end; + min_weight=0; beg=(end=(unsigned char*)o_0)-rlen; while (beg!=end) min_weight+=*beg++; + for (cur_pred=1; cur_pred<=4; cur_pred++) { + cur_weight=0; beg=(end=(unsigned char*)oo[cur_pred])-rlen; while (beg!=end) cur_weight+=*beg++; + if (cur_weight<min_weight) { min_weight=cur_weight; min_pred=cur_pred; } + } + // fprintf(stderr, "cp=%u\n", min_pred); + + out.vi_write((char*)(oo[min_pred]-rlen-1),rlen+1); + opleft=rlen; h=0; g=0; + // lines++; + } + } + // fprintf(stderr, "oen=%u opleft=%u lines=%u\n", len, opleft, lines); +} + +/* --- */ + +Encoder* PSEncoder::newPredictor(GenBuffer::Writable &out_, unsigned char type, unsigned char bpc_, slen_t columns_, unsigned char cpp_) { + switch ((unsigned)type) { + /* Imp: make these faster with `register int' etc. tricks */ + case 1: return new Filter::VerbatimE(out_); + case 2: return new TIFFPredictor2(out_, bpc_, columns_, cpp_); + case 10: return new PNGPredictorNone(out_, bpc_, columns_, cpp_); + case 11: return new PNGPredictorSub(out_, bpc_, columns_, cpp_); + case 12: return new PNGPredictorUp(out_, bpc_, columns_, cpp_); + case 13: return new PNGPredictorAverage(out_, bpc_, columns_, cpp_); + case 14: return new PNGPredictorPaeth(out_, bpc_, columns_, cpp_); + case 15: return new PNGPredictorAuto(out_, bpc_, columns_, cpp_); + case 45: return new PNGPredictorAutoUnsigned(out_, bpc_, columns_, cpp_); /* pts' extension */ + } + // fprintf(stderr, "pred=%d\n", type); + param_assert(0 && "invalid predictor requested"); + return (Encoder*)0; /*notreached*/ +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/encoder.hpp b/Build/source/utils/sam2p/encoder.hpp new file mode 100644 index 00000000000..d2548463a15 --- /dev/null +++ b/Build/source/utils/sam2p/encoder.hpp @@ -0,0 +1,101 @@ +/* encoder.hpp -- specific encoding filters + * by pts@fazekas.hu at Tue Feb 26 13:30:02 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef ENCODER_HPP +#define ENCODER_HPP 1 + +#include "config2.h" +#include "gensio.hpp" +#include <stdio.h> + +class PSEncoder: public Encoder { + public: + /** @return "Flate", "LZW", "DCT", "RunLength", "CCITTFax", "ASCIIHex", "ASCII85" */ + // inline char const* getLongname() const { return longname; } + /** @return "Fla", "LZW", "DCT", "RL", "CCF", "AHx", "A85" */ + // inline char const* getShortname() const { return shortname; } + // inline SimBuffer::Flat const& getFPSname() const { return filter_psname; } + // virtual void vi_write(char const*buf, slen_t len) =0; + inline virtual ~PSEncoder() {} + + /* The class methods below may return different implementations according to + * the command line and compile-time options. + */ + static PSEncoder* newASCIIHexEncode(GenBuffer::Writable &out_,unsigned maxcpl_); + static PSEncoder* newASCII85Encode(GenBuffer::Writable &out_,unsigned maxcpl_); + /** Fax (PSL2 CCITTFaxEncode filter, Uncompressed=true! (parts of the data + * can be inserted uncompressed, when the decoder decides that this is + * advantageous), K=-1,0,positive, + * EndOfLine=false, EncodedByteAlign=false, Columns=..., Rows=0, + * EndOfBlock=true, BlackIs1=false, DamagedRowsBeforeError=0 + * K must be -1, 0 or positive, see PLRM 3.13.3 + * K==-1: Group 4 pure 2D encoding. TIFF COMPRESSION_CCITTFAX4, + * GROUP4OPT_UNCOMPRESSED. + * K==0: Group 3 pure 1D encoding. TIFF COMPRESSION_CCITTFAX3, + * GROUP3OPT_UNCOMPRESSED. + * K>=1: Group 3 2D (mixed 1D and 2D), a 1D-line can be followed by at most + * K-1 2D-line. TIFF COMPRESSION_CCITTFAX3, GROUP3OPT_UNCOMPRESSED, + * GROUP3OPT_2DENCODING (K is explicitly raised to image height). + * @param EndOfLine should be false for PS/PDF, but must be true for TIFF. + */ + static PSEncoder* newCCITTFaxEncode(GenBuffer::Writable &out_,slendiff_t K, slen_t Columns, bool EndOfLine=false, bool BlackIs1=false); + /** PSL2 LZWEncode filter EarlyChange=true, UnitLength=8 LowBitFirst=false */ + static PSEncoder* newLZWEncode(GenBuffer::Writable &out_); + /** PSL3 FlateEncode (ZIP) filter Effort=...: 1..9: 9==highest compression. -1==5 */ + static PSEncoder* newFlateEncode(GenBuffer::Writable &out_, signed Effort=-1); + /** PSL2 RunLengthEncode filter, similar to TIFF PackBits, recordsize=... */ + static PSEncoder* newRunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize=0); + /** PSL2 DCTEncode. Calls the cjpeg utility (in the debian package + * libjpeg-progs) to do the task. The input must be RGB or Gray with + * BitsPerComponent==8. + */ + static PSEncoder* newDCTIJGEncode(GenBuffer::Writable &out_, + slen_t Columns, + slen_t Rows, + unsigned char Colors, /*1..4*/ + unsigned char quality /*libJPEG quality: 0..100 */ + ); + /** @param other_parameters "" or something + * like: "/HSamples [1 2 1]/ColorTransform 2" + */ + static PSEncoder* newDCTEncode(GenBuffer::Writable &out_, + slen_t Columns, + slen_t Rows, + unsigned char Colors, /*1..4*/ + unsigned char ColorTransform, /*0,1,2 3=default*/ + SimBuffer::Flat const& other_parameters + ); + /** PSL2 DCTEncode. Not supported yet. Imp: build support */ + static PSEncoder* newDCTEncode(GenBuffer::Writable &out_, + slen_t Columns, + slen_t Rows, + unsigned char Colors, /*1..4*/ + unsigned char quality=75, /*libJPEG quality: 0..100 */ + unsigned char const*HSamples=(unsigned char*)NULLP, /*all 1..4, NULLP OK*/ + unsigned char const*VSamples=(unsigned char*)NULLP, /*all 1..4, NULLP OK*/ + /* vvv pacify VC6.0; no unsigned char (*QuantTables)[64]=(unsigned char(*)[64])NULLP, */ + unsigned char (*QuantTables)[64]=0, /*NULLP OK*/ + double QFactor=1.0, /*0..1000000*/ + unsigned numHuffTables=0, + unsigned char **HuffTables=(unsigned char**)NULLP, /*NULLP OK*/ + unsigned char ColorTransform=2 /*0,1,2 3=default*/ + ); + // static Encoder* newTIFFPredictor2(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + // static Encoder* newPNGPredictor11(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + /** @param type: 1: no predictor, 2: TIFFPredictor2, 10: PNGPredictor0 (None) + * 11: PNGPredictor1 (Sub), 12: PNGPredictor2 (Up), + * 13: PNGPredictor3 (Average), 14: PNGPredictor4 (Paeth), + * 15: PNGPredictor5 (optimum). + */ + static Encoder* newPredictor(GenBuffer::Writable &out_, unsigned char type, unsigned char bpc_, slen_t columns_, unsigned char cpp_); + protected: + // char const *longname, *shortname; + // SimBuffer::B filter_psname; +}; + +#endif /* encoder.hpp */ diff --git a/Build/source/utils/sam2p/error.cpp b/Build/source/utils/sam2p/error.cpp new file mode 100644 index 00000000000..190d15d3d12 --- /dev/null +++ b/Build/source/utils/sam2p/error.cpp @@ -0,0 +1,182 @@ +/* + * error.cpp + * by pts@fazekas.hu at Fri Mar 1 11:46:27 CET 2002 + * added policies at Sat Sep 7 18:28:30 CEST 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "error.hpp" +#include "gensio.hpp" +#include <stdio.h> +#include <stdlib.h> /* exit() */ +#include <string.h> /* strlen() */ +#if _MSC_VER > 1000 +# include "windows.h" /* ExitThread() */ +#endif + +char const* Error::argv0=(char const*)NULLP; +char const* Error::long_argv0=(char const*)NULLP; +char const* Error::banner0=(char const*)NULLP; +char const* Error::tmpargv0=(char const*)"pRg_tMp"; + +static Filter::NullE devNull; +GenBuffer::Writable *Error::serr=new Files::FILEW(stderr); +static Error::Policy defaultPolicy={ + (SimBuffer::B*)NULLP, /* record */ + (Error::level_t)-9999, /* topSecret */ + (Error::level_t)-9999, /* topRecorded */ + (Error::level_t)0, /* killer (level>=0) */ + (Error::level_t)-99, /* printed */ + (Error::level_t)-199, /* recorded */ + Error::serr, /* err */ + (Error::Policy*)NULLP, /* prev */ + (Error::Policy*)NULLP, /* next */ + (Error::level_t)-9999, /* curlev */ +}; +Error::Policy *Error::policy_top=&defaultPolicy, *Error::policy_bottom=&defaultPolicy; + +char const*Error::level2str(level_t level) { + return level==ASSERT ? "failed_assertion" : /* Imp: make assert() produce this */ + level==FATAL ? "Fatal Error" : + level==ERROR_CONT ? "Error" : + level==EERROR ? "Error" : + level==WARNING_DEFER ? "Warning" : + level==WARNING ? "Warning" : + level==NOTICE ? "Notice" : + level==NOTICE_DEFER ? "Notice" : + level==INFO ? "Info" : + level==DEBUG ? "DEBUG" : + "??level" ; +} + +GenBuffer::Writable& Error::sev(level_t level) { + /* So they are trying to make an error? Let's see whether they can. */ + GenBuffer::Writable *err=policy_top->err; + // printf("curlev=%d\n", policy_top->curlev); + assert(policy_top->curlev==-9999 && "nested error/ unfinished prev err"); + policy_top->curlev=level; + /* printf("level=%d\n", level); */ + if (level>=policy_top->printed) { /* printed or killer */ + #if 0 /* Disables printing of "using template: " */ + /* vvv Delay printing this message after all recorded messages */ + if (policy_top->record!=NULLP) err=policy_top->record; + #endif + } else if (level>=policy_top->recorded) { /* recorded */ + if (NULLP==(err=policy_top->record)) err=policy_top->record=new SimBuffer::B(); + if (level>policy_top->topRecorded) policy_top->topRecorded=level; + } else { /* secret */ + if (level>policy_top->topSecret) policy_top->topSecret=level; + return devNull; + } + return *err << (argv0==(char const*)NULLP?"??argv0":argv0) << ": " << level2str(level) << ": "; + /* Processing will continue soon by GenBuffer::Writable& operator <<(GenBuffer::Writable& gb,Error*) */ +} + +GenBuffer::Writable& operator <<(GenBuffer::Writable& err,Error*) { + err << '\n'; + Error::level_t level=Error::policy_top->curlev; + if (level>=Error::policy_top->killer) { /* killer */ + /* Also print recorded messages throughout the the policy stack */ + Error::Policy *p=Error::policy_bottom; + while (p!=NULLP) { + if (NULLP!=p->record) Error::policy_top->err->vi_write(p->record->begin_(), p->record->getLength()); + p=p->next; + } + // if (level>=Error::policy_top->killer) + Error::cexit(level); + } + /* Note that the order of error messages might be scrambled, i.e `printed' + * is printed before `recorded'. + */ + Error::policy_top->curlev=(Error::level_t)-9999; /* pedantic but useless because of nesting */ + return err; +} + +void Error::pushPolicy(level_t killer_, level_t printed_, level_t recorded_, GenBuffer::Writable *err) { + Policy *p=new Policy(); + p->record=(SimBuffer::B*)NULLP; + p->topSecret=p->topRecorded=(Error::level_t)-9999; + p->killer=killer_; + p->printed=printed_; + p->recorded=recorded_; + p->err=(err==NULLP) ? policy_top->err : err; + p->prev=policy_top; + p->next=(Policy*)NULLP; + policy_top=p->prev->next=p; + p->curlev=(Error::level_t)-9999; /* pedantic but useless because of nesting */ +} + +SimBuffer::B *Error::getRecorded() { + SimBuffer::B *ret=policy_top->record; + policy_top->record=(SimBuffer::B*)NULLP; + return ret; +} + +void Error::setTopPrinted(level_t printed_) { + policy_top->printed=printed_; +} + +Error::level_t Error::getTopPrinted() { return policy_top->printed; } + +void Error::popPolicy() { + if (policy_top==policy_bottom) { + Error::sev(Error::ASSERT) << "popPolicy: underflow" << (Error*)0; + } else { + if (NULLP!=policy_top->record) { + (*Error::policy_top->err) << "-- recorded messages:\n"; + Error::policy_top->err->vi_write(policy_top->record->begin_(), policy_top->record->getLength()); + delete policy_top->record; + } + policy_top=policy_top->prev; + delete policy_top->next; + policy_top->next=(Policy*)NULLP; + } +} + +/* --- */ + +Error::Cleanup *Error::first_cleanup=(Error::Cleanup*)NULLP; + +void Error::cexit(int exitCode) { + Cleanup *next; + int exit2; + while (first_cleanup!=NULLP) { + // fprintf(stderr, "hand %p\n", first_cleanup); + if (exitCode<(exit2=first_cleanup->handler(first_cleanup))) exitCode=exit2; + next=first_cleanup->next; + delete [] (char*)first_cleanup; /* Allocated from as an array, but has no destructors. */ + first_cleanup=next; + } + #if _MSC_VER > 1000 + ExitThread(exitCode); + #else + exit(exitCode); /* <stdlib.h> */ + #endif +} + +Error::Cleanup* Error::newCleanup(Error::Cleanup::handler_t handler, void *data, slen_t size) { + param_assert(handler!=0); + // slen_t num_packets=(size+sizeof(Cleanup)-1)/sizeof(Cleanup); + Cleanup *new_=(Cleanup*)new char[size+sizeof(Cleanup)]; /* new Cleanup[1+num_packets]; */ + /* ^^^ should be a new Cleanup + new char[size]; now we can avoid alignment + * problems + */ + new_->handler=handler; + new_->size=size; + new_->data=data; + new_->next=first_cleanup; + first_cleanup=new_; + return new_; +} + +Error::Cleanup* Error::newCleanup(Error::Cleanup::handler_t handler, void *data, char const*cstr) { + slen_t slen1=strlen(cstr)+1; + Cleanup *new_=newCleanup(handler, data, slen1+1); + memcpy(new_->getBuf(), cstr, slen1); + return new_; +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/error.hpp b/Build/source/utils/sam2p/error.hpp new file mode 100644 index 00000000000..906b99dc90f --- /dev/null +++ b/Build/source/utils/sam2p/error.hpp @@ -0,0 +1,140 @@ +/* error.hpp -- handling errors/warnings etc. + * by pts@fazekas.hu at Fri Mar 1 11:32:36 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef ERROR_HPP +#define ERROR_HPP 1 + +#include "config2.h" +#include "gensi.hpp" + +/** This may be usafe if an error happens inside an error. Usage: + * Error::sev(Error::WARNING) << "Zero-length image." << (Error*)0; + */ +class Error { + public: + static char const* banner0; + static char const* argv0; + static char const* tmpargv0; + static char const* long_argv0; + /** Error types. */ + BEGIN_STATIC_ENUM(int,level_t) + ASSERT=4, FATAL=3, + EERROR=2, /* ERROR conflicts with the Win32 API :-( */ + ERROR_CONT=-2, /* error, but continue running program */ + WARNING=-3, + WARNING_DEFER=-4, /* warning, but defer (and later possibly omit) displaying it */ + NOTICE=-5, + NOTICE_DEFER=-6, INFO=-111, DEBUG=-222 + END_STATIC_ENUM() + /** Standard error stream (stderr) of the current process. */ + static GenBuffer::Writable *serr; + /** Returns address to statically allocated buffer. */ + static char const*level2str(level_t level); + /** This is the (carefully hidden :-)) method of raising errors (i.e + * displaying error messages and terminating the program). + * Example usage: + * Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires " + * "/Predictor " << 1 << (Error*)0; + * The error is interpreted according to the current policy. The policy + * divides errors into three categories: + * + * -- secret: nothing happens (even the error message is _not_ printed) + * -- recorded: nothing happens (even the error message is _not_ printed), + * but the message is remembered for further processing. + * -- printed: the error message is printed, and program execution continues + * Before printing this message, all recorded errors on the policy stack + * are also printed (deepest first). + * -- killer: like `printed', but runs cleanup handlers and terminates the + * program immediately. + * + * @param level is one of the constants mentioned above (FATAL, EERROR, + * WARNING, NOTICE etc). Can be positive, zero or negative. The larger + * the `level', the more severe the error is. The default policy is: + * level>=0 errors are killer, -99<=level<=-1 errors are printed, + * -199<=level<=-100 are recorded and level<=-200 errors are secret. + */ + static GenBuffer::Writable& sev(level_t level); + + public: + /** The field order is important in this struct, because of the initializers. */ + struct Policy { + /** All recorded messages. Default: NULL. This means empty. */ + SimBuffer::B *record; + /** The highest level of Secret category encountered so far. Default: -9999 */ + level_t topSecret; + /** The highest level of Recorded category encountered so far. Default: -9999 */ + level_t topRecorded; + /** Lower bound of these categories in this policy. */ + level_t killer, printed, recorded; + /** Error stream to print printed and killer messages. */ + GenBuffer::Writable *err; + /** NULL for top policy */ + Policy *prev, *next; + /** Level of the current error being raised. */ + level_t curlev; + }; + protected: + /** Boundaries of the policy stack. */ + static Policy *policy_top, *policy_bottom; + public: + friend GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*); + /** Creates a new policy and makes it active by pushing it onto the top of + * the policy stack. + */ + static void pushPolicy(level_t killer_, level_t printed_, level_t recorded_, GenBuffer::Writable *err=(GenBuffer::Writable*)NULLP); + /** @return the messages already recorded, and clears the `record' entry + * of the current policy. The caller is responsible for deleting the + * pointer returned. May return NULLP for empty records. Typical example: + * delete Error::getRecorded(); + */ + static SimBuffer::B *getRecorded(); + /** Prints all recorded error messages, and removes the topmost element of + * the policy stack. Typical example: + * delete Error::getRecorded(); popPolicy(); + */ + static void popPolicy(); + + /** @example Error::setTopPrinted(Error::ERROR_CONT); suppress anything + * below error, such as warnings. + */ + static void setTopPrinted(level_t printed_); + + static level_t getTopPrinted(); + + /** The Cleanup mechanism is similar to atexit(3) and on_exit(3). This is + * just a simple struct with no destructors, virtual methods or inheritance. + */ + struct Cleanup { + /** Must _not_ cause any Errors + * @return an exit code. If larger than the current one, replaces it + */ + typedef int (*handler_t)(Cleanup*); + handler_t handler; + /** size of extra data allocated */ + slen_t size; + /** arbitrary data */ + void *data; + /** NULLP: no next, end of chain */ + Cleanup *next; + inline char *getBuf() { return (char*)(this+1); } + inline slen_t getSize() { return size; } + }; + /** Creates and registers a new Cleanup, and puts it before old ones. */ + static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, slen_t size); + static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, char const*cstr); + /** Executes the cleanups (in reverse-registration order), and exits from + * the current process with the specified or higher exit code. + */ + static void cexit(int exitCode); + protected: + static Cleanup *first_cleanup; +}; + +GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*); + +#endif diff --git a/Build/source/utils/sam2p/examples/a_jpg.job b/Build/source/utils/sam2p/examples/a_jpg.job new file mode 100644 index 00000000000..b579462730a --- /dev/null +++ b/Build/source/utils/sam2p/examples/a_jpg.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002 +/InputFile (examples/a.jpg) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Asis /TransferEncoding/Binary + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/a_jpg2.job b/Build/source/utils/sam2p/examples/a_jpg2.job new file mode 100644 index 00000000000..14da8c383e7 --- /dev/null +++ b/Build/source/utils/sam2p/examples/a_jpg2.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002 +/InputFile (examples/a.jpg) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Rgb8 /TransferEncoding/Binary + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_gif.job b/Build/source/utils/sam2p/examples/fusi_gif.job new file mode 100644 index 00000000000..e6fca1fc2c8 --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_gif.job @@ -0,0 +1,11 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002 +/InputFile (examples/fusi.tiff) +/OutputFile (test.gif) +/Profile [ + << /FileFormat/GIF89a + /SampleFormat/Transparent4 + %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels + /TransferEncoding/Binary + /Compression/None >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_png.job b/Build/source/utils/sam2p/examples/fusi_png.job new file mode 100644 index 00000000000..0c12cdc9bee --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_png.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002 +/InputFile (examples/fusi.tiff) +%/InputFile (examples/fusiblack.ppm) +/OutputFile (test.png) +/Profile [ + << /FileFormat/PNG /SampleFormat/Transparent4 /TransferEncoding/Binary + /Compression/ZIP /Predictor 15 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_pnm.job b/Build/source/utils/sam2p/examples/fusi_pnm.job new file mode 100644 index 00000000000..4d37ac12979 --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_pnm.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 21:42:08 CEST 2002 +/InputFile (examples/fusi.gif) +/OutputFile (test.pnm) +/unknown pop +/Profile [ + << /FileFormat/PNM /SampleFormat/Transparent4 /TransferEncoding/Binary + /Compression/None >> +] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_tiff_bad_pdf.job b/Build/source/utils/sam2p/examples/fusi_tiff_bad_pdf.job new file mode 100644 index 00000000000..4bd35bbb51e --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_tiff_bad_pdf.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Sun Apr 14 15:14:32 CEST 2002 +/InputFile (examples/fusi.tiff) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Gray8 /TransferEncoding/Binary + /Compression/ZIP >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_tiff_eps.job b/Build/source/utils/sam2p/examples/fusi_tiff_eps.job new file mode 100644 index 00000000000..83663896f35 --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_tiff_eps.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Sun Apr 14 15:14:32 CEST 2002 +/InputFile (examples/fusi.tiff) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Gray8 /TransferEncoding/Binary + /Compression/ZIP >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_tra_eps.job b/Build/source/utils/sam2p/examples/fusi_tra_eps.job new file mode 100644 index 00000000000..6098f3f5cad --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_tra_eps.job @@ -0,0 +1,12 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002 +/InputFile (examples/fusi.tiff) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 + /SampleFormat/Transparent4 + %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels + /TransferEncoding/A85 + /Predictor 45 + /Compression/ZIP >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_trabin_eps.job b/Build/source/utils/sam2p/examples/fusi_trabin_eps.job new file mode 100644 index 00000000000..ba14ef8198b --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_trabin_eps.job @@ -0,0 +1,11 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002 +/InputFile (examples/fusi.tiff) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 + /SampleFormat/Transparent4 + %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels + /TransferEncoding/Binary + /Compression/None >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusi_trafax_eps.job b/Build/source/utils/sam2p/examples/fusi_trafax_eps.job new file mode 100644 index 00000000000..805a4c50b4b --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusi_trafax_eps.job @@ -0,0 +1,11 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002 +/InputFile (examples/fusi.tiff) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL2 + /SampleFormat/Transparent4 + %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels + /TransferEncoding/A85 + /Compression/Fax >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/fusiblack_png.job b/Build/source/utils/sam2p/examples/fusiblack_png.job new file mode 100644 index 00000000000..e664d0b1a63 --- /dev/null +++ b/Build/source/utils/sam2p/examples/fusiblack_png.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002 +%/InputFile (examples/fusi.tiff) +/InputFile (examples/fusiblack.ppm) +/OutputFile (test.png) +/Profile [ + << /FileFormat/PNG /SampleFormat/Indexed4 /TransferEncoding/Binary + /Compression/ZIP /Predictor 15 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/mixing_ijg.job b/Build/source/utils/sam2p/examples/mixing_ijg.job new file mode 100644 index 00000000000..7417f739df5 --- /dev/null +++ b/Build/source/utils/sam2p/examples/mixing_ijg.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/mixing1.xpm) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL2 /SampleFormat/RGB8 /TransferEncoding/A85 + /Compression/IJG +>> + ] +>> diff --git a/Build/source/utils/sam2p/examples/mixing_pcx_zip.job b/Build/source/utils/sam2p/examples/mixing_pcx_zip.job new file mode 100644 index 00000000000..aac2047fce2 --- /dev/null +++ b/Build/source/utils/sam2p/examples/mixing_pcx_zip.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/mixing1.pcx) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Indexed2 /TransferEncoding/A85 + /Compression/ZIP /Predictor 2>> + ] +>> diff --git a/Build/source/utils/sam2p/examples/mixing_zip.job b/Build/source/utils/sam2p/examples/mixing_zip.job new file mode 100644 index 00000000000..fd1233bb348 --- /dev/null +++ b/Build/source/utils/sam2p/examples/mixing_zip.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/mixing0.xpm) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Indexed2 /TransferEncoding/A85 + /Compression/ZIP /Predictor 2>> + ] +>> diff --git a/Build/source/utils/sam2p/examples/pts2.pbm b/Build/source/utils/sam2p/examples/pts2.pbm Binary files differnew file mode 100644 index 00000000000..006b4e3861d --- /dev/null +++ b/Build/source/utils/sam2p/examples/pts2.pbm diff --git a/Build/source/utils/sam2p/examples/pts2_pbm.job b/Build/source/utils/sam2p/examples/pts2_pbm.job new file mode 100644 index 00000000000..949d7d54d63 --- /dev/null +++ b/Build/source/utils/sam2p/examples/pts2_pbm.job @@ -0,0 +1,10 @@ +<<%sam2p-job; by pts@fazekas.hu at Sun Mar 17 16:21:44 CET 2002 +% This is file (named test0.job). +/InputFile (examples/pts2.pbm) +/OutputFile (test.eps) +/unknown pop +/Profile [ + << /FileFormat/PSL1 /SampleFormat/Gray8 /TransferEncoding/A85 + /Compression/ZIP /Hints<</Effort 6>> /Predictor 1 >> +] +>> diff --git a/Build/source/utils/sam2p/examples/pts2_pbm_zip0.job b/Build/source/utils/sam2p/examples/pts2_pbm_zip0.job new file mode 100644 index 00000000000..2a94da8acd1 --- /dev/null +++ b/Build/source/utils/sam2p/examples/pts2_pbm_zip0.job @@ -0,0 +1,10 @@ +<<%sam2p-job; by pts@fazekas.hu at Sun Mar 17 16:21:44 CET 2002 +% This is file (named test0.job). +/InputFile (examples/pts2.pbm) +/OutputFile (test.eps) +/unknown pop +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Gray8 /TransferEncoding/Binary + /Compression/ZIP /Hints<</Effort 0>> /Predictor 1 >> +] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner.gif b/Build/source/utils/sam2p/examples/ptsbanner.gif Binary files differnew file mode 100644 index 00000000000..8cccb071bb0 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner.gif diff --git a/Build/source/utils/sam2p/examples/ptsbanner2_jai.job b/Build/source/utils/sam2p/examples/ptsbanner2_jai.job new file mode 100644 index 00000000000..90ff2607cf9 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner2_jai.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002 +/InputFile (examples/ptsbanner2.jpg) +/OutputFile (test.eps) +%/LoadHints (asis) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Asis /TransferEncoding/Hex + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner2_jai_jpeg.job b/Build/source/utils/sam2p/examples/ptsbanner2_jai_jpeg.job new file mode 100644 index 00000000000..5057b82ef4b --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner2_jai_jpeg.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 13:49:02 CEST 2002 +/InputFile (examples/ptsbanner2.jpg) +/OutputFile (test.jpg) +%/LoadHints (asis) +/Profile [ + << /FileFormat/JPEG /SampleFormat/Asis /TransferEncoding/Binary + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner2_jai_pdf.job b/Build/source/utils/sam2p/examples/ptsbanner2_jai_pdf.job new file mode 100644 index 00000000000..6f514072c64 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner2_jai_pdf.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 12:26:49 CEST 2002 +/InputFile (examples/ptsbanner2.jpg) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDF1.2 /SampleFormat/Asis /TransferEncoding/A85 + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner__jpeg.job b/Build/source/utils/sam2p/examples/ptsbanner__jpeg.job new file mode 100644 index 00000000000..bfce6c0190f --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner__jpeg.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile (test.jpg) +%/LoadHints (asis) +/Profile [ + << /FileFormat/JPEG /SampleFormat/Rgb8 /TransferEncoding/Binary + /Compression/IJG >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_jpeg.job b/Build/source/utils/sam2p/examples/ptsbanner_jpeg.job new file mode 100644 index 00000000000..5a836e0d8ba --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_jpeg.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Sun Mar 17 22:34:14 CET 2002 +/InputFile (examples/ptsbanner2.jpg) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSLC /SampleFormat/Rgb8 /TransferEncoding/Hex + /Compression/None >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_lzw.job b/Build/source/utils/sam2p/examples/ptsbanner_lzw.job new file mode 100644 index 00000000000..f90230e4fc8 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_lzw.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/Hex + /Compression/LZW /Predictor 15 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_lzw_pdf.job b/Build/source/utils/sam2p/examples/ptsbanner_lzw_pdf.job new file mode 100644 index 00000000000..e6954a0cab9 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_lzw_pdf.job @@ -0,0 +1,12 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 19:03:10 CEST 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDF1.0 /SampleFormat/Indexed8 /TransferEncoding/Hex + % /Compression/LZW /Predictor 15 + % /Compression/RLE + /Compression/LZW /Predictor 2 + % /Compression/LZW + >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_lzw_pdfb.job b/Build/source/utils/sam2p/examples/ptsbanner_lzw_pdfb.job new file mode 100644 index 00000000000..00fbfe51f33 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_lzw_pdfb.job @@ -0,0 +1,10 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 19:03:39 CEST 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed8 /TransferEncoding/Hex + % /Compression/LZW /Predictor 2 % OK in pdftops 0.92 + /Compression/LZW /Predictor 10 % triggers bug in pdftops 0.92 + >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_png.job b/Build/source/utils/sam2p/examples/ptsbanner_png.job new file mode 100644 index 00000000000..8f65f2aa8b9 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_png.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile (test.png) +/Profile [ + << /FileFormat/PNG /SampleFormat/RGB8 /TransferEncoding/Binary + /Compression/ZIP /Predictor 12>> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_tralzw.job b/Build/source/utils/sam2p/examples/ptsbanner_tralzw.job new file mode 100644 index 00000000000..23df8053010 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_tralzw.job @@ -0,0 +1,18 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile(test.eps) +/Profile [ +% sasdasdasd /Korte [ + << /FileFormat /PSL2 /SampleFormat/Transparent8 + /TransferEncoding/Binary + /WarningOK true + % /TransferEncoding/Hex + % /Compression/LZW + /Predictor 1 + /Compression /RLE + /Hints << /K 42 >> + >> + ] +>> + + diff --git a/Build/source/utils/sam2p/examples/ptsbanner_xpm_zip.job b/Build/source/utils/sam2p/examples/ptsbanner_xpm_zip.job new file mode 100644 index 00000000000..d95c938420c --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_xpm_zip.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/ptsbanner.xpm) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Rgb4 /TransferEncoding/A85 + /Compression/ZIP /Predictor 2>> + ] % /a 4 +>> diff --git a/Build/source/utils/sam2p/examples/ptsbanner_zip.job b/Build/source/utils/sam2p/examples/ptsbanner_zip.job new file mode 100644 index 00000000000..afb7edd0487 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbanner_zip.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002 +/InputFile (examples/ptsbanner.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/RGB4 /TransferEncoding/A85 + /Compression/ZIP /Predictor 2>> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbannerg_jai.job b/Build/source/utils/sam2p/examples/ptsbannerg_jai.job new file mode 100644 index 00000000000..ce71fe78257 --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbannerg_jai.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002 +/InputFile (examples/ptsbannerg.jpg) +/OutputFile (test.eps) +%/LoadHints (asis) +/Profile [ + << /FileFormat/PSL3 /SampleFormat/Asis /TransferEncoding/Hex + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/ptsbannerg_jai_pdf.job b/Build/source/utils/sam2p/examples/ptsbannerg_jai_pdf.job new file mode 100644 index 00000000000..eb93a6eb23f --- /dev/null +++ b/Build/source/utils/sam2p/examples/ptsbannerg_jai_pdf.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 12:26:49 CEST 2002 +/InputFile (examples/ptsbannerg.jpg) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Asis /TransferEncoding/A85 + /Compression/JAI >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2p_fishg.job b/Build/source/utils/sam2p/examples/sam2p_fishg.job new file mode 100644 index 00000000000..8713cedb7a7 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2p_fishg.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002 +/InputFile (talk/fishg.gif) +/OutputFile (talk/fishg.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary + /Compression/LZW /Predictor 2 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2p_fisht.job b/Build/source/utils/sam2p/examples/sam2p_fisht.job new file mode 100644 index 00000000000..8713cedb7a7 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2p_fisht.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002 +/InputFile (talk/fishg.gif) +/OutputFile (talk/fishg.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary + /Compression/LZW /Predictor 2 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2p_fishwbb.job b/Build/source/utils/sam2p/examples/sam2p_fishwbb.job new file mode 100644 index 00000000000..b93a105e1b0 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2p_fishwbb.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002 +/InputFile (talk/fishwbb.gif) +/OutputFile (talk/fishwbb.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary + /Compression/LZW /Predictor 2 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2p_fishwbg.job b/Build/source/utils/sam2p/examples/sam2p_fishwbg.job new file mode 100644 index 00000000000..7719ef92eff --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2p_fishwbg.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002 +/InputFile (talk/fishwbg.gif) +/OutputFile (talk/fishwbg.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed4 /TransferEncoding/Binary + /Compression/LZW /Predictor 10>> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2p_fishwbg_bug.job b/Build/source/utils/sam2p/examples/sam2p_fishwbg_bug.job new file mode 100644 index 00000000000..a12b84870c0 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2p_fishwbg_bug.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002 +% Shows acroread4 bug (Predictor 2 with indexed images) +/InputFile (talk/fishwbg.gif) +/OutputFile (talk/fishwbg.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed4 /TransferEncoding/Binary + /Compression/LZW /Predictor 2 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2p_fishwww.job b/Build/source/utils/sam2p/examples/sam2p_fishwww.job new file mode 100644 index 00000000000..d8704f832f1 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2p_fishwww.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002 +/InputFile (talk/fishwww.gif) +/OutputFile (talk/fishwww.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Opaque /TransferEncoding/Binary + /Compression/LZW /Predictor 2 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sam2psho.job b/Build/source/utils/sam2p/examples/sam2psho.job new file mode 100644 index 00000000000..8262a3664f0 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sam2psho.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by pts@fazekas.hu at Thu Apr 25 09:09:51 CEST 2002 +/InputFile (talk/sam2psho.png) +/OutputFile (talk/sam2psho.pdf) +/Profile [ + << /FileFormat/PDFB1.0 /SampleFormat/Indexed8 /TransferEncoding/Binary + /Compression/LZW /Predictor 2 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/shot_gif.job b/Build/source/utils/sam2p/examples/shot_gif.job new file mode 100644 index 00000000000..544c3213788 --- /dev/null +++ b/Build/source/utils/sam2p/examples/shot_gif.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/shot_large.gif) +%/OutputFile (examples/shot.gif) +/OutputFile (test.gif) +/Profile [ + << /FileFormat/GIF89a /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/None >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/shot_i1.job b/Build/source/utils/sam2p/examples/shot_i1.job new file mode 100644 index 00000000000..b32e18948db --- /dev/null +++ b/Build/source/utils/sam2p/examples/shot_i1.job @@ -0,0 +1,7 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/shot.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL2 /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/RLE >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/shot_pdfb.job b/Build/source/utils/sam2p/examples/shot_pdfb.job new file mode 100644 index 00000000000..0b84da5771c --- /dev/null +++ b/Build/source/utils/sam2p/examples/shot_pdfb.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 20:55:37 CEST 2002 +/InputFile (examples/shot.gif) +/OutputFile (test.pdf) +% triggers Ghostscript 5.50 lowest-bit rendering bug +/Profile [ + << /FileFormat/PDFB1.2 /SampleFormat/Indexed1 /TransferEncoding/Binary + /Compression/ZIP /Predictor 45 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/shot_png.job b/Build/source/utils/sam2p/examples/shot_png.job new file mode 100644 index 00000000000..fd783f7bbd7 --- /dev/null +++ b/Build/source/utils/sam2p/examples/shot_png.job @@ -0,0 +1,7 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/shot_large.gif) +/OutputFile (test.png) +/Profile [ + << /FileFormat/PNG /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/ZIP /Predictor 45 >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/shot_ppm.job b/Build/source/utils/sam2p/examples/shot_ppm.job new file mode 100644 index 00000000000..2990b7f414b --- /dev/null +++ b/Build/source/utils/sam2p/examples/shot_ppm.job @@ -0,0 +1,10 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Mar 23 14:32:58 CET 2002 +/InputFile (examples/shot.gif) +/OutputFile (test.ppm) +/Profile [ + << /FileFormat/PNM /SampleFormat/Rgb8 + /TransferEncoding/ASCII + % /TransferEncoding/Binary + /Compression/None >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sziget_al.job b/Build/source/utils/sam2p/examples/sziget_al.job new file mode 100644 index 00000000000..0f3febfb4a0 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sziget_al.job @@ -0,0 +1,12 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/sziget_al.ppm) +%/InputFile (examples/sziget.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL2 /SampleFormat/Mask /TransferEncoding/Binary +% /Compression/RLE + /Compression/LZW +% /Compression/None + >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sziget_al_pdf.job b/Build/source/utils/sam2p/examples/sziget_al_pdf.job new file mode 100644 index 00000000000..897853d3a50 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sziget_al_pdf.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 20:49:05 CEST 2002 +/InputFile (examples/sziget_al.ppm) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDF1.0 /SampleFormat/Mask /TransferEncoding/Binary + /Compression/RLE + >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/sziget_ma.job b/Build/source/utils/sam2p/examples/sziget_ma.job new file mode 100644 index 00000000000..731d40b92b3 --- /dev/null +++ b/Build/source/utils/sam2p/examples/sziget_ma.job @@ -0,0 +1,8 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/sziget.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL2 /SampleFormat/Mask /TransferEncoding/Binary + /Compression/Fax >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/transparent_tr.job b/Build/source/utils/sam2p/examples/transparent_tr.job new file mode 100644 index 00000000000..adbaf72682f --- /dev/null +++ b/Build/source/utils/sam2p/examples/transparent_tr.job @@ -0,0 +1,7 @@ +<<%sam2p-job; by Fri Mar 22 17:54:01 CET 2002 +/InputFile (examples/transparent.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL1 /SampleFormat/Transparent /TransferEncoding/Binary /Compression/RLE >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/transparent_tr_pdf.job b/Build/source/utils/sam2p/examples/transparent_tr_pdf.job new file mode 100644 index 00000000000..c9e50bde11c --- /dev/null +++ b/Build/source/utils/sam2p/examples/transparent_tr_pdf.job @@ -0,0 +1,7 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 13:26:00 CEST 2002 +/InputFile (examples/transparent.gif) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDFB1.2 /SampleFormat/Transparent /TransferEncoding/Binary /Compression/ZIP >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/yellow_gif.job b/Build/source/utils/sam2p/examples/yellow_gif.job new file mode 100644 index 00000000000..ad7a7fa4a6e --- /dev/null +++ b/Build/source/utils/sam2p/examples/yellow_gif.job @@ -0,0 +1,7 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/yellow_large.gif) +/OutputFile (examples/yellow.gif) +/Profile [ + << /FileFormat/GIF89a /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/LZW >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/yellow_op.job b/Build/source/utils/sam2p/examples/yellow_op.job new file mode 100644 index 00000000000..043860ff142 --- /dev/null +++ b/Build/source/utils/sam2p/examples/yellow_op.job @@ -0,0 +1,9 @@ +<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002 +/InputFile (examples/yellow.gif) +/OutputFile (test.eps) +/Profile [ + << /FileFormat/PSL1 /SampleFormat/Opaque /TransferEncoding/Binary /Compression/RLE >> + % << /FileFormat/PSL1 /SampleFormat/Transparent /TransferEncoding/Binary /Compression/RLE >> + % << /FileFormat/PSL2 /SampleFormat/Indexed2 /TransferEncoding/Binary /Compression/RLE >> + ] +>> diff --git a/Build/source/utils/sam2p/examples/yellow_op_pdf.job b/Build/source/utils/sam2p/examples/yellow_op_pdf.job new file mode 100644 index 00000000000..c127f8fd6d2 --- /dev/null +++ b/Build/source/utils/sam2p/examples/yellow_op_pdf.job @@ -0,0 +1,7 @@ +<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 13:15:22 CEST 2002 +/InputFile (examples/yellow.gif) +/OutputFile (test.pdf) +/Profile [ + << /FileFormat/PDF1.0 /SampleFormat/Opaque /TransferEncoding/AHx /Compression/RLE >> + ] +>> diff --git a/Build/source/utils/sam2p/files b/Build/source/utils/sam2p/files new file mode 100644 index 00000000000..d4cc80039ff --- /dev/null +++ b/Build/source/utils/sam2p/files @@ -0,0 +1,157 @@ +main.hpp +config-vc6.h +sam2p16.ico +sam2p32.ico +vcsam2p.ico +vcsam2p.cpp +vcsam2p.dsp +vcsam2p.h +vcsam2p.ico +vcsam2p.rc +resource.h +StdAfx.cpp +StdAfx.h +hq.pl +c_lgcc.cpp +c_lgcc3.cpp +in_jai.hpp +jpegdump_main.cpp +sam2p_main.cpp +test_main.cpp +testfax_main.c +snprintf.h +snprintf.c +pts_fax.c +pts_fax.h +examples/pts2.pbm +examples/ptsbanner.gif +ccdep.pl +helpere.hpp +encoder.hpp +error.hpp +gensi.hpp +gensio.hpp +image.hpp +gensi.cpp +Makefile +rule.hpp +gensio.cpp +minips.hpp +cgif.c +encoder.cpp +error.cpp +image.cpp +in_bmp.cpp +in_gif.cpp +in_jai.cpp +in_jpeg.cpp +in_lbm.cpp +in_pcx.cpp +in_png.cpp +in_pnm.cpp +in_ps.cpp +pts_defl.c +pts_defl.h +in_tga.cpp +in_tiff.cpp +in_xpm.cpp +out_gif.cpp +crc32.c +crc32.h +cgif.h +cols2.pl +in_pnm.cpp +xpmc.h +in_xpm.cpp +in_tga.cpp +minips.cpp +rule.cpp +sam2p_main.cpp +Makehelp.in +pts_lzw.c +mkdist.sh +input-bmp.ci +input-pnm.ci +input-tga.ci +at_bitmap.h +pts_lzw.h +files +pts_defl.c +pts_defl.h +aclocal.m4 +configure.in +config2.h +config.h.in +configure +COPYING +README +appliers.cpp +in_jai.cpp +out_gif.cpp +mapping.hpp +mapping.cpp +contrib/aprea.ps +contrib/sam2p.tk +contrib/sam2ptol.pm +contrib/template.job +examples/a_jpg.job +examples/a_jpg2.job +examples/fusi_gif.job +examples/fusi_png.job +examples/fusi_pnm.job +examples/fusi_tiff_bad_pdf.job +examples/fusi_tiff_eps.job +examples/fusi_tra_eps.job +examples/fusi_trabin_eps.job +examples/fusi_trafax_eps.job +examples/fusiblack_png.job +examples/mixing_ijg.job +examples/mixing_pcx_zip.job +examples/mixing_zip.job +examples/pts2_pbm.job +examples/pts2_pbm_zip0.job +examples/ptsbanner2_jai.job +examples/ptsbanner2_jai_jpeg.job +examples/ptsbanner2_jai_pdf.job +examples/ptsbanner__jpeg.job +examples/ptsbanner_jpeg.job +examples/ptsbanner_lzw.job +examples/ptsbanner_lzw_pdf.job +examples/ptsbanner_lzw_pdfb.job +examples/ptsbanner_png.job +examples/ptsbanner_tralzw.job +examples/ptsbanner_xpm_zip.job +examples/ptsbanner_zip.job +examples/ptsbannerg_jai.job +examples/ptsbannerg_jai_pdf.job +examples/sam2p_fishg.job +examples/sam2p_fisht.job +examples/sam2p_fishwbb.job +examples/sam2p_fishwbg.job +examples/sam2p_fishwbg_bug.job +examples/sam2p_fishwww.job +examples/sam2psho.job +examples/shot_gif.job +examples/shot_i1.job +examples/shot_pdfb.job +examples/shot_png.job +examples/shot_ppm.job +examples/sziget_al.job +examples/sziget_al_pdf.job +examples/sziget_ma.job +examples/transparent_tr.job +examples/transparent_tr_pdf.job +examples/yellow_gif.job +examples/yellow_op.job +examples/yellow_op_pdf.job +bts.ttt +l1zip.psm +l1lzw.psm +psmlib.psm +ps_tiny.c +debian/README.debian +debian/changelog +debian/control +debian/copyright +debian/dirs +debian/rules diff --git a/Build/source/utils/sam2p/gensi.cpp b/Build/source/utils/sam2p/gensi.cpp new file mode 100644 index 00000000000..8f1ef125428 --- /dev/null +++ b/Build/source/utils/sam2p/gensi.cpp @@ -0,0 +1,1220 @@ +/* + * gensi.cpp + * by pts@fazekas.hu at Tue Feb 26 13:28:12 CET 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "gensi.hpp" +#include <string.h> /* strlen() */ +// #include <stdarg.h> /* va_list */ + +void GenBuffer::iter_char_sub(char const*beg, slen_t len, void *data) { + while (len--!=0) (1[(block_char_t**)data][0])(*beg++, 0[(void**)data]); +} + +struct copydata_t { + char *to; + slen_t cfrom; + slen_t clen; + slen_t sumlen; +}; +#define CD static_cast<copydata_t*>(data) +static void iter_copy_sub(char const*beg, slen_t len, void *data) { + slen_t i; + CD->sumlen+=len; + if (CD->clen==0) return; + i=CD->cfrom; + if (i>=len) { CD->cfrom-=len; return; } + if (i>0) { CD->cfrom=0; beg+=i; len-=i; } + if (len>=CD->clen) { memcpy(CD->to, beg, CD->clen); CD->clen=0; return; } + memcpy(CD->to, beg, len); + CD->to+=len; CD->clen-=len; +} +// #include <stdio.h> +slen_t GenBuffer::copyRange(char *to, slen_t cfrom, slen_t clen) const { + if (clen==0) return getLength(); + copydata_t cd= { to, cfrom, clen, 0 }; + each_sub(iter_copy_sub, &cd); +#if 1 + while (cd.clen--!=0) *cd.to++='\0'; /* padding */ +#else + fprintf(stderr,"cd.clen=%d\n", cd.clen); + while (cd.clen--!=0) { + fprintf(stderr,"padded.\n"); + *cd.to++='\0'; /* padding */ + } +#endif + return cd.sumlen; +} + +#if HAVE_LONG_LONG && NEED_LONG_LONG +# define LONGEXT PTS_CFG_LONGEST +#else +# define LONGEXT long +#endif + +/* Imp: ensure reentrace. Maybe vi_write wants to output a number which would + * overwrite ours... + */ +static char numtmp[sizeof(LONGEXT)*3+2]; + +bool GenBuffer::toBool(bool &dst) { + /* on 1 true yes ja igen igaz be oui vrai: 1tyjibov */ + /* off 0 false no nein nem hamis ki non -- : 0fnhk */ + slen_t len=copyRange(numtmp, 0, 3); + numtmp[0]|=32; numtmp[1]|=32; numtmp[2]|=32; /* poor man's uppercase */ + dst=true; + if (len==0) return true; + if ((numtmp[0]=='o' && numtmp[1]=='f' && numtmp[2]=='f') + || numtmp[0]=='0' || numtmp[0]=='f' || numtmp[0]=='n' || numtmp[0]=='h' + || numtmp[0]=='k') dst=false; + else if ((numtmp[0]<'0' || numtmp[0]>'9') && (numtmp[0]<'a' || numtmp[0]>'z')) return true; + return false; +} + +// #include <stdio.h> + +bool GenBuffer::toInteger(unsigned long &dst) { + /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */ + /* Imp: check for overflow! */ + slen_t len=copyRange(numtmp, 0, sizeof(numtmp)); + // fprintf(stderr,"len=%d\n", len); + if (len>=sizeof(numtmp)) return true; /* too long */ + /* ASSERT(numtmp null-terminated) */ + char *p=numtmp; + if (*p=='+') p++; + unsigned long i=0; + while (1) { + // fprintf(stderr,"toInteger'%c'\n", *p); + if (*p<'0' || *p>'9') break; + i=10*i+(*p-'0'); + p++; + } + dst=i; + return *p!='\0'; /* a non-digit arrived */ +} +bool GenBuffer::toInteger(signed long &dst) { + /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */ + slen_t len=copyRange(numtmp, 0, sizeof(numtmp)); + if (len>=sizeof(numtmp)) return true; /* too long */ + /* ASSERT(numtmp null-terminated) */ + char *p=numtmp; + bool neg=false; + if (*p=='+') p++; + else if (*p=='-') { neg=true; p++; } + unsigned long i=0; + while (1) { + if (*p<'0' || *p>'9') break; + i=10*i+(*p-'0'); + p++; + } + dst=neg?-(long)i:i; + return *p!='\0'; /* a non-digit arrived */ +} +#if HAVE_LONG_LONG && NEED_LONG_LONG +bool GenBuffer::toInteger(unsigned PTS_CFG_LONGEST &dst) { + /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */ + slen_t len=copyRange(numtmp, 0, sizeof(numtmp)); + if (len>=sizeof(numtmp)) return true; /* too long */ + /* ASSERT(numtmp null-terminated) */ + char *p=numtmp; + if (*p=='+') p++; + unsigned PTS_CFG_LONGEST i=0; + while (1) { + if (*p<'0' || *p>'9') break; + i=10*i+(*p-'0'); + p++; + } + dst=i; + return *p!='\0'; /* a non-digit arrived */ +} +bool GenBuffer::toInteger(signed PTS_CFG_LONGEST &dst) { + /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */ + slen_t len=copyRange(numtmp, 0, sizeof(numtmp)); + if (len>=sizeof(numtmp)) return true; /* too long */ + /* ASSERT(numtmp null-terminated) */ + char *p=numtmp; + bool neg=false; + if (*p=='+') p++; + else if (*p=='-') { neg=true; p++; } + unsigned PTS_CFG_LONGEST i=0; + while (1) { + if (*p<'0' || *p>'9') break; + i=10*i+(*p-'0'); + p++; + } + dst=neg?-i:i; + return *p!='\0'; /* a non-digit arrived */ +} +#endif +bool GenBuffer::toCString(char *&dst) { + slen_t len=getLength(); + dst=new char[len+1]; + copyRange(dst, 0, len+1); /* copies the terminating '\0' automatically. */ + return false; +} + +int GenBuffer::cmp(GenBuffer const& s2) const { + Sub u1, u2; + slen_t m; + int i; + first_sub(u1); + s2.first_sub(u2); + while (1) { + if (u1.len==0 && u2.len==0) return 0; /* (*this) == s2 */ + else if (u1.len==0) return -1; /* (*this) < s2 */ + else if (u2.len==0) return 1; /* (*this) > s2 */ + m=(u1.len<u2.len)?u1.len:u2.len; + if (0!=(i=memcmp(u1.beg,u2.beg,m))) return i; + if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m; + if (0==(u2.len-=m)) s2.next_sub(u2); else u2.beg+=m; + } +} + +int GenBuffer::cmp(char const* u2beg, slen_t u2len) const { + Sub u1; + slen_t m; + int i; + first_sub(u1); + while (1) { + if (u1.len==0 && u2len==0) return 0; /* (*this) == s2 */ + else if (u1.len==0) return -1; /* (*this) < s2 */ + else if (u2len ==0) return 1; /* (*this) > s2 */ + m=(u1.len<u2len)?u1.len:u2len; + if (0!=(i=memcmp(u1.beg,u2beg,m))) return i; + if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m; + u2len-=m; u2beg+=m; + } +} + +int GenBuffer::cmp(char const* u2beg) const { + return cmp(u2beg, strlen(u2beg)); +} + +/* --- */ + +bool GenBuffer::Readable::equal_content(GenBuffer::Readable &other) { + int i1, i2; + while (((i1=vi_getcc())&255) == ((i2=other.vi_getcc())&255) && i1!=-1) ; + return i1==i2; +} + +slen_t GenBuffer::Readable::vi_read(char *to_buf, slen_t max) { + register char *p=to_buf; + char *end=to_buf+max; + int c; + while (p!=end && 0<=(c=vi_getcc())) *p++=c; + return p-to_buf; +} + +int GenBuffer::Readable::readFill(char *to_buf, slen_t max) { + slen_t got, sum=0; + while (max>0 && 0<(got=vi_read(to_buf, max))) { to_buf+=got; sum+=got; max-=got; } + return sum; +} + +/* --- */ + +void GenBuffer::Writable::iter_write_sub(char const*beg, slen_t len, void *data) { + if (len!=0) static_cast<GenBuffer::Writable*>(data)->vi_write(beg, len); +} + +GenBuffer::Writable& GenBuffer::Writable::operator <<(char const*cstr) { + assert(cstr!=0); + vi_write(cstr, strlen(cstr)); + return*this; +} + +GenBuffer::Writable& GenBuffer::Writable::operator <<(void const*ptr) { + if (ptr==0) vi_write("(null)", 6); + else { + vi_write("(0d", 3); + /* Imp: hexadecimal pointer output */ + *this << (PTS_INTP_T)ptr; + vi_putcc(')'); + } + return*this; +} + +void GenBuffer::Writable::write_num(unsigned long n, unsigned zdigits) { + if (zdigits>=sizeof(numtmp)) { + memset(numtmp,'0',sizeof(numtmp)); + while (zdigits>2*sizeof(numtmp)) { + vi_write(numtmp, sizeof(numtmp)); + zdigits-=sizeof(numtmp); + } + vi_write(numtmp, zdigits-sizeof(numtmp)); + zdigits=sizeof(numtmp); + } + char *j=numtmp+sizeof(numtmp), *jend=j-zdigits; + while (j!=jend) { *--j='0'+n%10; n/=10; } + vi_write(j, zdigits); +} +#if HAVE_LONG_LONG && NEED_LONG_LONG +void GenBuffer::Writable::write_num(unsigned PTS_CFG_LONGEST n, unsigned zdigits) { + if (zdigits>=sizeof(numtmp)) { + memset(numtmp,'0',sizeof(numtmp)); + while (zdigits>2*sizeof(numtmp)) { + vi_write(numtmp, sizeof(numtmp)); + zdigits-=sizeof(numtmp); + } + vi_write(numtmp, zdigits-sizeof(numtmp)); + zdigits=sizeof(numtmp); + } + char *j=numtmp+sizeof(numtmp), *jend=j-zdigits; + while (j!=jend) { *--j='0'+n%10; n/=10; } + vi_write(j, zdigits); +} +#endif + +void GenBuffer::Writable::write_num(unsigned long n) { + char *j=numtmp+sizeof(numtmp); + do *--j='0'+n%10; while ((n/=10)!=0); + vi_write(j, numtmp+sizeof(numtmp)-j); +} +void GenBuffer::Writable::write_num(signed long nn) { + register unsigned long n; + char *j=numtmp+sizeof(numtmp); + if (nn<0) { + n=-nn; do *--j='0'+n%10; while ((n/=10)!=0); + *--j='-'; + } else { + n=nn; do *--j='0'+n%10; while ((n/=10)!=0); + } + vi_write(j, numtmp+sizeof(numtmp)-j); +} +#if HAVE_LONG_LONG && NEED_LONG_LONG +void GenBuffer::Writable::write_num(unsigned PTS_CFG_LONGEST n) { + char *j=numtmp+sizeof(numtmp); + do *--j='0'+n%10; while ((n/=10)!=0); + vi_write(j, numtmp+sizeof(numtmp)-j); +} +void GenBuffer::Writable::write_num(signed PTS_CFG_LONGEST nn) { + register unsigned PTS_CFG_LONGEST n; + char *j=numtmp+sizeof(numtmp); + if (nn<0) { + n=-nn; do *--j='0'+n%10; while ((n/=10)!=0); + *--j='-'; + } else { + n=nn; + do *--j='0'+n%10; while ((n/=10)!=0); + } + vi_write(j, numtmp+sizeof(numtmp)-j); +} +#endif + +GenBuffer::Writable& GenBuffer::Writable::vformat(slen_t n, char const *fmt, va_list ap) { + SimBuffer::B buf; + buf.vformat(n, fmt, ap); + vi_write(buf(), buf.getLength()); + return*this; +} +GenBuffer::Writable& GenBuffer::Writable::vformat(char const *fmt, va_list ap) { + SimBuffer::B buf; + buf.vformat(fmt, ap); + vi_write(buf(), buf.getLength()); + return*this; +} +GenBuffer::Writable& GenBuffer::Writable::format(slen_t n, char const *fmt, ...) { + va_list ap; + PTS_va_start(ap, fmt); + vformat(n, fmt, ap); + va_end(ap); + return *this; +} +GenBuffer::Writable& GenBuffer::Writable::format(char const *fmt, ...) { + va_list ap; + PTS_va_start(ap, fmt); + vformat(fmt, ap); + va_end(ap); + return *this; +} + +/* --- */ + +slen_t SimBuffer::Flat::copyRange(char *to, slen_t cfrom, slen_t clen) const { + if (cfrom<len) { /* added padding BUGFIX at Fri Mar 7 20:30:07 CET 2003 */ + slen_t dlen; + memcpy(to, beg+cfrom, dlen=cfrom+clen>len ? len-cfrom : clen); + to+=dlen; + } + while (clen--!=0) *to++='\0'; /* padding */ + return len; +} + +slen_t SimBuffer::Flat::findLast(char const c) const { + char const*p; + for (p=beg+len;p>=beg;p--) if (*p==c) return p-beg; + return len; +} + +slen_t SimBuffer::Flat::findFirst(char const c) const { + char const*p, *end=beg+len; + for (p=beg;p!=end;p++) if (*p==c) return p-beg; + return len; +} + +slen_t SimBuffer::Flat::findFirst(char const* s, slen_t slen) const { + if (slen==0) return 0; /* found */ + if (slen>len) return len; /* not found */ + char const c=*s; + char const*p=beg, *end=beg+len-slen+1; + if (slen==1) { + for (;p!=end;p++) if (*p==c) return p-beg; + } else { + for (;p!=end;p++) if (*p==c && 0==memcmp(p,s,slen)) return p-beg; + } + return len; +} + +int SimBuffer::Flat::cmp(SimBuffer::Flat const& s2) const { + return memcmp(beg, s2.beg, len<s2.len?len:s2.len) || (len>s2.len)-(len<s2.len); +} + +int SimBuffer::Flat::cmp(char const* s2beg, slen_t s2len) const { + return memcmp(beg, s2beg, len<s2len?len:s2len) || (len>s2len)-(len<s2len); +} + +/* --- */ + +SimBuffer::Static::Static(char const*cstr) { beg=cstr; len=strlen(cstr); } + +/* --- */ + +void SimBuffer::Appendable::vi_write(char const*str, slen_t slen) { + if (slen>0) { + char *p=vi_mkend(slen); + memcpy(p, str, slen); + } +} +void SimBuffer::Appendable::prepend(char const*str, slen_t slen) { + if (slen>0) { + char *p=vi_mkbeg(slen); + memcpy(p, str, slen); + } +} + +/* inlined. +void SimBuffer::Appendable::vi_putcc(char c) { + vi_mkend(1)[0]=c; +}*/ + +/* --- */ + +SimBuffer::Linked::~Linked() { + Node *n; + while (first!=0) { + if (first->beg!=(char*)(first+1)) delete [] first->beg; + n=first->next; delete [] first; first=n; + } +} + +slen_t SimBuffer::Linked::getLength() const { + slen_t len=0; + Node *n=first; + while (n!=0) { len+=n->len; n=n->next; } + return len; +} + +SimBuffer::Linked::Linked(GenBuffer const& other) { + slen_t len=other.getLength(); + Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len])); + n->beg=(char*)(n+1); + other.copyRange(n->beg, 0, len); + n->len=len; + n->next=0; + first=last=n; +} +SimBuffer::Linked::Linked(char const*str) { + slen_t len=strlen(str); + Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len])); + n->beg=(char*)(n+1); + memcpy(n->beg, str, len); + n->len=len; + n->next=0; + first=last=n; +} +SimBuffer::Linked& SimBuffer::Linked::operator=(GenBuffer const& other) { + slen_t len=other.getLength(); + Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len])); + n->beg=(char*)(n+1); + other.copyRange(n->beg, 0, len); + n->len=len; + n->next=0; + first=last=n; + return *this; +} +SimBuffer::Linked& SimBuffer::Linked::operator=(SimBuffer::Linked const& other) { + /* Imp: avoid code repeat */ + slen_t len=other.getLength(); + Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len])); + n->beg=(char*)(n+1); + other.copyRange(n->beg, 0, len); + n->len=len; + n->next=0; + first=last=n; + return *this; +} + +void SimBuffer::Linked::each_sub(GenBuffer::block_sub_t block, void *data) const { + Node *n=first; + while (n!=0) { block(n->beg, n->len, data); n=n->next; } +} +void SimBuffer::Linked::first_sub(Sub &sub) const { + if (first!=0) { + sub.data=first->next; + sub.beg=first->beg; + sub.len=first->len; + } else sub.len=0; +} +void SimBuffer::Linked::next_sub(Sub &sub) const { + if (sub.data!=0) { + sub.beg=static_cast<Node*>(sub.data)->beg; + sub.len=static_cast<Node*>(sub.data)->len; + sub.data=static_cast<Node*>(sub.data)->next; + } else sub.len=0; +} +char *SimBuffer::Linked::vi_mkend(slen_t len) { + Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len])); + n->beg=(char*)(n+1); + n->len=len; + n->next=0; + if (last==0) first=last=n; + else { last->next=n; last=n; } + return n->beg; +} +char *SimBuffer::Linked::vi_mkbeg(slen_t len) { + Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len])); + n->beg=(char*)(n+1); + n->len=len; + n->next=first; + first=n; + if (last==0) last=n; + return n->beg; +} + +/* --- */ + +SimBuffer::Resizable& SimBuffer::Resizable::operator=(GenBuffer const& s2) { + vi_grow2(0, s2.getLength()-getLength(), 0, 0); + assert(getLength()==s2.getLength()); + + Sub u1, u2; + slen_t m; + first_sub(u1); + s2.first_sub(u2); + assert(!((u1.len==0) ^ (u2.len==0))); /* s1 and s2 end in the same time */ + while (u1.len!=0) { + m=(u1.len<u2.len)?u1.len:u2.len; + memcpy(const_cast<char*>(u1.beg), u2.beg, m); + if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m; + if (0==(u2.len-=m)) s2.next_sub(u2); else u2.beg+=m; + assert(!((u1.len==0) ^ (u2.len==0))); /* s1 and s2 end in the same time */ + } + return*this; +} + +//void SimBuffer::Resizable::clear() { /* Inlined. */ +// vi_grow2(0, -getLength(), 0, 0); +//} + +void SimBuffer::Resizable::keepLeft(slen_t howmuch) { + slen_t len=getLength(); + vi_grow2(0, len>howmuch?0-len+howmuch:-(slendiff_t)len, 0, 0); + /* ^^^ BUGFIX at Tue Jun 11 19:57:03 CEST 2002 */ +} +void SimBuffer::Resizable::keepRight(slen_t howmuch) { + slen_t len=getLength(); + vi_grow2(len>howmuch?0-len+howmuch:-(slendiff_t)len, 0, 0, 0); + /* ^^^ BUGFIX at Tue Jun 11 19:57:03 CEST 2002 */ +} +void SimBuffer::Resizable::keepSubstr(slen_t from_offset, slen_t slen) { + slen_t len=getLength(); + if (from_offset>=len) vi_grow2(0, -(slendiff_t)len, 0, 0); + else if (from_offset+slen>=len) vi_grow2(-(slendiff_t)from_offset, 0, 0, 0); + else vi_grow2(-(slendiff_t)from_offset, len-from_offset-slen, 0, 0); +} + +/* --- */ + +void SimBuffer::B::vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg) { + assert(alloced>=len); + char *origbeg=const_cast<char*>(beg); + if (left<0) { if (len<=(slen_t)-left) len=0; else beg-=left; left=0; } /* ! */ + if (right<0) { if (len<=(slen_t)-right)len=0; else len+=right;right=0; } + /* ^^^ BUGFIX at Tue Jun 11 16:07:56 CEST 2002 */ + assert(left>=0); + assert(right>=0); + slen_t newlen=left+right+len; + assert(newlen>=len); + char *newbeg; + assert(alloced>=sizeof(small)/1); + if (beg==small) { + assert(alloced==sizeof(small)); + if (newlen>sizeof(small)) { + assert(newlen>len); + newbeg=new char[alloced=2*newlen]; + memcpy(newbeg+left, beg, len); + beg=newbeg; + } + } else { /* beg!=small */ + // assert(len>=alloced/2); /* -- may not always be true, especially not after appending a `long' */ + if (newlen<alloced/2) { /* shrink */ + // assert(newlen<=len); /* filled-expectations are true _after_ vi_grow2, not before */ + if (newlen>sizeof(small)) { + newbeg=new char[alloced=newlen]; + memcpy(newbeg+left, beg, len); + } else { + memcpy((newbeg=small)+left, beg, len); + delete [] origbeg; + alloced=sizeof(small); + } + beg=newbeg; + } else if (newlen>alloced) { /* grow */ + assert(newlen>sizeof(small)); + assert(newlen>len); + newbeg=new char[alloced=2*newlen]; + memcpy(newbeg+left, beg, len); + delete [] origbeg; + beg=newbeg; + } else if (beg!=origbeg) { /* called with negative `left' @param */ + assert(left==0); + memmove(origbeg, beg, len); /* Slow, may move the whole buffer. */ + } + } + // fprintf(stderr, "newlen=%u\n", newlen); + len=newlen; + if (lbeg) *lbeg=const_cast<char*>(beg); + if (rbeg) *rbeg=const_cast<char*>(beg+newlen-right); + assert(alloced==sizeof(small) || (alloced>sizeof(small) && len>=alloced/2)); + assert(alloced>=len); +} + +SimBuffer::B::B(char const* cstr): alloced(sizeof(small)) { + beg=small; + slen_t len_=strlen(cstr); + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), cstr, len); +} + +SimBuffer::B::B(char const* str, slen_t len_): alloced(sizeof(small)) { + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), str, len); +} + +SimBuffer::B::B(SimBuffer::B const& other): GenBuffer(), SimBuffer::Resizable(), SimBuffer::Flat(), alloced(sizeof(small)) { + beg=small; + if (other.len>sizeof(small)) { len=0; vi_grow2(0, other.len, 0, 0); } + else len=other.len; + assert(len==other.len); + memcpy(const_cast<char*>(beg), other.beg, len); +} + +SimBuffer::B::B(SimBuffer::Flat const& other): alloced(sizeof(small)) { + beg=small; + if (other.len>sizeof(small)) { len=0; vi_grow2(0, other.len, 0, 0); } + else len=other.len; + assert(len==other.len); + memcpy(const_cast<char*>(beg), other.beg, len); +} + +SimBuffer::B::B(SimBuffer::Flat const& other,int): alloced(sizeof(small)) { + beg=small; + if (other.len>=sizeof(small)) { len=0; vi_grow2(0, other.len+1, 0, 0); len--; } + else len=other.len; + assert(len==other.len); + memcpy(const_cast<char*>(beg), other.beg, len); + const_cast<char*>(beg)[len]='\0'; +} + +SimBuffer::B::B(SimBuffer::Flat const& other, slen_t from_offset, slen_t len_): alloced(sizeof(small)) { + /* substr */ + beg=small; + if (from_offset<other.len) { + if (from_offset+len_>other.len) len_=other.len-from_offset; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), other.beg+from_offset, len); + } else len=0; +} + +SimBuffer::B::B(GenBuffer const& other): alloced(sizeof(small)) { + slen_t len_=other.getLength(); + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + other.copyRange(const_cast<char*>(beg), 0, len_); +} + +/** Constructor: copy (consume) data from a readable stream. */ +SimBuffer::B::B(GenBuffer::Readable &other): alloced(sizeof(small)) { + beg=small; + len=0; +#if 000 + operator <<(other); +#else + B_append(other); +#endif +} + +SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl): alloced(sizeof(small)) { + slen_t len_=al+bl; + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), as, al); + memcpy(const_cast<char*>(beg)+al, bs, bl); +} + +SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl,int): alloced(sizeof(small)) { + slen_t len_=al+bl; + beg=small; + if (len_>=sizeof(small)) { len=0; vi_grow2(0, len_+1, 0, 0); len--; } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), as, al); + memcpy(const_cast<char*>(beg)+al, bs, bl); + const_cast<char*>(beg)[al+bl]='\0'; +} + +SimBuffer::B::B(GenBuffer const& a, GenBuffer const& b): alloced(sizeof(small)) { + slen_t al=a.getLength(); + slen_t bl=b.getLength(); + slen_t len_=al+bl; + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + a.copyRange(const_cast<char*>(beg), 0, al); + b.copyRange(const_cast<char*>(beg)+al, 0, bl); +} + +SimBuffer::B::B(GenBuffer const& a, GenBuffer const& b, GenBuffer const& c): alloced(sizeof(small)) { + slen_t al=a.getLength(); + slen_t bl=b.getLength(); + slen_t cl=c.getLength(); + slen_t len_=al+bl; + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + a.copyRange(const_cast<char*>(beg), 0, al); + b.copyRange(const_cast<char*>(beg)+al, 0, bl); + c.copyRange(const_cast<char*>(beg)+al+bl, 0, cl); +} + +SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl, char const* cs,slen_t cl): alloced(sizeof(small)) { + slen_t len_=al+bl+cl; + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), as, al); + memcpy(const_cast<char*>(beg)+al, bs, bl); + memcpy(const_cast<char*>(beg)+al+bl, cs, cl); +} + +SimBuffer::B::B(Flat const&b, char const*cs): alloced(sizeof(small)) { + slen_t cl=strlen(cs); + slen_t len_=b.len+cl; + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), b.beg, b.len); + memcpy(const_cast<char*>(beg)+b.len, cs, cl); +} + +SimBuffer::B::B(char const*as, Flat const&b, char const*cs): alloced(sizeof(small)) { + slen_t al=strlen(as); + slen_t cl=strlen(cs); + slen_t len_=al+b.len+cl; + beg=small; + if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); } + else len=len_; + assert(len==len_); + memcpy(const_cast<char*>(beg), as, al); + memcpy(const_cast<char*>(beg)+al, b.beg, b.len); + memcpy(const_cast<char*>(beg)+al+b.len, cs, cl); +} + +/* SimBuffer::B& operator<<(SimBuffer::B& self, GenBuffer::Readable &stream); */ +SimBuffer::B& SimBuffer::B::B_append(GenBuffer::Readable &stream) { + assert(alloced>=len); + slen_t oldlen, ask; + ask=stream.vi_availh(); + if (ask>0) { oldlen=len; vi_grow2(0, ask+1, 0, 0); len=oldlen; } + if (alloced!=len) len+=stream.readFill(const_cast<char*>(beg+len), alloced-len); + while (alloced==len) { /* more data to be read */ + oldlen=len; vi_grow2(0, alloced, 0, 0); len=oldlen; + stream.readFill(const_cast<char*>(beg+len), alloced-len); + } + return *this; +} + +SimBuffer::B& SimBuffer::B::term0() { + if (len==alloced) { vi_grow2(0,1,0,0); len--; } + const_cast<char*>(beg)[len]='\0'; + return *this; +} + +void SimBuffer::B::grow_set0_by(slendiff_t lendiff) { + char *rbeg; + vi_grow2(0, lendiff, 0, &rbeg); + if (lendiff>0) memset(rbeg, '\0', lendiff); +} + +char SimBuffer::B::getAt(slen_t idx) { + if (idx<len) return beg[idx]; + /* grow_set0_by(idx+1-len); */ + char *rbeg; + vi_grow2(0, idx-len+1, 0, &rbeg); + memset(rbeg, '\0', idx-len+1); + return '\0'; +} + +SimBuffer::B& SimBuffer::B::operator=(SimBuffer::Flat const& other) { + if (&other!=this) { + len=0; + vi_grow2(0, other.len, 0, 0); + memcpy(const_cast<char*>(beg), other.beg, len); + } + return*this; +} + +SimBuffer::B& SimBuffer::B::operator=(SimBuffer::B const& other) { + if (&other!=this) { + len=0; + vi_grow2(0, other.len, 0, 0); + memcpy(const_cast<char*>(beg), other.beg, len); + } + return*this; +} + +SimBuffer::B& SimBuffer::B::operator=(char const* cstr) { + slen_t slen=strlen(cstr); + len=0; + vi_grow2(0, slen, 0, 0); + memcpy(const_cast<char*>(beg), cstr, slen); + return*this; +} + +SimBuffer::B SimBuffer::B::substr(slen_t first, slen_t howmuch) const { + return SimBuffer::B(*this, first, howmuch); +} +SimBuffer::B SimBuffer::B::substr(slen_t first) const { + /* Actually, this will probably be shorter than end-begin */ + return SimBuffer::B(*this, first, len); +} +SimBuffer::B SimBuffer::B::right(slen_t howmuch) const { + return SimBuffer::B(*this, len<=howmuch?0:len-howmuch, howmuch); +} +SimBuffer::B SimBuffer::B::left(slen_t howmuch) const { + return SimBuffer::B(*this, 0, howmuch); +} + +#if 0 +void SimBuffer::B::append(char const*s, const slen_t len_) { + char *rbeg; + vi_grow2(0, len_, 0, &rbeg); + memcpy(rbeg, s, len_); +} +#endif + +SimBuffer::B operator+(const SimBuffer::Flat& s1, const SimBuffer::Flat& s2) { + return SimBuffer::B(s1.beg, s1.len, s2.beg, s2.len); +} +SimBuffer::B operator+(const char *s1, const SimBuffer::Flat& s2) { + return SimBuffer::B(s1, strlen(s1), s2.beg, s2.len); +} +SimBuffer::B operator+(const SimBuffer::Flat& s1, const char *s2) { + return SimBuffer::B(s1.beg, s1.len, s2, strlen(s2)); +} + +SimBuffer::B& SimBuffer::B::operator<<(SimBuffer::Flat const& other) { + char *d; + vi_grow2(0, other.len, 0, &d); + memcpy(d,other.beg,other.len); + return*this; +} + +SimBuffer::B& SimBuffer::B::operator<<(char c) { + if (len==alloced) { vi_grow2(0, 1, 0, 0); const_cast<char*>(beg)[len-1]=c; } + else const_cast<char*>(beg)[len++]=c; + return*this; +} +SimBuffer::B& SimBuffer::B::operator<<(char const *s) { + char *d; + slen_t slen=strlen(s); + vi_grow2(0, slen, 0, &d); + memcpy(d,s,slen); + return*this; +} +void SimBuffer::B::vi_write(char const*str, slen_t slen) { + if (slen>0) { + char *p; vi_grow2(0, slen, 0, &p); + memcpy(p, str, slen); + } +} + +#define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b)) +static inline bool is_path(char const c) { + return c=='-' || c=='.' || c=='_' || c=='/' + || USGE('z'-'a',c-'a') + || USGE('Z'-'A',c-'A') + || USGE('9'-'0',c-'0'); +} +static inline bool is_safe_c(char const c) { + return c!='\\' && c!='\'' && c!='\"' && USGE('~'-' ',c-' '); +} +static inline bool is_safe_ps(char const c) { + return c!='\\' && c!='(' && c!=')' && USGE('~'-' ',c-' '); +} + +SimBuffer::B& SimBuffer::B::appendDump(const char c, bool dq) { + char t[7]; register char *p=t; + if (dq) *p++='\''; + if (is_path(c)) { + *p++=c; + } else { + *p++='\\'; + *p++=('0'+((c>>6)&3)); + *p++=('0'+((c>>3)&7)); + *p++=('0'+(c&7)); + } + if (dq) *p++='\''; + vi_write(t, p-t); + return*this; +} + + +SimBuffer::B& SimBuffer::B::appendDump(const SimBuffer::Flat &other, bool dq) { + slen_t rlen=dq?2:0; + register char c; register char const*p; + char const *pend; char *dst; + for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_path(*p)?1:4; + vi_grow2(0, rlen, 0, &dst); + if (dq) *dst++='"'; + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if (is_path(c=*p)) { + *dst++=c; + } else { + *dst++='\\'; + *dst++=('0'+((c>>6)&3)); + *dst++=('0'+((c>>3)&7)); + *dst++=('0'+(c&7)); + } + } + if (dq) *dst++='"'; + assert(dst==end_()); + return*this; +} + +SimBuffer::B& SimBuffer::B::appendNpmq(const SimBuffer::Flat &other, bool dq) { + slen_t rlen=dq?2:0; + register char c; register char const*p; + char const *pend; char *dst; + for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_path(*p)?1:2; + vi_grow2(0, rlen, 0, &dst); + if (dq) *dst++='"'; + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if (is_path(c=*p)) { + *dst++=c; + } else { + *dst++='\\'; + *dst++=c; + } + } + if (dq) *dst++='"'; + assert(dst==end_()); + return*this; +} + +SimBuffer::B& SimBuffer::B::appendDumpC (const SimBuffer::Flat &other, bool dq) { + slen_t rlen=dq?2:0; + register char c; register char const*p; + char const *pend; char *dst; + for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_safe_c(*p)?1:4; + vi_grow2(0, rlen, 0, &dst); + if (dq) *dst++='"'; + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if (is_safe_c(c=*p)) { + *dst++=c; + } else { + *dst++='\\'; + *dst++=('0'+((c>>6)&3)); + *dst++=('0'+((c>>3)&7)); + *dst++=('0'+(c&7)); + } + } + if (dq) *dst++='"'; + assert(dst==end_()); + return*this; +} + +SimBuffer::B& SimBuffer::B::appendFnq(const SimBuffer::Flat &other, bool preminus) { + slen_t rlen=0; + register char c; register char const*p; + char const *pend; char *dst; + if (OS_COTY==COTY_WINNT || OS_COTY==COTY_WIN9X) { + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if ('\0'==(c=*p) || c=='"') break; + rlen++; + } + if (preminus && rlen!=0 && other.beg[0]=='-') rlen+=2; /* .\ */ + vi_grow2(0, rlen+2, 0, &dst); + *dst++='"'; /* Dat: "ab"c" ""def" is perfectly legal and parses to: `abc def' */ + p=other.beg; + if (preminus && other.beg[0]=='-') { *dst++='.'; *dst++='\\'; } + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if ('\0'==(c=*p) || c=='"') break; + *dst++=c; + } + *dst++='"'; + } else { /* Everything else is treated as UNIX */ + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if ('\0'==(c=*p)) break; + rlen+=is_path(c)?1: c=='\n'?3:2; + } + if (preminus && rlen!=0 && other.beg[0]=='-') rlen+=2; /* ./ */ + vi_grow2(0, rlen, 0, &dst); + if (preminus && other.beg[0]=='-') { *dst++='.'; *dst++='/'; } + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if ('\0'==(c=*p)) break; + if (is_path(c)) *dst++=c; + else if (c=='\n') { *dst++='"'; *dst++='\n'; *dst++='"'; } + else { *dst++='\\'; *dst++=c; } + } + } /* IF OS_COTY... */ + assert(dst==end_()); + return*this; +} + +SimBuffer::B& SimBuffer::B::appendDumpPS (const SimBuffer::Flat &other, bool dq) { + slen_t rlen=dq?2:0; + register char c; register char const*p; + char const *pend; + for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_safe_ps(*p)?1:4; + char *dst; vi_grow2(0, rlen, 0, &dst); + if (dq) *dst++='('; + for (p=other.beg,pend=p+other.len; p!=pend; p++) { + if (is_safe_ps(c=*p)) { + *dst++=c; + } else { + *dst++='\\'; + *dst++=('0'+((c>>6)&3)); + *dst++=('0'+((c>>3)&7)); + *dst++=('0'+(c&7)); + } + } + if (dq) *dst++=')'; + assert(dst==end_()); + return*this; +} + +SimBuffer::B& SimBuffer::B::appendHppq(const SimBuffer::Flat &other) { + vi_grow2(0, other.len, 0, 0); + char *pend=const_cast<char*>(beg)+len; + register char c, *p=pend-other.len; + memcpy(p, other.beg, other.len); + for (;p!=pend;pend++) { + c=*p; + *p++=( + (c>='a' && c<='z') ? (char)(c-'a'+'A') : + (c>='A' && c<='Z') ? c : + '_' + ); + } + return *this; +} + +SimBuffer::B& SimBuffer::B::appendUnslash(const SimBuffer::Flat &other, int iniq) { + slen_t rlen=0; + slen_t left=other.len; + register char c; register char const*p=other.beg; + if (iniq<=256) { + if (left<2 || *p!=iniq || p[left-1]!=iniq) return*this; + /* ^^^ return empty string */ + p++; left-=2; + } + while (0!=left) { /* Calculate lengths */ + c=*p++; + if (c!='\\' || left==1) { rlen++; left--; continue; } + c=*p++; + if (c>='0' && c<='7') { + rlen++; + if (left>=3 && p[0]>='0' && p[0]<='7') { + if (left>=4 && p[1]>='0' && p[1]<='7') { p+=2; left-=4; } + else { p+=1; left-=3; } + } else left-=2; + } else if ((c=='x' || c=='X') && left>=3 && 16!=(hexc2n(p[0]))) { + rlen++; + if (left>=4 && 16!=(hexc2n(p[1]))) { p+=2; left-=4; } + else { p+=1; left-=2; } + } else if ((c=='c' || c=='C') && left>=4 && (p[0]=='-' || p[0]=='[')) { + rlen++; left-=4; p+=2; + } else if (c=='l' && left>=3) { + rlen++; left-=3; p++; + } else if (c=='u' && left>=3) { + rlen++; left-=3; p++; + } else if (c=='\n') { + left-=2; + } else { /* backslash is used for escaping a single char */ + rlen++; left-=2; + } + } + + char *dst; vi_grow2(0, rlen, 0, &dst); + unsigned tmp1, tmp2; + left=other.len; p=other.beg; + if (iniq<=256) { + assert(!(left<2 || *p!=iniq || p[left-1]!=iniq)); + p++; left-=2; + } + while (0!=left) { + c=*p++; + if (c!='\\' || left==1) { *dst++=(c); left--; continue; } + c=*p++; + if (c>='0' && c<='7') { + if (left>=3 && p[0]>='0' && p[0]<='7') { + if (left>=4 && p[1]>='0' && p[1]<='7') { + *dst++=((char)((c<<6)+(p[0]<<3)+p[1]-'0'*73)); + p+=2; left-=4; + } else { + *dst++=((char)((c<<3)+p[0]-'0'*9)); + p+=1; left-=3; + } + } else { + *dst++=((char)(c-'0')); + left-=2; + } + } else if ((c=='x' || c=='X') && left>=3 && 16!=(tmp1=hexc2n(p[0]))) { + if (left>=4 && 16!=(tmp2=hexc2n(p[1]))) { + *dst++=((char)((tmp1<<4)+tmp2)); + p+=2; left-=4; + } else { + *dst++=((char)tmp1); + p+=1; left-=2; + } + } else if ((c=='c' || c=='C') && left>=4 && (p[0]=='-' || p[0]=='[')) { + *dst++=((char)(p[1]>='a' && p[1]<='z' ? (p[1]+'A'-'a')^64 : p[1]^64)); + left-=4; p+=2; + } else if (c=='l' && left>=3) { + *dst++=((char)(p[0]>='A' && p[0]<='Z' ? p[0]+'a'-'A' : p[0])); + left-=3; p++; + } else if (c=='u' && left>=3) { + *dst++=((char)(p[0]>='a' && p[0]<='z' ? p[0]+'A'-'a' : p[0])); + left-=3; p++; + } else if (c=='\n') { + left-=2; + } else { /* backslash is used for escaping a single char */ + if (c=='a') c=007; // \x07 (alarm bell) + else if (c=='b') c=010; // \x08 (backspace) (_not_ alarm bell) + else if (c=='e') c=033; // \x1B (escape) + else if (c=='f') c=014; // \x0C (form feed) + else if (c=='n') c=012; // \x0A (newline, line feed) + else if (c=='r') c=015; // \x0D (carriage return) + else if (c=='t') c=011; // \x09 (horizontal tab) + else if (c=='v') c=013; // \x0B (vertical tab) + *dst++=(c); left-=2; + // if (0!=left--) { *dst++=(*p++); left--; } /* already escaped 1 */ + } + } + return*this; +} + +void SimBuffer::B::space_pad_cpy(char *dst, char const*src, slen_t pad) { + while (pad!=0 && src[0]!='\0') { *dst++=*src++; pad--; } + while (pad--!=0) *dst++=' '; +} + +// #include <stdio.h> + +char *SimBuffer::B::substr_grow(slen_t first, slen_t oldmuch, slen_t newmuch) { + slen_t idx=first; + if (first<len) { + if (first+oldmuch>len) oldmuch=len-first; + if (newmuch<oldmuch) { first+=newmuch; oldmuch-=newmuch; newmuch=0; } + else if (newmuch>oldmuch) { first+=oldmuch; newmuch-=oldmuch; oldmuch=0; } + else return const_cast<char*>(beg)+first; + } else { + len=first=idx=oldmuch=0; + if (newmuch==0) { vi_grow2(0,0,0,0); return const_cast<char*>(beg); } + } + // fprintf(stderr, "newmuch=%u oldmuch=%u len=%u\n", newmuch, oldmuch, len); + if (newmuch>0) { + vi_grow2(0,newmuch,0,0); + char *p=const_cast<char*>(beg)+first; /* after vi_grow2() */ + memmove(p+newmuch, p, len-first-newmuch); + } else if (oldmuch>0) { + char *p=const_cast<char*>(beg)+first; /* before vi_grow2() */ + memmove(p, p+oldmuch, len-first-oldmuch); + vi_grow2(0,-(slendiff_t)oldmuch,0,0); + } else assert(0); + // fprintf(stderr, "len=%u oldmuch=%u\n", len, oldmuch); + return const_cast<char*>(beg)+idx; +} + +/* --- Tue Jul 2 10:47:14 CEST 2002 */ + +void GenBuffer::tolower_memcpy(char *dst, char const*s, slen_t slen) { + while (slen--!=0) *dst++=USGE('Z'-'A',*s-'A') ? *s+++'a'-'A' : *s++; +} +void GenBuffer::toupper_memcpy(char *dst, char const*s, slen_t slen) { + while (slen--!=0) *dst++=USGE('z'-'a',*s-'a') ? *s+++'A'-'a' : *s++; +} + +int GenBuffer::nocase_memcmp(char const*a, char const *s, slen_t slen) { + int i; + while (slen--!=0) { + i=(USGE('Z'-'A',*a-'A') ? *a+++'a'-'A' : *a++) + -(USGE('Z'-'A',*s-'A') ? *s+++'a'-'A' : *s++); + if (i>0) return 1; + if (i<0) return -1; + } + return 0; +} +int GenBuffer::nocase_strcmp(char const*a, char const*b) { + slen_t alen=strlen(a), blen=strlen(b), min=alen<blen?alen:blen; + int ret=nocase_memcmp(a, b, min); + return ret!=0 || alen==blen ? ret : alen<blen ? -1 : 1; +} + +bool GenBuffer::parseBool(char const *s, slen_t slen) { + if (slen==0) return true; + char c=s[0]; + if (slen==2 && (c=='o' || c=='O') && (s[1]=='n' || s[1]=='N') + || slen==3 && (c=='o' || c=='O') && (s[1]=='u' || s[1]=='U') + ) return true; + /* on true yes ja igen oui enable 1 true vrai? right sure allowed + * off false no nein nem non disable 0 false faux? wrong nope disallowed + */ + return c!='f' && c!='n' && c!='d' && c!='w' && c!='0' + && c!='F' && c!='N' && c!='D' && c!='W'; +} + +bool GenBuffer::strbegins(char const*a, char const *with) { + while (*with!='\0') if (*a++!=*with++) return false; + return true; +} + +bool GenBuffer::nocase_strbegins(char const*a, char const *with) { + while (*with!='\0') + if ((USGE('Z'-'A',*a-'A') ? *a+++'a'-'A' : *a++) + !=(USGE('Z'-'A',*with-'A') ? *with+++'a'-'A' : *with++) + ) return false; + return true; +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/gensi.hpp b/Build/source/utils/sam2p/gensi.hpp new file mode 100644 index 00000000000..b87d0a46ccc --- /dev/null +++ b/Build/source/utils/sam2p/gensi.hpp @@ -0,0 +1,720 @@ +/* gensi.hpp -- generic char buffer and I/O facilities + * by pts@fazekas.hu at Sun Feb 24 15:56:02 CET 2002 + */ +/* Imp: get rid of gensio.o (Buffer::Writable::printf requires B...) */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef GENSI_HPP +#define GENSI_HPP 1 + +#include "config2.h" +#include <stdarg.h> /* va_list */ + +#if 'a'!=97 || '!'!=33 +#error You need an ASCII system to compile this. +#endif + +/** A very generic, abstract char (pure 8-bit octet) buffer class. This class + * doesn't have any attributes. + */ +class GenBuffer { + public: + static inline unsigned hexc2n(char c) { + return ((unsigned char)(c-'0')<=(unsigned char)('9'-'0')) ? c-'0' + : ((unsigned char)(c-'A')<=(unsigned char)('F'-'A')) ? c-'A'+10 + : ((unsigned char)(c-'a')<=(unsigned char)('f'-'a')) ? c-'a'+10 + : 16; + } + /** English ASCII letters [a-zA-Z] */ + static void tolower_memcpy(char *dst, char const*s, slen_t slen); + /** English ASCII letters [a-zA-Z] */ + static void toupper_memcpy(char *dst, char const*s, slen_t slen); + /** All letters treated as lower case. @return -1, 0 or 1 */ + static int nocase_memcmp(char const*a, char const *s, slen_t slen); + static int nocase_strcmp(char const*a, char const *b); + /** All letters treated as lower case. @return -1, 0 or 1 */ + static bool nocase_strbegins(char const*a, char const *with); + static bool strbegins(char const*a, char const *with); + static bool parseBool(char const *s, slen_t slen); + + /* Imp: convert usage of each_sub to first_sub+next_sub */ + typedef void (*block_sub_t)(char const*beg, slen_t len, void *data); + typedef void (*block_char_t)(char c, void *data); + struct Sub { + char const*beg; + slen_t len; + void *data, *data2; + }; + /** Writable. */ + struct SubW { + char *beg; + slen_t len; + void *data, *data2; + }; + virtual slen_t getLength() const =0; + /** Iterates through each subrange of (this), and calls param `block' + * for each range. Must call block with positive `len's, and -- as a final + * call -- with len==0. + * @param data arbitrary data, to be passed to param `block' + */ + virtual void each_sub(block_sub_t block, void *data) const =0; + /** Iterates through each character of (this), and calls param `block' + * for each char. Implemented by calling (this).each_sub + */ + /** Produces sub.len==0 if empty. */ + virtual void first_sub(Sub &sub) const =0; + /** Produces sub.len==0 if no more subs. + * @param sub fields `beg' and `len' are assumed to contain garbage (!) + * before invocation. Only `data' and `data2' can be relied upon. + */ + virtual void next_sub(Sub &sub) const =0; + inline void each_char(block_char_t block, void *data) const { + void *t[2]= { (void*)data, (void*)block }; + each_sub(iter_char_sub, (void*)t); + } + inline bool isEmpty() const { return getLength()==0; } + /** @return true iff not empty */ + inline virtual operator void*() const { return (void*)(getLength()!=0); } + /** @return true iff not empty; pacify VC6.0 */ + // inline virtual operator bool() const { return (void*)(getLength()!=0); } + // inline virtual operator bool() const { return getLength()!=0; } + /** @return true iff empty */ + inline virtual bool operator!() const { return getLength()==0; } + /** @return getLength() */ + virtual slen_t copyRange(char *to, slen_t cfrom, slen_t clen) const; + /** @return true on conversion error */ + bool toBool(bool &dst); + /** @return true on conversion error (overflow etc.) */ + bool toInteger(unsigned long &dst); + /** @return true on conversion error (overflow etc.) */ + bool toInteger(signed long &dst); + #if HAVE_LONG_LONG && NEED_LONG_LONG + /** @return true on conversion error (overflow etc.) */ + bool toInteger(unsigned PTS_CFG_LONGEST &dst); + /** @return true on conversion error (overflow etc.) */ + bool toInteger(signed PTS_CFG_LONGEST &dst); + #endif + inline bool toInteger(unsigned short &i) { unsigned long l; bool b=toInteger(l); i=l; return b; } + inline bool toInteger( signed short &i) { signed long l; bool b=toInteger(l); i=l; return b; } + inline bool toInteger(unsigned int &i) { unsigned long l; bool b=toInteger(l); i=l; return b; } + inline bool toInteger( signed int &i) { signed long l; bool b=toInteger(l); i=l; return b; } + /** Allocates a fresh new, null-terminated string. @return true */ + bool toCString(char *&dst); + /** @return negative iff (this)<s2, positive iff (this)>s2 */ + virtual int cmp(GenBuffer const& s2) const; + /** @return negative iff (this)<s2, positive iff (this)>s2 */ + virtual int cmp(char const* s2, slen_t len) const; + /** Null-terminated, calls cmp(char const* s2, slen_t len). */ + int cmp(char const* s2) const; + friend bool operator==(const GenBuffer& s1, const GenBuffer& s2); + friend bool operator==(const char *s1, const GenBuffer& s2); + friend bool operator==(const GenBuffer& s1, const char *s2); + /* vvv G++ 2.91 doesn't autodetect these 15 operators :-( */ + friend bool operator!=(const GenBuffer& s1, const GenBuffer& s2); + friend bool operator!=(const char *s1, const GenBuffer& s2); + friend bool operator!=(const GenBuffer& s1, const char *s2); + friend bool operator<=(const GenBuffer& s1, const GenBuffer& s2); + friend bool operator<=(const char *s1, const GenBuffer& s2); + friend bool operator<=(const GenBuffer& s1, const char *s2); + friend bool operator<(const GenBuffer& s1, const GenBuffer& s2); + friend bool operator<(const char *s1, const GenBuffer& s2); + friend bool operator<(const GenBuffer& s1, const char *s2); + friend bool operator>=(const GenBuffer& s1, const GenBuffer& s2); + friend bool operator>=(const char *s1, const GenBuffer& s2); + friend bool operator>=(const GenBuffer& s1, const char *s2); + friend bool operator>(const GenBuffer& s1, const GenBuffer& s2); + friend bool operator>(const char *s1, const GenBuffer& s2); + friend bool operator>(const GenBuffer& s1, const char *s2); + + /** A very generic, abstract char (pure 8-bit octet) output (encoding + * stream, filter) class. Writing always succeeds, all data gets written. + * No attributes. + */ + class Writable { + public: + virtual void vi_write(char const*, slen_t) =0; + virtual void vi_putcc(char) =0; + inline Writable &operator <<(GenBuffer const& b) { + b.each_sub(iter_write_sub, this); + return*this; + } + inline Writable &operator <<(char c) { vi_putcc(c); return*this; } + /** Outputs a null-terminated, C string. Not `inline' because the use + * of strlen(). + */ + Writable& operator <<(char const*); + Writable& operator <<(void const*); + inline Writable& operator <<( signed short n) { write_num((signed long)n); return*this; } + inline Writable& operator <<( signed int n) { write_num((signed long)n); return*this; } + inline Writable& operator <<( signed long n) { write_num(n); return*this; } + inline Writable& operator <<(unsigned short n) { write_num((unsigned long)n); return*this; } + inline Writable& operator <<(unsigned int n) { write_num((unsigned long)n); return*this; } + inline Writable& operator <<(unsigned long n) { write_num(n); return*this; } + #if HAVE_LONG_LONG && NEED_LONG_LONG + inline Writable &operator <<(signed long long n) { write_num(n); return*this; } + inline Writable &operator <<(unsigned long long n) { write_num(n); return*this; } + #endif + inline Writable& operator <<(bool b) { + if (b) vi_write("true", 4); + else vi_write("false", 5); + return*this; + } + + /** appends at most `n' chars; uses SimBuffer::B::vformat as temp */ + virtual Writable& vformat(slen_t n, char const *fmt, va_list ap); + /** appends; uses SimBuffer::B::vformat as temp */ + virtual Writable& vformat(char const *fmt, va_list ap); + /** appends; calls vformat */ + Writable& format(slen_t n, char const *fmt, ...); + /** appends; calls vformat */ + Writable& format(char const *fmt, ...); + + void write_num(signed long n); + void write_num(unsigned long n); + #if HAVE_LONG_LONG && NEED_LONG_LONG + void write_num(signed PTS_CFG_LONGEST n); + void write_num(unsigned PTS_CFG_LONGEST n); + #endif + /** @param zdigits specifies the exact number of digits to be appended. + * Zeroes are prepended if necessary. + */ + void write_num(unsigned long n, unsigned zdigits); + #if HAVE_LONG_LONG && NEED_LONG_LONG + void write_num(unsigned PTS_CFG_LONGEST n, unsigned zdigits); + #endif + protected: + static void iter_write_sub(char const*beg, slen_t len, void *data); + }; + + /** Interface for a stream of characters. Similar to ISimplyiChar in + * CHsplit. No attributes. + */ + class Readable { + public: + /** @return -1 on EOF/error, a char (0..255) otherwise. + */ + virtual int vi_getcc() =0; + /** Does a single blocking read. Default functionality: calls vi_getcc() + * repeatedly. + * @return 0 on EOF/error, positive otherwise: number of characters + * successfully read. + */ + virtual slen_t vi_read(char *to_buf, slen_t max); + /** Does multiple blocking reads, tries to fill `to_buf'. Calls vi_read() + * repeatedly. + */ + int readFill(char *to_buf, slen_t max); + /** Returns a number not larger than the bytes available _altogether_ + * from this stream. The default implementation returns 0, which is + * always safe. For regular files, the method should return the size + * of the file (unless the size is too large to be represented as an + * slen_t), for pipes and sockets, the method should return 0. + */ + inline virtual slen_t vi_availh() { return 0; } + inline bool equal_content(Readable &other); + /** Does nothing or rewinds the stream to the beginning, so it can be + * read again. The default implementation does nothing. + */ + inline virtual void vi_rewind() {} + }; + + protected: + static void iter_char_sub(char const*beg, slen_t len, void *data); +}; + +// vvv Doesn't work in gcc 2.95 since we have abstract methods :-(. Must be +// declared inside class { ... }; +///GenBuffer::Writable &operator <<(GenBuffer::Writable a, GenBuffer b); + +/** Collection of some simplistic GenBuffer implementations. */ +class SimBuffer { + public: + class B; + /** A flat buffer, i.e occupying consecutive bytes in memory. This class is + * useless by itself since memory management (allocation and deletion of the + * memory area) isn't implemented. Example of virtual inheritance: needed + * because of SimBuffer::B. + */ + class Flat: virtual public GenBuffer { + protected: + friend class /*SimBuffer::*/B; /* can read `beg' and `len' */ + const char *beg; + slen_t len; + public: + inline virtual slen_t getLength() const { return len; } + virtual void each_sub(block_sub_t block, void *data) const { + if (len!=0) block(beg,len,data); + block(0,0,data); + } + inline virtual void first_sub(Sub &sub) const { sub.beg=beg; sub.len=len; }; + inline virtual void next_sub(Sub &sub) const { sub.len=0; } + inline char const*getCString() const { return beg; } + inline char const*operator()() const { return beg; } + inline char const*begin_() const { return beg; } + inline char const*end_() const { return beg+len; } + // inline operator char const*() const { return beg; } /* would kill void* */ + /** @param idx would cause overload conflict if declared len_t. No range check */ + inline char const&operator[](slendiff_t idx) const { return beg[idx]; } + /** @return true iff not empty */ + inline virtual operator void*() const { return (void*)(len!=0); } + // inline operator bool() const { return len!=0; } + /** @return true iff empty */ + inline virtual bool operator!() const { return len==0; } + /** + * This is deliberatly not an `operator char' + * to avoid the ambiguity of implicit auto-conversion. + * @return 1st char or 0. + */ + inline void toChar(char &ret) const { + ret= len==0 ? 0 : *beg; + } + /** Overridden. */ + virtual slen_t copyRange(char *to, slen_t cfrom, slen_t clen) const; + /** @return getLength() if not found, offset otherwise */ + slen_t findLast(char const c) const; + /** @return getLength() if not found, offset otherwise */ + slen_t findFirst(char const c) const; + /** @return getLength() if not found, offset otherwise */ + slen_t findFirst(char const* s, slen_t slen) const; + virtual int cmp(Flat const& s2) const; + virtual int cmp(char const* s2, slen_t len) const; + /** @param fallback default: '\0' + * @return if idx is too large: `fallback', otherwise: the asked char + */ + virtual inline char getAt0(slen_t idx, char fallback='\0') { + return idx>=len ? fallback : beg[idx]; + } + /* Dat: pacify VC6.0: use of undefined type 'SimBuffer' */ + friend /*SimBuffer::*/B operator+(const /*SimBuffer::*/Flat& s1, const /*SimBuffer::*/Flat& s2); + friend /*SimBuffer::*/B operator+(const char *s1, const /*SimBuffer::*/Flat& s2); + friend /*SimBuffer::*/B operator+(const /*SimBuffer::*/Flat& s1, const char *s2); + }; + + /** A statically allocated, read-only char buffer, probably inside the TEXT + * section (program code). Needs no delete()ing. `Does' memory management by + * not doing anything: statically allocated memory belongs to whole lifetime + * of the process, so it doesn't have to be freed. + */ + class Static: public Flat { + public: + Static(char const*); + Static(char const*beg_,slen_t len_) { beg=beg_; len=len_; } + }; + + /** A flat buffer of fixed length. Not particularly useful, try + * SimBuffer::B instead. + */ + class Fixed: public Flat { + public: + inline Fixed(slen_t len_) { beg=new char[len_]; len=len_; } + virtual inline ~Fixed() { + delete [] const_cast<char*>(beg); /* Dat: const_cast: pacify VC6.0 */ + } + private: + /** Disable this. */ + inline Fixed& operator=(Fixed const&) {return*this;} + }; + +#if 0 + /** Fixed-length, writable */ + class FixWrite: public GenBuffer { + public: + }; +#endif + + /** Abstract class. Example of virtual inheritance, needed because of + * SimBuffer::B. + */ + class Appendable: virtual public GenBuffer, public GenBuffer::Writable { + public: + /** Makes room for `len' more chars at the end of the string, and returns + * a pointer to the beginning of that location. Should be efficient. + */ + virtual char *vi_mkend(slen_t) =0; + /** Makes room for `len' more chars at the end of the string, and returns + * a pointer to the beginning of that location. May be inefficient. + */ + virtual char *vi_mkbeg(slen_t) =0; + /** Use this instead of append(...). */ + virtual void vi_write(char const*, slen_t); + inline virtual void vi_putcc(char c) { vi_mkend(1)[0]=c; } + /** There is no append(...) method. Use vi_write() instead. */ + void prepend(char const*, slen_t); + }; + + /** A one-way linked list of flat strings. Quickest for long memory appends. + * Does memory management. + */ + class Linked: public Appendable { + public: + struct Node { + char *beg; + slen_t len; + /** May be NULL. */ + Node *next; + }; + Node *first, *last; + inline Linked(): first(0), last(0) {} + virtual ~Linked(); + Linked(GenBuffer const& other); + Linked(char const*); + Linked& operator=(GenBuffer const& other); + Linked& operator=(Linked const& other); + virtual slen_t getLength() const; + virtual void each_sub(block_sub_t block, void *data) const; + virtual void first_sub(Sub &sub) const; + virtual void next_sub(Sub &sub) const; + virtual char *vi_mkend(slen_t len); + virtual char *vi_mkbeg(slen_t len); + }; + + /* Abstract class. */ + class Resizable: public Appendable { public: + /** Grows the string by the specified `left' and `right' amount on the + * sides. The amounts may be positive, zero or negative. For a negative + * amount, the `?beg' will be rendered invalid. For a nonnegative amount, + * `?beg' will point to the beginning of the new, uninitialized part of the + * buffer. + */ + virtual void vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg) =0; + Resizable& operator=(GenBuffer const& other); + inline void clearFree() { vi_grow2(0, -(slendiff_t)getLength(), 0, 0); } + inline void forgetAll() { vi_grow2(0, -(slendiff_t)getLength(), 0, 0); } + /** If howmuch>getLength(), then clears the string. */ + inline void forgetLast(slen_t howmuch) { vi_grow2(0, -(slendiff_t)howmuch, 0, 0); } + inline void forgetFirst(slen_t howmuch) { vi_grow2(-(slendiff_t)howmuch, 0, 0, 0); } + void keepLeft(slen_t howmuch); + void keepRight(slen_t howmuch); + void keepSubstr(slen_t from_offset, slen_t slen); + inline virtual char *vi_mkend(slen_t howmuch) { char *s; vi_grow2(0, howmuch, 0, &s); return s; } + inline virtual char *vi_mkbeg(slen_t howmuch) { char *s; vi_grow2(howmuch, 0, &s, 0); return s; } + }; + + /** A simple, non-shared, writable, flat memory buffer of bytes. Supports + * fast appends (with rare memory-rallocations) by pre-allocating at most + * twice as much memory. Prepends are + * slow, because they always include memory allocation and copying. + * Does memory management. + * Imp: check when `len' overflows (i.e 2*alloced etc.) + */ + class B: public Resizable, public Flat { + /* BUGFIX at Tue Sep 3 18:04:34 CEST 2002: + * original order was: public Flat, public Resizable, but I got the + * error message from gcc-3.2: gensi.hpp:398: sorry, not implemented: adjusting pointers for covariant returns + */ + protected: + /** Number of bytes preallocated. */ + slen_t alloced; + char small[8]; + public: + /** Overridden. */ + virtual void vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg); + + /** Destructor: must be virtual since we have virtual methods. */ + virtual ~B() { + if (beg!=small) delete [] const_cast<char*>(beg); + /* ^^^ Dat: const_cast: pacify VC6.0 */ + } + /** Constructor: the empty buffer. */ + inline B(): alloced(sizeof(small)) { beg=small; len=0; } + /** Constructor: copy data from a null-terminated C string. */ + B(char const*); + /** Constructor: copy data from a memory buffer. */ + B(char const*,slen_t); + /** Constructor: copy-constructor */ + B(B const&); + /** Constructor: copy data from a Flat buffer. */ + B(Flat const&); + /** Constructor: copy data from a Flat buffer, term0(). */ + B(Flat const&,int); + /** Constructor: copy data from a GenBuffer. */ + B(GenBuffer const&); + /** Constructor: copy (consume) data from a readable stream. */ + B(GenBuffer::Readable &); + /** Constructor: concatenate two (2) memory buffers. */ + B(char const*,slen_t, char const*,slen_t); + /** Constructor: concatenate two (2) memory buffers, term0(). */ + B(char const*,slen_t, char const*,slen_t,int); + /** Constructor: concatenate two GenBuffers. */ + B(GenBuffer const&, GenBuffer const&); + /** Constructor: concatenate three (3) memory buffers. */ + B(char const*,slen_t, char const*,slen_t, char const*,slen_t); + /** Constructor: concatenate three (3) GenBuffers. */ + B(GenBuffer const&, GenBuffer const&, GenBuffer const&); + /** Constructor: concatenate a flat buffer and a C string */ + B(Flat const&, char const*); + /** Constructor: concatenate three ... */ + B(char const*, Flat const&, char const*); + /** Constructor: a substring of a Flat buffer */ + B(Flat const&, slen_t from_offset, slen_t slen); + + /** Works even when other==&(this). @return (this) */ + B& operator=(/*SimBuffer::*/Flat const& other); + /** C++ SUXX: type conversion (Flat& -> B&) doesn't work as expected. + * Works even when other==&(this). @return (this) + */ + B& operator=(/*SimBuffer::*/B const& other); + /** @return (this) */ + B& operator=(char const*); + /** Reads (consumes) the whole `stream', and appends the bytes to (this). + * @return (this) declaring `operator<<' inside would ruin inherited `operator<<'s + */ + /* GenBuffer::Writable& operator<<(GenBuffer::Readable &stream); */ + + /** Pacify VC6.0 multiple inheritance*/ + inline virtual operator void*() const { return (void*)(len!=0); } + /** Pacify VC6.0 multiple inheritance */ + inline virtual bool operator!() const { return len==0; } + + friend /*SimBuffer::*/B& operator<<(/*SimBuffer::*/B& self, GenBuffer::Readable &stream); + /** Specific operators for faster implementation */ + B& operator<<(char c); + B& operator<<(char const* s); + /** Works even when other==&(this). @return (this) */ + B& operator<<(Flat const&); + /* C++ inheritance SUXXXX: now I have to re-define _every_ operator<< in GenBuffer::Writable... */ + B& operator <<(void const*); + inline B& operator <<( signed short n) { write_num((signed long)n); return*this; } + inline B& operator <<( signed int n) { write_num((signed long)n); return*this; } + inline B& operator <<( signed long n) { write_num(n); return*this; } + inline B& operator <<(unsigned short n) { write_num((unsigned long)n); return*this; } + inline B& operator <<(unsigned int n) { write_num((unsigned long)n); return*this; } + inline B& operator <<(unsigned long n) { write_num(n); return*this; } + #if HAVE_LONG_LONG && NEED_LONG_LONG + inline B &operator <<(signed long long n) { write_num(n); return*this; } + inline B &operator <<(unsigned long long n) { write_num(n); return*this; } + #endif + inline B& operator <<(bool b) { GenBuffer::Writable::operator<<(b); return*this; } + +#if 0 + friend SimBuffer::B& operator<<(SimBuffer::B& self, char const*s); + friend SimBuffer::B& operator<<(SimBuffer::B& self, char c); +#endif + + inline char *begin_() const { return const_cast<char*>(beg); } + inline char *end_ () const { return const_cast<char*>(beg)+len; } + inline bool isFull() const { return len==alloced; } + /** Ensures beg[len]=='\0'. @return (this) */ + B& term0(); + /** @param idx would cause overload conflict if declared len_t. No range check */ + inline char &operator[](slendiff_t idx) const { return const_cast<char*>(beg)[idx]; } + /** @param lendiff if negative, then makes the buffer shorter */ + void grow_set0_by(slendiff_t lendiff); + /** Grows the buffer if necessary, fills with '\0' */ + char getAt(slen_t idx); + /** Doesn't free unnecessary memory. */ + inline void clear() { len=0; } + /** Removes oldmuch chars from index first, and makes place for newmuch + * chars there. Returns the beginning of the new place. Calls memmove(). + * Tue Jun 11 15:33:33 CEST 2002 + */ + char *substr_grow(slen_t first, slen_t oldmuch, slen_t newmuch); + B substr(slen_t first, slen_t howmuch) const; + B substr(slen_t first) const; + B right(slen_t howmuch) const; + B left(slen_t howmuch) const; + static void space_pad_cpy(char *dst, char const*src, slen_t pad); + + /* vi_write() doesn't work if s is inside (this). + * There is no append(...) method. Use vi_write() instead. + */ + // void append(char const*s, const slen_t len_); + virtual void vi_write(char const*, slen_t); + + /* Original: B& vformat(slen_t n, char const *fmt, va_list ap); + * Pacify VC6.0: error C2555: 'SimBuffer::B::vformat' : overriding virtual function differs from 'GenBuffer::Writable::vformat' only by return type or calling convention + */ + /** appends at most `n' chars, no trailing '\0'. This is different from + * ANSI (old and C99) stdio.h, because those insert at most `n-1' chars + * (not counting the '\0'), _and_ a trailing '\0'. Truncates the output + * to `n' chars if it would be longer. (Truncation semantics changed at + * Tue Jun 11 14:27:12 CEST 2002. Old: truncate to no chars if longer) + */ + GenBuffer::Writable& vformat(slen_t n, char const *fmt, va_list ap); + /** appends as many chars as requrested */ + GenBuffer::Writable& vformat(char const *fmt, va_list ap); + /** appends; calls vformat(n); mandatorly non-inline because of ... */ + GenBuffer::Writable& format(slen_t n, char const *fmt, ...); + /** appends; calls vformat(); mandatorly non-inline because of ... */ + GenBuffer::Writable& format(char const *fmt, ...); + + /* + * Name: NonPathMeta + * Input: any binary + * Output: non-path characters pre-backslashed + * Description: Places backslashes in front of non-path characters: + * [^-_./a-zA-Z0-9]. + * Compatibility: UNIX shells: sh (Bourne Shell), bash, ksh, zsh. Use this in + * a shell script to protect a string from word splitting, variable + * substitution and everything else. Note that there will be problems + * only with \0 (depends on the shell) and \n (will be simply removed by + * the shell!). See also Quote::QShell for full shell compatility. + * Valid input type: binary + * Valid input: any binary + * On invalid input: impossible + * Inverse of valid: lossy: Quote::UnMeta + * Validity indicator: implemented + * Output type: some binary + * Direction: encode + * Method: each_byte + * Dependencies: - + */ + B& appendNpmq(const Flat &other, bool dq=false); + /** Quotes a filename (actually a pathname since it may include + * (sub)directories) specified in param `other' to be passed to the + * most common shell of the host operating system (/bin/sh, COMMAND.COM, + * CMD.EXE etc.) as a separate command line argument for a command + * invoked from the shell. + * + * Under UNIX, this differs from appendNpmq only when treating [\n\0]. + * Under Win32, the filename is surrounded by double quotes. Double quotes + * inside the filename are skipped. Other systems than Win32 are treated + * like UNIX. + * @param preminus prefix filenames starting with `-' with `./' ? + */ + B& appendFnq(const Flat &other, bool preminus=false); + /** + * Name: Quote::NonPathOctal; from quote.rb + * Input: any binary + * Output: non-path characters converted to octal + * Description: Converts non-path characters ([^-_./a-zA-Z0-9]) in + * a string to their prebackslashed, 3-digit octal representation (i.e + * \123). + * Compatibility: Ruby, ANSI C, K&R C, C++, Java (without \u....), + * TCL double quotes (without \u....), TCL unquoted strings (without + * \u....), Perl5, Pike, AWK, PostScript Level 1, bc. See also + * Quote::*Octal. + * Valid input type: binary + * Valid input: any binary + * On invalid input: impossible + * Inverse of valid: lossy: Quote::UnSlash + * Validity indicator: implemented + * Output type: \A[-\\._/a-zA-Z0-9]*\z + * Direction: encode + * Method: each_byte + * Dependencies: - + */ + B& appendDump(const Flat &other, bool dq=false); + B& appendDump(const char c, bool dq=false); + /** + * Name: Quote::Unslash + * Input: a double-quoted (backslashed) version of a string without + * the double quotes themselves + * Output: the original, unquoted (possibly binary) string + * Description: Converts a string expressed inside double quotes of some + * programming language (e.g Ruby, C, Java, Perl, Ruby) to its original, + * unquoted state. Transformation is done only after backslashes. The + * following `common' transformations are supported: \0, \00, \000 + * (octal), \a (alarm bell), \b (backslash), \e (escape), \f (form feed), + * \n (newline), \r (carriage return), \t (horizontal tab), \v (verical + * tab) \x61, \c[, \l (lowercase), \u (upper case), \NL (skip this), + * \", \\, \... . + * Compatibility: Ruby, ANSI C, C++, Java (without \u....), TCL double + * quotes (without \u....), TCL unquoted strings, Perl5, Pike, AWK, + * PostScript Level 1, bc, PHP. + * See also Quote::UnSlashPHPC for full PHP:StripCSlashes() compatibility. + * See also Quote::UnSlashKnr. Compatible with PHP stripcslashes(). + * See also Quote::UnSlashKnr. Differs from Quote::UnslashMiddle by not + * removing the double quotes from string edges. + * Valid input type: binary + * Valid input: any binary + * On invalid input: impossible + * Inverse of valid: lossy: Quote::NonPathOctal + * Validity indicator: implemented + * Output type: any binary + * Direction: decode + * Method: gsub + * Dependencies: - + * + * @param iniq the char that surrounds the quoted param `other' + * @param other a quoted string + * @return an empty string if iniq<256 and param `other' not delimited by iniq + */ + B& appendUnslash(const Flat &other, int iniq); + /** Appends as a C (double-quoted) string. */ + B& appendDumpC (const Flat &other, bool dq=false); + /** Appends as a PostScript (paren-quoted) string. */ + B& appendDumpPS (const Flat &other, bool dq=false); + /** Make `other' upper case (English), plus change all non-alpha chars + * to underscore. + */ + B& appendHppq(const Flat &other); + + protected: + inline char *grow_by(slen_t howmuch) { char *s; vi_grow2(0, howmuch, 0, &s); return s; } + /*SimBuffer::*/B& B_append(GenBuffer::Readable &stream); +#if 0 + SimBuffer::B& B_append(char c); + SimBuffer::B& B_append(char const*s); +#endif + }; +}; + +inline SimBuffer::B& operator<<(SimBuffer::B& self, GenBuffer::Readable &stream) { return self.B_append(stream); } +#if 0 +inline SimBuffer::B& operator<<(SimBuffer::B& self, char const*s) { return self.B_append(s); } +inline SimBuffer::B& operator<<(SimBuffer::B& self, char c) { return self.B_append(c); } +#endif + +/** Shorthand synonym */ +typedef SimBuffer::B Buffer; + +inline bool operator ==(const GenBuffer& s1, const GenBuffer& s2) { + return 0==s1.cmp(s2); +} +inline bool operator ==(const char *s1, const GenBuffer& s2) { + return 0==s2.cmp(s1); +} +inline bool operator ==(const GenBuffer& s1, const char *s2) { + return 0==s1.cmp(s2); +} +inline bool operator <(const GenBuffer& s1, const GenBuffer& s2) { + return 0>s1.cmp(s2); +} +inline bool operator <(const char *s1, const GenBuffer& s2) { + return 0<s2.cmp(s1); +} +inline bool operator <(const GenBuffer& s1, const char *s2) { + return 0>s1.cmp(s2); +} +inline bool operator >(const GenBuffer& s1, const GenBuffer& s2) { + return 0<s1.cmp(s2); +} +inline bool operator >(const char *s1, const GenBuffer& s2) { + return 0>s2.cmp(s1); +} +inline bool operator >(const GenBuffer& s1, const char *s2) { + return 0<s1.cmp(s2); +} +inline bool operator <=(const GenBuffer& s1, const GenBuffer& s2) { + return 0>=s1.cmp(s2); +} +inline bool operator <=(const char *s1, const GenBuffer& s2) { + return 0<=s2.cmp(s1); +} +inline bool operator <=(const GenBuffer& s1, const char *s2) { + return 0>=s1.cmp(s2); +} +inline bool operator >=(const GenBuffer& s1, const GenBuffer& s2) { + return 0<=s1.cmp(s2); +} +inline bool operator >=(const char *s1, const GenBuffer& s2) { + return 0>=s2.cmp(s1); +} +inline bool operator >=(const GenBuffer& s1, const char *s2) { + return 0<=s1.cmp(s2); +} +inline bool operator !=(const GenBuffer& s1, const GenBuffer& s2) { + return 0!=s1.cmp(s2); +} +inline bool operator !=(const char *s1, const GenBuffer& s2) { + return 0!=s2.cmp(s1); +} +inline bool operator !=(const GenBuffer& s1, const char *s2) { + return 0!=s1.cmp(s2); +} + +#endif diff --git a/Build/source/utils/sam2p/gensio.cpp b/Build/source/utils/sam2p/gensio.cpp new file mode 100644 index 00000000000..b81b9f34fb0 --- /dev/null +++ b/Build/source/utils/sam2p/gensio.cpp @@ -0,0 +1,884 @@ +/* + * gensio.cpp -- IO-specific methods + * by pts@fazekas.hu at Tue Feb 26 13:28:12 CET 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#if 0 +extern "C" int errno; +/* OK: autodetect with autoconf */ +extern "C" int _l_stat(const char *file_name, struct stat *buf); +/* OK: Imp: not in ANSI C, but we cannot emulate it! */ +extern "C" int _v_s_n_printf ( char *str, size_t n, const char *format, va_list ap ); +#else +#undef __STRICT_ANSI__ /* for __MINGW32__ */ +#define _BSD_SOURCE 1 /* vsnprintf(); may be emulated with fixup_vsnprintf() */ +#ifndef __APPLE__ /* SUXX: Max OS X has #ifndef _POSIX_SOURCE around lstat() :-( */ +#define _POSIX_SOURCE 1 /* also popen() */ +#endif +#define _POSIX_C_SOURCE 2 /* also popen() */ +#define _XOPEN_SOURCE_EXTENDED 1 /* Digital UNIX lstat */ +#ifndef _XPG4_2 +#define _XPG4_2 1 /* SunOS 5.7 lstat() */ +#endif +#undef _XOPEN_SOURCE /* pacify gcc-3.1 */ +#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */ +#endif + +#include "gensio.hpp" +#include "error.hpp" +#include <string.h> /* strlen() */ +#include <stdarg.h> /* va_list */ +#if _MSC_VER > 1000 +// extern "C" int getpid(void); +# include <process.h> +#else +# include <unistd.h> /* getpid() */ +#endif +#include <sys/stat.h> /* struct stat */ +#include <stdlib.h> /* getenv() */ +#include <errno.h> +#include <signal.h> /* signal() */ /* Imp: use sigaction */ +#if HAVE_DOS_BINARY +#undef __STRICT_ANSI__ +#include <fcntl.h> /* O_BINARY */ +#include <io.h> /* setmode() */ +#endif + +#define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b)) + +#if HAVE_PTS_VSNPRINTF /* Both old and c99 work OK */ +# define VSNPRINTF vsnprintf +#else +# if OBJDEP +# warning REQUIRES: snprintf.o +# endif +# include "snprintf.h" +# define VSNPRINTF fixup_vsnprintf /* Tested, C99. */ +#endif + +static void cleanup(int) { + Error::cexit(126); +} + +void Files::doSignalCleanup() { + signal(SIGINT, cleanup); + signal(SIGTERM, cleanup); +#ifdef SIGHUP + signal(SIGHUP, SIG_IGN); +#endif + /* Dat: don't do cleanup for SIGQUIT */ +} + +GenBuffer::Writable& SimBuffer::B::vformat(slen_t n, char const *fmt, va_list ap) { + /* Imp: test this code in various systems and architectures. */ + /* Dat: vsnprintf semantics are verified in configure AC_PTS_HAVE_VSNPRINTF, + * and a replacement vsnprintf is provided in case of problems. We don't + * depend on HAVE_PTS_VSNPRINTF_C99, because C99-vsnprintf is a run-time + * property. + * + * C99 vsnprintf semantics: vsnprintf() always returns a non-negative value: + * the number of characters (trailing \0 not included) that would have been + * printed if there were enough space. Only the first maxlen (@param) + * characters may be modified. The output is terminated by \0 iff maxlen!=0. + * NULL @param dststr is OK iff maxlen==0. Since glibc 2.1. + * old vsnprintf semantics: vsnprintf() returns a non-negative value or -1: + * 0 if maxlen==0, otherwise: -1 if maxlen is shorter than all the characters + * plus the trailing \0, otherwise: the number of characters (trailing \0 not + * included) that were printed. Only the first maxlen (@param) + * characters may be modified. The output is terminated by \0 iff maxlen!=0. + * NULL @param dststr is OK iff maxlen==0. + */ + if (n>0) { /* avoid problems with old-style vsnprintf */ + char *s; vi_grow2(0, n+1, 0, &s); len-=n+1; /* +1: sprintf appends '\0' */ + const_cast<char*>(beg)[len]='\0'; /* failsafe sentinel */ + slen_t did=VSNPRINTF(s, n+1, fmt, ap); + if (did>n) did=n; + /* ^^^ Dat: always true: (unsigned)-1>n, so this works with both old and c99 */ + /* Now: did contains the # chars to append, without trailing '\0' */ + /* Dat: we cannot check for -1, because `did' is unsigned */ + /* Dat: trailer '\0' doesn't count into `did' */ + len+=did; + } + return *this; +} +GenBuffer::Writable& SimBuffer::B::vformat(char const *fmt, va_list ap) { + char dummy, *s; + slen_t did=VSNPRINTF(&dummy, 1, fmt, ap), n; + if (did>0) { /* skip if nothing to be appended */ + /* vvv Dat: we cannot check for -1, because `did' is unsigned */ + if ((did+1)!=(slen_t)0) { /* C99 semantics; quick shortcut */ + vi_grow2(0, (n=did)+1, 0, &s); len-=n+1; + ASSERT_SIDE2(VSNPRINTF(s, n+1, fmt, ap), * 1U==did); + } else { /* old semantics: grow the buffer incrementally */ + if ((n=strlen(fmt))<16) n=16; /* initial guess */ + while (1) { + vi_grow2(0, n+1, 0, &s); len-=n+1; /* +1: sprintf appends '\0' */ + const_cast<char*>(beg)[len]='\0'; /* failsafe sentinel */ + did=VSNPRINTF(s, n+1, fmt, ap); + if ((did+1)!=(slen_t)0) { + assert(did!=0); /* 0 is caught early in this function */ + assert(did<=n); /* non-C99 semantics */ + break; + } + n<<=1; + } + } + len+=did; + } + return *this; +} + +GenBuffer::Writable& SimBuffer::B::format(slen_t n, char const *fmt, ...) { + va_list ap; + PTS_va_start(ap, fmt); + vformat(n, fmt, ap); + va_end(ap); + return *this; +} +GenBuffer::Writable& SimBuffer::B::format(char const *fmt, ...) { + va_list ap; + PTS_va_start(ap, fmt); + vformat(fmt, ap); + va_end(ap); + return *this; +} + +/* --- */ + +GenBuffer::Writable& Files::FILEW::vformat(slen_t n, char const *fmt, va_list ap) { + /* Dat: no vfnprintf :-( */ + SimBuffer::B buf; + buf.vformat(n, fmt, ap); + fwrite(buf(), 1, buf.getLength(), f); + return*this; +} +GenBuffer::Writable& Files::FILEW::vformat(char const *fmt, va_list ap) { + vfprintf(f, fmt, ap); + return*this; +} + +/* --- */ + +/** Must be <=32767. Should be a power of two. */ +static const slen_t BUFLEN=4096; + +void Encoder::vi_putcc(char c) { vi_write(&c, 1); } +int Decoder::vi_getcc() { char ret; return vi_read(&ret, 1)==1 ? (unsigned char)ret : -1; } +void Encoder::writeFrom(GenBuffer::Writable& out, FILE *f) { + char *buf=new char[BUFLEN]; + int wr; + while (1) { + if ((wr=fread(buf, 1, BUFLEN, f))<1) break; + out.vi_write(buf, wr); + } + delete [] buf; +} +void Encoder::writeFrom(GenBuffer::Writable& out, GenBuffer::Readable& in) { + char *buf=new char[BUFLEN]; + int wr; + while (1) { + if ((wr=in.vi_read(buf, BUFLEN))<1) break; + out.vi_write(buf, wr); + } + delete [] buf; +} + +/* --- */ + +Filter::FILEE::FILEE(char const* filename) { + if (NULLP==(f=fopen(filename,"wb"))) Error::sev(Error::EERROR) << "Filter::FILEE: error open4write: " << FNQ2(filename,strlen(filename)) << (Error*)0; + closep=true; +} +void Filter::FILEE::vi_write(char const*buf, slen_t len) { + if (len==0) close(); else fwrite(buf, 1, len, f); +} +void Filter::FILEE::close() { + if (closep) { fclose(f); f=(FILE*)NULLP; closep=false; } +} + +/* --- */ + +static FILE* fopenErr(char const* filename, char const* errhead) { + FILE *f; + if (NULLP==(f=fopen(filename,"rb"))) + Error::sev(Error::EERROR) << errhead << ": error open4read: " << FNQ2(filename,strlen(filename)) << (Error*)0; + return f; +} + +Filter::FILED::FILED(char const* filename) { + f=fopenErr(filename, "Filter::FileD"); + closep=true; +} +slen_t Filter::FILED::vi_read(char *buf, slen_t len) { + if (len==0) { close(); return 0; } + return fread(buf, 1, len, f); +} +void Filter::FILED::close() { + if (closep) { fclose(f); f=(FILE*)NULLP; closep=false; } +} + +/* --- */ + +Filter::UngetFILED::UngetFILED(char const* filename_, FILE *stdin_f, closeMode_t closeMode_) { + if (stdin_f!=NULLP && (filename_==NULLP || (filename_[0]=='-' && filename_[1]=='\0'))) { + f=stdin_f; + Files::set_binary_mode(fileno(f), true); + closeMode_&=~CM_unlinkp; + if (0!=(closeMode_&CM_keep_stdinp)) closeMode_&=~CM_closep; + filename_=(char const*)NULLP; /* BUGFIX at Tue Jan 4 23:45:31 CET 2005 */ + } else { + f=fopenErr(filename_, "Filter::UngetFileD"); + } + if (filename_!=NULLP) strcpy(const_cast<char*>(filename=new char[strlen(filename_)+1]), filename_); + else filename=(char*)NULLP; + /* fprintf(stderr,"filename:%s\n",filename); */ + closeMode=closeMode_; + ftell_at=0; + ofs=0; +} +// Filter::UngetFILED::checkFILE() { } +slen_t Filter::UngetFILED::vi_read(char *buf, slen_t len) { + slen_t delta; + if (len==0) { + close(); return 0; + } else if (unget.getLength()==0) { delta=0; do_read_f: + delta+=(f==NULLP ? 0 : fread(buf, 1, len, f)); + ftell_at+=delta; + return delta; + // delta+=fread(buf, 1, len, f); // write(1, buf, delta); // return delta; + } else if (ofs+len<=unget.getLength()) { + // printf("\nul=%d ft=%ld\n", unget.getLength(), ftell(f)); fflush(stdout); + memcpy(buf, unget()+ofs, len); /* Dat: don't remove from unget yet */ + ftell_at+=len; + // write(1, buf, len); + if ((ofs+=len)==unget.getLength()) { unget.forgetAll(); ofs=0; } + return len; + } else { + // printf("\num=%d ft=%d\n", unget.getLength(), ftell(f)); fflush(stdout); + delta=unget.getLength()-ofs; /* BUGFIX at Sat Apr 19 17:15:50 CEST 2003 */ + memcpy(buf, unget()+ofs, delta); + // write(1, buf, delta); + unget.forgetAll(); ofs=0; + buf+=delta; + len-=delta; + goto do_read_f; + } +} +void Filter::UngetFILED::close() { + if (0!=(closeMode&CM_closep)) { fclose(f); f=(FILE*)NULLP; closeMode&=~CM_closep; } + unget.forgetAll(); ofs=0; + if (filename!=NULLP) { + if (0!=(closeMode&CM_unlinkp)) { remove(filename); } + delete [] filename; + } +} + +int Filter::UngetFILED::vi_getcc() { + if (unget.getLength()==0) { do_getc: + int i=-1; + if (f!=NULLP && (i=MACRO_GETC(f))!=-1) ftell_at++; + return i; + } + if (ofs==unget.getLength()) { ofs=0; unget.forgetAll(); goto do_getc; } + ftell_at++; + return unget[ofs++]; +} +int Filter::UngetFILED::getc_seekable() { + /* Glibc stdio doesn't allow fseek() even if the seek would go into the + * read buffer, and fseek(f, 0, SEEK_CUR) fails for unseekable files. Fine. + */ + int c=MACRO_GETC(f); + return 0==fseek(f, -1L, SEEK_CUR) ? -2 : c; +} +bool Filter::UngetFILED::isSeekable() { + long pos, posend; + if (f==NULLP || 0!=(closeMode&CM_seekablep)) return true; + // return false; + clearerr(f); /* clears both the EOF and error indicators */ + if (-1L==(pos=ftell(f)) /* sanity checks on ftell() and fseek() */ + || 0!=fseek(f, 0L, SEEK_CUR) + || pos!=ftell(f) + || 0!=fseek(f, 0L, SEEK_END) + || (posend=ftell(f))==0 || posend<pos + || 0!=fseek(f, 0L, SEEK_SET) + || 0!=ftell(f) + || 0!=fseek(f, pos, SEEK_SET) + || pos!=ftell(f) + ) return false; + int c; + if ((c=getc_seekable())==-2 && pos==ftell(f)) { + // if (0!=fseek(f, -1L, SEEK_CUR) || pos!=ftell(f)) + // Error::sev(Error::EERROR) << "Filter::UngetFILED: cannot seek back" << (Error*)0; + return true; + } + unget << (char)c; /* not seekable, must unget the test character just read */ + return false; +} +FILE* Filter::UngetFILED::getFILE(bool seekable_p) { + FILE *tf; + if (!unget.isEmpty() || (seekable_p && !isSeekable())) { do_temp: + /* must create a temporary file */ + SimBuffer::B tmpnam; + if (filename==NULLP) Error::sev(Error::NOTICE) << "Filter::UngetFILED" << ": using temp for" << " `-' (stdin)" << (Error*)0; + else Error::sev(Error::NOTICE) << "Filter::UngetFILED" << ": using temp for" << ": " << FNQ2(filename,strlen(filename)) << (Error*)0; + if (NULLP==(tf=Files::open_tmpnam(tmpnam, "wb+"))) { + if (filename==NULLP) Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot open temp file for" << " `-' (stdin)" << (Error*)0; + else Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot open temp file for" << ": " << FNQ2(filename,strlen(filename)) << (Error*)0; + } + tmpnam.term0(); + /* vvv change filename, so CM_unlinkp can work */ + if (filename!=NULLP) { + if (0!=(closeMode&CM_unlinkp)) { remove(filename); } + delete [] filename; + } + strcpy(const_cast<char*>(filename=new char[tmpnam.getLength()+1]), tmpnam()); + Files::tmpRemoveCleanup(filename); + if (unget.getLength()-ofs==fwrite(unget()+ofs, 1, unget.getLength()-ofs, tf)) { + static const slen_t BUFSIZE=4096; /* BUGFIX at Sat Apr 19 15:43:59 CEST 2003 */ + char *buf=new char[BUFSIZE]; + unsigned got; + // fprintf(stderr, "ftf=%ld ofs=%d\n", ftell(f), ofs); + while ((0<(got=fread(buf, 1, BUFSIZE, f))) + && got==fwrite(buf, 1, got, tf)) {} + // fprintf(stderr,"got=%d ftell=%d\n", got, ftell(tf)); + delete [] buf; + } + unget.forgetAll(); ofs=0; + fflush(tf); rewind(tf); + if (ferror(tf) || ferror(f)) + Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot write temp file" << (Error*)0; + if (0!=(closeMode&CM_closep)) fclose(f); + closeMode|=CM_closep|CM_unlinkp; /* close and unlink the temporary file */ + /* ^^^ Imp: verify VC++ compilation, +others */ + f=tf; + } else if (f==NULLP) { /* no real file open */ + #if OS_COTY==COTY_UNIX + tf=fopen("/dev/null","rb"); + #else + #if OS_COPTY==COTY_WIN9X || OS_COTY==COTY_WINNT + tf=fopen("nul","rb"); + #else + tf=(FILE*)NULLP; + #endif + #endif + if (tf==NULLP) goto do_temp; /* perhaps inside chroot() */ + close(); + closeMode|=CM_closep|CM_unlinkp; /* close and unlink the temporary file */ + f=tf; + } + closeMode|=CM_seekablep; + return f; +} +void Filter::UngetFILED::seek(long abs_ofs) { + if (abs_ofs==vi_tell()) return; + (void) getFILE(true); /* ensure seekability */ + if (0!=fseek(f, abs_ofs, SEEK_SET)) + Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot seek" << (Error*)0; + assert(unget.isEmpty()); + assert(ofs==0); + ftell_at=abs_ofs; +} +void Filter::UngetFILED::unread(char const *s, slen_t slen) { + ftell_at-=slen; + if (slen==0) { + } else if (slen<=ofs) { + memcpy(const_cast<char*>(unget()+(ofs-=slen)), s, slen); + } else { + slen-=ofs; + ofs=0; + if (!unget.isEmpty() || 0!=fseek(f, -slen, SEEK_CUR)) { + assert(unget.isEmpty()); // !! + unget.vi_write(s, slen); /* complete garbage unless unget was empty */ + assert(unget.getLength()); + } + } + // fprintf(stderr, "%d..\n", unget.getLength()); +} +void Filter::UngetFILED::appendLine(GenBuffer::Writable &buf, int delimiter) { + // fprintf(stderr, "this=%p %d (%p)\n", this, unget.getLength(), unget()); + unget.term0(); + if (delimiter<0) { + char rbuf[4096]; + slen_t got; + /* vvv Imp: less memory copying, less stack usage? */ + while (0!=(got=vi_read(rbuf, sizeof(rbuf)))) buf.vi_write(rbuf, got); + } else if (unget.getLength()==0) { do_getc: + int i; + if (f!=NULLP) { + while ((i=MACRO_GETC(f))>=0 && i!=delimiter) { buf.vi_putcc(i); ftell_at++; } + if (i>=0) buf.vi_putcc(i); + } + } else { + char const *p=unget()+ofs, *p0=p, *pend=unget.end_(); + assert(ofs<=unget.getLength()); + while (p!=pend && *p!=delimiter) p++; + ftell_at+=p-p0; + if (p==pend) { buf.vi_write(p0, p-p0); ofs=0; unget.forgetAll(); goto do_getc; } + ftell_at++; p++; /* found delimiter in `unget' */ + buf.vi_write(p0, p-p0); + ofs+=p-p0; + } +} + +/* --- */ + +Filter::PipeE::PipeE(GenBuffer::Writable &out_, char const*pipe_tmpl, slendiff_t i): tmpname(), out(out_), tmpename() { + /* <code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */ + param_assert(pipe_tmpl!=(char const*)NULLP); + SimBuffer::B *pp; + char const*s=pipe_tmpl; + lex: while (s[0]!='\0') { /* Interate throuh the template, substitute temporary filenames */ + if (*s++=='%') switch (*s++) { + case '\0': case '%': + redir_cmd << '%'; + break; + case 'i': /* the optional integer passed in param `i' */ + redir_cmd << i; + break; + case '*': /* the optional unsafe string passed in param `i' */ + redir_cmd << (char const*)i; + break; + case 'd': case 'D': /* temporary file for encoded data output */ + pp=&tmpname; + put: + // if (*pp) Error::sev(Error::EERROR) << "Filter::PipeE" << ": multiple %escape" << (Error*)0; + /* ^^^ multiple %escape is now a supported feature */ + if (!*pp && !Files::find_tmpnam(*pp)) Error::sev(Error::EERROR) << "Filter::PipeE" << ": tmpnam() failed" << (Error*)0; + assert(! !*pp); /* pacify VC6.0 */ + // *pp << ext; + pp->term0(); + if ((unsigned char)(s[-1]-'A')<(unsigned char)('Z'-'A')) + redir_cmd.appendFnq(*pp, /*preminus:*/ true); /* Capital letter: quote from the shell */ + else redir_cmd << *pp; + break; + case 'e': case 'E': /* temporary file for error messages */ + pp=&tmpename; + goto put; + case 's': case 'S': /* temporary source file */ + pp=&tmpsname; + goto put; + default: + Error::sev(Error::EERROR) << "Filter::PipeE" << ": invalid %escape in pipe_tmpl" << (Error*)0; + } else redir_cmd << s[-1]; + } + #if 0 + if (!tmpname) Error::sev(Error::EERROR) << "Filter::PipeE" << ": no outname (%D) in cmd: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + #else + /* Append quoted file redirect to command, if missing */ + if (!tmpname) { s=" >%D"; goto lex; } + #endif + #if !HAVE_PTS_POPEN + if (!tmpsname) { s=" <%S"; goto lex; } + #endif + // tmpname="tmp.name"; + redir_cmd.term0(); + if (tmpname) { Files::tmpRemoveCleanup(tmpname()); remove(tmpname()); } /* already term0() */ + /* ^^^ Dat: remove() here introduces a race condition, but helps early error detection */ + if (tmpename) Files::tmpRemoveCleanup(tmpename()); /* already term0() */ + if (tmpsname) Files::tmpRemoveCleanup(tmpsname()); /* already term0() */ + /* </code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */ + + // fprintf(stderr, "rc: (%s)\n", redir_cmd()); + + #if HAVE_PTS_POPEN + if (!tmpsname) { + if (NULLP==(p=popen(redir_cmd(), "w"CFG_PTS_POPEN_B))) Error::sev(Error::EERROR) << "Filter::PipeE" << ": popen() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + signal(SIGPIPE, SIG_IGN); /* Don't abort process with SIGPIPE signals if child cannot read our data */ + } else { + #else + if (1) { + #endif + #if !HAVE_system_in_stdlib + Error::sev(Error::EERROR) << "Filter::PipeE" << ": no system() on this system" << (Error*)0; + #else + if (NULLP==(p=fopen(tmpsname(), "wb"))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": fopen(w) failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + #endif + } +} +void Filter::PipeE::vi_copy(FILE *f) { + writeFrom(out, f); + if (ferror(f)) Error::sev(Error::EERROR) << "Filter::PipeE: vi_copy() failed" << (Error*)0; + fclose(f); +} +void Filter::PipeE::vi_write(char const*buf, slen_t len) { + assert(p!=NULLP); + int wr; + if (len==0) { /* EOF */ + if (tmpsname) { + #if HAVE_system_in_stdlib + fclose(p); + if (0!=(Files::system3(redir_cmd()))) Error::sev(Error::EERROR) << "Filter::PipeE" << ": system() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + remove(tmpsname()); + #endif /* Dat: else is not required; would be unreachable code. */ + } else { + #if HAVE_PTS_POPEN + if (0!=pclose(p)) Error::sev(Error::EERROR) << "Filter::PipeE" << ": pclose() failed; error in external prg" << (Error*)0; + #endif + } + vi_check(); + p=(FILE*)NULLP; + FILE *f=fopen(tmpname(),"rb"); + if (NULLP==f) Error::sev(Error::EERROR) << "Filter::PipeE" <<": fopen() after pclose() failed: " << tmpname << (Error*)0; + vi_copy(f); + // if (ferror(f)) Error::sev(Error::EERROR) << "Filter::Pipe: fread() tmpfile failed" << (Error*)0; + // fclose(f); + /* ^^^ interacts badly when Image::load() is called inside vi_copy(), + * Image::load() calls fclose() + */ + if (tmpname ) remove(tmpname ()); + if (tmpename) remove(tmpename()); + if (tmpsname) remove(tmpsname()); + out.vi_write(0,0); /* Signal EOF to subsequent filters. */ + } else { + while (len!=0) { + wr=fwrite(buf, 1, len>0x4000?0x4000:len, p); +// assert(!ferror(p)); + if (ferror(p)) { + vi_check(); /* Give a chance to report a better error message when Broken File. */ + Error::sev(Error::EERROR) << "Filter::PipeE" << ": pipe write failed" << (Error*)0; + } + buf+=wr; len-=wr; + } + } +} +Filter::PipeE::~PipeE() {} +void Filter::PipeE::vi_check() {} + +/* --- */ + +Filter::PipeD::PipeD(GenBuffer::Readable &in_, char const*pipe_tmpl, slendiff_t i): state(0), in(in_) { + /* <code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */ + param_assert(pipe_tmpl!=(char const*)NULLP); + SimBuffer::B *pp=(SimBuffer::B*)NULLP; + char const*s=pipe_tmpl; + lex: while (s[0]!='\0') { /* Interate throuh the template, substitute temporary filenames */ + if (*s++=='%') switch (*s++) { + case '\0': case '%': + redir_cmd << '%'; + break; + case 'i': /* the optional integer passed in param `i' */ + redir_cmd << i; + break; + case '*': /* the optional unsafe string passed in param `i' */ + redir_cmd << (char const*)i; + break; + case 'd': case 'D': /* temporary file for encoded data output */ + pp=&tmpname; + put: + // if (*pp) Error::sev(Error::EERROR) << "Filter::PipeD: multiple %escape" << (Error*)0; + /* ^^^ multiple %escape is now a supported feature */ + if (!*pp && !Files::find_tmpnam(*pp)) Error::sev(Error::EERROR) << "Filter::PipeD" << ": tmpnam() failed" << (Error*)0; + assert(*pp); + pp->term0(); + if ((unsigned char)(s[-1]-'A')<(unsigned char)('Z'-'A')) + redir_cmd.appendFnq(*pp); /* Capital letter: quote from the shell */ + else redir_cmd << *pp; + break; + case 'e': case 'E': /* temporary file for error messages */ + pp=&tmpename; + goto put; + case 's': case 'S': /* temporary source file */ + pp=&tmpsname; + goto put; + /* OK: implement temporary file for input, option to suppress popen() */ + default: + Error::sev(Error::EERROR) << "Filter::PipeD: invalid %escape in pipe_tmpl" << (Error*)0; + } else redir_cmd << s[-1]; + } + #if 0 + if (!tmpname) Error::sev(Error::EERROR) << "Filter::PipeD" << ": no outname (%D) in cmd: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + #else + /* Append quoted file redirect to command, if missing */ + if (!tmpname) { s=" >%D"; goto lex; } + #endif + #if !HAVE_PTS_POPEN + if (!tmpsname) { s=" <%S"; goto lex; } + #endif + // tmpname="tmp.name"; + redir_cmd.term0(); + if (tmpname) Files::tmpRemoveCleanup(tmpname ()); /* already term0() */ + if (tmpename) Files::tmpRemoveCleanup(tmpename()); /* already term0() */ + if (tmpsname) { Files::tmpRemoveCleanup(tmpsname()); remove(tmpsname()); } /* already term0() */ + /* ^^^ Dat: remove() here introduces a race condition, but helps early error detection */ + /* </code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */ +} +slen_t Filter::PipeD::vi_read(char *tobuf, slen_t tolen) { + assert(!(tolen!=0 && state==2)); + if (state==2) return 0; /* Should really never happen. */ + /* Normal read operation with tolen>0; OR tolen==0 */ + if (state==0) { /* Read the whole stream from `in', write it to `tmpsname' */ + #if HAVE_PTS_POPEN + if (!tmpsname) { + if (NULLP==(p=popen(redir_cmd(), "w"CFG_PTS_POPEN_B))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": popen() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + signal(SIGPIPE, SIG_IGN); /* Don't abort process with SIGPIPE signals if child cannot read our data */ + vi_precopy(); + in.vi_read(0,0); + if (0!=pclose(p)) Error::sev(Error::EERROR) << "Filter::PipeD" << ": pclose() failed; error in external prg" << (Error*)0; + } else { + #else + if (1) { + #endif + #if !HAVE_system_in_stdlib + Error::sev(Error::EERROR) << "Filter::PipeD" << ": no system() on this system" << (Error*)0; + #else + if (NULLP==(p=fopen(tmpsname(), "wb"))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": fopen(w) failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + vi_precopy(); + in.vi_read(0,0); + fclose(p); + if (0!=(Files::system3(redir_cmd()))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": system() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0; + remove(tmpsname()); + #endif + } + vi_check(); + if (NULLP==(p=fopen(tmpname(),"rb"))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": fopen() after pclose() failed: " << tmpname << (Error*)0; + state=1; + } /* IF state==0 */ + assert(state==1); + if (tolen==0 || 0==(tolen=fread(tobuf, 1, tolen, p))) do_close(); + // putchar('{'); fwrite(tobuf, 1, tolen, stdout); putchar('}'); + return tolen; +} +void Filter::PipeD::do_close() { + fclose(p); p=(FILE*)NULLP; + if (tmpname ) remove(tmpname ()); + if (tmpename) remove(tmpename()); + if (tmpsname) remove(tmpsname()); + state=2; +} +void Filter::PipeD::vi_precopy() { + char *buf0=new char[BUFLEN], *buf; + slen_t len, wr; + while (0!=(len=in.vi_read(buf0, BUFLEN))) { + // printf("[%s]\n", buf0); + for (buf=buf0; len!=0; buf+=wr, len-=wr) { + wr=fwrite(buf, 1, len>0x4000?0x4000:len, p); + if (ferror(p)) { + vi_check(); /* Give a chance to report a better error message when Broken File. */ + Error::sev(Error::EERROR) << "Filter::PipeD" << ": pipe write failed" << (Error*)0; + } + } + } + delete [] buf0; +} +int Filter::PipeD::vi_getcc() { + char ret; int i; + // fprintf(stderr,"state=%u\n", state); + switch (state) { + case 0: return vi_read(&ret, 1)==1 ? (unsigned char)ret : -1; + case 1: if (-1==(i=MACRO_GETC(p))) do_close(); return i; + /* case: 2: fall-through */ + } + return -1; +} +void Filter::PipeD::vi_check() {} +Filter::PipeD::~PipeD() { if (state!=2) vi_read(0,0); } + +Filter::BufR::BufR(GenBuffer const& buf_): bufp(&buf_) { + buf_.first_sub(sub); +} +int Filter::BufR::vi_getcc() { + if (bufp==(GenBuffer const*)NULLP) return -1; /* cast: pacify VC6.0 */ + if (sub.len==0) { + bufp->next_sub(sub); + if (sub.len==0) { bufp=(GenBuffer const*)NULLP; return -1; } + } + sub.len--; return *sub.beg++; +} +slen_t Filter::BufR::vi_read(char *to_buf, slen_t max) { + if (max==0 || bufp==(GenBuffer const*)NULLP) return 0; + if (sub.len==0) { + bufp->next_sub(sub); + if (sub.len==0) { bufp=(GenBuffer const*)NULLP; return 0; } + } + if (max<sub.len) { + memcpy(to_buf, sub.beg, max); + sub.len-=max; sub.beg+=max; + return max; + } + max=sub.len; sub.len=0; + memcpy(to_buf, sub.beg, max); + return max; +} +void Filter::BufR::vi_rewind() { bufp->first_sub(sub); } + +Filter::FlatD::FlatD(char const* s_, slen_t slen_): s(s_), sbeg(s_), slen(slen_) {} +Filter::FlatD::FlatD(char const* s_): s(s_), sbeg(s_), slen(strlen(s_)) {} +void Filter::FlatD::vi_rewind() { s=sbeg; } +int Filter::FlatD::vi_getcc() { + if (slen==0) return -1; + slen--; return *(unsigned char const*)s++; +} +slen_t Filter::FlatD::vi_read(char *to_buf, slen_t max) { + if (max>slen) max=slen; + memcpy(to_buf, s, max); + s+=max; slen-=max; + return max; +} + +/* --- */ + + +#if HAVE_lstat_in_sys_stat +# define PTS_lstat lstat +#else +# define PTS_lstat stat +#endif + +/** @param fname must start with '/' (dir separator) + * @return true if file successfully created + */ +FILE *Files::try_dir(SimBuffer::B &dir, SimBuffer::B const&fname, char const*s1, char const*s2, char const*open_mode) { + if (dir.isEmpty() && s1==(char const*)NULLP) return (FILE*)NULLP; + SimBuffer::B full(s1!=(char const*)NULLP?s1:dir(), + s1!=(char const*)NULLP?strlen(s1):dir.getLength(), + s2!=(char const*)NULLP?s2:"", + s2!=(char const*)NULLP?strlen(s2):0, fname(), fname.getLength()); + full.term0(); + struct stat st; + FILE *f; + /* Imp: avoid race conditions with other processes pretending to be us... */ + if (-1!=PTS_lstat(full(), &st) + || (0==(f=fopen(full(), open_mode))) + || ferror(f) + ) return (FILE*)NULLP; + dir=full; + return f; +} + +#if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT +# define DIR_SEP "\\" +#else +# define DIR_SEP "/" +#endif + +FILE *Files::open_tmpnam(SimBuffer::B &dir, char const*open_mode, char const*extension) { + /* Imp: verify / on Win32... */ + /* Imp: ensure uniqueness on NFS */ + /* Imp: short file names */ + static unsigned PTS_INT32_T counter=0; + assert(Error::tmpargv0!=(char const*)NULLP); + SimBuffer::B fname(DIR_SEP "tmp_", 5, Error::tmpargv0,strlen(Error::tmpargv0)); + /* ^^^ Dat: we need DIR_SEP here, because the name of the tmp file may be + * passed to Win32 COMMAND.COM, which interprets "/" as a switch + */ + long pid=getpid(); + if (pid<0 && pid>-(1<<24)) pid=-pid; + fname << '_' << pid << '_' << counter++; + if (extension) fname << extension; + fname.term0(); + FILE *f=(FILE*)NULLP; + // char const* open_mode=binary_p ? "wb" : "w"; /* Dat: "bw" is bad */ + (void)( ((FILE*)NULLP!=(f=try_dir(dir, fname, 0, 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, PTS_CFG_P_TMPDIR, 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("TMPDIR"), 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("TMP"), 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("TEMP"), 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "/tmp", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("WINBOOTDIR"), "//temp", open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("WINDIR"), "//temp", open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/temp", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/windows/temp", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/winnt/temp", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/tmp", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, ".", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "..", 0, open_mode))) || + ((FILE*)NULLP!=(f=try_dir(dir, fname, "../..", 0, open_mode))) ); + return f; +} + +bool Files::find_tmpnam(SimBuffer::B &dir) { + FILE *f=open_tmpnam(dir); + if (f!=NULL) { fclose(f); return true; } + return false; +} + +bool Files::tmpRemove=true; + +static int cleanup_remove(Error::Cleanup *cleanup) { + if (Files::tmpRemove) return Files::removeIf(cleanup->getBuf()); + Error::sev(Error::WARNING) << "keeping tmp file: " << cleanup->getBuf() << (Error*)0; + return 0; +} + +void Files::tmpRemoveCleanup(char const* filename) { + Error::newCleanup(cleanup_remove, 0, filename); +} + +static int cleanup_remove_cond(Error::Cleanup *cleanup) { + if (*(FILE**)cleanup->data!=NULLP) { + fclose(*(FILE**)cleanup->data); + if (Files::tmpRemove) return Files::removeIf(cleanup->getBuf()); + Error::sev(Error::WARNING) << "keeping tmp2 file: " << cleanup->getBuf() << (Error*)0; + } + return 0; +} + +void Files::tmpRemoveCleanup(char const* filename, FILE**p) { + param_assert(p!=NULLP); + Error::newCleanup(cleanup_remove_cond, (void*)p, filename); +} + +int Files::removeIf(char const* filename) { + if (0==remove(filename) || errno==ENOENT) return 0; + return 1; +} + +slen_t Files::statSize(char const* filename) { + struct stat st; + if (-1==PTS_lstat(filename, &st)) return (slen_t)-1; + return st.st_size; +} + +/* Tue Jul 2 10:57:21 CEST 2002 */ +char const* Files::only_fext(char const*filename) { + char const *ret; + if (OS_COTY==COTY_WINNT || OS_COTY==COTY_WIN9X) { + if ((USGE('z'-'a',filename[0]-'a') || USGE('Z'-'A',filename[0]-'A')) + && filename[1]==':' + ) filename+=2; /* strip drive letter */ + ret=filename; + while (*filename!='\0') { + if (*filename=='/' || *filename=='\\') ret=++filename; + else filename++; + } + } else { /* Everything else is treated as UNIX */ + ret=filename; + while (filename[0]!='\0') if (*filename++=='/') ret=filename; + } + return ret; +} + +#if HAVE_DOS_BINARY +void Files::set_binary_mode(int fd, bool binary) { + /* Wed Dec 11 18:17:30 CET 2002 */ + setmode(fd, binary ? O_BINARY : O_TEXT); +} +#endif + +int Files::system3(char const *commands) { + #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT + char const *p; + p=commands; while (*p!='\0' && *p!='\n') p++; + if (*p=='\0') return system(commands); /* no newline -- simple run */ + SimBuffer::B tmpnam; + FILE *f=Files::open_tmpnam(tmpnam, /*binary_p:*/false, ".bat"); + tmpnam.term0(); + Files::tmpRemoveCleanup(tmpnam()); + fprintf(f, "@echo off\n%s\n", commands); + if (ferror(f)) Error::sev(Error::EERROR) << "system3: write to tmp .bat file: " << tmpnam << (Error*)NULLP; + fclose(f); + // printf("(%s)\n", tmpnam()); system("bash"); + // int ret=system(("sh "+tmpnam)()); + int ret=system(tmpnam()); + remove(tmpnam()); + return ret; + #else + return system(commands); + #endif +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/gensio.hpp b/Build/source/utils/sam2p/gensio.hpp new file mode 100644 index 00000000000..5b80d18dd60 --- /dev/null +++ b/Build/source/utils/sam2p/gensio.hpp @@ -0,0 +1,397 @@ +/* gensio.hpp -- generic char buffer and I/O facilities + * by pts@fazekas.hu at Tue Feb 26 13:30:02 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef GENSIO_HPP +#define GENSIO_HPP 1 + +#include "config2.h" +#include <stdarg.h> /* va_list */ +#include "gensi.hpp" +#include <stdio.h> + +/* Naming conventions: *Encode is a specific, well-known PostScript or PDF + * encoding filter documented by Adobe, *Encoder is something more general. + */ + +/** Writing 0 bytes for vi_write is interpreted as a close() operation. + * Constructor must not write anything to the underlying (lower-level) + * Encoder. Implementors must redefine vi_write(). Encoders may be stacked + * atop of each other. + */ +class Encoder: public GenBuffer::Writable { public: + /** Default: calls vi_write. */ + virtual void vi_putcc(char c); + /** vi_write() must be called with positive slen_t for normal writing, and + * vi_write(?,0); must be called to signal EOF. After that, it is prohibited + * to call vi_write() either way. + */ + virtual void vi_write(char const*buf, slen_t len) =0; + /** Copies all data (till EOF) from stream `f' to (this). */ + static void writeFrom(GenBuffer::Writable& out, FILE *f); + /** Copies all data (till EOF) from stream `f' to (this). */ + static void writeFrom(GenBuffer::Writable& out, GenBuffer::Readable &in); +}; /* class Encoder */ + +/** Implementors must redefine vi_read(), and they may redefine vi_getcc(). + * A .vi_read(?,0) has special meaning in a Decoder (but not in a normal + * Readable). + */ +class Decoder: public GenBuffer::Readable { public: + /** Calls vi_read(&ret,1). Note that this is the inverse of + * GenBuffer::Readable, because there vi_read() calls vi_getcc(). Decoders + * may be stacked atop of each other. + */ + virtual int vi_getcc(); + /** vi_read() must be called with positive slen_t for normal reading, and + * vi_read(?,0); must be called to signal that the caller would not read from + * the Decoder again, so the decoder is allowed to release the resources + * used. After that, it is prohibited to call vi_read() either way. + */ + virtual slen_t vi_read(char *to_buf, slen_t max) =0; +}; /* class Decoder */ + +class DecoderTeller: public Decoder { public: + /** Equivalent of ftell() */ + virtual long vi_tell() const=0; +}; + +class Filter { public: + /** Starts a child process (with popen(pipe_tmpl,"wb")), pipes data to it, + * writes output to a temporary file. After _everything_ is written, the + * temporary file is read and fed to out_. + */ + class PipeE: public Encoder { + public: + PipeE(GenBuffer::Writable &out_, char const*pipe_tmpl, slendiff_t i=0); + virtual ~PipeE(); + virtual void vi_write(char const*buf, slen_t len); + protected: + FILE *p; + SimBuffer::B tmpname; + GenBuffer::Writable &out; + SimBuffer::B tmpename, redir_cmd; + /** Temporary source file name `%S', forces system() instead of popen() */ + SimBuffer::B tmpsname; + /** vi_check() is called by this->vi_write(...) (and also when Broken Pipe) + * to check whether the encoding succeeded. vi_check() should raise an Error + * if it detects failure or simply return if it detects success. Default + * implementation: empty body which simly returns. + */ + virtual void vi_check(); + protected: + /** Copies the rest of (seekable) file `f' to `out' (subsequent filters). + * `f' is initially positioned at the beginning. Must call fclose(). + * vi_copy() should raise Error::...s. The default implementation + * just copies the data bytes verbatim. `out.vi_write(0,0);' will be called + * by vi_write(). + */ + virtual void vi_copy(FILE *f); + }; + + /** Gobbles all data written to it, just like /dev/null */ + class NullE: public Encoder { + inline virtual void vi_putcc(char) {} + inline virtual void vi_write(char const*, slen_t) {} + }; + + class VerbatimE: public Encoder { + public: + inline VerbatimE(GenBuffer::Writable& out_): out(&out_) {} + inline virtual void vi_write(char const*buf, slen_t len) { out->vi_write(buf,len); } + inline void setOut(GenBuffer::Writable& out_) { out=&out_; } + inline GenBuffer::Writable& getOut() const { return *out; } + protected: + GenBuffer::Writable* out; + }; + + class VerbatimCountE: public Encoder { + public: + inline VerbatimCountE(GenBuffer::Writable& out_): out(&out_), count(0) {} + inline virtual void vi_write(char const*buf, slen_t len) { out->vi_write(buf,len); count+=len; } + inline void setOut(GenBuffer::Writable& out_) { out=&out_; } + inline GenBuffer::Writable& getOut() const { return *out; } + inline slen_t getCount() const { return count; } + protected: + GenBuffer::Writable* out; + /** Number of bytes already written */ + slen_t count; + }; + + class FILEE: public Encoder { + public: + inline FILEE(FILE *f_,bool closep_): f(f_), closep(closep_) {} + FILEE(char const* filename); + inline virtual void vi_putcc(char c) { MACRO_PUTC(c,f); } + virtual void vi_write(char const*buf, slen_t len); + void close(); + protected: + FILE *f; + bool closep; + }; + + class PipeD: public Decoder { public: + PipeD(GenBuffer::Readable &in_, char const*pipe_tmpl, slendiff_t i=0); + virtual ~PipeD(); + /** Equivalent to vi_read(&ret,1). */ + virtual int vi_getcc(); + /** Upon the first non-zero call, opens `p', calls vi_precopy() and + * closes `in'. Upon all non-zero calls, + * reads the temporary file with fread(). Upon vi_read(?,0), removes the + * the temporary files. + */ + virtual slen_t vi_read(char *to_buf, slen_t max); + protected: + /** 0: never-read (initial state), 1: vi_precopy() already called, 2: EOF reached, `in' closed */ + int state; + /** opened with popen(?,"w") in state:0->1, then with fopen(?,"rb") in state==1 */ + FILE *p; + /** Temporary destination file name `%D' */ + SimBuffer::B tmpname; + GenBuffer::Readable ∈ + SimBuffer::B tmpename, redir_cmd; + /** Temporary source file name `%S', forces system() instead of popen() */ + SimBuffer::B tmpsname; + + /** Copies the whole `in' to writable pipe `p'. `p' will be closed by the + * caller; in.read(0,0) will be called by the caller. + * vi_precopy() should raise Error::...s. The default implementation + * just copies the data bytes verbatim. + */ + virtual void vi_precopy(); + /** vi_check() is called by this->vi_write(...) (and also when Broken Pipe) + * to check whether the encoding succeeded. vi_check() should raise an Error + * if it detects failure or simply return if it detects success. Default + * implementation: empty body which simly returns. + */ + virtual void vi_check(); + private: + void do_close(); + }; + + class VerbatimD: public Decoder { + public: + inline VerbatimD(GenBuffer::Readable& in_): in(in_) {} + /** Works fine even if len==0. */ + inline virtual slen_t vi_read(char *buf, slen_t len) { return in.vi_read(buf,len); } + protected: + GenBuffer::Readable& in; + }; + + class FILED: public DecoderTeller { + public: + inline FILED(FILE *f_,bool closep_): f(f_), closep(closep_) {} + FILED(char const* filename); + inline virtual ~FILED() { close(); } + inline virtual int vi_getcc() { return MACRO_GETC(f); } + virtual slen_t vi_read(char *buf, slen_t len); + void close(); + inline virtual long vi_tell() const { return ftell(f); } + protected: + FILE *f; + bool closep; + }; + + /** + * Sat Apr 19 12:05:49 CEST 2003 + * Always opens the file in binary mode. + * First reads from the unget buffer, then reads from a FILE*. A typical + * usage is: + * { Filter::UngetFILED f("in.txt"); // fopen("in.txt","rb"), true); + * f.getUnget() << "Prepend this in front of first line.\n"; + * int c; + * while ((c=f.vi_getcc()!=-1)) putchar(c); + * } + */ + class UngetFILED: public DecoderTeller { + public: + GenBuffer::Writable& getUnget() { return unget; } + BEGIN_STATIC_ENUM(unsigned char, closeMode_t) + CM_closep=1, + CM_unlinkp=2, + CM_keep_stdinp=4, /* CM_unlinkp, but keep STDIN open */ + CM_seekablep=8, /* it is sure that this->f is seekable */ + CM_MAX=4 + END_STATIC_ENUM() + inline UngetFILED(FILE *f_, closeMode_t closep_): f(f_), closeMode(closep_), ftell_at(0), ofs(0) {} + UngetFILED(char const* filename_, FILE* stdin_f=(FILE*)NULLP, closeMode_t closeMode_=CM_closep); + inline virtual ~UngetFILED() { close(); } + virtual int vi_getcc(); + virtual slen_t vi_read(char *buf, slen_t len); + /** Appends a line to buf, including delimiter unless EOF. + * @param delimiter: a char or negative to read to EOF + */ + void appendLine(GenBuffer::Writable &buf, int delimiter='\n'); + void close(); + // void checkFILE(); + inline virtual long vi_tell() const { return ftell_at; } // return ftell_add+ofs+(f!=NULLP ? ftell(f) : 0); } + /** + * @return equivalent to getc(f) if this->f is not seekable, but returns + * -2 if this->f is seekable. + */ + int getc_seekable(); + /** + * Actively tests whether FILE* is seekable. Doesn't work for regular files + * of 0 bytes. + */ + bool isSeekable(); + /** Reading (this) and reading the returned FILE* will be equivalent + * (unless this->getUnget() is used later). + * Creates a temporary file if this->unget is not empty. + * @param seekable_p if true, the returned FILE* must be seekable. Possibly + * creates a temporary file. + */ + FILE* getFILE(bool seekable_p); + /** Implies a getFILE() */ + void seek(long abs_ofs); + /** Tries to do an fseek(f, -slen, SEEK_CUR). On failure, appends to unget. + * The user should only unread() data obtained from vi_read(). + */ + void unread(char const *s, slen_t slen); + inline char const* getFilename() const { return filename; } + inline char const* getFilenameDefault(char const *def) const { return filename==NULLP ? def : filename; } + inline bool hadError() const { return f!=NULLP && ferror(f); } + protected: + FILE *f; + unsigned char closeMode; + slen_t ftell_at; + slen_t ofs; + SimBuffer::B unget; + char const* filename; + }; + + /** Reads from a memory of a GenBuffer via first_sub and next_sub. The + * GenBuffer should not be changed during the read. The GenBuffer isn't + * delete()d by (this) + */ + class BufR: public GenBuffer::Readable { + public: + BufR(GenBuffer const& buf_); + virtual int vi_getcc(); + virtual slen_t vi_read(char *to_buf, slen_t max); + virtual void vi_rewind(); + protected: + GenBuffer const* bufp; + GenBuffer::Sub sub; + }; + + /** Reads from a consecutive memory area, which won't be + * delete()d by (this) + */ + class FlatD: public DecoderTeller /*GenBuffer::Readable*/ { + public: + FlatD(char const* s_, slen_t slen_); + FlatD(char const* s_); + virtual int vi_getcc(); + virtual slen_t vi_read(char *to_buf, slen_t max); + virtual void vi_rewind(); + inline int getcc() { return slen!=0 ? (slen--, *(unsigned char const*)s++) : -1; } + inline virtual long vi_tell() const { return s-sbeg; } + inline long tell() const { return s-sbeg; } + protected: + char const *s, *sbeg; + slen_t slen; + }; +}; /* class Filter */ + +class Files { + public: + /** Formerly `class WritableFILE' */ + class FILEW: public GenBuffer::Writable { + public: + inline FILEW(FILE *f_): f(f_) {} + inline virtual void vi_putcc(char c) { MACRO_PUTC(c,f); } + inline virtual void vi_write(char const*buf, slen_t len) { fwrite(buf, 1, len, f); } + virtual GenBuffer::Writable& vformat(slen_t n, char const *fmt, va_list ap); + /** appends; uses SimBuffer::B as temp */ + virtual GenBuffer::Writable& vformat(char const *fmt, va_list ap); + inline void close() { fclose(f); } + inline void setF(FILE *f_) { f=f_; } + private: + FILE *f; + }; + + /** Formerly `class ReadableFILE'. Doesn't close the its FILE* automatically. */ + class FILER: public GenBuffer::Readable { + public: + inline FILER(FILE *f_): f(f_) {} + inline virtual int vi_getcc() { return MACRO_GETC(f); } + inline virtual slen_t vi_read(char *to_buf, slen_t max) { return fread(to_buf, 1, max, f); } + inline void close() { fclose(f); } + inline virtual void vi_rewind() { rewind(f); } + private: + FILE *f; + }; + + /** @return the beginning of the last substring in param filename that does + * not contain '/' (dir separator) + */ + static char const* only_fext(char const*filename); + + /** true iff temporary files should be removed at program finish end */ + static bool tmpRemove; + /** @param fname must start with '/' (dir separator) + * @return true if file successfully created + */ + static FILE *try_dir(SimBuffer::B &dir, SimBuffer::B const&fname, char const*s1, char const*s2, char const*open_mode="wb"); + /* The file will be opened for writing only. It won't be registered for + * for automatic removal. + * @param dir `dir' is empty: appends a unique filename for a temporary + * file. Otherwise: returns a unique filename in the specified directory. + * Creates the new file with 0 size. + * @param extension NULLP or a string specifying the extension of the file + * to create (should beginn with ".") + * @param open_mode "w", "wb" or "wb+" + * @return FILE* opened for writing for success, NULLP on failure + * --return true on success, false on failure + */ + static FILE *open_tmpnam(SimBuffer::B &dir, char const*open_mode="wb", char const*extension=(char const*)NULLP); + // static FILE *open_tmpnam(SimBuffer::B &dir, bool binary_p=true, char const*extension=(char const*)NULLP); + static bool find_tmpnam(SimBuffer::B &dir); + /** Calls lstat(). + * @return (slen_t)-1 on error, the size otherwise + */ + static slen_t statSize(char const* filename); + /** Ensures that file will be removed (if possible...) when the process + * terminates. Copies the string filename. + */ + static void tmpRemoveCleanup(char const* filename); + /** Ensures that file will be removed (if possible...) when the process + * terminates. Copies the string filename. The file will be removed iff + * (*p!=NULLP) when the cleanup handler runs. The cleanup handler fclose()s + * the file before removing it. + */ + static void tmpRemoveCleanup(char const* filename, FILE**p); + /** Removes the file/entity if exists. + * @return 0 on success (file hadn't existed, a directory component + * hadn't existed, or the file has been successfully removed), + * 1 otherwise + */ + static int removeIf(char const *filename); + + /** Sat Sep 7 20:58:54 CEST 2002 */ + static void doSignalCleanup(); + + /** Set the specified file descriptor to binary mode. Useful for stdin (0), + * stdout (1), stderr (2) on Win32 and DOS systems. On these systems, this + * call has the effect of `fopen(..., "rb");' On UNIX, file + * descriptors are always binary. + */ + #if HAVE_DOS_BINARY + static void set_binary_mode(int fd, bool binary); + #else + static inline void set_binary_mode(int,bool) {} + #endif + + /** Like the system(3) call, but it is able to run a string containing + * multiple lines of commands. On Win32, it creates a batch file if + * necessary. + */ + static int system3(char const *commands); +}; + +#endif diff --git a/Build/source/utils/sam2p/helpere.hpp b/Build/source/utils/sam2p/helpere.hpp new file mode 100644 index 00000000000..5687cfba2b6 --- /dev/null +++ b/Build/source/utils/sam2p/helpere.hpp @@ -0,0 +1,37 @@ +/* + * helpere.hpp -- help encoding images + * by pts@fazekas.hu at Tue Dec 9 10:53:21 CET 2003 + */ + +/* Don't use this here, because we don't have helpere.cpp +#ifdef __GNUC__ +#pragma interface +#endif +*/ + +#ifndef HELPERE_HPP +#define HELPERE_HPP 1 + +#include "image.hpp" +#include "error.hpp" +#include "gensio.hpp" + +/** Ugly multiple inheritance. !! unify with PNG, TIFF etc. */ +class HelperE: public Filter::NullE, public Filter::PipeE { + public: + inline HelperE(char const*filter_cmd, char const*mainfn=NULL): Filter::NullE(), Filter::PipeE(*(Filter::NullE*)this, filter_cmd, (slendiff_t)mainfn) { + /* ^^^ (slendiff_t) is unsafe cast */ + // GenBuffer::Writable &out_, char *pipe_tmpl, slendiff_t i=0) + } + inline virtual void vi_copy(FILE *f) { + // img=Image::load("-", SimBuffer::B(), (Image::filep_t)f, (char const*)"PNM"); + /* fclose(f); */ + Filter::UngetFILED ufd((char const*)NULLP, f, Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp); + img=Image::load((Image::Loader::UFD*)&ufd, SimBuffer::B(), (char const*)"PNM"); + } + inline Image::Sampled *getImg() const { return img; } + protected: + Image::Sampled *img; +}; + +#endif diff --git a/Build/source/utils/sam2p/hq.pl b/Build/source/utils/sam2p/hq.pl new file mode 100755 index 00000000000..61728ed0bba --- /dev/null +++ b/Build/source/utils/sam2p/hq.pl @@ -0,0 +1,33 @@ +#! /bin/sh -- +eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \ +;exec perl -x -S -- "$0" ${1+"$@"};#'if 0; +eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q +#!perl -w ++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0; +# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header + +# +# hq.pl -- convert binary STDIN to C language "quoted\\-string" +# by pts@fazekas.hu at Tue Dec 3 17:46:52 CET 2002 +# +# VC6.0 imposes the following restrictions: +# -- the number of (destination) characters inside a single "..." block may +# not exceed 2048 +# -- the number of "..." blocks may not exceed 999 if the /Zm999 compiler +# option is specified; this number should be minimized +# -- "\12319" causes a stupid warning, should be emitted as: "\123\51\61" +# -- output lines should not be too long (I limit them to 79 chars) +# + +my @numenc=('\60','\61','\62','\63','\64','\65','\66','\67','\70','\71'); +my @enc; +for (my $I=0;$I<256;$I++) { $enc[$I]=sprintf"\\%03o",$I } + +binmode STDIN if @ARGV; +binmode STDOUT; # UNIX NL in output +while (0<read STDIN, $_, 2040) { + s/([^\w\.\/\- ])(\d*)/$enc[ord$1].join("",@numenc[split"",$2])/ge; + s/(.{74}[^\\]{0,3})/$1\\\n/gs; + # ^^^ Dat: [^\\]{0,3} is for ensuring not breaking a \\ + print "\"$_\"\n"; +} diff --git a/Build/source/utils/sam2p/image.cpp b/Build/source/utils/sam2p/image.cpp new file mode 100644 index 00000000000..83e1c7f85f9 --- /dev/null +++ b/Build/source/utils/sam2p/image.cpp @@ -0,0 +1,1763 @@ +/* + * image.cpp (formerly sampled.cpp) + * by pts@fazekas.hu at Wed Feb 27 09:26:05 CET 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" +#include "error.hpp" +#include <string.h> /* strlen() */ +#include "gensio.hpp" + +/* --- 4-byte hashing */ + +#if SIZEOF_INT>=4 +typedef unsigned int u32_t; +typedef signed int s32_t; +#else +typedef unsigned long u32_t; +typedef signed long s32_t; +#endif + +/* vvv Dat: moved these out of Hash46 to pacify VC6.0 */ + const unsigned M=1409; + /** Number of _value_ data bytes (they are not hashed) */ + const unsigned D=2; + /** Size of each tuple in the array `t' */ + const unsigned HD=4+D; + /** A tuple is considered free iff its first byte equals FREE */ + const unsigned char FREE=255; + + +/** + * M=1409 + * h(K)=K%1409 + * h(i,K)=-i*(1+(K%1408)) (i in 0..1408) + * K=[a,r,g,b]=(a<<24)+(r<<16)+(g<<8)+b (4 bytes) + * h(K)=(253*a+722*r+(g<<8)+b)%1409 + * h(i,K)=-i*(1+(896*a+768*r+(g<<8)+b)%1408) + * + * -- No dynamic growing or re-hashing. Useful for hashing colormap palettes + * with a maximum size of 256. + * -- Deleting not supported. + * + * Implementation: Use 32 bit integers for calculation. + * + * Imp: remove unused attr `size' + */ +class Hash46 { + public: + /** Creates an empty hash. */ + Hash46(); + inline unsigned getSize() const { return size; } + inline unsigned getLength() const { return size; } + inline unsigned getMaxSize() const { return M; } + inline bool isFull() const { return size==M; } + /** @return NULLP or the pointer to a tuple */ + inline unsigned char* lookup(unsigned char k[4]) { + unsigned char *ret=walk(k); + return ret==NULLP || *ret==FREE ? (unsigned char*)NULLP : ret; + } + /** Can be called only if !isFull() + * @return NULL if isFull() and not found; otherwise: pointer to the tuple + * found or the place to which the insert can take place. + */ + unsigned char* walk(unsigned char k[4]); + protected: + /** Number of non-free tuples in the hash. */ + unsigned size; + unsigned char t[M*HD]; +}; + +Hash46::Hash46(): size(0) { + memset(t, FREE, sizeof(t)); +} + +unsigned char *Hash46::walk(unsigned char k[4]) { + u32_t hk, hik; + hk=HD*(((((u32_t)1<<24)%M)*k[0]+(((u32_t)1<<16)%M)*k[1]+ + (((u32_t)1<< 8)%M)*k[2]+k[3])%M); + hik=HD*(1+((((u32_t)1<<24)%(M-1))*k[0]+(((u32_t)1<<16)%(M-1))*k[1]+ + (((u32_t)1<< 8)%(M-1))*k[2]+k[3])%(M-1)); + /* fprintf(stderr, "hk=%u hik=%u\n", hk, hik); */ + register unsigned char *p=t+hk; + unsigned i=M; + /* fprintf(stderr, "?? %02x %02x %02x %02x\n", k[0], k[1], k[2], k[3]); */ + do { + /* fprintf(stderr, "examining %02x %02x %02x %02x %d\n", p[0], p[1], p[2], p[3], (k[0]=p[0] && k[1]==p[1] && k[2]==p[2])); */ + if (*p==FREE || (k[0]==p[0] && k[1]==p[1] && k[2]==p[2] && k[3]==p[3])) return p; + /* ^^^ huge == BUGFIX at Sun Apr 14 00:16:59 CEST 2002 */ + if (hk>=hik) { hk-=hik; p-=hik; } + else { hk+=M*HD-hik; p+=M*HD-hik; } + } while (--i!=0); + /* fprintf(stderr, "full\n"); */ + return (unsigned char*)NULLP; +} + +/* --- */ + +const unsigned char Image::Sampled::cs2cpp[6]= { 0, 1, 3, 3, 4, 4 }; +char const *Image::Sampled::cs2devcs(unsigned char cs) { + static const char *names[]={ (char*)NULLP, "Gray", "RGB", "RGB", "CMYK", "CMYK" }; + return cs>=1 && cs<=5 ? names[cs] : (char*)NULLP; +} + + +void Image::Sampled::init(slen_t l_comment, slen_t l_header, dimen_t wd_, dimen_t ht_, + /* ^^^ 24 is required for /Transparent in out_tiff_work */ + unsigned char bpc_, unsigned char ty_, unsigned char cpp_) { + static const slen_t PADDING=24; + bpc=bpc_; + ty=ty_; + wd=wd_; + ht=ht_; + cpp=cpp_; + // pred=1; + transpc=0x1000000UL; /* Dat: this means: no transparent color */ + rlen=(((rlen_t)bpc_)*cpp_*wd_+7)>>3; + beg=new char[len=l_comment+l_header+rlen*ht_+PADDING]; + rowbeg=(headp=const_cast<char*>(beg)+l_comment)+l_header; + trail=const_cast<char*>(beg)+len-bpc; +} + +Image::Gray* Image::Sampled::toGray0(unsigned char bpc_) { + unsigned char *crow=new unsigned char[wd*3+7*3], *p, *pend; + Image::Gray *img=new Image::Gray(wd, ht, bpc_); + unsigned char *outp=(unsigned char*)img->getRowbeg(); + dimen_t htc; + memset(crow+wd*3, '\0', 7*3); /* *3 BUGFIX at Tue Jan 18 17:04:15 CET 2005 */ + unsigned i; + /* Dat: not optimising for minimal rounding error since caller should ensure + * that there is no such error at all. + */ + if (bpc_==1) { + assert(img->getBpc()==1); + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow-3,pend=p+wd*3; p<pend; ) { + i =(*(p+=3)!=0)<<7; i|=(*(p+=3)!=0)<<6; i|=(*(p+=3)!=0)<<5; i|=(*(p+=3)!=0)<<4; + i|=(*(p+=3)!=0)<<3; i|=(*(p+=3)!=0)<<2; i|=(*(p+=3)!=0)<<1; i|=(*(p+=3)!=0); + *outp++=i; + } + } + } else if (bpc_==2) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow-3,pend=p+wd*3; p<pend; ) { + i =(*(p+=3)/85)<<6; i|=(*(p+=3)/85)<<4; i|=(*(p+=3)/85)<<2; i|=(*(p+=3)/85); + *outp++=i; + } + } + } else if (bpc_==4) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow-3,pend=p+wd*3; p<pend; ) { + i =(*(p+=3)/17)<<4; i|=(*(p+=3)/17); + *outp++=i; + } + } + } else if (bpc_==8) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow-3,pend=p+wd*3; p!=pend; ) { + *outp++=*(p+=3); + } + } + } else assert(0); + return img; +} +Image::RGB* Image::Sampled::toRGB0(unsigned char bpc_) { + unsigned char *crow=new unsigned char[wd*3+7], *p, *pend; + Image::RGB *img=new Image::RGB(wd, ht, bpc_); + unsigned char *outp=(unsigned char*)img->getRowbeg(); + dimen_t htc; + memset(crow+wd*3, '\0', 7); + unsigned i; + /* Dat: not optimising for minimal rounding error since caller should ensure + * that there is no such error at all. + */ + if (bpc_==1) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow,pend=crow+wd*3; p<pend; ) { + i =(*p++!=0)<<7; i|=(*p++!=0)<<6; i|=(*p++!=0)<<5; i|=(*p++!=0)<<4; + i|=(*p++!=0)<<3; i|=(*p++!=0)<<2; i|=(*p++!=0)<<1; i|=(*p++!=0); + *outp++=i; + } + } + } else if (bpc_==2) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow,pend=crow+wd*3; p<pend; ) { + i =(*p++/85)<<6; i|=(*p++/85)<<4; i|=(*p++/85)<<2; i|=(*p++/85); + *outp++=i; + } + } + } else if (bpc_==4) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow,pend=crow+wd*3; p<pend; ) { + i =(*p++/17)<<4; i|=(*p++/17); + *outp++=i; + } + } + } else if (bpc_==8) { + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)outp, htc); + outp+=wd*3; + } + } else assert(0); + return img; +} + +Image::Indexed* Image::Sampled::toIndexed0()/* const*/ { + unsigned char *crow=new unsigned char[wd*3], k[6], *p, *pend, *w; + Image::Indexed *img=new Image::Indexed(wd, ht, 256, 8); + dimen_t htc; + unsigned char *pal=(unsigned char*)img->getHeadp(), *outp=(unsigned char*)img->getRowbeg(); + unsigned ncols=0; + Hash46 h; + k[0]=0; + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow,pend=crow+wd*3; p!=pend; p+=3) { + memcpy(k+1, p, 3); + w=h.walk(k); + assert(w!=NULL); /* Hash cannot be full since h.M>=256. */ + /* fprintf(stderr, "w=%p\n", w); */ + if (*w==/*h.*/FREE) { + if (ncols==256) { delete img; delete [] crow; return (Image::Indexed*)NULLP; } + /* ^^^ too many colors; cannot convert image to indexed */ + memcpy(w,k,4); + memcpy(pal,k+1,3); + /* fprintf(stderr,"newcol=%02x #%02x%02x%02x\n", k[0], k[1], k[2], k[3]); */ + /* fprintf(stderr,"newcol=pal #%02x%02x%02x\n", pal[0], pal[1], pal[2]); */ + pal+=3; + *outp++=w[4]=ncols++; + } else { /* a color that we have already seen */ + *outp++=w[4]; + } + } + } + img->setNcolsMove(ncols); + delete [] crow; + + /* Now img is ready. The user should call packPal() to make it even tighter. */ + return img; +} + +void Image::Sampled::to8mul() { + if (bpc==8) return; + if (wd==0 || ht==0) { bpc=8; return; } + + unsigned oldBpc=bpc; + slen_t wdcpp=wd*cpp; + const char *oldBeg=beg; + unsigned char *p=(unsigned char*)rowbeg; + + bpc=8; + rlen=wd; + beg=new char[len=rowbeg-oldBeg+rlen*ht+bpc]; + headp= const_cast<char*>(beg)+(headp-oldBeg); + rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg); + trail= const_cast<char*>(beg)+len-bpc; + memcpy(const_cast<char*>(beg), oldBeg, rowbeg-beg); + + unsigned char *to=(unsigned char*)rowbeg, *toend; + unsigned int i, j; + Image::Sampled::dimen_t htc; + if (oldBpc==1) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp)&~7); + while (to!=toend) { + i=*p++; + *to++=(i>>7)*255; + *to++=((i>>6)&1)*255; + *to++=((i>>5)&1)*255; + *to++=((i>>4)&1)*255; + *to++=((i>>3)&1)*255; + *to++=((i>>2)&1)*255; + *to++=((i>>1)&1)*255; + *to++=( i&1)*255; + } + if (0!=(j=(wdcpp)&7)) { + i=*p; /* No mem overrun, even if (wd&7)==0 */ + while (j--!=0) { *to++=(i>>7)*255; i<<=1; } + } + } + } else if (oldBpc==2) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp)&~3); + while (to!=toend) { + i=*p++; + *to++=(i>>6)*85; + *to++=((i>>4)&3)*85; + *to++=((i>>2)&3)*85; + *to++=( i&3)*85; + } + if (0!=(j=(wdcpp)&3)) { + i=*p; /* No mem overrun, even if (wd&7)==0 */ + while (j--!=0) { *to++=(i>>6)*85; i<<=2; } + } + } + } else if (oldBpc==4) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp)&~1); + while (to!=toend) { + i=*p++; + *to++=(i>>4)*17; + *to++=( i&15)*17; + } + if (0!=((wdcpp)&1)) *to++=(*p++>>4)*17; + } + } else assert(0 && "invalid bpc"); + + delete [] const_cast<char*>(oldBeg); +} + +void Image::Sampled::to8nomul() { + if (bpc==8) return; + if (wd==0 || ht==0) { bpc=8; return; } + + unsigned oldBpc=bpc; + slen_t wdcpp=wd*cpp; + const char *oldBeg=beg; + unsigned char *p=(unsigned char*)rowbeg; + + bpc=8; + rlen=wd; + beg=new char[len=rowbeg-oldBeg+rlen*ht+bpc]; + headp= const_cast<char*>(beg)+(headp-oldBeg); + rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg); + trail= const_cast<char*>(beg)+len-bpc; + memcpy(const_cast<char*>(beg), oldBeg, rowbeg-beg); + + unsigned char *to=(unsigned char*)rowbeg, *toend; + unsigned int i, j; + Image::Sampled::dimen_t htc; + if (oldBpc==1) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp)&~7); + while (to!=toend) { + i=*p++; + *to++=(i>>7); + *to++=((i>>6)&1); + *to++=((i>>5)&1); + *to++=((i>>4)&1); + *to++=((i>>3)&1); + *to++=((i>>2)&1); + *to++=((i>>1)&1); + *to++=( i&1); + } + if (0!=(j=(wdcpp)&7)) { + i=*p++; /* No mem overrun, even if (wd&7)==0 */ + while (j--!=0) { *to++=(i>>7); i<<=1; } + } + } + } else if (oldBpc==2) { + // assert(0); + htc=ht; while (htc--!=0) { + toend=to+((wdcpp)&~3); + while (to!=toend) { + i=*p++; + *to++=(i>>6); + *to++=((i>>4)&3); + *to++=((i>>2)&3); + *to++=( i&3); + } + if (0!=(j=(wdcpp)&3)) { + i=*p++; + // fprintf(stderr,"j=%d\n",j); + while (j--!=0) { *to++=(i>>6); i<<=2; } + } + } + assert((slen_t)((char*)to-rowbeg)==(slen_t)wd*cpp*ht); + } else if (oldBpc==4) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp)&~1); + while (to!=toend) { + i=*p++; + *to++=(i>>4); + *to++=( i&15); + } + if (0!=((wdcpp)&1)) *to++=(*p++>>4); + } + } else assert(0 && "invalid bpc"); + + delete [] const_cast<char*>(oldBeg); +} + +unsigned char Image::Sampled::minRGBBpc() const { + unsigned char *crow=new unsigned char[wd*3], *p, *pend=crow+wd*3; + register unsigned minbpb=0; + dimen_t htc; + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow; p!=pend; p++) { + if ((*p&15)*17!=*p) { delete [] crow; return 8; } /* 4 bits are not enough */ + else if ((*p&3)*85!=*p) minbpb=3; /* 2 bits are not enough */ + else if ((*p&1)*255!=*p) minbpb|=1; /* 1 bit is not enough */ + } + } + delete [] crow; + return 1+minbpb; +} + +bool Image::Sampled::hasPixelRGB(Image::Sampled::rgb_t rgb) const { + /* by pts@fazekas.hu at Sat Jan 8 13:24:19 CET 2005 */ + /* Dat: this dumb implementation will be overridden */ + if (rgb>0xffffffUL) return false; + unsigned char *crow=new unsigned char[wd*3], *p, *pend=crow+wd*3, t[3]; + dimen_t htc; + t[0]=(rgb>>16)&255; t[1]=(rgb>>8)&255; t[2]=rgb&255; + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); + for (p=crow; p!=pend; p+=3) { + if (t[0]==p[0] && t[1]==p[1] && t[2]==p[2]) { delete [] crow; return true; } + } + } + delete [] crow; + return false; +} + +bool Image::Gray::hasPixelRGB(Image::Sampled::rgb_t rgb) const { + /* by pts@fazekas.hu at Sat Jan 8 13:24:19 CET 2005 */ + /* Dat: faster than Image::Sampled::hasPixelRGB */ + if (rgb>0xffffffUL) return false; + unsigned char t[3]; + t[0]=(rgb>>16)&255; t[1]=(rgb>>8)&255; t[2]=rgb&255; + if (t[0]!=t[1] || t[0]!=t[2]) return false; + if (bpc==8) { + unsigned char *p=(unsigned char*)rowbeg, *pend=p+wd*ht; + /* Imp: use memchr() if available */ + while (p!=pend && t[0]!=p[0]) p++; + return p!=pend; + } + unsigned char *crow=new unsigned char[wd*3], *p, *pend=crow+wd*3; + dimen_t htc; + for (htc=0;htc<ht;htc++) { + copyRGBRow((char*)crow, htc); /* Imp: avoid this if bpp==8 */ + p=crow; while (p!=pend && t[0]!=p[0]) p+=3; + if (p!=pend) { delete [] crow; return true; } + } + delete [] crow; + return false; +} + +Image::Indexed* Image::Sampled::addAlpha0(Image::Sampled *img, Image::Gray *al) { + Image::Indexed *iimg=(Image::Indexed*)img; + unsigned ncols=0; + if (img==NULLP) Error::sev(Error::EERROR) << "addAlpha: too many colors, transparency impossible" << (Error*)0; + iimg->to8(); + iimg->packPal(); + if ((ncols=iimg->getNcols())==256) Error::sev(Error::EERROR) << "addAlpha: too many colors, transparency impossible" << (Error*)0; + iimg->setNcolsMove(ncols+1); + /* fprintf(stderr,"old ncols=%u\n", ncols); */ + iimg->setPal(ncols,0); /* black */ + iimg->setTransp(ncols); + assert(iimg->getRlen()==iimg->getWd()); + assert(iimg->getWd()==al->getWd()); + char *p=iimg->getRowbeg(), *pend=p+iimg->getRlen()*iimg->getHt(), *alq=al->getRowbeg(); + while (p!=pend) { + if ((unsigned char)*alq++!=255) *p=ncols; /* make it transparent */ + p++; + } + return iimg; +} + +/* --- */ + +Image::Indexed::Indexed(Image::Sampled::dimen_t wd_, Image::Sampled::dimen_t ht_, unsigned short ncols_, unsigned char bpc_) { + param_assert(ncols_<=256); + /* vvv Dat: `3' is here for an extra palette entry */ + init(3,3*ncols_,wd_,ht_,bpc_,TY_INDEXED,1); + transp=-1; + cs=CS_Indexed_RGB; +} +void Image::Indexed::setNcols(unsigned short ncols_) { + headp=rowbeg-ncols_*3; +} +void Image::Indexed::setNcolsMove(unsigned short ncols_) { + param_assert(ncols_<=256); + unsigned ncols=getNcols(); + if (ncols_==ncols) return; + if (ncols_<ncols || (slen_t)(headp-beg)>=(ncols_-ncols)*3) { + memmove(rowbeg-ncols_*3, headp, ncols_*3); + /* ^^^ *3 BUGFIX at Sun Apr 14 00:50:34 CEST 2002 */ + } else { /* Imp: test this routine */ + /* Tue Jun 11 16:22:52 CEST 2002 */ + assert(ncols_>ncols); + const char *oldBeg=beg, *oldHeadp=headp, *oldRowbeg=rowbeg, *oldEnd=beg+len; + slen_t delta=(ncols_-ncols)*3; + // substr_grow(headp-oldBeg, ncols*3, ncols_*3); /* no such method */ + beg=new char[len+delta]; + headp= const_cast<char*>(beg)+(headp-oldBeg); + rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg)+delta; + trail= const_cast<char*>(beg)+(trail-oldBeg)+delta; + assert(beg+(headp-oldBeg)==rowbeg-ncols_*3); + /* Dat: this->xoffs is left unchanged */ + memcpy(headp, oldHeadp, oldRowbeg-oldHeadp); + memcpy(rowbeg, oldRowbeg, oldEnd-oldRowbeg); + delete [] const_cast<char*>(oldBeg); + } + headp=rowbeg-ncols_*3; +} +void Image::Indexed::setPal(unsigned char color, Image::Sampled::rgb_t rgb) { + assert(color<(rowbeg-headp)/3); + unsigned char *p=(unsigned char*)headp+3*color; + *p++=rgb>>16; + *p++=rgb>>8; + *p=rgb; +} +void Image::Indexed::setTransp(unsigned char color) { + // param_assert(color>=0); /* always */ + assert(transp==-1); + transp=color; + unsigned char *p=(unsigned char*)headp+3*color; + transpc=((Image::Sampled::rgb_t)p[0]<<16)+(p[1]<<8)+p[2]; +} +bool Image::Indexed::setTranspc(rgb_t color) { + char t[3]; + /** vvv BUGFIX at Sat Jun 15 13:40:30 CEST 2002 */ + if (color==0x1000000UL) return transp!=-1; /* no effect */ + if (color==transpc) return transp!=-1; /* would not change */ + t[0]=color>>16; t[1]=color>>8; t[2]=color; + char *p=headp, *pend=rowbeg; + while (p!=pend) { /* Examine the palette. */ + if (p[0]==t[0] && p[1]==t[1] && p[2]==t[2]) { + transpc=color; + transp=(p-headp)/3; /* destroy old transparency */ + return true; + } + p+=3; + } + /* No transparency set this time. Maybe there is an old one; unchanged. */ + return transp!=-1; +} + +void Image::Indexed::to8() { to8nomul(); } +Image::Indexed* Image::Indexed::toIndexed()/* const*/ { return this; } +Image::RGB* Image::Indexed::toRGB(unsigned char bpc_)/* const*/ { return toRGB0(bpc_); } +Image::Gray* Image::Indexed::toGray(unsigned char bpc_)/* const*/ { return toGray0(bpc_); } +bool Image::Indexed::canGray() const { + char *p=headp, *pend=rowbeg, *tp=p+transp*3; + /* ignore transparent color at Sat Jun 15 15:18:24 CEST 2002 */ + if (transp!=-1 && tp!=pend-3) { + while (p!=pend) { /* Examine the palette. */ + if (p!=tp && (p[0]!=p[1] || p[1]!=p[2])) return false; /* Found a non-gray color. */ + p+=3; + } + } else { + if (transp!=-1 && tp==pend-3) pend-=3; /* both conditions are important */ + while (p!=pend) { /* Examine the palette. */ + if (p[0]!=p[1] || p[1]!=p[2]) return false; /* Found a non-gray color. */ + p+=3; + } + } + return true; +} +unsigned char Image::Indexed::minRGBBpc() const { + unsigned char *p=(unsigned char*)headp, *pend=(unsigned char*)rowbeg; + unsigned char *tp=p+transp*3; + /* ignore transparent color at Sat Jun 15 15:18:24 CEST 2002 */ + register unsigned minbpb=0; + while (p!=pend) { /* Examine the palette. */ + if (p==tp) { p+=3; continue; } /* ignore transparent color */ + if ((*p&15)*17!=*p) return 8; /* 4 bits are not enough */ + else if ((*p&3)*85!=*p) minbpb=3; /* 2 bits are not enough */ + else if ((*p&1)*255!=*p) minbpb|=1; /* 1 bit is not enough */ + p++; + } + return 1+minbpb; +} +void Image::Indexed::copyRGBRow(char *to, Image::Sampled::dimen_t whichrow) const { + param_assert(whichrow<ht); + if (wd==0) return; + unsigned char *p=(unsigned char*)rowbeg+rlen*whichrow; + char *r, *toend=to+3*wd; + unsigned int i, j; + + if (bpc==1) { + toend-=3*(wd&7); + while (to!=toend) { + i=*p++; + r=headp+3*(i>>7); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>6)&1); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>5)&1); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>4)&1); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>3)&1); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>2)&1); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>1)&1); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*( i&1); *to++=*r++; *to++=*r++; *to++=*r++; + } + i=*p; /* No mem overrun, even if (wd&7)==0 */ + j=wd&7; + while (j--!=0) { r=headp+3*(i>>7); *to++=*r++; *to++=*r++; *to++=*r++; i<<=1; } + } else if (bpc==2) { + toend-=3*(wd&3); + while (to!=toend) { + i=*p++; + r=headp+3*(i>>6); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>4)&3); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*((i>>2)&3); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*( i&3); *to++=*r++; *to++=*r++; *to++=*r++; + } + i=*p; /* No mem overrun, even if (wd&7)==0 */ + j=wd&3; + while (j--!=0) { r=headp+3*(i>>6); *to++=*r++; *to++=*r++; *to++=*r++; i<<=2; } + } else if (bpc==4) { + toend-=3*(wd&1); + while (to!=toend) { + i=*p++; + r=headp+3*(i>>4); *to++=*r++; *to++=*r++; *to++=*r++; + r=headp+3*( i&15); *to++=*r++; *to++=*r++; *to++=*r++; + } + if (0!=(wd&1)) { r=headp+3*(*p>>4); *to++=*r++; *to++=*r++; *to++=*r++; } + } else if (bpc==8) { + // fprintf(stderr, "p=%u pp=%u ppp=%u\n", p[0], p[1], p[2]); + while (to!=toend) { + r=headp+3**p++; *to++=*r++; *to++=*r++; *to++=*r++; + } + } else assert(0 && "invalid bpc"); +} +void Image::Indexed::packPal() { + /* Convert samples, make bpc=8. */ + to8(); + + unsigned oldNcols=getNcols(); + unsigned char *p, *pend; + assert((rowbeg-headp)%3==0); + assert(transp>=-1); + assert(transp<(int)oldNcols); + if (oldNcols<=1) return; /* Cannot optimize further. */ + + /* Find unused colors. old2new[c]=(is c used at least once)?1:0 */ + unsigned char old2new[256], newpal[768]; + memset(old2new, 0, sizeof(old2new)); + for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) old2new[*p]=1; + + /* Find and eliminate duplicate colors. Build the new palette in the + * beginning of newpal. Use a Hash46 for a quick lookup of colors already + * seen. Use the previously computed old2new, but also overwrite it. + */ + Hash46 h; + int newTransp=-1; + unsigned char *op=old2new, *opend=op+oldNcols, *w, k[6], + *ptransp=(unsigned char*)headp+3*transp; /* ==p-3 if no transparent color */ + /* ^^^ headp BUGFIX at Fri Mar 22 18:02:18 CET 2002 */ + p=(unsigned char*)headp; + // fprintf(stderr, "oldNcols=%d\n", (int)oldNcols); + unsigned newNcols=0; + while (op!=opend) { + // fprintf(stderr, "color=%d %d\n", (int)(op-old2new), p-ptransp); + if (0!=*op) { /* Map the color only if it is used in the image. */ + // fprintf(stderr, "used=%d\n", (int)(op-old2new)); + if (p==ptransp) { k[0]=1; k[1]=k[2]=k[3]=0; newTransp=newNcols; } + else { k[0]=0; memcpy(k+1,p,3); } + w=h.walk(k); + assert(w!=NULL); /* Hash cannot be full since h.M>=256. */ + if (*w==/*h.*/FREE) { + memcpy(newpal+3*newNcols, p /* k+1 */, 3); + /* ^^^ side effect: make the transparent color black */ + memcpy(w,k,4); w[4]=newNcols; *op=newNcols++; + } else *op=w[4]; + } + p+=3; op++; + } + // fprintf(stderr,"newTransp=%d transp=%d\n", newTransp, transp); + + // assert((newTransp==-1) == (transp==-1)); + assert(newTransp==-1 || transp!=-1); + /* ^^^ BUGFIX: not true, because image may have transparency, but no + * transparent pixels. + */ + assert((char*)p==headp+oldNcols*3); + if (newNcols==oldNcols && transp==newTransp) { + /* Could not change # colors. */ + if (transp==-1) return; + if ((unsigned)transp==oldNcols-1) { setPal(transp, 0); return; } + } + + /* Make the transparent color last. */ + if (newTransp!=-1 && newTransp!=(int)newNcols-1) { + assert(transp!=-1); + unsigned newLast=newNcols-1; + memcpy(newpal+3*newTransp, newpal+3*newLast, 3); + memset(newpal+3*newLast, 0, 3); transpc=0; /* make it black */ + for (op=old2new; op!=opend; op++) if (*op==newLast) *op=newTransp; + old2new[transp]=newLast; + transp=newTransp=newLast; + p=newpal+newTransp*3; + } + + /* Update the image. */ + for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) { + assert(*p<oldNcols); + *p=old2new[*p]; + } + + /* Update the palette. */ + headp=rowbeg-3*newNcols; + memcpy(headp, newpal, 3*newNcols); + transp=newTransp; + /* vvv BUGFIX at Tue May 21 13:10:30 CEST 2002 */ + if (newTransp==-1) transpc=0x1000000UL; /* Dat: this means: no transparent color */ + else { transp=-1; setTransp(newTransp); } +} +void Image::Indexed::delete_separated(register Indexed **p) { + while (*p!=NULLP) delete *p++; +} +Image::Indexed **Image::Indexed::separate() { + assert(getNcols()>=1); + unsigned char ncols1=getNcols()-1; + signed nncols=getNcols()-(transp==-1 ? 0 : 1); + register unsigned char curcol; + Indexed **ret=new Indexed*[nncols+1], **curimg=ret; + Image::Sampled::dimen_t htc; + assert(cpp==1); + slen_t wdcpp=wd/* *cpp*/; + register unsigned char *p; + char *to, *toend; + register unsigned int i; + + ret[nncols]=(Indexed*)NULLP; + to8(); + for (curcol=0; curcol<=ncols1; curcol++) { + if (transp==(signed int)curcol) continue; + curimg[0]=new Indexed(wd, ht, /*ncols:*/2, /*bpc:*/1); + memcpy(curimg[0]->headp, headp+3*curcol, 3); /* copy the color value */ + curimg[0]->setTransp(1); + to=curimg[0]->rowbeg; p=(unsigned char*)rowbeg; + htc=ht; while (htc--!=0) { + toend=to+((wdcpp+7)>>3); + while (to!=toend) { + i =(*p++!=curcol)<<7; i|=(*p++!=curcol)<<6; + i|=(*p++!=curcol)<<5; i|=(*p++!=curcol)<<4; + i|=(*p++!=curcol)<<3; i|=(*p++!=curcol)<<2; + i|=(*p++!=curcol)<<1; i|=(*p++!=curcol); + *to++=i; + } + if (0!=(wdcpp&7)) p+=(wdcpp&7)-8; /* negative */ + } + curimg++; + } + assert(curimg==ret+nncols); + return ret; +} + +Image::Indexed *Image::Indexed::calcAlpha() { + /* by pts@fazekas.hu at Tue Jun 4 21:27:29 CEST 2002 */ + assert(getNcols()>=1); + packPal(); /* removes transparency if no transparent pixel */ + if (transp==-1) return (Image::Indexed*)NULLP; + to8(); + Indexed *ret=new Indexed(wd, ht, /*ncols:*/2, /*bpc:*/1); + Image::Sampled::dimen_t htc; + assert(cpp==1); + slen_t wdcpp=wd/* *cpp*/; + register unsigned char *p; + char *to, *toend; + register unsigned int i, i8, i7; + unsigned char transpx=transp; + + ret->headp[0]=ret->headp[0]=ret->headp[0]='\xFF'; /* white */ + ret->headp[3]=ret->headp[4]=ret->headp[5]='\x00'; /* black, transparent */ + ret->setTransp(1); + to=ret->rowbeg; p=(unsigned char*)rowbeg; + assert(transpx!=0); + #if 0 + printf("tx=%u\n", transpx); + printf("%u %u %u\n", headp[0], headp[1], headp[2]); + #endif + htc=ht; while (htc--!=0) { + // putchar('.'); printf("mod=%d\n",(to-ret->rowbeg)%ret->rlen); + // assert((to-ret->rowbeg)%ret->rlen==0); + toend=to+(wdcpp>>3); /* ((wdcpp+7)>>3)-1; */ + /* ^^^ BUGFIX at Tue Sep 17 11:08:46 CEST 2002 */ + assert(toend>=to); + while (to!=toend) { + #if 1 /* add ->pal[0] funcitonality at Sat Jun 15 14:24:25 CEST 2002 */ + i=0; i8=256; + /* vvv p[-1]=0 BUGFIX at Sun Dec 8 23:21:47 CET 2002 */ + while ((i8>>=1)!=0) if (*p++==transpx) { p[-1]=0; i|=i8; } + #else + i =(*p++==transpx)<<7; i|=(*p++==transpx)<<6; + i|=(*p++==transpx)<<5; i|=(*p++==transpx)<<4; + i|=(*p++==transpx)<<3; i|=(*p++==transpx)<<2; + i|=(*p++==transpx)<<1; i|=(*p++==transpx); + #endif + *to++=i; + } + #if 1 /* This works even when p gets modified; this puts fixed 0 pads at EOLs */ + if ((wdcpp&7)!=0) { + i7=1<<(7-(wdcpp&7)); i8=256; i=0; + /* vvv p[-1]=0 BUGFIX at Sun Dec 8 23:21:47 CET 2002 */ + while ((i8>>=1)!=i7) if (*p++==transpx) { p[-1]=0; i|=i8; } + *to++=i; + } + #else + if (0!=(wdcpp&7)) p+=(wdcpp&7)-8; /* negative */ + #endif + } + assert(ret->rlen==((wd+7)>>3)); + /* printf("rlen=%d %d\n", ret->rlen, to-ret->rowbeg); */ + assert(to==ret->rowbeg+ht*ret->rlen); + return ret; +} + +void Image::Indexed::setBpc(unsigned char bpc_) { + unsigned ncols=getNcols(); + if (bpc_==0) { + if (ncols<=2) bpc_=1; + else if (ncols<=4) bpc_=2; + else if (ncols<=16) bpc_=4; + else bpc_=8; + } else { + if (bpc_==1) assert(ncols<=2); + else if (bpc_==2) assert(ncols<=4); + else if (bpc_==4) assert(ncols<=16); + else if (bpc_!=8) param_assert(0 && "invalid bpc_"); + } + // fprintf(stderr, "bpc: %u -> %u\n", bpc, bpc_); + if (bpc==bpc_) return; + to8(); /* Imp: make the transition without the intermediate 8-bits... */ + if (bpc_==8) return; + if (ht==0 || wd==0) { bpc=bpc_; return; } + + const char *oldBeg=beg; + unsigned char *p=(unsigned char*)rowbeg; + assert(cpp==1); + slen_t wdcpp=wd/* *cpp*/; + bpc=bpc_; + rlen=(((rlen_t)bpc_)*wd+7)>>3; + beg=new char[len=rowbeg-oldBeg+rlen*ht+bpc]; + headp= const_cast<char*>(beg)+(headp-oldBeg); + rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg); + trail= const_cast<char*>(beg)+len-bpc; + memcpy(const_cast<char*>(beg), oldBeg, rowbeg-beg); + + unsigned char *to=(unsigned char*)rowbeg, *toend; + unsigned int i; + Image::Sampled::dimen_t htc; + if (bpc_==1) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp+7)>>3); + while (to!=toend) { + i =*p++<<7; i|=*p++<<6; i|=*p++<<5; i|=*p++<<4; + i|=*p++<<3; i|=*p++<<2; i|=*p++<<1; i|=*p++; + *to++=i; + } + if (0!=(wdcpp&7)) p+=(wdcpp&7)-8; /* negative */ + } + } else if (bpc_==2) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp+3)>>2); + while (to!=toend) { + i =*p++<<6; i|=*p++<<4; i|=*p++<<2; i|=*p++; + *to++=i; + } + if (0!=(wdcpp&3)) p+=(wdcpp&3)-4; + } + } else if (bpc_==4) { + htc=ht; while (htc--!=0) { + toend=to+((wdcpp+1)>>1); + while (to!=toend) { + i =*p++<<4; i|=*p++; + *to++=i; + } + if (0!=(wdcpp&1)) p--; + } + } else assert(0 && "invalid bpc"); + delete [] const_cast<char*>(oldBeg); +} +Image::Sampled::rgb_t Image::Indexed::getPal(unsigned char color) const { + unsigned char *p=(unsigned char*)headp+3*color; + return ((Image::Sampled::rgb_t)p[0]<<16)+(p[1]<<8)+p[2]; +} + +void Image::Indexed::dumpDebug(GenBuffer::Writable& gw) { + gw <<"% ncols=" << getNcols() + << " rlen=" << rlen + << " ht=" << ht + << " wd=" << wd + << " cpp=" << (unsigned)cpp + << " bpc=" << (unsigned)bpc + << " transp=" << transp + << " transpc=" << (transp==-1?"none":rgb2webhash(getPal(transp))) + << " ty=" << (unsigned)ty + //<< " pred=" << (unsigned)pred + << '\n'; + unsigned char *p=(unsigned char*)headp; + while (p!=(unsigned char*)rowbeg) { + gw << rgb2webhash(((Image::Sampled::rgb_t)p[0]<<16)+(p[1]<<8)+p[2]) << '\n'; + p+=3; + } + gw << '\n'; + gw.vi_write(rowbeg,rlen*ht); +} + +Image::Sampled* Image::Indexed::addAlpha(Image::Gray *al) { + // Error::sev(Error::WARNING) << "Indexed: alpha channel ignored" << (Error*)0; return this; + if (al->getHt()!=ht || al->getWd()!=wd) Error::sev(Error::EERROR) << "addAlpha: image dimension mismatch" << (Error*)0; + bool ign_mid=false; + unsigned char lightest, darkest; + al->to8(); + al->calcExtrema(lightest, darkest); + if (darkest==255) return this; /* no transparent pixels at all */ + to8(); + if (transp>=0) { /* Already have a transparent index. Join. */ + register char *p=rowbeg; + register unsigned char transp_=transp; + char *pend=rowbeg+rlen*ht, *alq=al->getRowbeg(); + /* Imp: choose an image color instead of black... */ + /* Dat: 0..254: transparent, 255: opaque */ + while (p!=pend) { + if ((unsigned char)(*alq+1)>1) ign_mid=true; + /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */ + if ((unsigned char)*alq++!=255) p[0]=transp_; /* black out transparent-wannabe pixels */ + p++; + } + } else { /* No transparent color yet. */ + packPal(); + unsigned ncols=getNcols(); + char *p=rowbeg, *pend=rowbeg+rlen*ht, *alq=al->getRowbeg(); + /* Imp: choose an image color instead of black... */ + /* Dat: 0..254: transparent, 255: opaque */ + while (p!=pend) { + if ((unsigned char)(*alq+1)>1) ign_mid=true; + /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */ + if ((unsigned char)*alq++!=255) p[0]=ncols; /* may set to 0 if ncols==256 */ + p++; + } + if (ncols==256) { /* Try again, probably now we have less colors */ + packPal(); + if ((ncols=getNcols())==256) Error::sev(Error::EERROR) << "Indexed::addAlpha: too many colors, transparency impossible" << (Error*)0; + for (p=rowbeg,alq=al->getRowbeg(); p!=pend; p++) + if ((unsigned char)*alq++!=255) *p=ncols; + } + setNcolsMove(ncols+1); + setPal(ncols,0); /* black */ + setTransp(ncols); + } + if (ign_mid) Error::sev(Error::WARNING) << "addAlpha: half-transparent pixels made transparent" << (Error*)0; + return this; +} +void Image::Indexed::makeTranspZero() { + if (transp<1) return; /* no transparency or already 0 */ + unsigned char oldBpc=bpc; + register unsigned char transpch=transp; + /* Imp: make this faster by not converting to 8 bits */ + if (oldBpc!=8) to8(); + + /* Update the image. */ + register unsigned char *p; unsigned char *pend; + for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) { + if (*p==0) *p=transp; + else if (*p==transpch) *p=0; + } + rgb_t rzero=getPal(0), rtransp=getPal(transp); + setPal(transp, rzero); setPal(0, rtransp); + transp=0; + if (oldBpc!=8) setBpc(oldBpc); +} + +/* --- */ + +Image::Gray::Gray(Image::Sampled::dimen_t wd_, Image::Sampled::dimen_t ht_, unsigned char bpc_) { + init(0,0,wd_,ht_,bpc_,TY_GRAY,1); + cs=CS_GRAYSCALE; +} +void Image::Gray::to8() { to8mul(); } +Image::RGB * Image::Gray::toRGB(unsigned char bpc_)/* const*/ { return toRGB0(bpc_); } +Image::Gray* Image::Gray::toGray(unsigned char bpc_)/* const*/ { return bpc==bpc_ ? this : toGray0(bpc_); } +Image::Indexed* Image::Gray::toIndexed()/* const*/ { + Image::Indexed *img=new Image::Indexed(wd, ht, (1<<bpc), bpc); + unsigned i; + rgb_t rgb; + if (bpc==1) { + img->setPal(0,0); + img->setPal(1,0xffffffL); + } else if (bpc==2) { + img->setPal(0,0); + img->setPal(1,0x555555L); + img->setPal(2,0xaaaaaaL); + img->setPal(3,0xffffffL); + } else if (bpc==4) { + for (i=0,rgb=0;i<16;i++,rgb+=(rgb_t)0x111111L) img->setPal(i,rgb); + } else if (bpc==8) { + for (i=0,rgb=0;i<256;i++,rgb+=(rgb_t)0x010101L) img->setPal(i,rgb); + } + memcpy(img->getRowbeg(), rowbeg, beg+len-rowbeg); + return img; +} +bool Image::Gray::canGray() const { return true; } +void Image::Gray::copyRGBRow(char *to, Image::Sampled::dimen_t whichrow) const { + param_assert(whichrow<ht); + if (wd==0) return; + unsigned char *p=(unsigned char*)rowbeg+rlen*whichrow; + char *toend=to+3*wd; + unsigned int i, j, k; + + if (bpc==1) { + toend-=3*(wd&7); + while (to!=toend) { + i=*p++; + k=(i>>7)*255; *to++=k; *to++=k; *to++=k; + k=((i>>6)&1)*255; *to++=k; *to++=k; *to++=k; + k=((i>>5)&1)*255; *to++=k; *to++=k; *to++=k; + k=((i>>4)&1)*255; *to++=k; *to++=k; *to++=k; + k=((i>>3)&1)*255; *to++=k; *to++=k; *to++=k; + k=((i>>2)&1)*255; *to++=k; *to++=k; *to++=k; + k=((i>>1)&1)*255; *to++=k; *to++=k; *to++=k; + k=( i&1)*255; *to++=k; *to++=k; *to++=k; + } + i=*p; /* No mem overrun, even if (wd&7)==0 */ + j=wd&7; + while (j--!=0) { k=(i>>7)*255; *to++=k; *to++=k; *to++=k; i<<=1; } + } else if (bpc==2) { + toend-=3*(wd&3); + while (to!=toend) { + i=*p++; + k=(i>>6)*85; *to++=k; *to++=k; *to++=k; + k=((i>>4)&3)*85; *to++=k; *to++=k; *to++=k; + k=((i>>2)&3)*85; *to++=k; *to++=k; *to++=k; + k=( i&3)*85; *to++=k; *to++=k; *to++=k; + } + i=*p; /* No mem overrun, even if (wd&7)==0 */ + j=wd&3; + while (j--!=0) { k=(i>>6)*85; *to++=k; *to++=k; *to++=k; i<<=2; } + } else if (bpc==4) { + toend-=3*(wd&1); + while (to!=toend) { + i=*p++; + k=(i>>4)*17; *to++=k; *to++=k; *to++=k; + k=( i&15)*17; *to++=k; *to++=k; *to++=k; + } + if (0!=(wd&1)) { k=(*p>>4)*17; *to++=k; *to++=k; *to++=k; } + } else if (bpc==8) { + while (to!=toend) { *to++=*p; *to++=*p; *to++=*p++; } + } else assert(0 && "invalid bpc"); +} +#if 0 +void Image::Gray::setBpc(unsigned char bpc_) { + (void)bpc_; + assert(0 && "unimplemented"); /* unimplemented */ +} +#endif + +Image::Sampled* Image::Gray::addAlpha(Image::Gray *al) { + // Error::sev(Error::WARNING) << "Gray: alpha channel ignored" << (Error*)0; return this; + if (al->getHt()!=ht || al->getWd()!=wd) Error::sev(Error::EERROR) << "addAlpha: image dimension mismatch" << (Error*)0; + bool ign_mid=false; + unsigned char lightest, darkest; + al->to8(); + al->calcExtrema(lightest, darkest); + if (darkest==255) return this; /* no transparent pixels at all */ + char *p=rowbeg, *pend=rowbeg+rlen*ht, *alq=al->getRowbeg(); + /* Imp: choose an image color instead of black... */ + /* Dat: 0..254: transparent, 255: opaque */ + while (p!=pend) { + if ((unsigned char)(*alq+1)>1) ign_mid=true; + /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */ + if ((unsigned char)*alq++!=255) *p=0; /* black out transparent-wannabe pixels */ + p++; + } + if (ign_mid) Error::sev(Error::WARNING) << "addAlpha: half-transparent pixels made transparent" << (Error*)0; + return addAlpha0(toIndexed(), al); +} + +void Image::Gray::calcExtrema(unsigned char &lightest, unsigned char &darkest) { + to8(); + unsigned l=0, d=255, val; + char *p=rowbeg, *pend=rowbeg+ht*wd; + while (p!=pend) { + val=*(unsigned char*)p++; + if (val>l) l=val; + if (val<d) d=val; + } + lightest=l; darkest=d; +} + + +/* --- */ + +Image::RGB::RGB(Image::Sampled::dimen_t wd_, Image::Sampled::dimen_t ht_, unsigned char bpc_) { + init(0,0,wd_,ht_,bpc_,TY_RGB,3); + cs=CS_RGB; +} +void Image::RGB::to8() { to8mul(); } +Image::Gray* Image::RGB::toGray(unsigned char bpc_)/* const*/ { return toGray0(bpc_); } +Image::RGB* Image::RGB::toRGB(unsigned char bpc_)/* const*/ { return bpc==bpc_ ? this : toRGB0(bpc_); } +Image::Indexed* Image::RGB::toIndexed()/* const*/ { return toIndexed0(); } +bool Image::RGB::canGray() const { return false; } +void Image::RGB::copyRGBRow(char *to, Image::Sampled::dimen_t whichrow) const { + param_assert(whichrow<ht); + if (wd==0) return; + unsigned char *p=(unsigned char*)rowbeg+rlen*whichrow; + char *toend=to+3*wd; + unsigned int i, j, k; + + if (bpc==1) { + toend-=(wd*3)&7; + while (to!=toend) { + i=*p++; + k=(i>>7)*255; *to++=k; + k=((i>>6)&1)*255; *to++=k; + k=((i>>5)&1)*255; *to++=k; + k=((i>>4)&1)*255; *to++=k; + k=((i>>3)&1)*255; *to++=k; + k=((i>>2)&1)*255; *to++=k; + k=((i>>1)&1)*255; *to++=k; + k=( i&1)*255; *to++=k; + } + i=*p; /* No mem overrun, even if (wd&7)==0 */ + j=(wd*3)&7; + while (j--!=0) { k=(i>>7)*255; *to++=k; i<<=1; } + } else if (bpc==2) { + toend-=(wd*3)&3; + while (to!=toend) { + i=*p++; + k=(i>>6)*85; *to++=k; + k=((i>>4)&3)*85; *to++=k; + k=((i>>2)&3)*85; *to++=k; + k=( i&3)*85; *to++=k; + } + i=*p; /* No mem overrun, even if (wd&7)==0 */ + j=(wd*3)&3; + while (j--!=0) { k=(i>>6)*85; *to++=k; i<<=2; } + } else if (bpc==4) { + toend-=(wd*3)&7; + while (to!=toend) { + i=*p++; + k=(i>>4)*17; *to++=k; + k=( i&15)*17; *to++=k; + } + if (0!=((wd*3)&1)) *to++=(*p>>4)*17; + } else if (bpc==8) { + memcpy(to, p, 3*wd); + } else assert(0 && "invalid bpc"); +} +#if 0 +void Image::RGB::setBpc(unsigned char bpc_) { + (void)bpc_; + assert(0 && "unimplemented"); /* unimplemented */ +} +#endif + +Image::Sampled* Image::RGB::addAlpha(Image::Gray *al) { + if (al->getHt()!=ht || al->getWd()!=wd) Error::sev(Error::EERROR) << "addAlpha: image dimension mismatch" << (Error*)0; + bool ign_mid=false; + unsigned char lightest, darkest; + al->to8(); + al->calcExtrema(lightest, darkest); + if (darkest==255) return this; /* no transparent pixels at all */ + char *p=rowbeg, *pend=rowbeg+rlen*ht, *alq=al->getRowbeg(); + /* Imp: choose an image color instead of black... */ + /* Dat: 0..254: transparent, 255: opaque */ + while (p!=pend) { + if ((unsigned char)(*alq+1)>1) ign_mid=true; + /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */ + if ((unsigned char)*alq++!=255) p[0]=p[1]=p[2]=0; /* black out transparent-wannabe pixels */ + p+=3; + } + if (ign_mid) Error::sev(Error::WARNING) << "addAlpha: half-transparent pixels made transparent" << (Error*)0; + return addAlpha0(toIndexed(), al); +} + +/* --- */ + +char *Image::Sampled::rgb2webhash(rgb_t rgb) { + static char tmp[8]; + char *p=tmp; + *p='#'; + *++p='0'+(rgb>>20); if (*p>'9') *p+='a'-'0'-10; + *++p='0'+((rgb>>16)&15); if (*p>'9') *p+='a'-'0'-10; + *++p='0'+((rgb>>12)&15); if (*p>'9') *p+='a'-'0'-10; + *++p='0'+((rgb>>8)&15); if (*p>'9') *p+='a'-'0'-10; + *++p='0'+((rgb>>4)&15); if (*p>'9') *p+='a'-'0'-10; + *++p='0'+((rgb )&15); if (*p>'9') *p+='a'-'0'-10; + *++p='\0'; + return tmp; +} + +GenBuffer::Writable& operator<<(GenBuffer::Writable& gw, Image::Sampled const& img) { + slen_t buflen=img.getWd()*3; + char *buf=new char[buflen]; + Image::Sampled::dimen_t y, ht=img.getHt(); + /* vvv in the xv program: image file must be >=30 bytes long to be treated as image */ + gw << "P6\n###############\n" << img.getWd() << ' ' << ht; + if (img.getTranspc()>=0x1000000UL) gw << "\n#Opaque"; + else gw << "\n#T" << img.rgb2webhash(img.getTranspc()); + gw << "\n255\n"; + for (y=0; y<ht; y++) { + img.copyRGBRow(buf, y); + gw.vi_write(buf, buflen); + } + delete [] buf; + return gw; +} + +static Image::Loader *first=(Image::Loader*)NULLP; + +void Image::register0(Image::Loader *anew) { + param_assert(anew!=NULLP); + anew->next=first; + first=anew; +} + +#if 0 /* removed by code refactoring */ +Image::Sampled* Image::load(char const* format, filep_t f_, SimBuffer::Flat const& loadHints) { +#endif + +// #include <unistd.h> /* sleep() */ + +#if 0 +Rule::Sampled *Rule::load(char const* filename) { + static char buf[2*Applier::MAGIC_LEN]; + FILE *f=fopen(filename, "rb"); + unsigned got=0; + if (f==NULLP) Error::sev(Error::EERROR) << "Cannot open/read image file: " << FNQ(filename) << (Error*)0; + slen_t ret=fread(buf, 1, Applier::MAGIC_LEN, f); + /* vvv Imp: clarify error message: may be a read error */ + if (ret==0) Error::sev(Error::EERROR) << "Zero-length image file: " << FNQ(filename) << (Error*)0; + if (ret<Applier::MAGIC_LEN) memset(buf+ret, '\0', Applier::MAGIC_LEN-ret); +#if 0 + unsigned long pos=fseek(f, 0, SEEK_END); + pos=(pos<=Applier::MAGIC_LEN)?0:pos-Applier::MAGIC_LEN; + if (0!=fseek(f, pos, SEEK_SET) + || (got=fread(buf+Applier::MAGIC_LEN, 1, Applier::MAGIC_LEN, f))==0 +#else + if (0 +#endif + || (rewind(f), 0) + || ferror(f)) + Error::sev(Error::EERROR) << "I/O error in image file: " << FNQ(filename) << (Error*)0; + if (got!=0 && got!=Applier::MAGIC_LEN) memmove(buf+2*Applier::MAGIC_LEN-got, buf+Applier::MAGIC_LEN, got); + Applier *p=first; + Applier::reader_t reader; + while (p!=NULLP) { + if (NULLP!=(reader=p->checker(buf,buf+Applier::MAGIC_LEN))) { return reader(f); } + p=p->next; + } + Error::sev(Error::EERROR) << "Unknown image format: " << FNQ(filename) << (Error*)0; + // Error::sev(Error::WARNING) << "Zero-length image1." << (Error*)0; + // Error::sev(Error::WARNING) << "Zero-length image2." << (Error*)0; + return 0; /*notreached*/ +} +#endif + + +Image::Sampled *Image::load(Image::Loader::UFD* ufd0, SimBuffer::Flat const& loadHints, char const* format) { + Filter::UngetFILED &ufd=*(Filter::UngetFILED*)ufd0; + /* Dat: format arg used in in_pnm.cpp */ + static char buf[Loader::MAGIC_LEN+1]; + slen_t ret=ufd.vi_read(buf, Loader::MAGIC_LEN); + /* vvv Imp: clarify error message: may be a read error */ + if (ufd.hadError()) Error::sev(Error::EERROR) << "I/O error pre in image file: " << FNQ(ufd.getFilenameDefault("-")) << (Error*)0; + if (ret==0) Error::sev(Error::EERROR) << "Zero-length image file: " << FNQ(ufd.getFilenameDefault("-")) << (Error*)0; + if (ret<Loader::MAGIC_LEN) memset(buf+ret, '\0', Loader::MAGIC_LEN-ret); + buf[Loader::MAGIC_LEN]='\0'; + /* Dat: do not read the trailer onto buf+Loader::MAGIC_LEN, because no ->checker() uses it yet. */ + Loader *p=first; + Loader::reader_t reader; + ufd.unread(buf, ret); /* tries to seek back, on failure calls ufd.getUnget().vi_write() */ + // ^^^ rewind(f); /* checker might have read */ + /* ^^^ do this early for the checkers */ + while (p!=NULLP) { + /* vvv each checker() must rewind ufd for itself */ + if ((format==(char const*)NULLP || 0==strcmp(p->format, format)) + && (Loader::checker_t)NULLP!=p->checker + && (Loader::reader_t)NULLP!=(reader=p->checker(buf,buf+Loader::MAGIC_LEN, loadHints, ufd0)) + ) { + // fprintf(stderr, "%p %p\n", ufd0, &ufd); + return reader(ufd0, loadHints); + } + p=p->next; + } + // sleep(1000); + Error::sev(Error::EERROR) << "Unknown input image format: " << FNQ(ufd.getFilenameDefault("-")) << (Error*)0; + return 0; /*notreached*/ +} + +#if 0 /* not used anywhere */ +Image::Sampled *Image::load(char const* filename, SimBuffer::Flat const& loadHints, filep_t stdin_f, char const* format) { + Filter::UngetFILED ufd(filename, stdin_f==NULLP ? stdin : (FILE*)stdin_f, + Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp); + return load((Image::Loader::UFD*)&ufd, loadHints, format); + // Imp: better error message, something like: if (f==NULLP) Error::sev(Error::EERROR) << "Cannot open/read image file: " << FNQ(filename) << (Error*)0; +} +#endif + +#if 0 /* before Sat Apr 19 13:42:04 CEST 2003 */ +Image::Sampled *Image::load(char const* filename, SimBuffer::Flat const& loadHints, filep_t stdin_f, char const* format) { + /* Dat: format arg used in in_pnm.cpp */ + static char buf[2*Loader::MAGIC_LEN]; + bool stdin_p=filename[0]=='-' && filename[1]=='\0'; + FILE *f=!stdin_p ? fopen(filename, "rb") : stdin_f!=NULLP ? (FILE*)stdin_f : stdin; + unsigned got=0; + if (f==NULLP) Error::sev(Error::EERROR) << "Cannot open/read image file: " << FNQ(filename) << (Error*)0; + slen_t ret=fread(buf, 1, Loader::MAGIC_LEN, f); + /* vvv Imp: clarify error message: may be a read error */ + if (ret==0) Error::sev(Error::EERROR) << "Zero-length image file: " << FNQ(filename) << (Error*)0; + if (ret<Loader::MAGIC_LEN) memset(buf+ret, '\0', Loader::MAGIC_LEN-ret); +#if 0 + /* Dat: do not read the trailer, because no ->checker() uses it yet. */ + unsigned long pos=fseek(f, 0, SEEK_END); + pos=(pos<=Loader::MAGIC_LEN)?0:pos-Loader::MAGIC_LEN; + if (0!=fseek(f, pos, SEEK_SET) + || (got=fread(buf+Loader::MAGIC_LEN, 1, Loader::MAGIC_LEN, f))==0 +#else + if (0 +#endif + || (rewind(f), 0) + || ferror(f)) + Error::sev(Error::EERROR) << "I/O error pre in image file: " << FNQ(filename) << (Error*)0; + if (got!=0 && got!=Loader::MAGIC_LEN) memmove(buf+2*Loader::MAGIC_LEN-got, buf+Loader::MAGIC_LEN, got); + Loader *p=first; + Loader::reader_t reader; + while (p!=NULLP) { + if ((format==(char const*)NULLP || 0==strcmp(p->format, format)) + && (Loader::checker_t)NULLP!=p->checker + && (Loader::reader_t)NULLP!=(reader=p->checker(buf,buf+Loader::MAGIC_LEN, loadHints, f)) + ) { + rewind(f); /* checker might have read */ + Image::Sampled *ret=reader(f, loadHints); + if (ferror(f) || (!stdin_p && 0!=fclose(f))) /* don't close stdin */ + Error::sev(Error::EERROR) << "I/O error post in image file: " << FNQ(filename) << (Error*)0; + return ret; + } + p=p->next; + } + Error::sev(Error::EERROR) << "Unknown input image format: " << FNQ(filename) << (Error*)0; + // Error::sev(Error::WARNING) << "Zero-length image1." << (Error*)0; + // Error::sev(Error::WARNING) << "Zero-length image2." << (Error*)0; + return 0; /*notreached*/ +} +#endif + +unsigned Image::printLoaders(GenBuffer::Writable &out) { + unsigned num=0; + Loader *p=first; + while (p!=NULLP) { + if (p->checker!=(Loader::checker_t)NULLP && p->format!=(char const*)NULLP) { num++; out << ' ' << p->format; } + p=p->next; + } + return num; +} + +/* --- */ + +Image::SampledInfo::SampledInfo(Sampled *img_) + :hasTransp(false) + ,nncols(257) + ,canGray(false) + ,minRGBBpc(8) + ,img(img_) + ,imgs((Indexed**)NULLP) { + param_assert(img_!=NULLP); + Sampled *bak=img; + if ((img=img->toIndexed())==NULLP) { + img=bak; + } else { + if (bak!=img) delete bak; + assert(img->getTy()==img->TY_INDEXED); + Indexed *iimg=PTS_dynamic_cast(Image::Indexed*,img); + iimg->packPal(); + nncols=iimg->getNcols(); + if (true==(hasTransp=iimg->hasTransp())) nncols--; + } + minRGBBpc=img->minRGBBpc(); + if ((canGray=img->canGray())==true && nncols==257) nncols=256; + sf=(sf_t)((img->getTy()==img->TY_BLACKBOX) ? 0+SF_Asis : 0+SF_None); + /* Dat: 0+: pacify gcc-3.1 */ +} + +Image::SampledInfo::~SampledInfo() { + delete img; + if (imgs!=NULLP) { Image::Indexed::delete_separated(imgs); delete imgs; } +} + +void Image::SampledInfo::separate() { + // bool ok; + // ASSERT_SIDE(ok=(sf!=SF_Transparent2 && sf!=SF_Transparent4 && sf!=SF_Transparent8)); + // if (!ok) return; + if (sf!=SF_Transparent2 && sf!=SF_Transparent4 && sf!=SF_Transparent8) return; + Indexed *iimg=PTS_dynamic_cast(Indexed*,img); + imgs=iimg->separate(); +} + +bool Image::SampledInfo::setSampleFormat(sf_t sf_, bool WarningOK, bool TryOnly, Sampled::rgb_t Transparent) { + /* at Sat Jun 15 11:48:51 CEST 2002: added transparency warnings */ + /* fprintf(stderr, "sf=%u sf_=%u transparent=0x%lx\n", sf, sf_, Transparent+0UL); */ + // assert(sf_==SF_Asis); + Indexed *iimg; + Sampled *bak=img; + param_assert(sf_!=SF_None); + param_assert(sf==SF_None || sf==SF_Asis || sf==sf_); + if (sf_==sf) return true; /* already converted */ + bool zero=img->getWd()==0 || img->getHt()==0; + if (sf==SF_Asis && sf_!=SF_Asis && sf_!=SF_Bbox) { + Error::sev(Error::WARNING) << "SampleFormat: can't convert image loaded as Asis to other" << (Error*)0; + return false; + } + switch (sf_) { + case SF_Bbox: + sf=SF_Bbox; return true; + case SF_Opaque: + if (!hasTransp && nncols==1 && PTS_dynamic_cast(Indexed*,img)->setTranspc(Transparent)) { hasTransp=true; nncols=0; } + if (hasTransp || nncols!=1) return false; + assert(img->getTy()==img->TY_INDEXED); + /* The color can be calculated: PTS_dynamic_cast(Indexed*>(img)->getPal(0); */ + /* Conversion is not necessary. */ + sf=SF_Opaque; return true; + case SF_Transparent: + if (!hasTransp && nncols==1 && PTS_dynamic_cast(Indexed*,img)->setTranspc(Transparent)) { hasTransp=true; nncols=0; } + if (!hasTransp || nncols!=0) return false; + assert(img->getTy()==img->TY_INDEXED); + /* Conversion is not necessary. */ + sf=SF_Transparent; return true; + case SF_Gray1: + /* vvv strict hasTransp added at Mon Sep 9 22:53:24 CEST 2002 */ + if (nncols>2 || !canGray || minRGBBpc>1 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + /* ^^^ Imp: !! make the hasPixelRFB() check a lot faster (cache results) */ + if (TryOnly) return WarningOK || (nncols>=2 && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + /* Dat: nncols may be 1 or 2 ! (both transparent and opaque black) */ + Error::sev(Error::WARNING) << + (nncols<=1 ? "SampleFormat: Mask would be better than " + : "SampleFormat: Transparent2 would be better than ") + << "Gray1" << (Error*)0; + } + if (nncols<2) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Opaque would be better than Gray1" << (Error*)0; + } + img=img->toGray(1); if (bak!=img) delete bak; + assert(img!=NULLP); + assert(img->getBpc()==1); + sf=SF_Gray1; return true; + case SF_Indexed1: + if (nncols>2 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || nncols>=2; + if (nncols<2) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Opaque would be better than Indexed1" << (Error*)0; + } + if (canGray && minRGBBpc==1) { + Error::sev(Error::NOTICE) << "SampleFormat: Gray1 would be better than Indexed1" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + // img=img->toIndexed(); /* should be a no-op */ + // assert(img!=NULLP); if (bak!=img) delete bak; + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(1); + if (iimg->setTranspc(Transparent)) return false; /* Dat: false if must be changed to become transparent; Imp: undo changes */ + } + sf=SF_Indexed1; return true; + case SF_Mask: + if (!hasTransp && nncols==2 && PTS_dynamic_cast(Indexed*,img)->setTranspc(Transparent)) { hasTransp=true; nncols=1; } + if (nncols>1 || zero) return false; + if (TryOnly) return WarningOK || nncols+(hasTransp?1:0)==2; + if (nncols==1 && !hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Opaque would be better than Mask" << (Error*)0; + } + if (nncols==0) { + assert(hasTransp); + Error::sev(Error::WARNING) << "SampleFormat: Transparent would be better than Mask" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(1); + if (!iimg->setTranspc(Transparent)) return false; + iimg->packPal(); + } + /* printf("gett=%d\n", PTS_dynamic_cast(Indexed*,img)->getTransp()); */ + /* vvv BUGFIX: <1U -> <2U */ + assert(PTS_dynamic_cast(Indexed*,img)->getTransp()==-1 || PTS_dynamic_cast(Indexed*,img)->getTransp()+0U<2U); + /* ^^^ color 0 is opaque, color 1 is transparent, thanks to + * img->packPal() called in SampleInfo() -- but setTranspc may have changed this + */ + sf=SF_Mask; return true; + case SF_Transparent2: + if (nncols==4) { + (iimg=PTS_dynamic_cast(Indexed*,img))->setTranspc(Transparent); /* Imp: are we Indexed*?? */ + hasTransp=iimg->hasTransp(); + } + if (nncols>3 || zero) return false; + if (TryOnly) return WarningOK || (hasTransp && nncols>=2); + Error::sev(Error::NOTICE) << "SampleFormat: Transparent2 separates colors" << (Error*)0; + if (!hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Indexed2 would be better than Transparent2" << (Error*)0; + } + if (nncols<2) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Mask would be better than Transparent2" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(2); /* BUGFIX at Sat Jun 15 13:55:25 CEST 2002 */ + iimg->setTranspc(Transparent); + // imgs=iimg->separate(); /* postponed because of GIF89a output */ + } + sf=SF_Transparent2; return true; + case SF_Gray2: + if (nncols>4 || !canGray || minRGBBpc>2 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>2 && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << + (nncols<=3 ? "SampleFormat: Transparent2 would be better than " + : "SampleFormat: Transparent4 would be better than ") + << "Gray2" << (Error*)0; + } + if (nncols<=2) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray1 would be better than Gray2" << (Error*)0; + } + img=img->toGray(2); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Gray2; return true; + case SF_Indexed2: + if (nncols>4 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || nncols>2; + if (nncols<=2) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Indexed1 would be better than Indexed2" << (Error*)0; + } + if (canGray && minRGBBpc<=2) { + Error::sev(Error::NOTICE) << "SampleFormat: Gray2 would be better than Indexed2" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(2); + if (iimg->setTranspc(Transparent)) return false; + } + sf=SF_Indexed2; return true; + case SF_Transparent4: + if (nncols==16) PTS_dynamic_cast(Indexed*,img)->setTranspc(Transparent); + if (nncols>15 || zero) return false; + if (TryOnly) return WarningOK || (hasTransp && nncols>=4); + Error::sev(Error::NOTICE) << "SampleFormat: Transparent4 separates colors" << (Error*)0; + if (!hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Indexed4 would be better than Transparent4" << (Error*)0; + } + if (nncols<4) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Transparent2 would be better than Transparent4" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(4); + iimg->setTranspc(Transparent); + // imgs=iimg->separate(); /* postponed because of GIF89a output */ + } + sf=SF_Transparent4; return true; + case SF_Rgb1: + if (nncols>8 || minRGBBpc>1 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>4 && !canGray && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Transparent4 would be better than " << "Rgb1" << (Error*)0; + } + if (canGray) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray1 would be better than Rgb1" << (Error*)0; + } + if (nncols<=4) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: " + << (hasTransp ? "Transparent2 may" : "Indexed2 would") + << " be better than Rgb1" << (Error*)0; + } + img=img->toRGB(1); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Rgb1; return true; + case SF_Gray4: + if (nncols>16 || !canGray || minRGBBpc>4 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + /* ^^^ BUGFIX at Sat Jun 1 18:27:10 CEST 2002 */ + if (TryOnly) return WarningOK || (nncols>4 && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << + (nncols<=15 ? "SampleFormat: Transparent4 would be better than " + : "SampleFormat: Transparent8 may be better than ") + << "Gray4" << (Error*)0; + } + if (nncols<=4) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray2 would be better than Gray4" << (Error*)0; + } + img=img->toGray(4); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Gray4; return true; + case SF_Indexed4: + if (nncols>16 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>4 && minRGBBpc>=4); + if (nncols<=4) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Indexed2 would be better than Indexed4" << (Error*)0; + } + if (minRGBBpc<=1) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: RGB1 would be better than Indexed4" << (Error*)0; + } + if (canGray && minRGBBpc<=4) { + if (!WarningOK) return false; + Error::sev(Error::NOTICE) << "SampleFormat: Gray4 would be better than Indexed4" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(4); + if (iimg->setTranspc(Transparent)) return false; + } + sf=SF_Indexed4; return true; + case SF_Transparent8: + if (nncols==256) PTS_dynamic_cast(Indexed*,img)->setTranspc(Transparent); + if (nncols>255 || zero) return false; + if (!WarningOK) return false; + if (TryOnly) return true; + Error::sev(Error::WARNING) << "SampleFormat: Transparent8 separates too many colors" << (Error*)0; + if (!hasTransp) { + Error::sev(Error::WARNING) << "SampleFormat: Indexed8 would be much better than Transparent8" << (Error*)0; + } + if (nncols<16) { + Error::sev(Error::WARNING) << "SampleFormat: Transparent4 would be better than Transparent8" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(8); /* should be a no-op */ + iimg->setTranspc(Transparent); + // imgs=iimg->separate(); /* postponed because of GIF89a output */ + } + sf=SF_Transparent8; return true; + case SF_Rgb2: + if (nncols>64 || minRGBBpc>2 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>16 && !canGray && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Transparent8 would be better than " << "Rgb2" << (Error*)0; + } + if (canGray) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray2 would be better than Rgb2" << (Error*)0; + } + if (nncols<=16) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: " + << (hasTransp ? "Transparent4 may" : "Indexed4 would") + << " be better than Rgb2" << (Error*)0; + } + img=img->toRGB(2); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Rgb2; return true; + case SF_Gray8: + if (nncols>256 || !canGray || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>16 && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << + (nncols<=255 ? "SampleFormat: Transparent8 may be better than " + : "SampleFormat: ignoring transparency for ") + << "Gray8" << (Error*)0; + } + if (minRGBBpc<=4) { + /* BUGFIX at Wed Jul 3 01:07:44 CEST 2002 */ + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray4 would be better than Gray8" << (Error*)0; + } + img=img->toGray(8); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Gray8; return true; + case SF_Indexed8: + // fprintf(stderr, "nncols=%u hasTransp=%u zero=%u\n", nncols, hasTransp, zero); + if (nncols>256 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + // assert(0); + if (TryOnly) return WarningOK || (nncols>16 && minRGBBpc>=8); + if (nncols<=16) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Indexed4 would be better than Indexed8" << (Error*)0; + } + if (minRGBBpc<=2) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: RGB2 would be better than Indexed8" << (Error*)0; + } + if (canGray) { + if (!WarningOK) return false; + Error::sev(Error::NOTICE) << "SampleFormat: Gray8 would be better than Indexed8" << (Error*)0; + } + assert(img->getTy()==img->TY_INDEXED); + { iimg=PTS_dynamic_cast(Indexed*,img); + iimg->setBpc(8); /* should be a no-op */ + if (iimg->setTranspc(Transparent)) return false; + } + sf=SF_Indexed8; return true; + case SF_Rgb4: + // fprintf(stderr, "minrgbbpc=%d to=%d\n", minRGBBpc, TryOnly); + if (minRGBBpc>4 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>256 && !canGray && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << + (nncols<=255 ? "SampleFormat: Transparent8 may be better than " + : "SampleFormat: ignoring transparency for ") + << "Rgb4" << (Error*)0; + } + if (canGray) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray4 would be better than Rgb4" << (Error*)0; + } + if (nncols<=256) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: " + << (hasTransp && nncols<=255 ? "Transparent8 may" : "Indexed8 would") + << " be better than Rgb4" << (Error*)0; + } + img=img->toRGB(4); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Rgb4; return true; + case SF_Rgb8: + if (zero || hasTransp || img->hasPixelRGB(Transparent)) return false; + if (TryOnly) return WarningOK || (nncols>256 && !canGray && minRGBBpc>=8 && !hasTransp); + if (hasTransp) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << + (nncols<=255 ? "SampleFormat: Transparent8 may be better than " + : "SampleFormat: ignoring transparency for ") + << "Rgb8" << (Error*)0; + } + if (canGray) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Gray8 would be better than Rgb8" << (Error*)0; + } + if (minRGBBpc<=4) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: Rgb4 would be better than Rgb8" << (Error*)0; + } + if (nncols<=256) { + if (!WarningOK) return false; + Error::sev(Error::WARNING) << "SampleFormat: " + << (hasTransp && nncols<=255 ? "Transparent8 may" : "Indexed8 would") + << " be better than Rgb8" << (Error*)0; + } + img=img->toRGB(8); if (bak!=img) delete bak; + assert(img!=NULLP); + sf=SF_Rgb8; return true; + case SF_Asis: + if (img->getTy()!=img->TY_BLACKBOX) { + Error::sev(Error::WARNING) << "SampleFormat: cannot convert image to /Asis" << (Error*)0; + return false; + } + sf=SF_Asis; return true; + } + assert(0 && "unknown SampleFormat requested"); + return false; /* NOTREACHED */ +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/image.hpp b/Build/source/utils/sam2p/image.hpp new file mode 100644 index 00000000000..d339a9f14c1 --- /dev/null +++ b/Build/source/utils/sam2p/image.hpp @@ -0,0 +1,377 @@ +/* image.hpp -- classes for sampled (indexed, gray and rgb) images + * by pts@fazekas.hu Wed Feb 27 09:24:47 CET 2002 + */ +/* Imp: find memory leaks */ +/* Imp: keep future transparency in toIndexed(...) */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef SAMPLED_HPP +#define SAMPLED_HPP 1 + +#include "config2.h" +#include "gensi.hpp" + +class Image { + public: + class RGB; + class Gray; + class Indexed; + /** Generic, sampled, rectangular image data. Abstract class. + * Each sample is 1, 2, 4 or 8 bits. Regions: + * beg..head-1: comment, ignored (e.g unused part of the indexed palette) + * headp..rowbeg-1: header: not predicted or compressed (e.g the indexed palette) + * rowbeg+0*rlen..rowbeg+0*rlen+rlen-1: sample data of the 0th row, compressed and predicted + * rowbeg+1*rlen..rowbeg+1*rlen+rlen-1: sample data of the 1st row + * rowbeg+2*rlen..rowbeg+2*rlen+rlen-1: sample data of the 1st row + * ... + * rowbeg+(h-1)*rlen..rowbeg+h*rlen-1: sample data of the last row + * trail..beg+len: trailer, ignored. Its length must be >=bpc. + */ + class Sampled: public SimBuffer::Flat { + public: + /** Can hold 1 component of a sample of a single pixel. */ + typedef unsigned char sample_t; + /** Can hold a height or depth of the image */ + typedef unsigned int dimen_t; + /** Can hold a row length (in byte), which isn't greater than 3*(image width). */ + typedef unsigned int rlen_t; + /** RGB = (red<<16)+(green<<8)+(blue). red, green and blue are 0..255 */ + #if SIZEOF_LONG>4 && SIZEOF_INT>=4 + typedef unsigned int rgb_t; + #else + typedef unsigned long rgb_t; + #endif + BEGIN_STATIC_ENUM1(unsigned char) + TY_INDEXED=1, TY_GRAY=2, TY_RGB=3, TY_OTHER=4, TY_BLACKBOX=5 + END_STATIC_ENUM() + BEGIN_STATIC_ENUM1(unsigned char) // static const unsigned char + CS_UNKNOWN=0, /* error/unspecified */ + CS_GRAYSCALE=1, /* monochrome */ + CS_RGB=2, /* red/green/blue */ + CS_YCbCr=3, /* Y/Cb/Cr (also known as YUV) */ + CS_CMYK=4, /* C/M/Y/K */ + CS_YCCK=5, /* Y/Cb/Cr/K */ + CS_Indexed_RGB=12 + END_STATIC_ENUM() + static const unsigned char cs2cpp[6]; + /** @return NULLP on error */ + static char const *cs2devcs(unsigned char cs); + protected: + char *headp; + char *rowbeg; + char *trail; + /** Extra offset */ + slen_t xoffs; + + /** Length of one row, in bytes. Each row must begin on a byte boundary, so + * extra bits are appended after the rightmost pixel. These bits are + * arbitrary, and are ignored by the PostScript interpreter. + */ + rlen_t rlen; + /** Image height, in pixels. */ + dimen_t ht; + /** Image width, in pixels. */ + dimen_t wd; + /** Color space. */ + unsigned char cs; + /** Components per pixel. (number of planes, image depth). 1 for indexed, + * 1 for gray, 3 for RGB + */ + unsigned char cpp; + /** BitsPerComponent: 1, 2, 4 or 8. PostScript allows 12 too. */ + unsigned char bpc; + /** Transparent color value. Imp: ... */ + rgb_t transpc; + /** Image type, TY_... */ + unsigned char ty; + /** Initializes various fields, allocates memory. Called from descendants' + * constructors. + */ + void init(slen_t l_comment, slen_t l_header, dimen_t wd_, dimen_t ht_, + unsigned char bpc_, unsigned char ty_, unsigned char cpp_); + /** Convert samples, make bpc=8, multiplication. */ + void to8mul(); + /** Convert samples, make bpc=8, no multiplication. */ + void to8nomul(); + /** Calls copyRGBRow. + * @return an Image::Indexed version of (this) iff the number of + * colors<=256. Otherwise, returns NULLP. + */ + Indexed* toIndexed0()/* const*/; + /** No averaging is done, only the red component is extracted */ + Gray* toGray0(unsigned char bpc_); + RGB * toRGB0(unsigned char bpc_); + /** @return if any pixels are not gray: false. otherwise: true or false. */ + public: + inline bool hasTransp() const { return transpc!=0x1000000UL; } + virtual bool canGray() const =0; + /** @return an RGB BitsPerComponent number (1,2,4 or 8) to which the image + * could be converted without any loss. The default implementation calls + * copyRGBRow(). + */ + virtual unsigned char minRGBBpc() const; + inline virtual ~Sampled() { delete [] const_cast<char*>(beg); } + /** Copies whichrow as wd*3 bytes (R0,G0,B0,R1,G1,B1...) to `to' */ + virtual void copyRGBRow(char *to, dimen_t whichrow) const =0; + virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const; + inline char *getRowbeg() const { return rowbeg; } + inline dimen_t getWd() const { return wd; } + inline dimen_t getHt() const { return ht; } + inline unsigned char getTy() const { return ty; } + inline unsigned char getBpc() const { return bpc; } + inline unsigned char getCpp() const { return cpp; } + inline unsigned char getCs() const { return cs; } + inline slen_t getXoffs() const { return xoffs; } + inline rlen_t getRlen() const { return rlen; } + inline rgb_t getTranspc() const { return transpc; } + inline char *getHeadp() const { return headp; } + /** Convert samples, make bpc=8. */ + virtual void to8() =0; + /** @return NULLP if too many colors for indexed; otherwise a new Image::Indexed. + * The caller should `delete' (this) if toIndexed()==NULLP. + */ + virtual /*Image::*/Indexed* toIndexed() =0; + virtual /*Image::*/RGB* toRGB(unsigned char bpc_) =0; + virtual /*Image::*/Gray* toGray(unsigned char bpc_) =0; + // virtual void setBpc(unsigned char bpc_) =0; + friend GenBuffer::Writable& operator<<(GenBuffer::Writable&, /*Image::*/Sampled const&); + /** @return address of static buffer: "#RRGGBB" */ + static char *rgb2webhash(rgb_t); + /** @return (this) or an image containing (this) composed with alpha + * channel `al' + */ + virtual Sampled* addAlpha(/*Image::*/Gray *al) =0; + /** assert(al.bpp=8) etc. Imp: document this */ + static Indexed* addAlpha0(Sampled *img, Gray *al); + }; + + class Indexed: public Sampled { + public: + /** @param ncols_ must be >= the colors used */ + Indexed(dimen_t wd_, dimen_t ht_, unsigned short ncols_, unsigned char bpc_); + inline unsigned short getNcols() const { return (rowbeg-headp)/3; } + /** Destroys the color table, and creates one with ncols_ colors. + * @param ncols_ must be <= the ncols_ specified in the constructor + */ + void setNcols(unsigned short ncols_); + /** Decreases the size of the palette (forgets last colors) to the + * specified amount. + */ + void setNcolsMove(unsigned short ncols_); + void setPal(unsigned char coloridx, rgb_t rgb); + rgb_t getPal(unsigned char coloridx) const; + /** @param coloridx must be >=0, transp must be -1 */ + void setTransp(unsigned char coloridx); + /** @return new hasTransp */ + bool setTranspc(rgb_t color); + virtual void copyRGBRow(char *to, dimen_t whichrow) const; + /* virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const; */ + /** Packs (compresses) the palette so that it will be continuous in + * 0..ncols-1, and each color will be used exactly once. The + * transparent color (if present) will become black. As a side-effect, + * packPal() may set (this)->bpc=8. + */ + void packPal(); + virtual void to8(); + virtual /*Image::*/Indexed* toIndexed(); + virtual /*Image::*/RGB* toRGB(unsigned char bpc_); + virtual /*Image::*/Gray* toGray(unsigned char bpc_); + virtual bool canGray() const; + inline signed short getTransp() const { return transp; } + inline signed short getClearTransp() { signed short ret=transp; transp=-1; return ret; } + /** if (transp>0) transp=0;, converts image data. Does not change bpc. */ + void makeTranspZero(); + virtual unsigned char minRGBBpc() const; + /** Separates the current image into Indexed1 images. The caller is + * recommended to call packPal() first to reduce the number of required + * images. + * As a side-effect, + * separate() may set (this)->bpc=8. + * @return the array of images after full color separation: that is + * a dynamically allocated array of `getNcols()-(getTransp()!=-1)' + * Indexed images: each image is Indexed1, color 0 is opaque (with the + * color obtained from (this)), color 1 is transparent. The returned + * array is NULLP-terminated. + */ + Indexed **separate(); + /** Also calls packPal(). As a side effect, changes all transparent + * pixels to color index 0. + * @return NULLP if no transparent pixels. + */ + Indexed *calcAlpha(); + /** Deletes all elements of p, but not p itself. + * @param p a NULLP-terminated list of (Indexed*)s. + */ + static void delete_separated(Indexed **p); + /** Reorganizes the image so it will have the specified bpc. Issues a + * runtime error if the specified bpc cannot be achieved. + * @param bpc_ the desired bpc, or 0: the best achievable. + */ + virtual void setBpc(unsigned char bpc_); + void dumpDebug(GenBuffer::Writable& gw); + protected: + /* Index of the transparent color, or -1. */ + signed short transp; + virtual /*Image::*/Sampled* addAlpha(/*Image::*/Gray *al); + }; + class Gray: public Sampled { + public: + Gray(dimen_t wd_, dimen_t ht_, unsigned char bpc_); + virtual void copyRGBRow(char *to, dimen_t whichrow) const; + virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const; + virtual void to8(); + virtual /*Image::*/Indexed* toIndexed(); + virtual bool canGray() const; + // virtual void setBpc(unsigned char bpc_); + virtual /*Image::*/RGB * toRGB(unsigned char bpc_); + virtual /*Image::*/Gray * toGray(unsigned char bpc_); + virtual /*Image::*/Sampled* addAlpha(/*Image::*/Gray *al); + /** Calls to8(). */ + void calcExtrema(unsigned char &lightest, unsigned char &darkest); + }; + class RGB: public Sampled { + public: + RGB(dimen_t wd_, dimen_t ht_, unsigned char bpc_); + virtual void copyRGBRow(char *to, dimen_t whichrow) const; + /* virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const; */ + virtual void to8(); + virtual /*Image::*/Indexed* toIndexed(); + virtual bool canGray() const; + // virtual void setBpc(unsigned char bpc_); + virtual /*Image::*/RGB * toRGB(unsigned char bpc_); + virtual /*Image::*/Gray * toGray(unsigned char bpc_); + virtual /*Image::*/Sampled* addAlpha(/*Image::*/Gray *al); + }; + + /** Avoid including <stdio.h> */ + typedef void *filep_t; + + /** Describes a driver that can load a specific image file format. */ + struct Loader { + /** Filter::UngetFILED */ + class UFD; + /** A function that can (allocate and) load a sampled image. Never + * returns NULL. On error, it calls Error::.... The filep_t argument + * should be really cast back to FILE*. The reader must fclose the FILE*. + */ + // typedef Sampled*(*reader_t)(filep_t, SimBuffer::Flat const& loadHints); + typedef Sampled*(*reader_t)(UFD* ufd, SimBuffer::Flat const& loadHints); + BEGIN_STATIC_ENUM1(unsigned) MAGIC_LEN=64 END_STATIC_ENUM() + /** A function that checks the magic numbers at the beginning of a file + * (already read into buf), and returns NULL if it cannot load an image + * of that type, or a reader_t that will load the image. If (and only if!) + * file is shorter than 64 bytes, the buf is padded with '\000' bytes. + * @param f may read from freely if necessary (MAGIC_LEN is short), but + * has to call rewind(f) before reading + */ + typedef reader_t(*checker_t)(char buf[MAGIC_LEN], char bufend[MAGIC_LEN], SimBuffer::Flat const& loadHints, UFD* ufd); + /** A null-terminated, compact string describing (not defining!) the image + * file format. + * Examples: "GIF", "XPM", "PNM" + */ + char const*format; + checker_t checker; + /** Null or next loader. */ + Loader *next; + }; + + /** Registers a new type of image Loader, i.e a new image file format. The + * new image format will be put in front of all others, and will be checked + * first + */ + static void register0(Loader *); + /** Loads the image contained in te file `filename'. + * @param format NULLP is unknown (load any format) + * or an Image::Loader::format already registered + */ + static Sampled* load(Loader::UFD* ufd, SimBuffer::Flat const& loadHints, char const* format); + static Sampled* load(char const *filename, SimBuffer::Flat const& loadHints, filep_t stdin_f=(filep_t*)NULLP, char const* format=(char const*)NULLP); + /* Prints the list of available Loaders (->format), separated by spaces. + * Returns the number of available Loaders. Prepends a space if >= loaders. + */ + static unsigned printLoaders(GenBuffer::Writable &); + + /** SampleFormat constants */ + BEGIN_STATIC_ENUM(unsigned, sf_t) + SF_None=0, /* no specific sample format */ + SF_Opaque=1, + SF_Transparent=2, + SF_Gray1=3, + SF_Indexed1=4, + SF_Mask=5, + SF_Transparent2=6, + SF_Gray2=7, + SF_Indexed2=8, + SF_Transparent4=9, + SF_Rgb1=10, + SF_Gray4=11, + SF_Indexed4=12, + SF_Transparent8=13, + SF_Rgb2=14, + SF_Gray8=15, + SF_Indexed8=16, + SF_Rgb4=17, + SF_Rgb8=18, + SF_Asis=19, + SF_Bbox=20, + SF_max=31 + END_STATIC_ENUM() + + /** Contains (and memory-manages) an image, and optimization information + * as a cache. + */ + class SampledInfo { + public: + SampledInfo(Sampled *img_); + ~SampledInfo(); + inline Sampled* getImage() const { return img; } + /** + * Source image, may be modified even if TryOnly==false. If + * modified, the original will be freed. + * @param sf desired sample format, see Image::SF_* constants + * @param WarningOK if false: make the conversion fail if it would produces + * a Warning + * @param TryOnly if true: don't do the real conversion (but may do auxilary, + * idempontent, helper conversion), assume it has succeeded + * @param Transparent: as part of the conversion, try to make this RGB color + * transparent + * @return true iff the conversion succeeded. Note that img may be the same + * pointer even when true is returned + */ + bool setSampleFormat(sf_t sf, bool WarningOK, bool TryOnly, Sampled::rgb_t Transparent); + inline Indexed **getImgs() const { return imgs; } + inline Sampled *getImg() const { return img; } + inline unsigned getNncols() const { return nncols; } + void separate(); + inline bool canGrayy() const { return canGray; } + inline unsigned char minRGBBpcc() const { return minRGBBpc; } + inline bool hasTranspp() const { return hasTransp; } + inline unsigned char minGrayBpcc() const { return canGray ? minRGBBpc : 0; } + inline void clearTransp() { hasTransp=false; } + protected: + bool hasTransp; + /** Number of non-transparent colors, or 257 if >=257. */ + unsigned nncols; + /** Has only gray colors. */ + bool canGray; + unsigned char minRGBBpc; + Sampled *img; + /** The array of images after full color separation. May be NULLP (default), + * or a dynamically allocated array of `nncols' Indexed images: each + * image is Indexed1, color 0 is opaque (with any value), color 1 + * is transparent. + */ + Indexed **imgs; + sf_t sf; + }; +}; + +/** Dumps this Image as a rawbits PPM file (plus a comment indicating transparency) + * @return the Writable. + */ +GenBuffer::Writable& operator<<(GenBuffer::Writable&, Image::Sampled const&); + +#endif diff --git a/Build/source/utils/sam2p/in_bmp.cpp b/Build/source/utils/sam2p/in_bmp.cpp new file mode 100644 index 00000000000..8784916d13d --- /dev/null +++ b/Build/source/utils/sam2p/in_bmp.cpp @@ -0,0 +1,47 @@ +/* + * in_bmp.cpp -- read a Windows(?) BMP bitmap file + * by pts@fazekas.hu at Sat Mar 2 00:46:54 CET 2002 + * + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" +#include "error.hpp" + +#if USE_IN_BMP + +#include "gensio.hpp" +#include "input-bmp.ci" + +static Image::Sampled *in_bmp_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + Image::Sampled *ret=0; + bitmap_type bitmap=bmp_load_image(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false)); + /* Imp: Work without duplicated memory allocation */ + if (BITMAP_PLANES(bitmap)==1) { + Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + ret=img; + } else if (BITMAP_PLANES(bitmap)==3) { + Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + ret=img; + } else assert(0 && "invalid BMP depth"); + delete [] BITMAP_BITS(bitmap); + return ret; +} + +static Image::Loader::reader_t in_bmp_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return (buf[0]=='B' && buf[1]=='M' + && buf[6]==0 && buf[7]==0 && buf[8]==0 && buf[9]==0 + && (unsigned char)(buf[14])<=64 && buf[15]==0 && buf[16]==0 && buf[17]==0) + ? in_bmp_reader : 0; +} + +#else +#define in_bmp_checker NULLP +#endif /* USE_IN_BMP */ + +Image::Loader in_bmp_loader = { "BMP", in_bmp_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_gif.cpp b/Build/source/utils/sam2p/in_gif.cpp new file mode 100644 index 00000000000..f88768bbe1a --- /dev/null +++ b/Build/source/utils/sam2p/in_gif.cpp @@ -0,0 +1,85 @@ +/* + * in_gif.cpp -- read a Compuserve GIF file + * by pts@fazekas.hu at Fri Mar 1 22:28:46 CET 2002 + * + */ + +/*The creators of the GIF format require the following + acknowledgement: + The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated. +*/ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#define _POSIX_SOURCE 1 +#define _POSIX_C_SOURCE 2 + +#include "config2.h" /* SUXX, ignores features.h */ + +#if USE_IN_GIF + +#include "cgif.h" +#include "cgif.c" /* _POSIX_SOURCE */ +#include "image.hpp" +#include "error.hpp" +#include "gensio.hpp" + +#undef CGIFFF +#define CGIFFF CGIF:: + +static Image::Sampled *in_gif_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + Image::Indexed *img; + CGIFFF GifFileType *giff; + CGIFFF SavedImage *sp; + CGIFFF ColorMapObject *cm; + char const *err; + + /* Dat: (CGIFFF GetGifError() || "unknown error") doesn't work like in Perl or Ruby */ + if (0==(giff=CGIFFF DGifOpenFILE(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false))) || GIF_ERROR==CGIFFF DGifSlurp(giff)) + Error::sev(Error::EERROR) << "GIF: " << ((err=CGIFFF GetGifError()) ? err : "unknown error") << (Error*)0; + if (giff->ImageCount<1) + Error::sev(Error::EERROR) << "GIF: no image in file" << (Error*)0; + + sp=giff->SavedImages+0; + cm = (sp->ImageDesc.ColorMap ? sp->ImageDesc.ColorMap : giff->SColorMap); + img=new Image::Indexed(sp->ImageDesc.Width, sp->ImageDesc.Height, cm->ColorCount, 8); + CGIFFF GifColorType *co=cm->Colors, *ce=co+cm->ColorCount; + char *p=img->getHeadp(); + while (co!=ce) { *p++=(char)co->Red; *p++=(char)co->Green; *p++=(char)co->Blue; co++; } + // fprintf(stderr, "transp=%d\n", sp->transp); + if (sp->transp!=-1) img->setTransp(sp->transp); + /* ^^^ comment out this line to ignore transparency of the GIF file */ + + assert(1L*sp->ImageDesc.Width*sp->ImageDesc.Height<=img->end_()-img->getRowbeg()); + memcpy(img->getRowbeg(), sp->RasterBits, (slen_t)sp->ImageDesc.Width*sp->ImageDesc.Height); + + CGIFFF DGifCloseFile(giff); /* also frees memory structure */ + + return img; +} + +static Image::Loader::reader_t in_gif_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return (0==memcmp(buf,"GIF87a",6) || 0==memcmp(buf,"GIF89a",6)) ? in_gif_reader : 0; +} + +#define in_gif_name "GIF" + +#else +#include <string.h> +#include "image.hpp" +#include "error.hpp" +#define in_gif_name (char const*)NULLP +/* #define in_gif_checker (Image::Loader::checker_t)NULLP */ +static Image::Loader::reader_t in_gif_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + if (0==memcmp(buf,"GIF87a",6) || 0==memcmp(buf,"GIF89a",6)) { + Error::sev(Error::WARNING) << "loader: please `configure --enable-gif' for loading GIF files" << (Error*)0; + } + return 0; +} +#endif /* USE_IN_GIF */ + +Image::Loader in_gif_loader = { in_gif_name, in_gif_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_jai.cpp b/Build/source/utils/sam2p/in_jai.cpp new file mode 100644 index 00000000000..287205c0853 --- /dev/null +++ b/Build/source/utils/sam2p/in_jai.cpp @@ -0,0 +1,392 @@ +/* + * in_jai.cpp -- read a JPEG file as-is + * by pts@math.bme.hu at Sun Mar 17 20:15:25 CET 2002 + */ +/* Imp: test this code with various JPEG files! */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" +#include "error.hpp" + +#if USE_IN_JAI + +#include "in_jai.hpp" +#include <string.h> /* memchr() */ +#include <stdio.h> + +/* --- */ + +class JAI: public Image::Sampled { + public: + /** (Horiz<<4+Vert) sampling factor for the first color component. Usually + * 0x11, but TIFF defaults to 0x22. + */ + JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_); + virtual void copyRGBRow(char *to, dimen_t whichrow) const; + virtual void to8(); + virtual Image::Indexed* toIndexed(); + virtual bool canGray() const; + // virtual void setBpc(unsigned char bpc_); + virtual Image::RGB * toRGB(unsigned char bpc_); + virtual Image::Gray * toGray(unsigned char bpc_); + virtual unsigned char minRGBBpc() const; + virtual Image::Sampled* addAlpha(Image::Gray *al); + void fixEOI(); +}; + +JAI::JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_) { + param_assert(cs_<=5); + // init(0,0,wd_,ht_,bpc_,TY_BLACKBOX,cs2cpp[cs_]); + cs=cs_; + bpc=8; (void)bpc_; // bpc=bpc_; /* /DCTDecode supports only BitsPerComponent==8 */ + ty=TY_BLACKBOX; + wd=wd_; + ht=ht_; + cpp=cs2cpp[cs_]; + // pred=1; + transpc=0x1000000UL; /* Dat: this means: no transparent color */ + rlen=0; + beg=new char[len=0+flen_+0+bpc]; + rowbeg=(headp=const_cast<char*>(beg))+flen_; + xoffs=SOF_offs_; + trail=const_cast<char*>(beg)+len-bpc; + const_cast<char*>(beg)[len-1]=hvs_; /* dirty place */ +} + +void JAI::fixEOI() { + /* by pts@fazekas.hu at Tue Jun 4 15:36:12 CEST 2002 */ + if (rowbeg[-2]!='\xFF' || rowbeg[-1]!='\xD9') { + *rowbeg++='\xFF'; + *rowbeg++='\xD9'; + } +} + +Image::Sampled* JAI::addAlpha(Image::Gray *) { + Error::sev(Error::WARNING) << "JAI: alpha channel ignored" << (Error*)0; + return this; +} + + +unsigned char JAI:: minRGBBpc() const { return bpc; } +void JAI::copyRGBRow(char*, dimen_t) const { assert(0); } +void JAI::to8() { assert(0); } +Image::Indexed* JAI::toIndexed() { return (Image::Indexed*)NULLP; } +bool JAI::canGray() const { return cs==CS_GRAYSCALE; } +Image::RGB * JAI::toRGB(unsigned char) { assert(0); return 0; } +Image::Gray * JAI::toGray(unsigned char) { assert(0); return 0; } + +/* --- The following code is based on standard/image.c from PHP4 */ + +/* some defines for the different JPEG block types */ +#define M_SOF0 0xC0 /* Start Of Frame0: Baseline JPEG */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_APP0 0xe0 +#define M_APP1 0xe1 +#define M_APP2 0xe2 +#define M_APP3 0xe3 +#define M_APP4 0xe4 +#define M_APP5 0xe5 +#define M_APP6 0xe6 +#define M_APP7 0xe7 +#define M_APP8 0xe8 +#define M_APP9 0xe9 +#define M_APP10 0xea +#define M_APP11 0xeb +#define M_APP12 0xec +#define M_APP13 0xed +#define M_APP14 0xee +#define M_APP15 0xef + + +#if 0 +static unsigned int jai_next_marker(FILE *fp) + /* get next marker byte from file */ +{ + int c; + +#if 0 /**** pts ****/ + /* skip unimportant stuff */ + c = MACRO_GETC(fp); + while (c != 0xff) { + if ((c = MACRO_GETC(fp)) == EOF) + return M_EOI; /* we hit EOF */ + } +#else + if (0xff!=(c=MACRO_GETC(fp))) return M_EOI; +#endif + + + /* get marker byte, swallowing possible padding */ + do { + if ((c = MACRO_GETC(fp)) == EOF) + return M_EOI; /* we hit EOF */ + } while (c == 0xff); + + return (unsigned int) c; +} +#endif + +#if 0 +static inline int getc_(FILE *f) { return MACRO_GETC(f); } +static inline long ftell_(FILE *f) { return ftell(f); } +template <class T> +static unsigned short jai_read2(T *fp); +template <class T> +static void jai_handle_jpeg(struct jai_gfxinfo *result, T *fp) { +#endif +/* Dat: removed templates at Tue Mar 11 19:59:16 CET 2003, because decoding + * JPEG headers isn't time-critical + */ + +static inline unsigned short jai_read2(GenBuffer::Readable *fp) { +#if 0 + unsigned char a[ 2 ]; + /* just return 0 if we hit the end-of-file */ + if (fread(a,sizeof(a),1,fp) != 1) return 0; + return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]); +#else + int a=fp->vi_getcc(), b=fp->vi_getcc(); + /* just return 0 if we hit the end-of-file */ + return a>=0 && b>=0 ? (a<<8)+b : 0; +#endif +} + +/** main loop to parse JPEG structure */ +void jai_parse_jpeg(struct jai_gfxinfo *result, DecoderTeller *fp, bool must_be_baseline) { + int c; + unsigned int length; + unsigned char had_adobe; + + result->bad=9; /* signal invalid return value */ + result->id_rgb=0; + result->had_jfif=0; + result->colortransform=127; /* no Adobe marker yet */ + // fseek(fp, 0L, SEEK_SET); /* position file pointer on SOF */ + + /* Verify JPEG header */ + /* Dat: maybe 0xFF != '\xFF' */ + if ((c=fp->vi_getcc())!=0xFF) return; + while ((c=fp->vi_getcc())==0xFF) ; + if (c!=M_SOI) return; + + result->bad=1; + // fprintf(stderr, "welcome ofs=%ld\n", fp->vi_tell()); + while (1) { + if ((c=fp->vi_getcc())!=0xFF) { result->bad=8; return; } + while ((c=fp->vi_getcc())==0xFF) ; + if (c==-1) { result->bad=2; return; } + switch (c) { + case M_SOF0: do_SOF: + if (result->bad!=1) { result->bad=4; return; } /* only one M_SOF allowed */ + result->SOF_type=c-M_SOF0; + result->SOF_offs=fp->vi_tell(); + // fprintf(stderr, "SOF_offs=%d\n", result->SOF_offs); + /* handle SOFn block */ + length=jai_read2(fp); + result->bpc = fp->vi_getcc(); + result->height = jai_read2(fp); + result->width = jai_read2(fp); + result->cpp = fp->vi_getcc(); + if ((length-=8)!=3U*result->cpp) return; + if (result->bpc!=8) { result->bad=6; return; } + if (result->cpp!=1 && result->cpp!=3 && result->cpp!=4) { result->bad=5; return; } + assert(length>=3); + if (result->cpp==3) { + result->id_rgb =fp->vi_getcc()=='R'; result->hvs=fp->vi_getcc(); fp->vi_getcc(); + result->id_rgb&=fp->vi_getcc()=='G'; fp->vi_getcc(); fp->vi_getcc(); + result->id_rgb&=fp->vi_getcc()=='B'; fp->vi_getcc(); fp->vi_getcc(); + } else { length-=2; fp->vi_getcc(); result->hvs=fp->vi_getcc(); while (length--!=0) fp->vi_getcc(); } + result->bad=2; + break; + case M_SOF1: + case M_SOF2: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + if (!must_be_baseline) goto do_SOF; + // fprintf(stderr, "SOF%u\n", marker-M_SOF0); assert(0); + result->bad=3; + return; + case M_SOS: /* we are about to hit image data. We're done. Success. */ + if (result->bad==2 /* && !feof(fp)*/) { /* Dat: !feof() already guaranteed */ + if (result->cpp==1) { + result->colorspace=Image::Sampled::CS_GRAYSCALE; + } else if (result->cpp==3) { + result->colorspace=Image::Sampled::CS_YCbCr; + if (result->had_jfif!=0) ; + else if (result->colortransform==0) result->colorspace=Image::Sampled::CS_RGB; + else if (result->colortransform==1) ; + else if (result->colortransform!=127) Error::sev(Error::EERROR) << "JAI: unknown ColorTransform: " << (unsigned)result->colortransform << (Error*)0; + else if (result->id_rgb!=0) result->colorspace=Image::Sampled::CS_RGB; + /* Imp: check for id_ycbcr */ + else Error::sev(Error::WARNING) << "JAI: assuming YCbCr color space" << (Error*)0; + } else if (result->cpp==4) { + result->colorspace=Image::Sampled::CS_CMYK; + if (result->colortransform==0) ; + else if (result->colortransform==2) result->colorspace=Image::Sampled::CS_YCCK; + else if (result->colortransform!=127) Error::sev(Error::EERROR) << "JAI: unknown ColorTransform: " << (unsigned)result->colortransform << (Error*)0; + } else assert(0); + result->bad=0; + } + /* fall through */ + case M_EOI: /* premature EOF */ + return; + case M_APP0: /* JFIF application-specific marker */ + length=jai_read2(fp); + if (length==2+4+1+2+1+2+2+1+1) { + result->had_jfif=fp->vi_getcc()=='J' && fp->vi_getcc()=='F' && fp->vi_getcc()=='I' && + fp->vi_getcc()=='F' && fp->vi_getcc()==0; + length-=7; + } else length-=2; + while (length--!=0) fp->vi_getcc(); + break; + case M_APP14: /* Adobe application-specific marker */ + length=jai_read2(fp); + if ((length-=2)==5+2+2+2+1) { + had_adobe=fp->vi_getcc()=='A' && fp->vi_getcc()=='d' && fp->vi_getcc()=='o' && + fp->vi_getcc()=='b' && fp->vi_getcc()=='e' && ((unsigned char)fp->vi_getcc())>=1; + fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); + if (had_adobe) result->colortransform=fp->vi_getcc(); + else fp->vi_getcc(); + } else while (length--!=0) fp->vi_getcc(); + break; + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP15: + /* fall through */ + default: { /* anything else isn't interesting */ + /* skip over a variable-length block; assumes proper length marker */ + unsigned short length; + length = jai_read2(fp); + length -= 2; /* length includes itself */ + #if 0 /**** pts: fseek would disturb later ftell()s and feof()s */ + fseek(fp, (long) length, SEEK_CUR); /* skip the header */ + #else + while (length--!=0) fp->vi_getcc(); /* make feof(fp) correct */ + #endif + } + } + } +} + +char *jai_errors[]={ + (char*)NULLP, + /*1*/ "missing SOF0 marker", + /*2*/ "premature EOF", + /*3*/ "not a Baseline JPEG (SOF must be SOF0)", + /*4*/ "more SOF0 markers", + /*5*/ "bad # components", + /*6*/ "bad bpc", + /*7*/ "?", + /*8*/ "0xFF expected", + /*9*/ "invalid JPEG header", + // /*10*/ "not ending with EOI", /* not output by jai_handle_jpeg! */ +}; + +static Image::Sampled *in_jai_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) { + // assert(0); + struct jai_gfxinfo gi; + Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd; + FILE *file_=ufdd->getFILE(/*seekable:*/true); + jai_parse_jpeg(&gi, ufdd); + // jai_parse_jpeg(&gi, (FILE*)file_); + // long ftel=ftell((FILE*)file_); + if (gi.bad!=0) Error::sev(Error::EERROR) << "JAI: " << jai_errors[gi.bad] << (Error*)0; + // printf("ftell=%lu\n", ftell((FILE*)file_)); + fseek((FILE*)file_, 0L, 2); /* EOF */ + long flen=ftell((FILE*)file_); /* skip extra bytes after EOI. Imp: no need to do this */ + // fprintf(stderr, "flen=%lu\n", flen); + assert(flen>2); + rewind((FILE*)file_); + JAI *ret=new JAI(gi.width,gi.height,gi.bpc,gi.colorspace,flen,gi.SOF_offs,gi.hvs); + if (fread(ret->getHeadp(), flen, 1, (FILE*)file_)!=1 || ferror((FILE*)file_)) { + ret->fixEOI(); + /* fclose((FILE*)file_); */ + Error::sev(Error::EERROR) << "JAI: IO error" << (Error*)0; + } + /* fclose((FILE*)file_); */ + return ret; +} + +static Image::Loader::reader_t in_jai_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const& loadHints, Image::Loader::UFD* ufd) { + if (0!=memcmp(buf, "\xff\xd8\xff", 3) + || !(loadHints.findFirst((char const*)",jpeg-asis,",6)!=loadHints.getLength() || loadHints.findFirst((char const*)",asis,",6)!=loadHints.getLength()) + ) return 0; + Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd; + ufdd->seek(0); + Image::Loader::reader_t ret=jai_is_baseline_jpeg(ufdd) ? in_jai_reader : 0; + ufdd->seek(0); + return ret; +} + +#if 0 /* Filter::FlatR* used by JPEGSOF0Encode::vi_write() in appliers.cpp */ +static inline int getc_(Filter::FlatR *f) { return f->getcc(); } +static inline long ftell_(Filter::FlatR *f) { return f->tell(); } +void jai_parse_jpeg(struct jai_gfxinfo *result, Filter::FlatR *f) { + jai_handle_jpeg(result, f); +} +void jai_parse_jpeg(struct jai_gfxinfo *result, FILE *f) { + jai_handle_jpeg(result, f); +} +#endif + +#if 0 /* unused */ +int jai_is_baseline_jpeg(char const* filename) { + /* by pts@fazekas.hu at Tue Mar 11 20:27:56 CET 2003 */ + FILE *f=fopen(filename, "rb"); + if (!f) return -1; + Filter::FILED filed(f, /*closep:*/true); + return jai_is_baseline_jpeg(&filed); +} +#endif +int jai_is_baseline_jpeg(/*DecoderTeller*/Filter::UngetFILED *fp) { + char buf[3]; + struct jai_gfxinfo gi; + bool qfalse=(3!=fp->vi_read(buf, 3) || 0!=memcmp(buf, "\xff\xd8\xff", 3)); + fp->unread(buf, 3); + if (qfalse) return false; + fp->getFILE(/*seekable*/true); /* make it seekable, so the caller can seek back */ + jai_parse_jpeg(&gi, fp, /*must_be_baseline:*/false); + fp->seek(0); + return gi.bad!=0 ? -1 : gi.SOF_type==0; +} +#else +#define in_jai_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_JAI */ + +Image::Loader in_jai_loader = { "JAI", in_jai_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_jai.hpp b/Build/source/utils/sam2p/in_jai.hpp new file mode 100644 index 00000000000..b9bdae11f63 --- /dev/null +++ b/Build/source/utils/sam2p/in_jai.hpp @@ -0,0 +1,46 @@ +/* in_jai.hpp -- Tue Jun 11 19:05:04 CEST 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef IN_JAI_HPP +#define IN_JAI_HPP 1 + +#include "config2.h" + +#if USE_IN_JAI + +#include "gensio.hpp" + +struct jai_gfxinfo { + /** 0 for baseline JPEG, 1..15 for other JPEG compression */ + unsigned char SOF_type; + unsigned char colorspace; + unsigned char bad, bpc, cpp, had_jfif, colortransform, id_rgb; + /** (Horiz<<4+Vert) sampling factor for the first color component. Usually + * 0x11, but TIFF defaults to 0x22. + */ + unsigned char hvs; + /*Image::Sampled::dimen_t*/slen_t height, width; + /** Offset of byte just _after_ the first SOF marker (FF C0 or alike) + * from the beginning of the file. + */ + slen_t SOF_offs; +}; + +extern char *jai_errors[]; +#if 0 + extern void jai_parse_jpeg(struct gfxinfo *result, Filter::FlatR *f); + extern void jai_parse_jpeg(struct gfxinfo *result, FILE *f); +#else + extern void jai_parse_jpeg(struct jai_gfxinfo *result, DecoderTeller *fp, bool must_be_baseline=true); + /** Doesn't treat `-' as a special filename. @return 0, 1, or -1 on I/O error */ + extern int jai_is_baseline_jpeg(char const* filename); + extern int jai_is_baseline_jpeg(/*DecoderTeller*/ Filter::UngetFILED *fp); +#endif + +#endif + +#endif /* in_jai.hpp */ diff --git a/Build/source/utils/sam2p/in_jpeg.cpp b/Build/source/utils/sam2p/in_jpeg.cpp new file mode 100644 index 00000000000..74df59b6d1d --- /dev/null +++ b/Build/source/utils/sam2p/in_jpeg.cpp @@ -0,0 +1,37 @@ +/* + * in_jpeg.cpp -- read JPEG (JFIF and other) files with djpeg + * by pts@fazekas.hu at Sun Apr 14 14:50:30 CEST 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" + +#if USE_IN_JPEG + +#include "error.hpp" +#include "gensio.hpp" +#include "helpere.hpp" +#include <string.h> /* memchr() */ +#include <stdio.h> /* printf() */ + +static Image::Sampled *in_jpeg_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + // Error::sev(Error::EERROR) << "Cannot load JPEG images yet." << (Error*)0; + HelperE helper("djpeg"); /* Run external process `djpeg' to convert JPEG -> PNM */ + Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd); + ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */ + return helper.getImg(); +} + +static Image::Loader::reader_t in_jpeg_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const& loadHints, Image::Loader::UFD*) { + return (0==memcmp(buf, "\xff\xd8", 2)) && loadHints.findFirst((char const*)",asis,",6)==loadHints.getLength() + ? in_jpeg_reader : 0; +} + +#else +#define in_jpeg_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_XPM */ + +Image::Loader in_jpeg_loader = { "JPEG", in_jpeg_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_lbm.cpp b/Build/source/utils/sam2p/in_lbm.cpp new file mode 100644 index 00000000000..e633ff70341 --- /dev/null +++ b/Build/source/utils/sam2p/in_lbm.cpp @@ -0,0 +1,277 @@ +/* + * in_lbm.cpp -- read a Deluxe Paint IFF/ILBM file + * by pts@fazekas.hu at Fri Mar 1 17:12:16 CET 2002 + * -- Fri Mar 1 22:28:03 CET 2002 + * + * I've ripped the reader code from xscavenger's source, and enhanced it + * a little bit (at Fri Mar 1 17:12:43 CET 2002), but I still think that + * this can read only the minority of the LBM files around. + */ +/* Imp: get docs about the LBM format, and rewrite this from scratch */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" +#include "error.hpp" + +#if USE_IN_LBM + +#include <string.h> /* memchr() */ +#include "gensio.hpp" + +#define FORM 0x464f524dL +#define ILBM 0x494c424dL +#define PBM 0x50424d20L +#define CMAP 0x434d4150L +#define BODY 0x424f4459L +#define BMHD 0x424d4844L +/* typedef unsigned char uchar; */ +#define MAXBYTES 128 /* ?? */ + +/* --- */ + +#if SIZEOF_INT>=4 +typedef unsigned int u32_t; +typedef signed int s32_t; +#else +typedef unsigned long u32_t; +typedef signed long s32_t; +#endif + +class LBMRead { + public: + inline LBMRead(FILE *f_): f(f_) {} + /* inline ~LBMRead() { fclose(f); } */ + Image::Sampled *doit(); + protected: + inline int getcn(); + void errUnEOF(); + void err(char *s); + u32_t getUnpack(unsigned len, char *where); + u32_t getu32(); + unsigned getu16(); + FILE *f; +}; + +//static inline int fixbyte(char *take,int bit,int depth) { +// int res=0,mask=1; +// while (depth--) { +// if (*take & bit) res|=mask; +// mask<<=1; +// take+=MAXBYTES; +// } +// return res; +//} +#if 0 +static void debit(char *picput, char *lines, unsigned wd, unsigned depth) { + unsigned depth2, bit=128, res, i, mask; + unsigned byteswide=((wd+15)>>4)<<1; + unsigned char *take; + for (i=0;i<wd;i++) { + mask=1; depth2=depth; take=(unsigned char*)lines; res=0; while (depth2--!=0) { + if (0!=(*take&bit)) res|=mask; + mask<<=1; + take+=byteswide; + } + *picput++=res; + if (bit==1) { bit=128; ++lines; } else bit>>=1; + } +} +#endif + +void LBMRead::errUnEOF() { + Error::sev(Error::EERROR) << "LBM: unexpected EOF" << (Error*)0; +} +void LBMRead::err(char *s) { + Error::sev(Error::EERROR) << s << (Error*)0; +} + +inline int LBMRead::getcn() { + int i=MACRO_GETC(f); + if (i==-1) errUnEOF(); + return i; +} + +u32_t LBMRead::getUnpack(unsigned len, char *where) { + /* RLE decompression */ + int ch,ch2; + u32_t sofar=0; + while (len>0) { + ch=getcn(); + if (ch<128) { + ch++; + assert(ch>=1); + if (len<(unsigned)ch) err("LBM: packet#1 too long"); + len-=ch; + sofar+=1+ch; + while (ch--) *where++=getcn(); + } else { + ch=1-(ch-256); /* 2..129 */ + assert(ch>=1); + // fprintf(stderr, "len=%u ch=%u\n", len, ch); + if (len<(unsigned)ch) err("LBM: packet#2 too long"); + len-=ch; + // fprintf(stderr, "xlen=%u ch=%u\n", len, ch); + ch2=getcn(); + sofar+=2; + while (ch--) *where++=ch2; + } + } + return sofar; +} + +u32_t LBMRead::getu32() { + u32_t val1=0; + val1=getcn()<<24L; + val1|=getcn()<<16L; + val1|=getcn()<<8; + val1|=getcn(); + return val1; +} +unsigned LBMRead::getu16() { + u32_t val1=0; + val1|=getcn()<<8; + val1|=getcn(); + return val1; +} + +Image::Sampled *LBMRead::doit() { + char temparea[16]; + u32_t type, size, i; + unsigned char comp=0; + unsigned j; + int ii; + Image::Sampled::dimen_t lbm_wd, lbm_ht, byteswide, depth=0; /* pts */ + unsigned transp=256; + Image::Sampled *img=(Image::Sampled*)NULLP; + bool had_cmap=false, had_body=false, do_skip, had_transp=false; + + /* sprintf(temparea,"%s/%s/%s",localname,localdirname,name); */ + for (i=0;i<12;i++) temparea[i]=getcn(); + if (0!=memcmp(temparea,"FORM",4) || + 0!=memcmp(temparea+8,"ILBM",4)) err("LBM: magic says: this is not an LBM"); + lbm_wd=lbm_ht=byteswide=0; + while ((ii=MACRO_GETC(f))!=-1 && ii!='\0') { + ungetc(ii,f); + if ((type=getu32())==0xffffffffL) break; + size=getu32(); + do_skip=(size&1); /* pad to even size */ + // fprintf(stderr,"size=%u\n", size); + if (type==BMHD) { + if (img!=NULLP) err("LBM: duplicate BMHD"); + // if (size>sizeof(temparea)) { + // for (i=0;i<sizeof(temparea);i++) temparea[i]=getcn(); + // for (;i<size;i++) getcn(); + // } else for (i=0;i<size;i++) temparea[i]=getcn(); + if (size<20) errUnEOF(); + lbm_wd=getu16(); + lbm_ht=getu16(); + if (getu32()!=0) err("LBM: expected offsets==0"); + depth=getcn(); + if (depth!=24 && (depth<1 || depth>8)) err("LBM: invalid color depth"); + if (getcn()!=0) err("LBM: expected masking==0"); + if ((comp=getcn())>=2) err("LBM: expected comp==0 || comp==1"); + getcn(); /* ignore padding */ + transp=getu16(); /* index of transparent color */ + // fprintf(stderr, "htt=%u transp=%u\n", lbm_ht, transp); + getu16(); /* Ignore aspect ratio. */ + if (lbm_wd!=getu16() || lbm_ht!=getu16()) err("LBM: inconsistent dimens"); + /* ^^^ Dat: pagex, pagey */ + byteswide=((lbm_wd+15)>>4)<<1; + /*printf("(%d,%d) %d bpp\n",lbm_wd,lbm_ht,depth);*/ + if (depth==24) { + had_cmap=true; + img=new Image::RGB(lbm_wd, lbm_ht, 8); + } else { + img=new Image::Indexed(lbm_wd, lbm_ht, 1<<depth, 8); + memset(img->getHeadp(), '\0', 3*(1<<depth)); /* clear palette */ + } + } else if (type==BODY) { + if (!had_cmap) err("LBM: should be CMAP, BODY"); + // fprintf(stderr, "wd=%u, %u exp=%u\n", lbm_wd, size, byteswide*depth*lbm_ht); + if (comp==0 && size!=byteswide*depth*lbm_ht) err("LBM: wrong BODY length"); + char *buf=new char[byteswide*depth], *picput=img->getRowbeg(); // const_cast<char*>(img->getCString()); + for (i=0;i<lbm_ht;i++) { + // fprintf(stderr, "i=%u ht=%u\n", i, lbm_ht); + if (comp) { for (j=0;j<depth;j++) size-=getUnpack(byteswide, buf+byteswide*j); } + else { for (j=0;j<depth*byteswide;j++) buf[j]=getcn(); } + /* ^^^ Imp: test !comp: find uncompressed LBM files */ + if ((s32_t)size<0) goto dtl; + + /* debit() */ + /* LBM compression is quite stupid: it run-length-compresses + * individiual bits of the color depth as 8-bit bytes. Plus it requires + * each bit vector to be aligned to 16-bit boundary. + */ + Image::Sampled::dimen_t depth2, bit=128, res, i, mask; + // unsigned byteswide=((lbm_wd+15)>>4)<<1; + unsigned char *take, *lines=(unsigned char*)buf; + if (depth!=24) { + for (i=0;i<lbm_wd;i++) { + mask=1; depth2=depth; take=lines; res=0; while (depth2--!=0) { + if (0!=(*take&bit)) res|=mask; + mask<<=1; + take+=byteswide; + } + if (res==transp) had_transp=true; + *picput++=res; + if (bit==1) { bit=128; ++lines; } else bit>>=1; + } + } else { + u32_t res; + for (i=0;i<lbm_wd;i++) { + mask=1; depth2=24; take=lines; res=0; while (depth2--!=0) { + if (0!=(*take&bit)) res|=mask; + mask<<=1; + take+=byteswide; + } + /* No transparency here. */ + *picput++=res; /* Shift order verified. */ + *picput++=res>>8; + *picput++=res>>16; + if (bit==1) { bit=128; ++lines; } else bit>>=1; + } + } + } + // fprintf(stderr,"size=%u\n", size); + if (size>1) { dtl: err("LBM: data too long"); } + if (size==1) getcn(); + if (had_transp) { assert(depth!=24); static_cast<Image::Indexed*>(img)->setTransp(transp); } + // img->getRowbeg()[0]='\001'; img->getRowbeg()[1]='\002'; + delete [] buf; + had_body=true; + } else if (type==CMAP) { + if (img==NULLP) err("LBM: should be: BMHD, CMAP"); + if (had_cmap) err("LBM: duplicate CMAP"); + if (size>3*(1U<<depth)) err("LBM: CMAP too large"); + char *colormap=img->getHeadp(); + // fprintf(stderr,"Si=%d size=%u\n", img->getRowbeg()-colormap, size); + for (i=0;i<size;i++) colormap[i]=getcn(); + had_cmap=true; + } else { + Error::sev(Error::WARNING) << "LBM: unknown tag ignored: " << type << (Error*)0; + while (size--) MACRO_GETC(f); + } + if (do_skip) getcn(); + // fprintf(stderr,"do_skip=%d t=%lu\n", do_skip, ftell(f)); + } + if (!had_body) err("LBM: missing BODY"); + return img; +} + +static Image::Sampled *in_lbm_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + return LBMRead(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false)).doit(); + /* ^^^ Destructor: fclose((FILE*)file_); */ +} + +static Image::Loader::reader_t in_lbm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return (0==memcmp(buf,"FORM",4) && 0==memcmp(buf+8,"ILBM",4)) ? in_lbm_reader : 0; +} + +#else +#define in_lbm_checker NULLP +#endif /* USE_IN_XPM */ + +Image::Loader in_lbm_loader = { "LBM", in_lbm_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_pcx.cpp b/Build/source/utils/sam2p/in_pcx.cpp new file mode 100644 index 00000000000..49655d7b03d --- /dev/null +++ b/Build/source/utils/sam2p/in_pcx.cpp @@ -0,0 +1,534 @@ +/* + * in_pcx.cpp: loads PCX images + * modified by pts@fazekas.hu at Fri Apr 12 22:16:08 CEST 2002 + * -- Fri Apr 12 23:54:57 CEST 2002 + * + * xvpcx.c - load routine for PCX format pictures + * + * LoadPCX(fname, pinfo) - loads a PCX file + */ + +/**** pts ****/ +#include "config2.h" +#include "image.hpp" + +#if USE_IN_PCX +#include "error.hpp" +#include "gensio.hpp" +#include <string.h> + + +/* Imp: palette handling etc. according to PCX_VER, see decode.c */ +#define dimen Image::Sampled::dimen_t +#define pcxError(bname,conststr) Error::sev(Error::WARNING) << "PCX: " conststr << (Error*)0 +#define WaitCursor() +#define xvbzero(p,len) memset(p, '\0', len) +#define FatalError(conststr) Error::sev(Error::EERROR) << "PCX: " conststr << (Error*)0 +#define return_pcxError(bname, conststr) Error::sev(Error::EERROR) << "PCX: " conststr << (Error*)0 +#define byte unsigned char +#define size_t slen_t +#define malloc_byte(n) new byte[n] +#define free(p) delete p +#define DEBUG 1 +/* the following list give indicies into saveColors[] array in xvdir.c */ +#define F_FULLCOLOR 0 +#define F_GREYSCALE 1 +#define F_BWDITHER 2 +/* values 'picType' can take */ +#define PIC8 8 +#define PIC24 24 +#define xv_fopen(filename,read_mode) fopen(filename,"rb") +#define BaseName(x) ((char*)0) +#define PARM(parm) parm +/* info structure filled in by the LoadXXX() image reading routines */ + +typedef struct { byte *pic; /* image data */ + dimen w, h; /* pic size */ +#if 0 /**** pts ****/ + byte r[256],g[256],b[256]; +#else + /* byte pal[3*256]; */ + byte *pal; +# define PAL_R(pinfo,idx) (pinfo)->pal[3*(idx)] +# define PAL_G(pinfo,idx) (pinfo)->pal[3*(idx)+1] +# define PAL_B(pinfo,idx) (pinfo)->pal[3*(idx)+2] +#endif /* colormap, if PIC8 */ +#if 0 /**** pts ****/ + int colType; /* def. Color type to save in */ + int type; /* PIC8 or PIC24 */ + int normw, normh; /* 'normal size' of image file + (normally eq. w,h, except when + doing 'quick' load for icons */ + int frmType; /* def. Format type to save in */ + char fullInfo[128]; /* Format: field in info box */ + char shrtInfo[128]; /* short format info */ + char *comment; /* comment text */ + int numpages; /* # of page files, if >1 */ + char pagebname[64]; /* basename of page files */ +#endif + } PICINFO; + + +/* #include "copyright.h" */ + +/* + * the following code has been derived from code written by + * Eckhard Rueggeberg (Eckhard.Rueggeberg@ts.go.dlr.de) + */ + + +/* #include "xv.h" */ + +/* offsets into PCX header */ +#define PCX_ID 0 +#define PCX_VER 1 +#define PCX_ENC 2 +#define PCX_BPP 3 +#define PCX_XMINL 4 +#define PCX_XMINH 5 +#define PCX_YMINL 6 +#define PCX_YMINH 7 +#define PCX_XMAXL 8 +#define PCX_XMAXH 9 +#define PCX_YMAXL 10 +#define PCX_YMAXH 11 + /* hres (12,13) and vres (14,15) not used */ +#define PCX_CMAP 16 /* start of 16*3 colormap data */ +#define PCX_PLANES 65 +#define PCX_BPRL 66 +#define PCX_BPRH 67 + +#define PCX_MAPSTART 0x0c /* Start of appended colormap */ + + +static int pcxLoadImage8 PARM((char *, FILE *, PICINFO *, byte *)); +static int pcxLoadImage24 PARM((char *, FILE *, PICINFO *, byte *)); +static void pcxLoadRaster PARM((FILE *, byte *, int, byte *, dimen, dimen)); +#if 0 /**** pts ****/ +static int pcxError PARM((char *, char *)); +#endif + + +/*******************************************/ +static Image::Sampled *LoadPCX +#if 0 /**** pts ****/ + ___((char *fname, PICINFO *pinfo), (fname, pinfo), (char *fname; PICINFO *pinfo;)) +#else + ___((FILE *fp, PICINFO *pinfo), (fname, pinfo), (char *fname; PICINFO *pinfo;)) +#endif +/*******************************************/ +{ + Image::Sampled *ret=(Image::Sampled*)NULLP; + byte hdr[128]; +#if 0 /**** pts ****/ + long filesize; + char *bname; + FILE *fp; + char *errstr; byte *image; + int gray; +#endif + int i, colors, fullcolor; + + pinfo->pic = (byte *) NULL; + pinfo->pal = (byte *) NULL; +#if 0 /**** pts ****/ + pinfo->type = PIC8; + pinfo->comment = (char *) NULL; + bname = BaseName(fname); + + /* open the stream */ + fp = xv_fopen(fname,"r"); + if (!fp) return_pcxError(bname, "unable to open file"); +#endif + +#if 0 /**** pts ****/ + /* figure out the file size */ + fseek(fp, 0L, 2); + filesize = ftell(fp); + fseek(fp, 0L, 0); +#endif + + /* read the PCX header */ + fread(hdr, (size_t) 128, (size_t) 1, fp); + if (ferror(fp) || feof(fp)) { + /* fclose(fp); */ + return_pcxError(bname, "EOF reached in PCX header.\n"); + } + + if (hdr[PCX_ID] != 0x0a || hdr[PCX_VER] > 5) { + /* fclose(fp); */ + return_pcxError(bname,"unrecognized magic number"); + } + + pinfo->w = (hdr[PCX_XMAXL] + ((int) hdr[PCX_XMAXH]<<8)) + - (hdr[PCX_XMINL] + ((int) hdr[PCX_XMINH]<<8)); + + pinfo->h = (hdr[PCX_YMAXL] + ((int) hdr[PCX_YMAXH]<<8)) + - (hdr[PCX_YMINL] + ((int) hdr[PCX_YMINH]<<8)); + + pinfo->w++; pinfo->h++; + + colors = 1 << (hdr[PCX_BPP] * hdr[PCX_PLANES]); + fullcolor = (hdr[PCX_BPP] == 8 && hdr[PCX_PLANES] == 3); + +#if USE_DEBUG_MESSAGES + if (DEBUG) { + fprintf(stderr,"PCX: %dx%d image, version=%d, encoding=%d\n", + pinfo->w, pinfo->h, hdr[PCX_VER], hdr[PCX_ENC]); + fprintf(stderr," BitsPerPixel=%d, planes=%d, BytePerRow=%d, colors=%d\n", + hdr[PCX_BPP], hdr[PCX_PLANES], + hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8), + colors); + } +#endif + + if (colors>256 && !fullcolor) { + /* fclose(fp); */ + return_pcxError(bname,"No more than 256 colors allowed in PCX file."); + } + + if (hdr[PCX_ENC] != 1) { + /* fclose(fp); */ + return_pcxError(bname,"Unsupported PCX encoding format."); + } + + /* load the image, the image function fills in pinfo->pic */ + if (!fullcolor) { + Image::Indexed *img=new Image::Indexed(pinfo->w, pinfo->h, colors, 8); + pinfo->pal=(byte*)img->getHeadp(); + ASSERT_SIDE(pcxLoadImage8((char*)NULLP/*bname*/, fp, pinfo, hdr)); + memcpy(img->getRowbeg(), pinfo->pic, pinfo->w*pinfo->h); + ret=img; + } else { + Image::RGB *img=new Image::RGB(pinfo->w, pinfo->h, 8); + ASSERT_SIDE(pcxLoadImage24((char*)NULLP/*bname*/, fp, pinfo, hdr)); + memcpy(img->getRowbeg(), pinfo->pic, pinfo->w*pinfo->h*3); + ret=img; + } + free(pinfo->pic); + pinfo->pic=(byte*)NULLP; + + + if (ferror(fp) | feof(fp)) /* just a warning */ + pcxError(bname, "PCX file appears to be truncated."); + + if (colors>16 && !fullcolor) { /* handle trailing colormap */ + while (1) { + i=MACRO_GETC(fp); + if (i==PCX_MAPSTART || i==EOF) break; + } + +#if 0 /**** pts ****/ + for (i=0; i<colors; i++) { + PAL_R(pinfo,i) = MACRO_GETC(fp); + PAL_G(pinfo,i) = MACRO_GETC(fp); + PAL_B(pinfo,i) = MACRO_GETC(fp); + } +#else + fread(pinfo->pal, 1, colors*3, fp); +#endif + + if (ferror(fp) || feof(fp)) { + pcxError(bname,"Error reading PCX colormap. Using grayscale."); + for (i=0; i<256; i++) PAL_R(pinfo,i) = PAL_G(pinfo,i) = PAL_B(pinfo,i) = i; + } + } + else if (colors<=16) { /* internal colormap */ +#if 0 /**** pts ****/ + for (i=0; i<colors; i++) { + PAL_R(pinfo,i) = hdr[PCX_CMAP + i*3]; + PAL_G(pinfo,i) = hdr[PCX_CMAP + i*3 + 1]; + PAL_B(pinfo,i) = hdr[PCX_CMAP + i*3 + 2]; + } +#else + memcpy(pinfo->pal, hdr+PCX_CMAP, colors*3); +#endif + } + + if (colors == 2) { /* b&w */ +#if 0 /**** pts ****/ + if (MONO(PAL_R(pinfo,0), PAL_G(pinfo,0), PAL_B(pinfo,0)) == + MONO(PAL_R(pinfo,1), PAL_G(pinfo,1), PAL_B(pinfo,1))) { +#else + if (PAL_R(pinfo,0)==PAL_R(pinfo,1) && PAL_G(pinfo,0)==PAL_G(pinfo,1) && PAL_B(pinfo,0)==PAL_B(pinfo,1)) { +#endif + /* create cmap */ + PAL_R(pinfo,0) = PAL_G(pinfo,0) = PAL_B(pinfo,0) = 255; + PAL_R(pinfo,1) = PAL_G(pinfo,1) = PAL_B(pinfo,1) = 0; +#if USE_DEBUG_MESSAGES + if (DEBUG) fprintf(stderr,"PCX: no cmap: using 0=white,1=black\n"); +#endif + } + } + /* fclose(fp); */ + + /* finally, convert into XV internal format */ +#if 0 /**** pts ****/ + pinfo->type = fullcolor ? PIC24 : PIC8; + pinfo->frmType = -1; /* no default format to save in */ +#endif + +#if 0 /**** pts ****/ + /* check for grayscaleitude */ + gray = 0; + if (!fullcolor) { + for (i=0; i<colors; i++) { + if ((PAL_R(pinfo,i) != PAL_G(pinfo,i)) || (PAL_R(pinfo,i) != PAL_B(pinfo,i))) break; + } + gray = (i==colors) ? 1 : 0; + } + + + if (colors > 2 || (colors==2 && !gray)) { /* grayscale or PseudoColor */ + pinfo->colType = (gray) ? F_GREYSCALE : F_FULLCOLOR; +#if 0 /**** pts ****/ + sprintf(pinfo->fullInfo, + "%s PCX, %d plane%s, %d bit%s per pixel. (%ld bytes)", + (gray) ? "Greyscale" : "Color", + hdr[PCX_PLANES], (hdr[PCX_PLANES]==1) ? "" : "s", + hdr[PCX_BPP], (hdr[PCX_BPP]==1) ? "" : "s", + filesize); +#endif + } + else { + pinfo->colType = F_BWDITHER; +#if 0 /**** pts ****/ + sprintf(pinfo->fullInfo, "B&W PCX. (%ld bytes)", filesize); +#endif + } + +#if 0 /**** pts ****/ + sprintf(pinfo->shrtInfo, "%dx%d PCX.", pinfo->w, pinfo->h); + pinfo->normw = pinfo->w; pinfo->normh = pinfo->h; +#endif +#endif + + return ret; +} + + + +/*****************************/ +static int pcxLoadImage8 ___((char *fname, FILE *fp, PICINFO *pinfo, byte *hdr), (fname, fp, pinfo, hdr), + (char *fname; + FILE *fp; + PICINFO *pinfo; + byte *hdr;)) +{ + /* load an image with at most 8 bits per pixel */ + (void)fname; /**** pts ****/ + + byte *image; + + /* note: overallocation to make life easier... */ + image = (byte *) malloc_byte((size_t) (pinfo->h + 1) * pinfo->w + 16); + if (!image) FatalError("Can't alloc 'image' in pcxLoadImage8()"); + + xvbzero((char *) image, (size_t) ((pinfo->h+1) * pinfo->w + 16)); + + switch (hdr[PCX_BPP]) { + case 1: case 2: case 4: case 8: pcxLoadRaster(fp, image, hdr[PCX_BPP], hdr, pinfo->w, pinfo->h); break; + default: + free(image); + return_pcxError(fname, "Unsupported # of bits per plane."); + } + + pinfo->pic = image; + return 1; +} + + +/*****************************/ +static int pcxLoadImage24 ___((char *fname, FILE *fp, PICINFO *pinfo, byte *hdr), (fname, fp, pinfo, hdr), + (char *fname; + FILE *fp; + PICINFO *pinfo; + byte *hdr;)) +{ + byte *pix, *pic24; + int c; + unsigned i, j, w, h, cnt, planes, bperlin, nbytes; +#if 0 /***** pts ****/ + int maxv; /* ImageMagick does not have one */ + byte scale[256]; +#endif + + (void)fname; /**** pts ****/ + + w = pinfo->w; h = pinfo->h; + + planes = (int) hdr[PCX_PLANES]; + bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8); + + /* allocate 24-bit image */ + pic24 = (byte *) malloc_byte((size_t) w*h*planes); + if (!pic24) FatalError("couldn't malloc 'pic24'"); + + xvbzero((char *) pic24, (size_t) w*h*planes); + +#if 0 /**** pts ****/ + maxv = 0; +#endif + pix = pinfo->pic = pic24; + i = 0; /* planes, in this while loop */ + j = 0; /* bytes per line, in this while loop */ + nbytes = bperlin*h*planes; + + while (nbytes > 0 && (c = MACRO_GETC(fp)) != EOF) { + if (c>=0xC0) { /* have a rep. count */ + cnt = c & 0x3F; + c = MACRO_GETC(fp); + if (c == EOF) { MACRO_GETC(fp); break; } + } + else cnt = 1; + +#if 0 /**** pts ****/ + if (c > maxv) maxv = c; +#endif + + while (cnt-- > 0) { + if (j < w) { + *pix = c; + pix += planes; + } + j++; + nbytes--; + if (j == bperlin) { + j = 0; + if (++i < planes) { + pix -= (w*planes)-1; /* next plane on this line */ + } + else { + pix -= (planes-1); /* start of next line, first plane */ + i = 0; + } + } + } + } + + +#if 0 /**** pts ****/ + /* scale all RGB to range 0-255, if they aren't */ + + if (maxv<255) { + for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv; + + for (i=0, pix=pic24; i<h; i++) { + if ((i&0x3f)==0) WaitCursor(); + for (j=0; j<w*planes; j++, pix++) *pix = scale[*pix]; + } + } +#endif + + return 1; +} + + + +/*****************************/ +static void pcxLoadRaster ___((FILE *fp, byte *image, int depth, byte *hdr, dimen w, dimen h), (fp, image, depth, hdr, w, h), + (FILE *fp; + byte *image, *hdr; + int depth; + dimen w,h;)) +{ + /* was supported: 8 bits per pixel, 1 plane, or 1 bit per pixel, 1-8 planes */ + + unsigned row, bcnt, bperlin, pad, cnt, pmask, i, pleft; + int b; + byte *oldimage; + + bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8); + if (depth == 1) pad = (bperlin * 8) - w; + else pad = bperlin - w; + + row = bcnt = 0; + + pmask = 1; oldimage = image; + pleft=hdr[PCX_PLANES]; + + while ( (b=MACRO_GETC(fp)) != EOF) { + if (b>=0xC0) { /* have a rep. count */ + cnt = b & 0x3F; + b = MACRO_GETC(fp); + if (b == EOF) { MACRO_GETC(fp); return; } + } + else cnt = 1; + + for (i=0; i<cnt; i++) { + switch (depth) { + case 1: + *image++|=(b&0x80)?pmask:0; + *image++|=(b&0x40)?pmask:0; + *image++|=(b&0x20)?pmask:0; + *image++|=(b&0x10)?pmask:0; + *image++|=(b&0x8)?pmask:0; + *image++|=(b&0x4)?pmask:0; + *image++|=(b&0x2)?pmask:0; + *image++|=(b&0x1)?pmask:0; + break; + case 2: /**** pts ****/ + *image++|=((b>>6)&3)*pmask; + *image++|=((b>>4)&3)*pmask; + *image++|=((b>>2)&3)*pmask; + *image++|=((b )&3)*pmask; + break; + case 4: /**** pts ****/ + *image++|=((b>>4)&15)*pmask; + *image++|=((b )&15)*pmask; + break; + default: + *image++=(byte)b; + } + + bcnt++; + + if (bcnt == bperlin) { /* end of a line reached */ + bcnt = 0; + + if (--pleft==0) { /* moved to next row */ + pleft=hdr[PCX_PLANES]; + pmask=1; + image -= pad; + oldimage = image; + row++; + if (row >= h) return; /* done */ + } + else { /* next plane, same row */ + image = oldimage; + pmask<<=depth; + } + } + } + } +} + +#if 0 /**** pts ****/ +/*******************************************/ +static int pcxError(fname,st) + char *fname, *st; +{ + SetISTR(ISTR_WARNING,"%s: %s", fname, st); + return 0; +} +#endif + +static Image::Sampled *in_pcx_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + PICINFO pinfo_; + return LoadPCX(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false), &pinfo_); +} +static Image::Loader::reader_t in_pcx_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return buf[PCX_ID]==0x0a + && (unsigned char)buf[PCX_VER]<=5 + && buf[PCX_ENC]==1 + && buf[PCX_BPP]<=8 + ? in_pcx_reader : 0; +} + +#else +#define in_pcx_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_PCX */ + +Image::Loader in_pcx_loader = { "PCX", in_pcx_checker, 0 }; + +/* __END__ */ diff --git a/Build/source/utils/sam2p/in_png.cpp b/Build/source/utils/sam2p/in_png.cpp new file mode 100644 index 00000000000..dc5f22e1a66 --- /dev/null +++ b/Build/source/utils/sam2p/in_png.cpp @@ -0,0 +1,65 @@ +/* + * in_png.cpp -- read PNG (Portable Network Graphics, PNG is Not GIF) files with pngtopnm + * by pts@fazekas.hu at Sun Apr 14 14:50:30 CEST 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" + +#if USE_IN_PNG + +#include "error.hpp" +#include "gensio.hpp" +#include "helpere.hpp" +#include <string.h> /* memchr() */ +#include <stdio.h> /* printf() */ + +static Image::Sampled *in_png_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) { + // Error::sev(Error::EERROR) << "Cannot load PNG images yet." << (Error*)0; + char const* cmd= +#if 0 + #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT + "pngtopnm %S >%D\npngtopnm -alpha %S >>%D"; + #else + #if OS_COTY==COTY_UNIX + "(pngtopnm <%S && pngtopnm -alpha <%S) >%D"; + #else + "pngtopnm %S >%D\npngtopnm -alpha %S >>%D"; + #endif + #endif +#else /* Wed Feb 5 19:03:58 CET 2003 */ + #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT + "png22pnm -rgba %S >%D"; + #else + #if OS_COTY==COTY_UNIX + #if 1 + "(png22pnm -rgba %S || (pngtopnm <%S && pngtopnm -alpha <%S)) >%D"; + #else + /* Dat: not using this to suppress `sh: png22pnm: command not found', because + * it would hide precious error messages printed by png22pnm. + */ + "((png22pnm -rgba %S 2>/dev/null)|| (pngtopnm <%S && pngtopnm -alpha <%S)) >%D"; + #endif + #else + "png22pnm -rgba %S >%D"; + #endif + #endif +#endif + HelperE helper(cmd); /* Run external process pngtopnm */ + Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd); + ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */ + return helper.getImg(); +} + +static Image::Loader::reader_t in_png_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return 0==memcmp(buf,"\211PNG\r\n\032\n",8) ? in_png_reader : 0; +} + +#else +#define in_png_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_PNG */ + +Image::Loader in_png_loader = { "PNG", in_png_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_pnm.cpp b/Build/source/utils/sam2p/in_pnm.cpp new file mode 100644 index 00000000000..4c5181a0be9 --- /dev/null +++ b/Build/source/utils/sam2p/in_pnm.cpp @@ -0,0 +1,76 @@ +/* + * in_pnm.cpp -- read a NetPBM PNM bitmap file + * by pts@fazekas.hu at Sat Mar 2 00:46:54 CET 2002 + * + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" +#include "error.hpp" + +#if USE_IN_PNM + +#include "gensio.hpp" +#include "input-pnm.ci" +#include <string.h> + +static Image::Sampled *in_pnm_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) { + Image::Sampled *ret=0; + #if 0 + FILE *f=((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false); + bitmap_type bitmap=pnm_load_image(f); + #else + Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd; + bitmap_type bitmap=pnm_load_image(ufdd); + #endif + /* Imp: Work without duplicated memory allocation */ + if (BITMAP_PLANES(bitmap)==1) { + Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + ret=img; + } else if (BITMAP_PLANES(bitmap)==3) { + Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + /* fwrite(BITMAP_BITS(bitmap), 1, (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap), stdout); */ + ret=img; + } else assert(0 && "invalid PNM depth"); + delete [] BITMAP_BITS(bitmap); + if (ufdd->vi_getcc()=='P') { + ufdd->unread("P", 1); + // Error::sev(Error::NOTICE) << "PNM: loading alpha after PNM: " + // " ftell=" << ftell(f) << + // " bytes=" << ((unsigned)bitmap.width*bitmap.height*bitmap.np) << (Error*)0; + bitmap=pnm_load_image(ufdd); + // fwrite(bitmap.bitmap,1,(unsigned)bitmap.width*bitmap.height*bitmap.np,stdout); + /* Dat: black pixel is transparent */ + if (BITMAP_PLANES(bitmap)!=1) Error::sev(Error::EERROR) << "PNM: alpha must be PBM or PGM" << (Error*)0; + Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + delete [] BITMAP_BITS(bitmap); + Image::Sampled *old=ret; + // old->packPal(); /* automatically called */ + if ((ret=old->addAlpha(img))!=old) { + Error::sev(Error::NOTICE) << "PNM: loaded alpha after PNM" << (Error*)0; + delete old; + } else { + Error::sev(Error::NOTICE) << "PNM: loaded alpha, but no transparent pixels" << (Error*)0; + } + } + /* fclose(f); */ + return ret; +} + +static Image::Loader::reader_t in_pnm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return (buf[0]=='P' && (buf[1]>='1' && buf[1]<='6') && + (buf[2]=='\t' || buf[2]==' ' || buf[2]=='\r' || buf[2]=='\n' || buf[2]=='#')) + ? in_pnm_reader : 0; +} + +#else +#define in_pnm_checker NULLP +#endif /* USE_IN_PNM */ + +Image::Loader in_pnm_loader = { "PNM", in_pnm_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_ps.cpp b/Build/source/utils/sam2p/in_ps.cpp new file mode 100644 index 00000000000..6eef951fc4c --- /dev/null +++ b/Build/source/utils/sam2p/in_ps.cpp @@ -0,0 +1,181 @@ +/* + * in_ps.cpp -- read PS and PDF files using GS + * by pts@fazekas.hu at Tue Sep 30 12:33:11 CEST 2003 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" + +#if USE_IN_PS || USE_IN_PDF + +#include "error.hpp" +#include "gensio.hpp" +#include "helpere.hpp" +#include <string.h> /* memchr() */ +#include <stdio.h> /* printf() */ + +#if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT +# define GS "gswin32c" +#else +# define GS "gs" +#endif + +#endif /* USE_IN_PS || USE_IN_PDF */ + +/** Adds a Ghostscript invocation command. Works for both PS and PDF. */ +static void add_gs_cmd(SimBuffer::B &cmd, SimBuffer::Flat const& hints) { + cmd << GS " -r72 -q -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -dLastPage=1 -sDEVICE=pnmraw -dDELAYSAFER -dBATCH -dNOPAUSE -sOutputFile=%D "; + char const *p=hints(), *r; + /* Dat: hints ends by ',' '\0' */ + // Files::FILEW(stdout) << hints << ";;\n"; + while (*p!=',') p++; /* Dat: safe, because hints is assumed to start and end by ',' */ + while (1) { + assert(*p==','); + if (*++p=='\0') break; + if (p[0]=='g' && p[1]=='s' && p[2]=='=') { + r=p+=3; + while (*p!=',') p++; + cmd.vi_write(r, p-r); /* Dat: -r... in here overrides -r72 above */ + cmd << ' '; + } else { + while (*p!=',') p++; + } + } +} + +#if USE_IN_PS + +/* !! -r144 and scale back..., also for PDF -- to enhance image quality */ + +#undef DO_KEEP_TEMP +#define DO_KEEP_TEMP 0 + +static Image::Sampled *in_ps_reader_low(Image::Loader::UFD* ufd, char const*bboxline, SimBuffer::Flat const& hints) { + SimBuffer::B mainfn; + if (!Files::find_tmpnam(mainfn)) Error::sev(Error::EERROR) << "in_ps_reader" << ": tmpnam() failed" << (Error*)0; + mainfn.term0(); + #if DO_KEEP_TEMP + printf("m: %s\n", mainfn()); + #else + Files::tmpRemoveCleanup(mainfn()); + #endif + FILE *f=fopen(mainfn(),"w"); + fprintf(f, "%s/setpagedevice/pop load def\n", bboxline); /* Imp: /a4/letter etc. */ + fprintf(f, "_IFN (r) file cvx exec\n"); /* Dat: doesn't rely on GS to + recognise EPSF-x.y comment, so works with both old and new gs */ + // ^^^ !! DOS EPSF etc. instead of exec/run + fclose(f); + // Error::sev(Error::EERROR) << "Cannot load PS images yet." << (Error*)0; + /* Dat: -dLastPage=1 has no effect, but we keep it for PDF compatibility */ + /* !! keep only 1st page, without setpagedevice for PS files */ + /* Dat: -dSAFER won't let me open the file with `/' under ESP Ghostscript 7.05.6 (2003-02-05) */ + /* Imp: win9X command line too long? */ + SimBuffer::B cmd; + add_gs_cmd(cmd,hints); + cmd << " -s_IFN=%S -- %*"; + HelperE helper(cmd.term0()(), mainfn()); /* Run external process GS */ + Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd; + int i=ufdd->vi_getcc(); + if (i<0) Error::sev(Error::EERROR) << "in_ps_reader: Empty PostScript file." << (Error*)0; /* should never happen */ + ((Filter::PipeE*)&helper)->vi_putcc(i); + Encoder::writeFrom(*(Filter::PipeE*)&helper, *ufdd); + ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */ + #if !DO_KEEP_TEMP + remove(mainfn()); + #endif + return helper.getImg(); +} + +static Image::Sampled *in_ps_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const& hints) { + return in_ps_reader_low(ufd, "", hints); +} + +static Image::Sampled *in_eps_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const& hints) { + double llx=0.0, lly=0.0, urx=0.0, ury=0.0; + Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd; + /* ^^^ SUXX: no warning for ufdd=ufdd */ + /* SUXX: valgrind, checkergcc: no indication of segfault due to stack overflow inside fgetc() */ + SimBuffer::B line; /* Imp: limit for max line length etc. */ + #if 0 + while ((line.clearFree(), ufdd->appendLine(line), line)) { + line.term0(); + printf("line: %s", line()); + } + #endif + slen_t line0ofs; + int had=0; + while ((line0ofs=line.getLength(), ufdd->appendLine(line), line0ofs!=line.getLength())) { + char const *thisline=line()+line0ofs; + line.term0(); + // printf("line: %s", thisline); + if (thisline[0]=='\n' || thisline[0]=='\r') continue; /* empty line */ + if (thisline[0]=='%' && thisline[1]=='!') continue; /* %!PS-... */ + if (thisline[0]!='%' || thisline[1]!='%') break; /* non-ADSC comment */ + if (had<3 && 4==sscanf(thisline+2, "ExactBoundingBox:%lg%lg%lg%lg", &llx, &lly, &urx, &ury)) had=3; + else if (had<2 && 4==sscanf(thisline+2, "HiResBoundingBox:%lg%lg%lg%lg", &llx, &lly, &urx, &ury)) had=2; + else if (had<1 && 4==sscanf(thisline+2, "BoundingBox:%lg%lg%lg%lg", &llx, &lly, &urx, &ury)) had=1; + /* Dat: finds MetaPost hiresbbox after %%EndComments */ + // printf("line: %s", line()+line0ofs); + } + ufdd->unread(line(), line.getLength()); line.clearFree(); + char bboxline[300]; + if (had!=0) { + // fprintf(stderr, "bbox=[%"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g]\n", llx, lly, urx, ury); + /* Dat: we must call translate _after_ setpagedevice (so it will take effect), at least with ESP Ghostscript 7.05.6 (2003-02-05); BUGFIX at Fri Aug 12 22:49:07 CEST 2005 */ + sprintf(bboxline, + "<</PageSize[%"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g]>>setpagedevice\n" + "%"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g translate\n" + , urx-llx, ury-lly, -llx, -lly); + } else { + Error::sev(Error::WARNING) << "in_eps_reader: missing EPS bbox" << (Error*)0; + bboxline[0]='\0'; + } + + return in_ps_reader_low(ufd, bboxline, hints); +} + +static Image::Loader::reader_t in_ps_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + if (0!=memcmp(buf,"%!PS-Adobe-",11)) return 0; + char const *p=buf+11, *pend=buf+Image::Loader::MAGIC_LEN; + while (p!=pend && *p!=' ' && *p!='\t') p++; + while (p!=pend && (*p==' ' || *p=='\t')) p++; + /* Imp: option to accept BoundingBox for non-EPS PS */ + return (0==strncmp(p,"EPSF-",5)) ? in_eps_reader : in_ps_reader; + /* ^^^ BUGFIX at Fri Nov 26 12:13:58 CET 2004 */ + /* ^^^ BUGFIX again at Thu Jan 6 10:25:54 CET 2005 */ +} + +#else +#define in_ps_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_PS */ + +Image::Loader in_ps_loader = { "PS", in_ps_checker, 0 }; + +#if USE_IN_PDF + +static Image::Sampled *in_pdf_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const& hints) { + // Error::sev(Error::EERROR) << "Cannot load PDF images yet." << (Error*)0; + SimBuffer::B cmd; + add_gs_cmd(cmd,hints); + cmd << " -- %S"; + /* Dat: -dSAFER won't let me open the file with `/' under ESP Ghostscript 7.05.6 (2003-02-05) */ + /* Imp: win9X command line too long? */ + fprintf(stderr, "gs_cmd=(%s)\n", cmd.term0()()); + HelperE helper(cmd.term0()()); /* Run external process GS */ + Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd); + ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */ + return helper.getImg(); +} + +static Image::Loader::reader_t in_pdf_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return 0==memcmp(buf,"%PDF-",5) ? in_pdf_reader : 0; +} + +#else +#define in_pdf_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_PDF */ + +Image::Loader in_pdf_loader = { "PDF", in_pdf_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_tga.cpp b/Build/source/utils/sam2p/in_tga.cpp new file mode 100644 index 00000000000..d164ef2525f --- /dev/null +++ b/Build/source/utils/sam2p/in_tga.cpp @@ -0,0 +1,50 @@ +/* + * in_tga.cpp -- read a Truevision Targa TGA file + * by pts@fazekas.hu at Sat Mar 2 00:49:35 CET 2002 + * + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" +#include "error.hpp" +#include "gensio.hpp" /* Filter::UngetFILED */ + +#if USE_IN_TGA + +#include "input-tga.ci" /* defines tga_load_image */ + +static Image::Sampled *in_tga_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + Image::Sampled *ret=0; + bitmap_type bitmap=tga_load_image(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false)); + /* Imp: Work without duplicated memory allocation */ + if (BITMAP_PLANES(bitmap)==1) { + Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + ret=img; + } else if (BITMAP_PLANES(bitmap)==3) { + Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8); + memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap)); + ret=img; + } else assert(0 && "invalid TGA depth"); + delete [] BITMAP_BITS(bitmap); + return ret; +} + +static Image::Loader::reader_t in_tga_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + /* vvv Unfortunately not all targa images have that footer */ + /* return 0==memcmp(bufend+Image::Loader::MAGIC_LEN-18, "TRUEVISION-XFILE", 16) */ + /* vvv 30..127: Aladdin Ghostscript adds 58 bytes of header */ + return (unsigned char)buf[0]>=30 && (unsigned char)buf[0]<=63 && + (unsigned char)buf[1]<=11 && + ((unsigned char)buf[16]<=8 || (unsigned char)buf[16]==24) + ? in_tga_reader : 0; +} + +#else +#define in_tga_checker NULLP +#endif /* USE_IN_XPM */ + +Image::Loader in_tga_loader = { "TGA", in_tga_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_tiff.cpp b/Build/source/utils/sam2p/in_tiff.cpp new file mode 100644 index 00000000000..a3e68d4e92d --- /dev/null +++ b/Build/source/utils/sam2p/in_tiff.cpp @@ -0,0 +1,66 @@ +/* + * in_tiff.cpp -- read TIFF (Tag Image File Format) files with tif22pnm + * by pts@fazekas.hu at Sun Apr 14 14:50:30 CEST 2002 + */ +/* Imp: get docs about the TIFF format, and rewrite this from scratch */ +/* Imp: use xviff.c */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" + +#if USE_IN_TIFF + +#include "error.hpp" +#include "gensio.hpp" +#include "helpere.hpp" +#include <string.h> /* memchr() */ +#include <stdio.h> /* printf() */ + +static Image::Sampled *in_tiff_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + // Error::sev(Error::EERROR) << "Cannot load TIFF images yet." << (Error*)0; + // HelperE helper("tifftopnm %S"); /* Cannot extract alpha channel */ + // HelperE helper("tif22pnm -rgba %S"); /* tif22pnm <= 0.07 */ + char const *cmd= + #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT +#if 0 /* unsafe if both tifftopnm and png22pnm exist */ + "tifftopnm <%S >%D\ntif22pnm -rgba %S pnm: %D"; /* slow but safe */ +#else + "tif22pnm -rgba %S pnm:"; +#endif + #else + #if OS_COTY==COTY_UNIX + #if 1 + "(tif22pnm -rgba %S pnm: || tifftopnm %S)"; + #else + /* Dat: not using this to suppress `sh: tif22pnm: command not found', because + * it would hide precious error messages printed by tif22pnm. + */ + "((tif22pnm -rgba %S pnm: 2>/dev/null)|| tifftopnm %S)"; + #endif + #else + "tif22pnm -rgba %S pnm:"; /* Wants to seek in the file. */ + #endif + #endif + HelperE helper(cmd); + Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd); + ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */ + return helper.getImg(); +} + +static Image::Loader::reader_t in_tiff_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + /* MM\x00\x2a: TIFF image data, big-endian + * II\x2a\x00: TIFF image data, little-endian + * The second word of TIFF files is the TIFF version number, 42, which has + * never changed. The TIFF specification recommends testing for it. + */ + return (0==memcmp(buf,"MM\x00\x2a",4) || 0==memcmp(buf,"II\x2a\x00",4)) ? in_tiff_reader : 0; +} + +#else +#define in_tiff_checker (Image::Loader::checker_t)NULLP +#endif /* USE_IN_XPM */ + +Image::Loader in_tiff_loader = { "TIFF", in_tiff_checker, 0 }; diff --git a/Build/source/utils/sam2p/in_xpm.cpp b/Build/source/utils/sam2p/in_xpm.cpp new file mode 100644 index 00000000000..a092036aca1 --- /dev/null +++ b/Build/source/utils/sam2p/in_xpm.cpp @@ -0,0 +1,409 @@ +/* + * in_xpm.cpp -- read an XPM file + * by pts@math.bme.hu at Fri Mar 1 09:56:54 CET 2002 + */ +/* Imp: test this code with various xpm files! */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "image.hpp" + +#if USE_IN_XPM + +#if OBJDEP +# warning REQUIRES: mapping.o +#endif + +#ifndef USE_BIG_MEMORY +#define USE_BIG_MEMORY 0 +#endif + +#include "mapping.hpp" +#include "error.hpp" +#include "xpmc.h" + +#include <string.h> /* memchr() */ +#include "gensio.hpp" + +#define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b)) + +#if 0 +/** @return true iff params are different strings (not respecting case) */ +static int my_strcase_neq(char *s1, char *s2) { + while ((USGE(*s1,'A') && USGE('Z',*s1) ? *s1+'a'-'A' : *s1) == + (USGE(*s2,'A') && USGE('Z',*s2) ? *s2+'a'-'A' : *s2)) { + if (*s1=='\0') return 0; + s1++; s2++; + } + return 1; +} +#endif + +#define my_strcase_neq(s1,s2) GenBuffer::nocase_strcmp(s1,s2) + +/** @ return RGB long */ +static Image::Sampled::rgb_t parse_rgb(char const*s) { + unsigned v=0, len; + Image::Sampled::rgb_t ret; + if (!s || !*s) return 0x2000000; /* not found */ + // fprintf(stderr, "'%s'\n", s); + if (*s=='#') { /* an #RRGGBB web-style color spec; or #RRRRGGGGBBBB */ + unsigned dif=0; + ++s; + while (dif<13 && (USGE(5,(s[dif]|32)-'a') || USGE(9,s[dif]-'0'))) dif++; /* find at most 13 hex digits */ + if (s[dif]!='\0' || (dif!=12 && dif!=6)) return 0x2000000; /* not found, spec length error */ + dif=(dif==12) ? 3 : 1; + // shr=24; while (shr!=0) { + ret= (Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<20; + s++; + ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<16; + s+=dif; /* ignore lower two hex digits of 16-bit sample value */ + ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<12; + s++; + ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<8; + s+=dif; /* ignore lower two hex digits of 16-bit sample value */ + ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<4; + s++; + ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' ); + return ret; + } + /* vvv 223==255-32: ignore case when hashing */ + char const *p=s; + while (*p!='\0') v=xpmColors_mul*v+(223&*(unsigned char const*)p++); + p=xpmColors_dat+xpmColors_ofs[(v&65535)%xpmColors_mod]; + while (*p!='\0') { + len=strlen(p); + if (0==my_strcase_neq(p,s)) { + p+=len; + ret=(((Image::Sampled::rgb_t)((unsigned char const*)p)[1])<<16)+ + (((Image::Sampled::rgb_t)((unsigned char const*)p)[2])<<8)+ + (((Image::Sampled::rgb_t)((unsigned char const*)p)[3])); + return (ret==0x30201) ? 0x1000000 : ret; /* transparent color */ + } + p+=len+4; + } + return 0x2000000; /* not found */ +} + +class XPMTok { + public: + /* Imp: report line numbers on errors */ + BEGIN_STATIC_ENUM1(int) + T_NO_UNGOT=-1, + T_COMMA=257 /* The comma token, outside strings. */ + END_STATIC_ENUM() + /* XPM states */ + BEGIN_STATIC_ENUM1(char) + ST_OUT=0, /* outside s string */ + ST_STR=1, /* inside a string */ + ST_EOF=2 /* EOF */ + END_STATIC_ENUM() + int getcc(); + /** Reads an unsigned int. */ + Image::Sampled::dimen_t getDimen(); + Image::Sampled::rgb_t getColor(); + void read(char *buf, unsigned len); + inline void readInStr(char *buf, unsigned len); + inline XPMTok(FILE *f_): f(f_), state(ST_OUT), ungot(T_NO_UNGOT) {} + inline void ungetcc(int c) { if (c>=0) ungot=c; } + void getComma(); + protected: + FILE *f; + /** Current state. */ + char state; + int ungot; +}; + +int XPMTok::getcc() { + int i; + if (ungot>=0 /*T_NO_UNGOT<0*/) { i=ungot; ungot=T_NO_UNGOT; return i; } + /* Imp: ignore C and C++ style comments (so we won't recognise strings inside comments) */ + switch (state) { + case ST_OUT: st_out: + while (1) { + switch ((i=MACRO_GETC(f))) { + case -1: state=ST_EOF; return -1; + case ',': return T_COMMA; + case '"': state=ST_STR; goto st_str; + default: /* ignore outside strings */ break; + } + } + case ST_STR: st_str: + i=MACRO_GETC(f); + if (i==-1) { ue: Error::sev(Error::EERROR) << "XPM: unexpected EOF" << (Error*)0; } + else if (i=='"') { state=ST_OUT; goto st_out; } + else if (i=='\\') { + if ((i=MACRO_GETC(f))==-1) goto ue; + if (i=='\n') goto st_str; + /* Imp: handle octal, hexadecimal, \n etc. */ + } + return i&255; + default: return -1; + } +} +Image::Sampled::dimen_t XPMTok::getDimen() { + Image::Sampled::dimen_t ret=0, bak; + int i; + while ((i=getcc())==' ' || i=='\t') ; + if (USGE(i,'0') && USGE('9',i)) { + ret=i-'0'; + while (USGE((i=getcc()),'0') && USGE('9',i)) { + bak=ret; + ret=ret*10+(i-'0'); + if (ret/10!=bak) Error::sev(Error::EERROR) << "XPM: dimen overflow" << (Error*)0; + } + ungetcc(i); + return ret; + } else Error::sev(Error::EERROR) << "XPM: dimen expected" << (Error*)0; + return 0; /*notreached*/ +} +void XPMTok::getComma() { + if (getcc()!=T_COMMA) Error::sev(Error::EERROR) << "XPM: comma expected at " << ftell(f) << (Error*)0; +} +void XPMTok::read(char *buf, unsigned len) { + int i; + while (len--!=0) { + i=getcc(); + // fprintf(stderr,"i=%d\n", i); + if (i>=0 && i<=255) *buf++=i; else Error::sev(Error::EERROR) << "XPM: data expected" << (Error*)0; + } +} +void XPMTok::readInStr(char *buf, unsigned len) { + /* Dat: this is OK noew */ + // assert(state==ST_STR); + assert(ungot<0); + param_assert(len>=1); + if (state!=ST_STR) { len--; goto real; } + int i; + while (len--!=0) { + if ((i=MACRO_GETC(f))>=0 && i<=255 && i!='"' && i!='\\') *buf++=i; + else { assert(i>=0); ungetc(i,f); real: + i=getcc(); + // fprintf(stderr,"i=%d\n", i); + if (i>=0 && i<=255) *buf++=i; else Error::sev(Error::EERROR) << "XPM: data expected" << (Error*)0; + } + } +} +Image::Sampled::rgb_t XPMTok::getColor() { + static char tmp[32]; + int i; + while ((i=getcc())==' ' || i=='\t') ; + if (i=='g') { at_g: + i=getcc(); + if (i!='4') ungetcc(i); + goto at_col; + } else if (i=='c' || i=='m' || i=='b' || i=='s') { at_col: + while ((i=getcc())==' ' || i=='\t') ; + char *p=tmp, *pend=tmp+sizeof(tmp)-1; + while (i>=33 && i<=126) { + if (p==pend) goto cexp; /* color name too long */ + *p++=i; + i=getcc(); + } + *p='\0'; + if (i==' ' || i=='\t') { /* Maybe another color will come */ + while ((i=getcc())==' ' || i=='\t') ; + if (i=='g') goto at_g; + else if (i=='c' || i=='m' || i=='b' || i=='s') goto at_col; + } + if (i!=T_COMMA) goto cexp; + Image::Sampled::rgb_t ret=parse_rgb(tmp); + if (ret==0x2000000) Error::sev(Error::EERROR) << "XPM: unknown color: " << tmp << (Error*)0; + return ret; + } else { cexp: Error::sev(Error::EERROR) << "XPM: color expected" << (Error*)0; } + return 0; /*notreached*/ +} + +static Image::Sampled *in_xpm_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) { + // Error::sev(Error::EERROR) << "Cannot load XPM images yet." << (Error*)0; + XPMTok tok(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false)); + Image::Sampled::dimen_t wd=tok.getDimen(); + Image::Sampled::dimen_t ht=tok.getDimen(); + Image::Sampled::dimen_t colors=tok.getDimen(); + Image::Sampled::dimen_t cpp=tok.getDimen(); /* chars per pixel */ + + /* width height ncolors cpp [x_hot y_hot] */ + int i; /* multiple purpose */ + while ((i=tok.getcc())==' ' || i=='\t' || USGE(9,i-'0')) ; + tok.ungetcc(i); tok.getComma(); + + // Error::sev(Error::DEBUG) << "wd="<<wd<<" ht="<<ht<<" colors="<<colors<<" cpp="<<cpp << (Error*)0; + if (1UL*cpp*colors>65535) Error::sev(Error::EERROR) << "XPM: too many colors" << (Error*)0; + // if (cpp==1) { + // } + Image::Sampled::dimen_t transp=colors; /* No transparent colors yet. */ + /* vvv Dat: last cpp bytes of tab are used for storing current pixel. */ + char *tab=new char[cpp*(colors+1)], *p, *pend; /* BUGFIX: unsinged at Fri Nov 26 12:18:21 CET 2004 */ + Image::Sampled::rgb_t *rgb=new Image::Sampled::rgb_t[colors], *rp; + for (rp=rgb,p=tab,pend=tab+cpp*colors; p!=pend; p+=cpp,rp++) { + tok.read(p,cpp); + *rp=tok.getColor(); + if (*rp==0x1000000) { + if (transp!=colors) Error::sev(Error::WARNING) << "XPM: subsequent transparency might be blacked" << (Error*)0; + else transp=rp-rgb; + } + } + /* Now: transp: index of the last transparent color */ + /* Dat: since (0x1000000&0xffffff)==0, transparent colors will have palette enrty black */ + + char *outbuf=0; /* avoid gcc warning */ + Image::Sampled *ret; + Image::Indexed *iimg=(Image::Indexed*)NULLP; + tok.ungetcc(tok.T_COMMA); + + if (colors<=256) { + ret=iimg=new Image::Indexed(wd,ht,colors,8); + if (transp!=colors) iimg->setTransp(transp); + } else { + ret=new Image::RGB(wd,ht,8); + if (transp!=colors) Error::sev(Error::WARNING) << "XPM: too many colors, transparency blacked" << (Error*)0; + } + outbuf=ret->getRowbeg(); + + if (cpp==1) { /* Easy job: make an Indexed image; defer .packPal() */ + assert(colors<=256); + signed short bin[256], s; + memset(bin, 255, sizeof(bin)); /* Make bin[*]=-1 */ + for (i=0;(unsigned)i<colors;i++) { + iimg->setPal(i, rgb[i]); + bin[(unsigned char)tab[i]]=i; + } + assert(p==pend); + while (ht--!=0) { + tok.getComma(); + for (p=outbuf+ret->getRlen(); outbuf!=p; ) { + if ((i=tok.getcc())<0 || i>255) Error::sev(Error::EERROR) << "XPM: data expected" << (Error*)0; + if ((s=bin[i])<0) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + *outbuf++=s; + } + } + #if USE_BIG_MEMORY + } else if (cpp==2 && colors<=256) { /* Similarly easy job: make an Indexed image; defer .packPal() */ + signed short *bin=new short[65536], s; + memset(bin, 255, sizeof(bin)); /* Make bin[*]=-1 */ + for (i=0,p=tab; (unsigned)i<colors; i++, p+=2) { + iimg->setPal(i, rgb[i]); + bin[(p[0]<<8)+p[1]]=i; + } + assert(p==pend); + while (ht--!=0) { + tok.getComma(); + for (p=outbuf+ret->getRlen(); outbuf!=p; ) { + tok.readInStr(pend,2); + if ((s=bin[(pend[0]<<8)+pend[1]])<0) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + *outbuf++=s; + } + } + delete [] bin; + } else if (cpp==2 && colors<=65535) { + Image::Sampled::rgb_t rgb1; + unsigned short *bin=new unsigned short[65536], s; + memset(bin, 255, sizeof(bin)); /* Make bin[*]=max */ + for (i=0,p=tab; (unsigned)i<colors; i++, p+=2) bin[(p[0]<<8)+p[1]]=i; + while (ht--!=0) { + tok.getComma(); + for (p=outbuf+ret->getRlen(); outbuf!=p; ) { + tok.readInStr(pend,2); + if ((s=bin[(pend[0]<<8)+pend[1]])==(unsigned short)-1) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + *outbuf++=(rgb1=rgb[s])>>16; + *outbuf++=rgb1>>8; + *outbuf++=rgb1; + } + } + delete [] bin; + #endif /* USE_BIG_MEMORY */ + } else { /* Now comes the slow, but general solution */ + #if USE_IN_XPM_MAPPING /* use Mapping */ + if (colors<=256) { + Mapping::H h(1); + char c; + /* vvv `c' might become negative, but it is harmless */ + for (p=tab,pend=tab+cpp*colors,c=0; p!=pend; p+=cpp,c++) + h.set(p, cpp, &c); /* every color-string should be unique; but no error message if it isn't */ + while (ht--!=0) { + tok.getComma(); + for (p=outbuf+ret->getRlen(); outbuf!=p; ) { + tok.readInStr(pend,cpp); + if (NULLP==(pend=h.get(pend, cpp))) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + *outbuf++=*pend; + } + } + } else { /* most general case with Mapping */ + if (transp!=colors) Error::sev(Error::WARNING) << "XPM: too many colors, transparency blacked" << (Error*)0; + /* Dat: reading a JPEG downsampled to a 256-color XPM takes 3000 ms + * with Mapping, and 31000 ms without mapping. Nice speed increase. + */ + Mapping::H h(3); + char tmpcol[3]; + for (p=tab,pend=tab+cpp*colors,rp=rgb; p!=pend; p+=cpp,rp++) { + tmpcol[0]=rp[0]>>16; + tmpcol[1]=rp[0]>>8; + tmpcol[2]=rp[0]; + h.set(p, cpp, tmpcol); /* every color-string should be unique; but no error message if it isn't */ + } + while (ht--!=0) { + tok.getComma(); + for (p=outbuf+ret->getRlen(); outbuf!=p; outbuf+=3) { + tok.readInStr(pend,cpp); + if (NULLP==(pend=h.get(pend, cpp))) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + memcpy(outbuf, pend, 3); + } + } + } + #else /* don't USE_IN_XPM_MAPPING */ + Image::Sampled::dimen_t lastcol=0, x; + p=tab; /* cache pointer for the last color (lastcol) */ + if (colors<=256) { + assert(cpp>1); + for (lastcol=0;lastcol<colors;lastcol++) iimg->setPal(lastcol, rgb[lastcol]); + lastcol=0; + while (ht--!=0) { + // putchar('.'); + tok.getComma(); + for (x=0;x<wd;x++) { + tok.read(pend,cpp); + if (0!=memcmp(p,pend,cpp)) { + p=tab; lastcol=0; while (p!=pend && 0!=memcmp(p,pend,cpp)) { p+=cpp; lastcol++; } + if (p==pend) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + if (rgb[lastcol]==0x1000000) p=tab+cpp*(lastcol=transp); /* fix single transp */ + } + *outbuf++=lastcol; + } + } + } else { /* colors>256 */ + while (ht--!=0) { + tok.getComma(); + for (x=0;x<wd;x++) { + tok.read(pend,cpp); + if (0!=memcmp(p,pend,cpp)) { + p=tab; lastcol=0; while (p!=pend && 0!=memcmp(p,pend,cpp)) { p+=cpp; lastcol++; } + if (p==pend) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0; + } + *outbuf++=rgb[lastcol]>>16; + *outbuf++=rgb[lastcol]>>8; + *outbuf++=rgb[lastcol]; + } + } + } + #endif + } + delete [] tab; + delete [] rgb; + /* Dat: we don't check for EOF. Imp: emit a warning? */ + // Error::sev(Error::DEBUG) << "rp[-1]=" << rp[-1] << (Error*)0; + // while (-1!=(i=tok.getcc())) { putchar(i); } + /* fclose((FILE*)file_); */ + return ret; +} + +static Image::Loader::reader_t in_xpm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) { + return (0==memcmp(buf, "/* XPM */", 9)) ? in_xpm_reader : 0; +} + +#else +# define in_xpm_checker NULLP +#endif /* USE_IN_XPM */ + +Image::Loader in_xpm_loader = { "XPM", in_xpm_checker, 0 }; diff --git a/Build/source/utils/sam2p/input-bmp.ci b/Build/source/utils/sam2p/input-bmp.ci new file mode 100644 index 00000000000..1a9a491ca94 --- /dev/null +++ b/Build/source/utils/sam2p/input-bmp.ci @@ -0,0 +1,482 @@ +/* This code is ripped from Autotrace-0.29. Small modifications by pts. */ + +/* input-bmp.ci: reads any bitmap I could get for testing */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* #include "types.h" */ +#include "at_bitmap.h" +/* #include "message.h" */ +/* #include "xstd.h" */ +/* #include "input-bmp.h" */ + +#define MAXCOLORS 256 +/* #define Image long */ + +#define BitSet(byte, bit) (((byte) & (bit)) == (bit)) + +#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0) + +struct Bitmap_File_Head_Struct +{ + char zzMagic[2]; /* 00 "BM" */ + unsigned long bfSize; /* 02 */ + unsigned short zzHotX; /* 06 */ + unsigned short zzHotY; /* 08 */ + unsigned long bfOffs; /* 0A */ + unsigned long biSize; /* 0E */ +} Bitmap_File_Head; + +struct Bitmap_Head_Struct +{ + unsigned long biWidth; /* 12 */ + unsigned long biHeight; /* 16 */ + unsigned short biPlanes; /* 1A */ + unsigned short biBitCnt; /* 1C */ + unsigned long biCompr; /* 1E */ + unsigned long biSizeIm; /* 22 */ + unsigned long biXPels; /* 26 */ + unsigned long biYPels; /* 2A */ + unsigned long biClrUsed; /* 2E */ + unsigned long biClrImp; /* 32 */ + /* 36 */ +} Bitmap_Head; + +static long ToL (unsigned char *); +static short ToS (unsigned char *); +static int ReadColorMap (FILE *, + unsigned char[256][3], + int, + int, + int *); +static unsigned char *ReadImage (FILE *, + int, + int, + unsigned char[256][3], + int, + int, + int, + int); + +#if PTS_SAM2P +bitmap_type bmp_load_image (FILE* filename) +#else +bitmap_type bmp_load_image (at_string filename) +#endif +{ + FILE *fd; + unsigned char buffer[64]; + int ColormapSize, rowbytes, Maps=0, Grey; + unsigned char ColorMap[256][3]; + bitmap_type image; + + #if PTS_SAM2P /**** pts ****/ + fd=filename; + #else + fd = fopen (filename, "rb"); + + if (!fd) + FATAL1 ("Can't open \"%s\"\n", filename); + #endif + + /* It is a File. Now is it a Bitmap? Read the shortest possible header.*/ + + if (!ReadOK(fd, buffer, 18) || (strncmp((const char *)buffer,"BM",2))) + #if PTS_SAM2P /**** pts ****/ + FATALP ("BMP: Not a valid BMP file"); + #else + FATAL ("Not a valid BMP file %s\n"); + #endif + + /* bring them to the right byteorder. Not too nice, but it should work */ + + Bitmap_File_Head.bfSize = ToL (&buffer[0x02]); + Bitmap_File_Head.zzHotX = ToS (&buffer[0x06]); + Bitmap_File_Head.zzHotY = ToS (&buffer[0x08]); + Bitmap_File_Head.bfOffs = ToL (&buffer[0x0a]); + Bitmap_File_Head.biSize = ToL (&buffer[0x0e]); + + /* What kind of bitmap is it? */ + + if (Bitmap_File_Head.biSize == 12) /* OS/2 1.x ? */ + { + if (!ReadOK (fd, buffer, 8)) + FATALP ("BMP: Error reading BMP file header #1"); + + Bitmap_Head.biWidth = ToS (&buffer[0x00]); /* 12 */ + Bitmap_Head.biHeight = ToS (&buffer[0x02]); /* 14 */ + Bitmap_Head.biPlanes = ToS (&buffer[0x04]); /* 16 */ + Bitmap_Head.biBitCnt = ToS (&buffer[0x06]); /* 18 */ + Bitmap_Head.biCompr = 0; + Bitmap_Head.biSizeIm = 0; + Bitmap_Head.biXPels = Bitmap_Head.biYPels = 0; + Bitmap_Head.biClrUsed = 0; + Maps = 3; + } + else if (Bitmap_File_Head.biSize == 40) /* Windows 3.x */ + { + if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4)) + FATALP ("BMP: Error reading BMP file header #2"); + + Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */ + Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */ + Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */ + Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */ + Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */ + Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */ + Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */ + Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */ + Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */ + Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */ + /* 36 */ + Maps = 4; + } + else if (Bitmap_File_Head.biSize <= 64) /* Probably OS/2 2.x */ + { + if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4)) + FATALP ("BMP: Error reading BMP file header #3"); + + Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */ + Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */ + Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */ + Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */ + Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */ + Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */ + Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */ + Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */ + Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */ + Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */ + /* 36 */ + Maps = 3; + } + else + FATALP ("BMP: Error reading BMP file header #4"); + + /* Valid options 1, 4, 8, 16, 24, 32 */ + /* 16 is awful, we should probably shoot whoever invented it */ + + /* There should be some colors used! */ + + ColormapSize = (Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps; + + if ((Bitmap_Head.biClrUsed == 0) && (Bitmap_Head.biBitCnt <= 8)) + Bitmap_Head.biClrUsed = ColormapSize; + + /* Sanity checks */ + + if (Bitmap_Head.biHeight == 0 || Bitmap_Head.biWidth == 0) + FATALP ("BMP: Error reading BMP file header #5"); + + if (Bitmap_Head.biPlanes != 1) + FATALP ("BMP: Error reading BMP file header #6"); + + if (ColormapSize > 256 || Bitmap_Head.biClrUsed > 256) + FATALP ("BMP: Error reading BMP file header #7"); + + /* Windows and OS/2 declare filler so that rows are a multiple of + * word length (32 bits == 4 bytes) + */ + + rowbytes= ( (Bitmap_Head.biWidth * Bitmap_Head.biBitCnt - 1) / 32) * 4 + 4; + +#ifdef DEBUG + printf("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, Comp: %u, Zeile: %u\n", + Bitmap_File_Head.bfSize,Bitmap_Head.biClrUsed,Bitmap_Head.biBitCnt,Bitmap_Head.biWidth, + Bitmap_Head.biHeight, Bitmap_Head.biCompr, rowbytes); +#endif + + /* Get the Colormap */ + + if (ReadColorMap (fd, ColorMap, ColormapSize, Maps, &Grey) == -1) + FATALP ("BMP: Cannot read the colormap"); + +#ifdef DEBUG + printf("Colormap read\n"); +#endif + + /* Get the Image and return the ID or -1 on error*/ + image.bitmap = ReadImage (fd, + Bitmap_Head.biWidth, + Bitmap_Head.biHeight, + ColorMap, + Bitmap_Head.biBitCnt, + Bitmap_Head.biCompr, + rowbytes, + Grey); + BITMAP_WIDTH (image) = (unsigned short) Bitmap_Head.biWidth; + BITMAP_HEIGHT (image) = (unsigned short) Bitmap_Head.biHeight; + BITMAP_PLANES (image) = Grey ? 1 : 3; + + return (image); +} + +static int +ReadColorMap (FILE *fd, + unsigned char buffer[256][3], + int number, + int size, + int *grey) +{ + int i; + unsigned char rgb[4]; + + *grey=(number>2); + for (i = 0; i < number ; i++) + { + if (!ReadOK (fd, rgb, size)) + FATALP ("BMP: Bad colormap"); + + /* Bitmap save the colors in another order! But change only once! */ + + buffer[i][0] = rgb[2]; + buffer[i][1] = rgb[1]; + buffer[i][2] = rgb[0]; + *grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2])); + } + return 0; +} + +static unsigned char* +ReadImage (FILE *fd, + int width, + int height, + unsigned char cmap[256][3], + int bpp, + int compression, + int rowbytes, + int grey) +{ + unsigned char v,howmuch; + int xpos = 0, ypos = 0; + unsigned char *image; + unsigned char *temp, *buffer; + long rowstride, channels; + unsigned short rgb; + int i, j, notused; + + if (bpp >= 16) /* color image */ + { + XMALLOCT (image, unsigned char*, width * height * 3 * sizeof (unsigned char)); + channels = 3; + } + else if (grey) /* grey image */ + { + XMALLOCT (image, unsigned char*, width * height * 1 * sizeof (unsigned char)); + channels = 1; + } + else /* indexed image */ + { + XMALLOCT (image, unsigned char*, width * height * 1 * sizeof (unsigned char)); + channels = 1; + } + + XMALLOCT (buffer, unsigned char*, rowbytes); + rowstride = width * channels; + + ypos = height - 1; /* Bitmaps begin in the lower left corner */ + + switch (bpp) { + + case 32: + { + while (ReadOK (fd, buffer, rowbytes)) + { + temp = image + (ypos * rowstride); + for (xpos= 0; xpos < width; ++xpos) + { + *(temp++)= buffer[xpos * 4 + 2]; + *(temp++)= buffer[xpos * 4 + 1]; + *(temp++)= buffer[xpos * 4]; + } + --ypos; /* next line */ + } + } + break; + + case 24: + { + while (ReadOK (fd, buffer, rowbytes)) + { + temp = image + (ypos * rowstride); + for (xpos= 0; xpos < width; ++xpos) + { + *(temp++)= buffer[xpos * 3 + 2]; + *(temp++)= buffer[xpos * 3 + 1]; + *(temp++)= buffer[xpos * 3]; + } + --ypos; /* next line */ + } + } + break; + + case 16: + { + while (ReadOK (fd, buffer, rowbytes)) + { + temp = image + (ypos * rowstride); + for (xpos= 0; xpos < width; ++xpos) + { + rgb= ToS(&buffer[xpos * 2]); + *(temp++)= (unsigned char)(((rgb >> 10) & 0x1f) * 8); + *(temp++)= (unsigned char)(((rgb >> 5) & 0x1f) * 8); + *(temp++)= (unsigned char)(((rgb) & 0x1f) * 8); + } + --ypos; /* next line */ + } + } + break; + + case 8: + case 4: + case 1: + { + if (compression == 0) + { + while (ReadOK (fd, &v, 1)) + { + for (i = 1; (i <= (8 / bpp)) && (xpos < width); i++, xpos++) + { + temp = (unsigned char*) (image + (ypos * rowstride) + (xpos * channels)); + *temp= (unsigned char)(( v & ( ((1<<bpp)-1) << (8-(i*bpp)) ) ) >> (8-(i*bpp))); + } + if (xpos == width) + { + notused = ReadOK (fd, buffer, rowbytes - 1 - + (width * bpp - 1) / 8); + ypos--; + xpos = 0; + + } + if (ypos < 0) + break; + } + break; + } + else + { + while (ypos >= 0 && xpos <= width) + { + notused = ReadOK (fd, buffer, 2); + if ((unsigned char) buffer[0] != 0) + /* Count + Color - record */ + { + for (j = 0; ((unsigned char) j < (unsigned char) buffer[0]) && (xpos < width);) + { +#ifdef DEBUG2 + printf("%u %u | ",xpos,width); +#endif + for (i = 1; + ((i <= (8 / bpp)) && + (xpos < width) && + ((unsigned char) j < (unsigned char) buffer[0])); + i++, xpos++, j++) + { + temp = image + (ypos * rowstride) + (xpos * channels); + *temp = (unsigned char) ((buffer[1] & (((1<<bpp)-1) << (8 - (i * bpp)))) >> (8 - (i * bpp))); + } + } + } + if (((unsigned char) buffer[0] == 0) && ((unsigned char) buffer[1] > 2)) + /* uncompressed record */ + { + howmuch = buffer[1]; + for (j = 0; j < howmuch; j += (8 / bpp)) + { + notused = ReadOK (fd, &v, 1); + i = 1; + while ((i <= (8 / bpp)) && (xpos < width)) + { + temp = image + (ypos * rowstride) + (xpos * channels); + *temp = (unsigned char) ((v & (((1<<bpp)-1) << (8-(i*bpp)))) >> (8-(i*bpp))); + i++; + xpos++; + } + } + + if ((howmuch % 2) && (bpp==4)) + howmuch++; + + if ((howmuch / (8 / bpp)) % 2) + notused = ReadOK (fd, &v, 1); + /*if odd(x div (8 div bpp )) then blockread(f,z^,1);*/ + } + if (((unsigned char) buffer[0] == 0) && ((unsigned char) buffer[1]==0)) + /* Line end */ + { + ypos--; + xpos = 0; + } + if (((unsigned char) buffer[0]==0) && ((unsigned char) buffer[1]==1)) + /* Bitmap end */ + { + break; + } + if (((unsigned char) buffer[0]==0) && ((unsigned char) buffer[1]==2)) + /* Deltarecord */ + { + notused = ReadOK (fd, buffer, 2); + xpos += (unsigned char) buffer[0]; + ypos -= (unsigned char) buffer[1]; + } + } + break; + } + } + break; + default: + /* This is very bad, we should not be here */ + ; + } + + /* fclose (fd); */ + if (bpp <= 8) + { + unsigned char *temp2, *temp3; + unsigned char index; + temp2 = temp = image; + XMALLOCT (image, unsigned char*, width * height * 3 * sizeof (unsigned char)); + temp3 = image; + for (ypos = 0; ypos < height; ypos++) + { + for (xpos = 0; xpos < width; xpos++) + { + index = *temp2++; + *temp3++ = cmap[index][0]; + if (!grey) + { + *temp3++ = cmap[index][1]; + *temp3++ = cmap[index][2]; + } + } + } + free (temp); + } + + free (buffer); + return image; +} + +#if 0 /**** pts ****/ +FILE *errorfile; +char *prog_name = "bmp"; +char *filename; +int interactive_bmp; +#endif + +static long +ToL (unsigned char *puffer) +{ + return (puffer[0] | puffer[1]<<8 | puffer[2]<<16 | puffer[3]<<24); +} + +static short +ToS (unsigned char *puffer) +{ + return ((short)(puffer[0] | puffer[1]<<8)); +} diff --git a/Build/source/utils/sam2p/input-pnm.ci b/Build/source/utils/sam2p/input-pnm.ci new file mode 100644 index 00000000000..9598ba8c687 --- /dev/null +++ b/Build/source/utils/sam2p/input-pnm.ci @@ -0,0 +1,493 @@ +/* This code is ripped from Autotrace-0.29. Small modifications by pts. */ + +/* input-pnm.ci: + * The pnm reading and writing code was written from scratch by Erik Nygren + * (nygren@mit.edu) based on the specifications in the man pages and + * does not contain any code from the netpbm or pbmplus distributions. + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +/* #include "types.h" */ +#include "at_bitmap.h" +/* #include "input-pnm.h" */ +/* #include "message.h" */ +/* #include "xstd.h" */ + +/* #include <math.h> -- ceil(); emulated */ +#include <stdlib.h> /* atoi(...) */ + +/**** pts ****/ +/* #include <ctype.h> */ +#define isspace(c) ((c)=='\0' || (c)==' ' || ((unsigned char)((c)-011)<=(unsigned char)(015-011))) +/* ^^^ not strictly POSIX C locale */ +#define isdigit(c) ((unsigned char)(c-'0')<=(unsigned char)('9'-'0')) + +#if 0 +# define FILEE FILE +# define fread_FILEE(s,slen,f) fread(s, 1, slen, f) +#else +# define FILEE /*Filter::UngetFILED*/GenBuffer::Readable +# define fread_FILEE(s,slen,f) f->vi_read(s, slen) +#endif + +/* Declare local data types + */ + +typedef struct _PNMScanner +{ + FILEE *fd; /* The file descriptor of the file being read */ + char cur; /* The current character in the input stream */ + int eof; /* Have we reached end of file? */ +} PNMScanner; + +typedef struct _PNMInfo +{ + unsigned int xres, yres; /* The size of the image */ + int maxval; /* For ascii image files, the max value + * which we need to normalize to */ + int np; /* Number of image planes (0 for pbm) */ + int asciibody; /* 1 if ascii body, 0 if raw body */ + /* Routine to use to load the pnm body */ + void (* loader) (PNMScanner *, struct _PNMInfo *, unsigned char *); +} PNMInfo; + +/* Contains the information needed to write out PNM rows */ +typedef struct _PNMRowInfo +{ + FILEE *fd; /* File descriptor */ + char *rowbuf; /* Buffer for writing out rows */ + int xres; /* X resolution */ + int np; /* Number of planes */ + unsigned char *red; /* Colormap red */ + unsigned char *grn; /* Colormap green */ + unsigned char *blu; /* Colormap blue */ +} PNMRowInfo; + +/* Save info */ +typedef struct +{ + int raw; /* raw or ascii */ +} PNMSaveVals; + +typedef struct +{ + int run; /* run */ +} PNMSaveInterface; + +#define BUFLEN 512 /* The input buffer size for data returned + * from the scanner. Note that lines + * aren't allowed to be over 256 characters + * by the spec anyways so this shouldn't + * be an issue. */ + +#define SAVE_COMMENT_STRING "# CREATOR: The GIMP's PNM Filter Version 1.0\n" + +/* Declare some local functions. + */ + +static void pnm_load_ascii (PNMScanner *scan, + PNMInfo *info, + unsigned char *pixel_rgn); +static void pnm_load_raw (PNMScanner *scan, + PNMInfo *info, + unsigned char *pixel_rgn); +static void pnm_load_rawpbm (PNMScanner *scan, + PNMInfo *info, + unsigned char *pixel_rgn); + +static void pnmscanner_destroy (PNMScanner *s); +#if 0 +static void pnmscanner_createbuffer (PNMScanner *s, + unsigned int bufsize); +static void pnmscanner_getchar (PNMScanner *s); +static void pnmscanner_getsmalltoken (PNMScanner *s, unsigned char *buf); +#endif +static void pnmscanner_eatwhitespace (PNMScanner *s); +static void pnmscanner_gettoken (PNMScanner *s, + unsigned char *buf, + unsigned int bufsize); +static unsigned pnmscanner_getint(PNMScanner *s); + +static PNMScanner * pnmscanner_create (FILEE *fd); + + +#define pnmscanner_eof(s) ((s)->eof) +#define pnmscanner_fd(s) ((s)->fd) + +#if 0 +/* pnmscanner_getchar --- + * Reads a character from the input stream + */ +static void +pnmscanner_getchar (PNMScanner *s) +{ + if (s->inbuf) + { + s->cur = s->inbuf[s->inbufpos++]; + if (s->inbufpos >= s->inbufvalidsize) + { + if (s->inbufsize > s->inbufvalidsize) + s->eof = 1; + else + s->inbufvalidsize = fread(s->inbuf, 1, s->inbufsize, s->fd); + s->inbufpos = 0; + } + } + else + s->eof = !fread(&(s->cur), 1, 1, s->fd); +} +#endif + +#define pnmscanner_getchar(s) do { s->eof = !fread_FILEE(&(s->cur), 1, s->fd); } while(0) + +/* pnmscanner_eatwhitespace --- + * Eats up whitespace from the input and returns when done or eof. + * Also deals with comments. + */ +static inline void pnmscanner_eatwhitespace(PNMScanner *s) { /**** pts ****/ + while (1) { + if (s->cur=='#') { + do pnmscanner_getchar(s); while (s->cur!='\n'); + } else if (!isspace(s->cur)) { + break; + } + pnmscanner_getchar(s); + } +} + + +static struct struct_pnm_types +{ + char name; + int np; + int asciibody; + int maxval; + void (* loader) (PNMScanner *, struct _PNMInfo *, unsigned char *pixel_rgn); +} pnm_types[] = +{ + { '1', 0, 1, 1, pnm_load_ascii }, /* ASCII PBM */ + { '2', 1, 1, 255, pnm_load_ascii }, /* ASCII PGM */ + { '3', 3, 1, 255, pnm_load_ascii }, /* ASCII PPM */ + { '4', 0, 0, 1, pnm_load_rawpbm }, /* RAW PBM */ + { '5', 1, 0, 255, pnm_load_raw }, /* RAW PGM */ + { '6', 3, 0, 255, pnm_load_raw }, /* RAW PPM */ + { 0 , 0, 0, 0, NULL} +}; + +#if PTS_SAM2P +bitmap_type pnm_load_image (FILEE* filename) +#else +bitmap_type pnm_load_image (at_string filename) +#endif +{ + char buf[BUFLEN]; /* buffer for random things like scanning */ + PNMInfo *pnminfo; + PNMScanner * volatile scan; + int ctr; + FILEE* fd; + bitmap_type bitmap; + + #if PTS_SAM2P /**** pts ****/ + fd=filename; + #else + /* open the file */ + fd = xfopen (filename, "rb"); + if (fd == NULL) + { + FATAL("PNM: can't open file\n"); + BITMAP_BITS (bitmap) = NULL; + BITMAP_WIDTH (bitmap) = 0; + BITMAP_HEIGHT (bitmap) = 0; + BITMAP_PLANES (bitmap) = 0; + return (bitmap); + } + #endif + + + /* allocate the necessary structures */ + /* pnminfo = (PNMInfo *) malloc (sizeof (PNMInfo)); */ + XMALLOCTU(pnminfo, PNMInfo); + + scan = NULL; + /* set error handling */ + + scan = pnmscanner_create(fd); + + /* Get magic number */ + pnmscanner_gettoken (scan, (unsigned char *)buf, BUFLEN); + if (pnmscanner_eof(scan)) + FATALP ("PNM: premature end of file"); + if (buf[0] != 'P' || buf[2]) + FATALP ("PNM: is not a valid file"); + + /* Look up magic number to see what type of PNM this is */ + for (ctr=0; pnm_types[ctr].name; ctr++) + if (buf[1] == pnm_types[ctr].name) + { + pnminfo->np = pnm_types[ctr].np; + pnminfo->asciibody = pnm_types[ctr].asciibody; + pnminfo->maxval = pnm_types[ctr].maxval; + pnminfo->loader = pnm_types[ctr].loader; + } + if (!pnminfo->loader) + FATALP ("PNM: file not in a supported format"); + + pnmscanner_gettoken(scan, (unsigned char *)buf, BUFLEN); + if (pnmscanner_eof(scan)) + FATALP ("PNM: premature end of file"); + pnminfo->xres = isdigit(*buf)?atoi(buf):0; + if (pnminfo->xres<=0) + FATALP ("PNM: invalid xres while loading"); + + pnmscanner_gettoken(scan, (unsigned char *)buf, BUFLEN); + if (pnmscanner_eof(scan)) + FATALP ("PNM: premature end of file"); + pnminfo->yres = isdigit(*buf)?atoi(buf):0; + if (pnminfo->yres<=0) + FATALP ("PNM: invalid yres while loading"); + + if (pnminfo->np != 0) /* pbm's don't have a maxval field */ + { + pnmscanner_gettoken(scan, (unsigned char *)buf, BUFLEN); + if (pnmscanner_eof(scan)) + FATALP ("PNM: premature end of file"); + + pnminfo->maxval = isdigit(*buf)?atoi(buf):0; + if ((pnminfo->maxval<=0) + || (pnminfo->maxval>255 && !pnminfo->asciibody)) + FATALP ("PNM: invalid maxval while loading"); + } + + BITMAP_WIDTH (bitmap) = (unsigned short) pnminfo->xres; + BITMAP_HEIGHT (bitmap) = (unsigned short) pnminfo->yres; + + BITMAP_PLANES (bitmap) = (pnminfo->np)?(pnminfo->np):1; + /* BITMAP_BITS (bitmap) = (unsigned char *) malloc (pnminfo->yres * pnminfo->xres * BITMAP_PLANES (bitmap)); */ + XMALLOCT(BITMAP_BITS (bitmap), unsigned char *, pnminfo->yres * pnminfo->xres * BITMAP_PLANES (bitmap)); + pnminfo->loader (scan, pnminfo, BITMAP_BITS (bitmap)); + /* vvv Dat: We detect truncation late truncated files will just have garbage :-( */ + if (pnmscanner_eof(scan)) + FATALP ("PNM: truncated image data"); + + /* Destroy the scanner */ + pnmscanner_destroy (scan); + + /* free the structures */ + /* free (pnminfo); */ + XFREE(pnminfo); + + /* close the file */ + /* xfclose (fd, filename); */ + + return (bitmap); +} + +static void +pnm_load_ascii (PNMScanner *scan, + PNMInfo *info, + unsigned char *data) +{ + register unsigned char *d, *dend; + unsigned u, s; + #if 0 /**** pts ****/ + /* Buffer reads to increase performance */ + /* !! convert(1) is faster -- maybe buffering helps? */ + pnmscanner_createbuffer(scan, 4096); + #endif + d = data; + if (info->np==0) { /* PBM */ + dend=d+info->xres*info->yres; + while (d!=dend) { + /* pnmscanner_getsmalltoken(scan, (unsigned char *)buf); */ + pnmscanner_eatwhitespace(scan); + *d++=-(scan->cur=='0'); + pnmscanner_getchar(scan); + } + } else { /* PGM or PPM */ /**** pts ****/ + dend=d+info->xres*info->yres*info->np; + switch (s=info->maxval) { + case 255: + while (d!=dend) { + *d++=pnmscanner_getint(scan); /* Dat: removed isdigit() */ + } + break; + case 15: + while (d!=dend) { + *d++ = pnmscanner_getint(scan)*17; + } + break; + case 3: + while (d!=dend) { + *d++ = pnmscanner_getint(scan)*85; + } + break; + case 0: /* avoid division by 0 */ + case 1: + while (d!=dend) { + *d++ = -(0==pnmscanner_getint(scan)); /* (*buf=='0')?0xff:0x00; */ + } + default: + while (d!=dend) { + u=pnmscanner_getint(scan); + *d++ = (0UL+u*255UL+(s>>1))/s; /* always <= 255 */ + } + } + } +} + +static void +pnm_load_raw (PNMScanner *scan, + PNMInfo *info, + unsigned char *data) +{ + unsigned char *d, *dend; + unsigned s=info->maxval; + slen_t delta, scanlines; + FILEE *fd=pnmscanner_fd(scan); + + scanlines = info->yres; + d = data; + delta=info->xres * info->np; + dend=d+delta*scanlines; + while (d!=dend) { + if (info->xres*info->np != fread_FILEE((char*)d, delta, fd)) return; + d+=delta; + } + d=data; + switch (s=info->maxval) { /**** pts ****/ + case 1: case 0: + for (; d!=dend; d++) if (*d!=0) *d=255; + break; + case 3: + while (d!=dend) *d++*=85; + break; + case 15: + while (d!=dend) *d++*=17; + break; + case 255: + break; + default: + for (; d!=dend; d++) *d=(0UL+*d*255UL+(s>>1))/s; /* always <= 255 */ + break; + } +} + +static void +pnm_load_rawpbm (PNMScanner *scan, + PNMInfo *info, + unsigned char *data) +{ + unsigned char *buf; + unsigned char curbyte; + unsigned char *d; + unsigned int x, i; + unsigned int start, end, scanlines; + FILEE *fd; + unsigned int rowlen, bufpos; + + fd = pnmscanner_fd(scan); + /****pts****/ /* rowlen = (unsigned int)ceil((double)(info->xres)/8.0);*/ + rowlen=(info->xres+7)>>3; + /* buf = (unsigned char *)malloc(rowlen*sizeof(unsigned char)); */ + XMALLOCT(buf, unsigned char*, rowlen*sizeof(unsigned char)); + + start = 0; + end = info->yres; + scanlines = end - start; + d = data; + + for (i = 0; i < scanlines; i++) + { + if (rowlen != fread_FILEE((char*)buf, rowlen, fd)) + FATALP ("PNM: error reading file"); + bufpos = 0; + curbyte = buf[0]; + + for (x = 0; x < info->xres; x++) + { + if ((x % 8) == 0) { + curbyte = buf[bufpos++]; + /* // if (curbyte!=0) printf("%d <%u>\n", x, curbyte); */ + } + /* // if (curbyte!=0) printf("[%u]\n", curbyte); */ + d[x] = (curbyte&0x80) ? 0x00 : 0xff; + curbyte <<= 1; + } + + d += info->xres; + } + + XFREE(buf); +} + +/**************** FILE SCANNER UTILITIES **************/ + +/* pnmscanner_create --- + * Creates a new scanner based on a file descriptor. The + * look ahead buffer is one character initially. + */ +static PNMScanner * +pnmscanner_create (FILEE *fd) +{ + PNMScanner *s; + + XMALLOCTU (s, PNMScanner); + s->fd = fd; + s->eof = !fread_FILEE(&(s->cur), 1, s->fd); + return s; +} + +/* pnmscanner_destroy --- + * Destroys a scanner and its resources. Doesn't close the fd. + */ +static void +pnmscanner_destroy (PNMScanner *s) +{ + XFREE(s); +} + +#if 0 /**** pts ****/ +/* pnmscanner_createbuffer --- + * Creates a buffer so we can do buffered reads. + */ +static void +pnmscanner_createbuffer (PNMScanner *s, + unsigned int bufsize) +{ + /* s->inbuf = (char *)malloc(sizeof(char)*bufsize); */ + XMALLOCT(s->inbuf, char*, sizeof(char)*bufsize); + s->inbufsize = bufsize; + s->inbufpos = 0; + s->inbufvalidsize = fread(s->inbuf, 1, bufsize, s->fd); +} +#endif + +/* pnmscanner_gettoken --- + * Gets the next token, eating any leading whitespace. + */ +static void pnmscanner_gettoken (PNMScanner *s, + unsigned char *buf, + unsigned int bufsize) +{ + unsigned char *bufend=buf+bufsize-1; + pnmscanner_eatwhitespace(s); + while (!pnmscanner_eof(s) && !isspace(s->cur) && s->cur!='#') { + if (buf!=bufend) *buf++=s->cur; + pnmscanner_getchar(s); + } + *buf='\0'; +} + +static unsigned pnmscanner_getint(PNMScanner *s) { + unsigned ret=0; + pnmscanner_eatwhitespace(s); + while (!pnmscanner_eof(s)) { + if (isdigit(s->cur)) ret=10*ret+s->cur-'0'; + else if (isspace(s->cur) || s->cur=='#') break; + pnmscanner_getchar(s); + } + return ret; +} diff --git a/Build/source/utils/sam2p/input-tga.ci b/Build/source/utils/sam2p/input-tga.ci new file mode 100644 index 00000000000..9f8b72dcf0a --- /dev/null +++ b/Build/source/utils/sam2p/input-tga.ci @@ -0,0 +1,604 @@ +/* This code is ripped from Autotrace-0.29. Small modifications by pts. */ + +/* input-tga.ci reads tga files */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +/* #include <unistd.h> */ + +#include "at_bitmap.h" +/* #include "message.h" */ +/* #include "xstd.h" */ +/* #include "input-tga.h" */ /* BUGFIX by pts: bmp -> tga */ + +/* TODO: + - Handle loading images that aren't 8 bits per channel. +*/ + +/* Round up a division to the nearest integer. */ +#define ROUNDUP_DIVIDE(n,d) (((n) + (d - 1)) / (d)) + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define INDEXED 1 +#define INDEXEDA 2 +#define GRAY 3 +#define TGA_RGB 5 +#define INDEXED_IMAGE 1 +#define INDEXEDA_IMAGE 2 +#define GRAY_IMAGE 3 +#define GRAYA_IMAGE 4 +#define TGA_RGB_IMAGE 5 +#define TGA_RGBA_IMAGE 6 + +typedef struct _TgaSaveVals +{ + int rle; +} TgaSaveVals; + +typedef struct _TgaSaveInterface +{ + int run; +} TgaSaveInterface; + +struct tga_header +{ + unsigned char idLength; + unsigned char colorMapType; + + /* The image type. */ +#define TGA_TYPE_MAPPED 1 +#define TGA_TYPE_COLOR 2 +#define TGA_TYPE_GRAY 3 +#define TGA_TYPE_MAPPED_RLE 9 +#define TGA_TYPE_COLOR_RLE 10 +#define TGA_TYPE_GRAY_RLE 11 + unsigned char imageType; + + /* Color Map Specification. */ + /* We need to separately specify high and low bytes to avoid endianness + and alignment problems. */ + unsigned char colorMapIndexLo, colorMapIndexHi; + unsigned char colorMapLengthLo, colorMapLengthHi; + unsigned char colorMapSize; + + /* Image Specification. */ + unsigned char xOriginLo, xOriginHi; + unsigned char yOriginLo, yOriginHi; + + unsigned char widthLo, widthHi; + unsigned char heightLo, heightHi; + + unsigned char bpp; + + /* Image descriptor. + 3-0: attribute bpp + 4: left-to-right ordering + 5: top-to-bottom ordering + 7-6: zero + */ +#define TGA_DESC_ABITS 0x0f +#define TGA_DESC_HORIZONTAL 0x10 +#define TGA_DESC_VERTICAL 0x20 + unsigned char descriptor; +}; + +#if 0 +static struct +{ + unsigned int extensionAreaOffset; + unsigned int developerDirectoryOffset; +#define TGA_SIGNATURE "TRUEVISION-XFILE" + char signature[16]; + char dot; + char null; +} tga_footer; +#endif + + +static bitmap_type ReadImage (FILE *fp, + struct tga_header *hdr); +#if PTS_SAM2P /**** pts ****/ +bitmap_type tga_load_image (FILE* filename) +#else +bitmap_type tga_load_image (at_string filename) +#endif +{ + FILE *fp; + struct tga_header hdr; + + bitmap_type image; + + image.bitmap = NULL; + + #if PTS_SAM2P /**** pts ****/ + fp=filename; + #else + fp = fopen (filename, "rb"); + if (!fp) + FATAL1 ("TGA: can't open \"%s\"\n", filename); + #endif + + memset(&hdr, '\0', sizeof(hdr)); + +#if 0 + /* Check the footer. */ + if (fseek (fp, 0L - (sizeof (tga_footer)), SEEK_END) + || fread (&tga_footer, sizeof (tga_footer), 1, fp) != 1) +#if PTS_SAM2P + FATALP("TGA: Cannot read footer"); +#else + FATAL1 ("TGA: Cannot read footer from \"%s\"\n", filename); +#endif + /* Check the signature. */ + if (fseek (fp, 0, SEEK_SET) || +#else + if (0 || +#endif + fread (&hdr, sizeof (hdr), 1, fp) != 1) +#if PTS_SAM2P + FATALP("TGA: Cannot read header"); +#else + FATAL1 ("TGA: Cannot read header from \"%s\"\n", filename); +#endif + + /* Skip the image ID field. */ + { +#if 0 + if (hdr.idLength && fseek (fp, hdr.idLength, SEEK_CUR)) +#else + char buf[256]; + if (hdr.idLength!=fread(buf, 1, hdr.idLength, fp)) +#endif +#if PTS_SAM2P + FATALP("TGA: Cannot skip ID field"); +#else + FATAL1 ("TGA: Cannot skip ID field in \"%s\"\n", filename); +#endif + } + + image = ReadImage (fp, &hdr); + /* fclose (fp); */ + return image; +} + + +static int +std_fread (unsigned char *buf, + int datasize, + int nelems, + FILE *fp) +{ + + return fread (buf, datasize, nelems, fp); +} + +#define RLE_PACKETSIZE 0x80 + +/* Decode a bufferful of file. */ +static int +rle_fread (unsigned char *buf, + int datasize, + int nelems, + FILE *fp) +{ + static unsigned char *statebuf = 0; + static int statelen = 0; + static int laststate = 0; + + int j, k; + int buflen, count, bytes; + unsigned char *p; + + /* Scale the buffer length. */ + buflen = nelems * datasize; + + j = 0; + while (j < buflen) + { + if (laststate < statelen) + { + /* Copy bytes from our previously decoded buffer. */ + bytes = MIN (buflen - j, statelen - laststate); + memcpy (buf + j, statebuf + laststate, bytes); + j += bytes; + laststate += bytes; + + /* If we used up all of our state bytes, then reset them. */ + if (laststate >= statelen) + { + laststate = 0; + statelen = 0; + } + + /* If we filled the buffer, then exit the loop. */ + if (j >= buflen) + break; + } + + /* Decode the next packet. */ + count = fgetc (fp); + if (count == EOF) + { + return j / datasize; + } + + /* Scale the byte length to the size of the data. */ + bytes = ((count & ~RLE_PACKETSIZE) + 1) * datasize; + + if (j + bytes <= buflen) + { + /* We can copy directly into the image buffer. */ + p = buf + j; + } + else { + /* Allocate the state buffer if we haven't already. */ + if (!statebuf) + statebuf = (unsigned char *) malloc (RLE_PACKETSIZE * datasize); + p = statebuf; + } + + if (count & RLE_PACKETSIZE) + { + /* Fill the buffer with the next value. */ + if (fread (p, datasize, 1, fp) != 1) + { + return j / datasize; + } + + /* Optimized case for single-byte encoded data. */ + if (datasize == 1) + memset (p + 1, *p, bytes - 1); + else + for (k = datasize; k < bytes; k += datasize) + memcpy (p + k, p, datasize); + } + else + { + /* Read in the buffer. */ + if (fread (p, bytes, 1, fp) != 1) + { + return j / datasize; + } + } + + /* We may need to copy bytes from the state buffer. */ + if (p == statebuf) + statelen = bytes; + else + j += bytes; + } + +return nelems; +} + +static bitmap_type +ReadImage (FILE *fp, + struct tga_header *hdr) +{ + bitmap_type image; + unsigned char *buffer; + unsigned char *alphas; + + int width, height, bpp, abpp, pbpp, nalphas; + int j, k; + int pelbytes, wbytes, bsize, npels, pels; + int rle, badread; + int itype=0, dtype; + unsigned char *cmap = NULL; + int (*myfread)(unsigned char *, int, int, FILE *); + + /* Find out whether the image is horizontally or vertically reversed. */ + char horzrev = (char) (hdr->descriptor & TGA_DESC_HORIZONTAL); + char vertrev = (char) (!(hdr->descriptor & TGA_DESC_VERTICAL)); + + image.bitmap = NULL; + + /* Reassemble the multi-byte values correctly, regardless of + host endianness. */ + width = (hdr->widthHi << 8) | hdr->widthLo; + height = (hdr->heightHi << 8) | hdr->heightLo; + + bpp = hdr->bpp; + abpp = hdr->descriptor & TGA_DESC_ABITS; + + if (hdr->imageType == TGA_TYPE_COLOR || + hdr->imageType == TGA_TYPE_COLOR_RLE) + pbpp = MIN (bpp / 3, 8) * 3; + else if (abpp < bpp) + pbpp = bpp - abpp; + else + pbpp = bpp; + + if (abpp + pbpp > bpp) + { + WARNINGP3 ("TGA: ",pbpp," bit image, ",abpp," bit alpha is greater than ",bpp," total bits per pixel"); + + /* Assume that alpha bits were set incorrectly. */ + abpp = bpp - pbpp; + WARNINGP1 ("TGA: reducing to * bit alpha: ", abpp); + } + else if (abpp + pbpp < bpp) + { + WARNINGP3 ("TGA: ",pbpp," bit image, ",abpp," bit alpha is less than ",bpp," total bits per pixel"); + + /* Again, assume that alpha bits were set incorrectly. */ + abpp = bpp - pbpp; + WARNINGP1 ("TGA: increasing to * bit alpha: ", abpp); + } + + rle = 0; + switch (hdr->imageType) + { + case TGA_TYPE_MAPPED_RLE: + rle = 1; + case TGA_TYPE_MAPPED: + itype = INDEXED; + + /* Find the size of palette elements. */ + pbpp = MIN (hdr->colorMapSize / 3, 8) * 3; + if (pbpp < hdr->colorMapSize) + abpp = hdr->colorMapSize - pbpp; + else + abpp = 0; + + + if (bpp != 8) + /* We can only cope with 8-bit indices. */ + FATALP ("TGA: index sizes other than 8 bits are unimplemented"); + + if (abpp) + dtype = INDEXEDA_IMAGE; + else + dtype = INDEXED_IMAGE; + break; + + case TGA_TYPE_GRAY_RLE: + rle = 1; + case TGA_TYPE_GRAY: + itype = GRAY; + + if (abpp) + dtype = GRAYA_IMAGE; + else + dtype = GRAY_IMAGE; + break; + + case TGA_TYPE_COLOR_RLE: + rle = 1; + case TGA_TYPE_COLOR: + itype = TGA_RGB; + + if (abpp) + dtype = TGA_RGBA_IMAGE; + else + dtype = TGA_RGB_IMAGE; + break; + + default: + FATALP1 ("TGA: unrecognized image type ", (unsigned)hdr->imageType); +} + + if ((abpp && abpp != 8) || + ((itype == TGA_RGB || itype == INDEXED) && pbpp != 24) || + (itype == GRAY && pbpp != 8)) + /* FIXME: We haven't implemented bit-packed fields yet. */ + FATALP ("TGA: channel sizes other than 8 bits are unimplemented"); + + /* Check that we have a color map only when we need it. */ + if (itype == INDEXED) + { + if (hdr->colorMapType != 1) + FATALP1 ("TGA: indexed image has invalid color map type ", + (unsigned)hdr->colorMapType); + } + else if (hdr->colorMapType != 0) + FATALP1 ("TGA: non-indexed image has invalid color map type ", + (unsigned)hdr->colorMapType); + + alphas = 0; + nalphas = 0; + if (hdr->colorMapType == 1) + { + /* We need to read in the colormap. */ + int index, colors; + unsigned int length; + + index = (hdr->colorMapIndexHi << 8) | hdr->colorMapIndexLo; + length = (hdr->colorMapLengthHi << 8) | hdr->colorMapLengthLo; + + if (length == 0) + FATALP1 ("TGA: invalid color map length ", length); + + pelbytes = ROUNDUP_DIVIDE (hdr->colorMapSize, 8); + colors = length + index; + cmap = (unsigned char *) malloc (colors * pelbytes); + + /* Zero the entries up to the beginning of the map. */ + memset (cmap, 0, index * pelbytes); + + /* Read in the rest of the colormap. */ + if (fread (cmap + (index * pelbytes), pelbytes, length, fp) != length) + FATALP1 ("TGA: error reading colormap; ftell == ", ftell (fp)); + + /* If we have an alpha channel, then create a mapping to the alpha + values. */ + if (pelbytes > 3) + alphas = (unsigned char *) malloc (colors); + + k = 0; + for (j = 0; j < colors * pelbytes; j += pelbytes) + { + /* Swap from BGR to TGA_RGB. */ + unsigned char tmp = cmap[j]; + cmap[k ++] = cmap[j + 2]; + cmap[k ++] = cmap[j + 1]; + cmap[k ++] = tmp; + + /* Take the alpha values out of the colormap. */ + if (alphas) + alphas[nalphas ++] = cmap[j + 3]; + } + + /* If the last color was transparent, then omit it from the + mapping. */ + if (nalphas && alphas[nalphas - 1] == 0) + colors --; + + /* Now pretend as if we only have 8 bpp. */ + abpp = 0; + pbpp = 8; + pelbytes = 1; + } + else + pelbytes = 3; + + image.bitmap = (unsigned char *) malloc (width * height * 3 * sizeof(unsigned char)); + BITMAP_WIDTH (image) = (unsigned short) width; + BITMAP_HEIGHT (image) = (unsigned short) height; + BITMAP_PLANES (image) = (unsigned short) 3; + + /* Calculate TGA bytes per pixel. */ + bpp = ROUNDUP_DIVIDE (pbpp + abpp, 8); + + /* Maybe we need to reverse the data. */ + buffer = NULL; + if (horzrev || vertrev) + buffer = (unsigned char *) malloc (width * height * pelbytes * sizeof (unsigned char)); + if (rle) + myfread = rle_fread; + else + myfread = std_fread; + + wbytes = width * pelbytes; + badread = 0; + + npels = width * height; + bsize = wbytes * height; + + /* Suck in the data one height at a time. */ + if (badread) + pels = 0; + else + pels = (*myfread) (image.bitmap, bpp, npels, fp); + + if (pels != npels) + { + if (!badread) + { + /* Probably premature end of file. */ + WARNINGP1 ("TGA: error reading; ftell == ", ftell (fp)); + badread = 1; + } + + + /* Fill the rest of this tile with zeros. */ + memset (image.bitmap + (pels * bpp), 0, ((npels - pels) * bpp)); + } + /* If we have indexed alphas, then set them. */ + if (nalphas) + { + /* Start at the end of the buffer, and work backwards. */ + k = (npels - 1) * bpp; + for (j = bsize - pelbytes; j >= 0; j -= pelbytes) + { + /* Find the alpha for this index. */ + image.bitmap[j + 1] = alphas[image.bitmap[k]]; + image.bitmap[j] = image.bitmap[k --]; + } + } + + if (itype == GRAY) + for (j = bsize/3 - 1; j >= 0; j -= 1) + { + /* Find the alpha for this index. */ + image.bitmap[3*j] = image.bitmap[j]; + image.bitmap[3*j+1] = image.bitmap[j]; + image.bitmap[3*j+2] = image.bitmap[j]; + } + + + if (pelbytes >= 3) + { + /* Rearrange the colors from BGR to TGA_RGB. */ + for (j = 0; j < bsize; j += pelbytes) + { + unsigned char tmp = image.bitmap[j]; + image.bitmap[j] = image.bitmap[j + 2]; + image.bitmap[j + 2] = tmp; + } + } + + + + if (horzrev || vertrev) + { + unsigned char *tmp; + if (vertrev) + { + /* We need to mirror only vertically. */ + for (j = 0; j < bsize; j += wbytes) + memcpy (buffer + j, + image.bitmap + bsize - (j + wbytes), wbytes); + } + else if (horzrev) + { + /* We need to mirror only horizontally. */ + for (j = 0; j < bsize; j += wbytes) + for (k = 0; k < wbytes; k += pelbytes) + memcpy (buffer + k + j, + image.bitmap + (j + wbytes) - (k + pelbytes), pelbytes); + } + else + { + /* Completely reverse the pixels in the buffer. */ + for (j = 0; j < bsize; j += pelbytes) + memcpy (buffer + j, + image.bitmap + bsize - (j + pelbytes), pelbytes); + } + + /* Swap the buffers because we modified them. */ + tmp = buffer; + buffer = image.bitmap; + image.bitmap = tmp; + } + + if (fgetc (fp) != EOF) + WARNINGP ("TGA: too much input data, ignoring extra..."); + + free (buffer); + + if (hdr->colorMapType == 1) + { + unsigned char *temp, *temp2, *temp3; + unsigned char index; + int xpos, ypos; + + temp2 = temp = image.bitmap; + image.bitmap = temp3 = (unsigned char *) malloc (width * height * 3 * sizeof (unsigned char)); + + for (ypos = 0; ypos < height; ypos++) + { + for (xpos = 0; xpos < width; xpos++) + { + index = *temp2++; + *temp3++ = cmap[3*index+0]; + *temp3++ = cmap[3*index+1]; + *temp3++ = cmap[3*index+2]; + } + } + free (temp); + free (cmap); + } + + if (alphas) + free (alphas); + + return image; +} /* read_image */ diff --git a/Build/source/utils/sam2p/jpegdump_main.cpp b/Build/source/utils/sam2p/jpegdump_main.cpp new file mode 100644 index 00000000000..17098ebe5df --- /dev/null +++ b/Build/source/utils/sam2p/jpegdump_main.cpp @@ -0,0 +1,304 @@ +\/* + * jpegdump_main.cpp -- dump a JPEG stream + * by pts@math.bme.hu at Tue Jun 4 13:19:00 CEST 2002 + */ + + +/* Structure of a typical JPEG file: +(D8:SOI) (E0:APP0) (FE:COM)? (DB:DQT)*2 (C0:SOF0) (C4:DHT)*4 (DA:SOS) +... (D9:EOI) +*/ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "config2.h" +#include <stdio.h> + +#if OBJDEP +#warning PROVIDES: jpegdump_main +#endif + +typedef slen_t dimen_t; +static const unsigned char + CS_UNKNOWN=0, /* error/unspecified */ + CS_GRAYSCALE=1, /* monochrome */ + CS_RGB=2, /* red/green/blue */ + CS_YCbCr=3, /* Y/Cb/Cr (also known as YUV) */ + CS_CMYK=4, /* C/M/Y/K */ + CS_YCCK=5, /* Y/Cb/Cr/K */ + CS_Indexed_RGB=12; + + +/* --- The following code is based on standard/image.c from PHP4 */ + +/* some defines for the different JPEG block types */ +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_COM 0xFE /* comment */ +#define M_DQT 0xDB /* QuantTables */ +#define M_DHT 0xC4 /* HuffTables */ +#define M_APP0 0xe0 +#define M_APP1 0xe1 +#define M_APP2 0xe2 +#define M_APP3 0xe3 +#define M_APP4 0xe4 +#define M_APP5 0xe5 +#define M_APP6 0xe6 +#define M_APP7 0xe7 +#define M_APP8 0xe8 +#define M_APP9 0xe9 +#define M_APP10 0xea +#define M_APP11 0xeb +#define M_APP12 0xec +#define M_APP13 0xed +#define M_APP14 0xee +#define M_APP15 0xef + + +static unsigned short jai_read2(FILE *fp) { + unsigned char a[ 2 ]; + + /* just return 0 if we hit the end-of-file */ + if (fread(a,sizeof(a),1,fp) != 1) return 0; + + return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]); +} + +static unsigned int jai_next_marker(FILE *fp) + /* get next marker byte from file */ +{ + int c; + + /* skip unimportant stuff */ + + c = MACRO_GETC(fp); + + while (c != 0xff) { + if ((c = MACRO_GETC(fp)) == EOF) + return M_EOI; /* we hit EOF */ + } + + /* get marker byte, swallowing possible padding */ + do { + if ((c = MACRO_GETC(fp)) == EOF) + return M_EOI; /* we hit EOF */ + } while (c == 0xff); + + // printf("marker=%02X\n", c); + return (unsigned int) c; +} + +static void jai_skip_variable(FILE *fp) + /* skip over a variable-length block; assumes proper length marker */ +{ + unsigned short length; + + printf("%lu: skip variable\n", ftell(fp)); + + length = jai_read2(fp); + length -= 2; /* length includes itself */ + if (length>0) { + printf("... variable length=%u\n", length); + #if 0 + fseek(fp, (long) length, SEEK_CUR); /* skip the header */ + #endif + while (length--!=0) MACRO_GETC(fp); /* make feof(fp) correct */ + printf("%lu: skipped variable; feof=%u\n", ftell(fp), feof(fp)); + } +} + +struct gfxinfo { + unsigned char bad, bpc, cpp, had_jfif, colortransform, id_rgb; + dimen_t height, width; + /** Offset of byte just _after_ the first SOF marker (FF C0 or alike) + * from the beginning of the file. + */ + slen_t SOF_offs; +}; + +/** main loop to parse JPEG structure */ +static void jai_handle_jpeg(struct gfxinfo *result, FILE *fp) { + unsigned int length, marker; + unsigned char had_adobe, id, hvs, qtn; + + result->bad=1; /* signal invalid return value */ + result->id_rgb=0; + result->had_jfif=0; + result->colortransform=127; /* no Adobe marker yet */ + // fseek(fp, 0L, SEEK_SET); /* position file pointer on SOF */ + + if (MACRO_GETC(fp) != 0xFF || MACRO_GETC(fp)!=M_SOI) return; /* JPEG header... */ + printf("2: marker D8 (SOI)\n"); + + for (;;) { + assert(!feof(fp)); + printf("... %lu\n", ftell(fp)); + marker=jai_next_marker(fp); + printf("%lu: marker %02X\n", ftell(fp), marker); + switch (marker) { + case M_SOF0: + if (result->bad!=1) { result->bad=4; return; } /* only one M_SOF allowed */ + result->SOF_offs=ftell(fp); + /* handle SOFn block */ + length=jai_read2(fp); + result->bpc = MACRO_GETC(fp); + result->height = jai_read2(fp); + result->width = jai_read2(fp); + result->cpp = MACRO_GETC(fp); + if ((length-=8)!=3U*result->cpp) return; + if (result->cpp==3) { + result->id_rgb =(id=MACRO_GETC(fp)=='R'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp); + printf("Comp#1 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n", + id, hvs>>4, hvs&15, qtn); + result->id_rgb&=(id=MACRO_GETC(fp)=='G'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp); + printf("Comp#2 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n", + id, hvs>>4, hvs&15, qtn); + result->id_rgb&=(id=MACRO_GETC(fp)=='B'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp); + printf("Comp#3 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n", + id, hvs>>4, hvs&15, qtn); + } else while (length--!=0) MACRO_GETC(fp); + if (result->cpp!=1 && result->cpp!=3 && result->cpp!=4) { + result->bad=5; return; + } + if (feof(fp)) { result->bad=8; return; } + result->bad=2; + break; + case M_SOF1: + case M_SOF2: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + // fprintf(stderr, "SOF%u\n", marker-M_SOF0); assert(0); + result->bad=3; + return; + case M_SOS: /* we are about to hit image data. We're done. */ + jai_skip_variable(fp); /* anything else isn't interesting */ + if (feof(fp)) { result->bad=8; return; } + if (result->bad==2 && !feof(fp)) result->bad=0; + /* Dat: we should really return() here, because the SOS marker is + * followed by binary data, not surrounded by markers. + */ + break; + case M_EOI: /* end of image or EOF */ + if (feof(fp)) result->bad=6; + else if (MACRO_GETC(fp)!=EOF) result->bad=7; + return; + case M_APP0: /* JFIF application-specific marker */ + length=jai_read2(fp); + if (length==2+4+1+2+1+2+2+1+1) { + result->had_jfif=MACRO_GETC(fp)=='J' && MACRO_GETC(fp)=='F' && MACRO_GETC(fp)=='I' && + MACRO_GETC(fp)=='F' && MACRO_GETC(fp)==0; + length-=7; + } else length-=2; + while (length--!=0) MACRO_GETC(fp); + if (feof(fp)) { result->bad=8; return; } + break; + case M_APP14: /* Adobe application-specific marker */ + length=jai_read2(fp); + if ((length-=2)==5+2+2+2+1) { + had_adobe=MACRO_GETC(fp)=='A' && MACRO_GETC(fp)=='d' && MACRO_GETC(fp)=='o' && + MACRO_GETC(fp)=='b' && MACRO_GETC(fp)=='e' && ((unsigned char)MACRO_GETC(fp))>=1; + MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); + if (had_adobe) result->colortransform=MACRO_GETC(fp); + else MACRO_GETC(fp); + } else while (length--!=0) MACRO_GETC(fp); + if (feof(fp)) { result->bad=8; return; } + break; + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP15: + /* fall through */ + default: + jai_skip_variable(fp); /* anything else isn't interesting */ + if (feof(fp)) { result->bad=8; return; } + break; + } } +} + +static char *jai_errors[]={ + (char*)NULLP, + /*1*/ "missing SOF0 marker", + /*2*/ "EOF|EOI before SOS", /* "premature EOF", */ + /*3*/ "not a Baseline JPEG (SOF must be SOF0)", + /*4*/ "more SOF0 markers", + /*5*/ "bad # components", + /*6*/ "EOF before EOI", + /*7*/ "extra bytes after EOI", + /*8*/ "EOF before end of parametric marker", +}; + +int main(int argc, char **argv) { + struct gfxinfo gi; + FILE *f=argc>=2 ? fopen(argv[1], "rb"): stdin; + jai_handle_jpeg(&gi, f); + if (gi.bad==1) { + printf("JAI: Warning: %s.\n", jai_errors[gi.bad]); + gi.cpp=1; + gi.width=0; + gi.height=0; + gi.SOF_offs=0; + gi.bpc=0; + } else if (gi.bad!=0) { printf("JAI: %s.\n", jai_errors[gi.bad]); if (gi.bad!=1) return 1; } + unsigned char colorspace; + if (gi.cpp==1) { + colorspace=CS_GRAYSCALE; + } else if (gi.cpp==3) { + colorspace=CS_YCbCr; + if (gi.had_jfif!=0) ; + else if (gi.colortransform==0) colorspace=CS_RGB; + else if (gi.colortransform==1) ; + else if (gi.colortransform!=127) { printf("JAI: unknown ColorTransform: %u\n", (unsigned)gi.colortransform); return 2; } + else if (gi.id_rgb!=0) colorspace=CS_RGB; + /* Imp: check for id_ycbcr */ + else printf("JAI: assuming YCbCr color space\n"); + } else if (gi.cpp==4) { + colorspace=CS_CMYK; + if (gi.colortransform==0) ; + else if (gi.colortransform==2) colorspace=CS_YCCK; + else if (gi.colortransform!=127) { printf("JAI: unknown ColorTransform: %u\n", (unsigned)gi.colortransform); return 2; } + } else assert(0); + fseek(f, 0L, 2); /* EOF */ + long flen=ftell(f); /* skip extra bytes after EOI */ + fclose(f); + printf("%lu: flen\n", flen); + printf("bpc=%u cpp=%u had_jfif=%u colortransform=%u id_rgb=%u colorspace=%u\n", + gi.bpc, gi.cpp, gi.had_jfif, gi.colortransform, gi.id_rgb, colorspace); + printf("wd=%u ht=%u SOF_offs=%u\n", gi.width, gi.height, gi.SOF_offs); + return 0; +} + +/* __EOF__ */ diff --git a/Build/source/utils/sam2p/l1lzw.psm b/Build/source/utils/sam2p/l1lzw.psm new file mode 100644 index 00000000000..9c1ad58d1d4 --- /dev/null +++ b/Build/source/utils/sam2p/l1lzw.psm @@ -0,0 +1,656 @@ +/* l1lzw.psm + * by pts@fazekas.hu at Sun Sep 22 01:23:57 CEST 2002 + * formerly lzwdecode.psm -- a real, effective implementation of PostScript + * LanguageLevel2 and PDF /LZWDecode filters (same as the LZW + * compression used in TIFF raster image files), in PostScript Level1 + * derived from lzwdecode.c by pts@fazekas.hu (at Wed Sep 4 11:11:45 CEST 2002) + * by pts@fazekas.hu at Wed Sep 4 11:30:18 CEST 2002 + * first run at Wed Sep 4 14:18:43 CEST 2002 + * linux-2.2.8 fine at Wed Sep 4 14:46:05 CEST 2002 + * rets linux-2.2.8 fine at Wed Sep 4 15:58:24 CEST 2002 + * works at Wed Sep 4 16:41:29 CEST 2002 + * linux-2.2.8 58388480 uncompressed: + * lzwdecode.c: 17s user time (*1) + * lzw_codec.c: 6s user time (*0.353) + * lzwdecode.psm: 1080s user time (*63.53) + * stack-reorg works at Thu Sep 5 12:31:23 CEST 2002 + * lzwdecode.psm: 980s user time (*57.65) + * lzwdecode.eps works at Thu Sep 5 14:31:23 CEST 2002 + * last non-` at Sat Sep 21 23:40:03 CEST 2002 + * + * Note that the LZW compression (but not uncompression) is patented by + * Unisys (patent number #4,558,302), so use this program at your own legal + * risk! + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +% OK: test with aaaaaaaaaaaa (stack overflow) + +#include "psmlib.psm" + +#if USE_A85D +#else + #if USE_HEXD + #else + #define USE_BINARY 1 + #endif +#endif + +#if USE_NO_BIND + #define BIND_DEF def +#else + #define BIND_DEF bind def +#endif + +#if USE_PIN +/* --- .pin begins */ + +%<Head> +%!PS-Adobe-3.0`E +%%Inflater: pts@fazekas.hu l1lzw.psm +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +%</Head> + +%<Open> +save`s `R +%</Open> + +% vvv 50 +%<Abbr acount=26 xcount=30> +begin +%</Abbr> + +%<A x "load def"/> % best to make it first +%<A E def/> % best to make it second +% K: .toksubs. +%<D T .stream./> +%<D F .stream./> + +%<A + add/> +%<A , and/> +%<A - sub/> +%<A . lt/> +%<A : for/> +%<A ; getinterval/> +%<A * gt/> +%<A = eq/> +%<A @ loop/> +%<A A currentfile/> +%C! +%D! +%<A H index/> +%<A J 4096/> +%<A L length/> +%<A O pop/> +%S! +%<A X exit/> +%<A a packedarray/> +%<A b bitshift/> +%<A c exch/> +%d! +%<A g get/> +%<A y copy/> +%<A i ifelse/> +%<A j if/> +%<A r read/> +%<A s string/> +%<A t put/> +%<A u dup/> +% %<A | -1670420001/> -- not needed, long enough +%<A ~ ne/> +#if USE_SHORT_NAMES +%<D e Flzwdecode_init/> +%<D f Flzwdecode_do/> +%<D I Fclear/> +%<D k prefix/> +%<D l suffix/> +%<D m stack/> +%<D n preread/> +%<D o past/> +%<D p nentry/> +%<D q had_eof/> +%<D v nentrybig/> +%<D w nentryb/> +%<D h stackslice/> +%<D z gcode/> +%<D B Fmain/> +#endif +#if USE_A85D +%<D d a85_getc/> +%<D S xS/> +%<D D xD/> +%<D C xC/> +#endif +#if USE_HEXD +%<D d .hexd.un/> +%<A S readhexstring/> +%<D D .hexd.un/> +%<D C .hexd./> +#endif +#if USE_BINARY +%<D d .binary.un/> +#if USE_PALETTE +%<D S readstring/> +#endif +%<D D .binary.un/> +%<D C .binary.un/> +#endif + +%<TokSubs name=K inlining=0/> + +%<Test> +#if USE_BINARY + /F /filter where {pop false}{true} ifelse def +#else + #if USE_A85D + {mark currentfile/ASCII85Decode filter/T exch def}stopped + #endif + #if USE_HEXD + {mark currentfile/ASCIIHexDecode filter/T exch def}stopped + #endif + /F exch def cleartomark +#endif +`w `h `b[1 0 0 -1 0 `h] +#if USE_TRUE +true +#else +F +#endif +%</Test> + +%<S len=4096> +4096 string +%</S> + +#if USE_SHORT_NAMES_OLD + #define a85_getc d + #define Flzwdecode_init e + #define Flzwdecode_do f + #define Fclear I +#endif + +#if USE_CURRENTFILE + #define STDIN currentfile +#endif + +%<True> + % Fmain + % ^^^ must call it here, because _now_ `currentfile fileposition` is at the real image data + % vvv avoid Fmain here because of the substituted constant 4717 (and also size increase!) + Flzwdecode_init + % !! Imp: less code here, init as a macro + /Fmain 4096 string def + { Fmain Flzwdecode_do } `i + Fmain Flzwdecode_do pop % make sure that mEOD has been read + TE_read_eod +%</True> + +%<False> +#if USE_BINARY +/F currentfile/LZWDecode filter def +#else +/F T/LZWDecode filter def +#endif +F `i +F closefile +#if !USE_BINARY +T closefile +#endif +%</False> + +%<Defs> +#else +40 dict begin % LZWDict +#endif + +#if 0 +% (a) () 0 1 +% DumpStack +% TYPE_STACK(-str -int) +% ZZZZZZZZZ +% (a) 3 +% ASSERT_STACK(-str -int,(1)) +% pop pop +#endif + + +% Defaults: /EarlyChange 1 /UnitLength 8 /LowBitFirst false +#if !USE_EARLYCHANGE_1 +/EarlyChange 1 def +#endif +#if !USE_UNITLENGTH_8 +/UnitLength 8 def +#endif +#if !USE_LOWBITFIRST_FALSE +/LowBitFirst false def +#endif + +/* OK: test with aaaaaaaaaaaa (stack overflow) */ +#define STACKSIZE 4096 +#define STACKSIZE_M1 4095 + +#if USE_SHORT_NAMES_OLD +#endif + +% Uninitialized const-vars +/prefix 4096 array def % array[0..4095] of 0..4095 +/suffix 4096 string def +/stack STACKSIZE string def +#if USE_CURRENTFILE +#else + /STDIN (%stdin) (r) file def + /STDOUT (%stdout) (w) file def % Fmain +#endif +#if USE_HEXD + /C(.)def +#endif + +% Uninitialized vars +#if USE_UNITLENGTH_8 + #define mClear 256 + #define mEOD 257 +#endif +#if !USE_NO_NULLDEF + /preread null def + /past null def + /nentry null def + /had_eof null def % 0..2 + #if !USE_UNITLENGTH_8 + /mEOD null def + /mClear null def + #endif + /nentrybig null def + /nentryb null def + /gcode null def % Flzwdecode_do + /stackslice null def % Flzwdecode_do + #if USE_A85D + /S null def + /D null def + /C null def + #endif +#endif + +#if USE_PIN +{ +#endif + +#if USE_A85D + /a85_getc{ % Simple getchar() of ASCII85Decode filter :-)), formerly /d + PSM_A85_GETC + }BIND_DEF +#endif + +%** - Fclear - +/Fclear { + #if USE_UNITLENGTH_8 + /nentry 258 def + /nentryb 9 def + #if USE_EARLYCHANGE_1 + /nentrybig 512 def + #else + /nentrybig 513 EarlyChange sub def + #endif + #else + /nentry 1 UnitLength bitshift 2 add def + /nentryb UnitLength 1 add def + /nentrybig 1 nentryb bitshift + #if !USE_EARLYCHANGE_1 + 1 EarlyChange sub add + #endif + def + #endif + 0 1 nentry 3 sub { + % Stack: code(0..255) + dup prefix exch dup + % Stack: code prefix code code + put + suffix exch dup put + } for +} BIND_DEF + +%** - Flzwdecode_init - +%** The caller should have modified /EarlyChange, /UnitLength and /LowBitFirst +/Flzwdecode_init { + TE_init + /past 8 def + /preread 0 def + /had_eof 0 def + #if !USE_EARLYCHANGE_1 + ASSERT_TRUE(EarlyChange 0 INT_EQ EarlyChange 1 INT_EQ BOOL_BIN(or,(ora1)), (lsp->EarlyChange==0 || lsp->EarlyChange==1)) + #endif + #if USE_UNITLENGTH_8 + Fclear + #else + ASSERT_TRUE(3 UnitLength INT_LE UnitLength 8 INT_LE and, (3<=lsp->UnitLength && lsp->UnitLength<=8)) + Fclear + /mClear 1 UnitLength bitshift def + /mEOD 1 UnitLength bitshift 1 add def + #endif + /stackslice stack 0 0 getinterval def + /gcode {} def +} BIND_DEF + +%** <str> Flzwdecode_do <str.pre> +%** The caller should have called Flzwdecode_init. Flzwdecode_do fills the +%** entire str.pre unless EOF on input prevents this. str.pre can have any +%** length. Doesn`t depend of str.pre passed to it on the previous invocation. +/Flzwdecode_do { + ASSERT_TRUE(10 nentry INT_LE,(lsp->nentry>=10)) + dup % Silently leave on stack + stackslice had_eof + % Stack: reto rets==reto stackslice had_eof + { % W2:WHILE(1) + % Stack: len++ stackslice had_eof* + dup 0 INT_NE { + /had_eof exch def + pop + /stackslice stack 0 0 getinterval def + exit % exit(W2) + }if % return(len) + ASSERT_STACK(-str -str -str -int,(W2.in)) + pop + % Stack: len++ stackslice + % Stack: reto rets stackslice + ASSERT_STACK(-str -str -str,(3)) + /* Flush stack. */ + 2 copy length exch length ge { % return from the stack (rets.length<=stackslice.length + % Stack: reto rets stackslice + dup 0 3 index length getinterval + % Stack: reto rets stackslice stackslice[0.. rets.length] + 2 index copy pop + % Stack: reto rets stackslice + /stackslice exch 2 index length dup + % Stack: reto rets /stackslice stackslice rets.length rets.length + 2 index length exch sub + % Stack: reto rets /stackslice stackslice rets.length stackslice.length-rets.length + getinterval def + 0 0 getinterval + % Stack: reto rets[0,0] + ASSERT_STACK(-str -str,(4)) + exit % exit(W2) + }if + % vvv flush the whole stack into rets + 2 copy exch + copy pop % stackslice -> rets + length dup + % Stack: reto rets stackslice.length stackslice.length + 2 index length exch sub + % Stack: reto rets stackslice.length rets.length-stackslice.length + getinterval + % Stack: reto rets + ASSERT_STACK(-str -str,(5)) + ASSERT_TRUE(dup length 1 exch INT_LE,(len>=1)) + % Stack: len++ + + /* Read next code (0..4095) from input to `code` */ + nentry nentrybig INT_EQ { + /nentryb nentryb 1 add def + /nentrybig 1 nentryb bitshift + #if !USE_EARLYCHANGE_1 + 1 EarlyChange sub add + #endif + def + }if + ASSERT_TRUE(4 nentryb INT_LE nentryb 12 INT_LE and, (4<=nentryb && nentryb<=12)) + ASSERT_STACK(-str -str,(6)) + + { % W1:WHILE(1) + ASSERT_STACK(-str -str,(7)) + % Stack: len++ + % assert(had_eof==0); -- cannot check this right here... + ASSERT_TRUE(1 past INT_LE past 8 INT_LE and,(1<=past && past<=8)) + ASSERT_TRUE(1 nentryb INT_LE nentryb 13 INT_LE and,(1<=nentryb && nentryb<=13)) + #if !USE_LOWBITFIRST_FALSE + LowBitFirst { + % Dat: this is untested, even the stack + /code 0 def + 0 1 netryb 1 sub { + % Stack: len++ i + past 8 INT_EQ { + /preread TE_read(def /past 0 def) + #if !USE_NO_EOF + { + TE_read_pop pop + /had_eof 2 def exit % exit from inner `for` + }ifelse + #endif + }if + preread 1 and 0 INT_NE { + 1 exch bitshift code INT_BIN(add,(ora2)) /code exch def + }{pop}ifelse + % Stack: len++ + /preread preread -1 bitshift def + /past past 1 add def + }for + had_eof 0 INT_NE {0 had_eof exit}if % exit(W1) + code + }{ % else: !LowBitFirst + #endif + past nentryb add + % Stack: len++ past* + ASSERT_STACK(-str -str -int,(8)) + dup 7 INT_GT { + dup 16 INT_GT { + 16 sub + preread 8 bitshift + % Stack: len++ past* code + /preread TE_read(def) + #if !USE_NO_EOF + { + TE_read_pop pop + % Stack: len++ past* code + pop + /past exch def + 0 2 + % Stack: len++ garbage had_eof* + exit % exit(W1) + }ifelse + #endif + }{ + 8 sub + 0 % /code + }ifelse + % Stack: len++ past* code + ASSERT_STACK(-str -str -int -int,(9)) + ASSERT_TRUE(1 index 1 exch INT_LE 2 index 8 INT_LE and,(1<=lsp->past && lsp->past<=8)) + preread INT_BIN(add,(or1)) + % Stack: len++ past* code|preread + 1 index bitshift + % Stack: len++ past* code*==(code|preread)<<past* + /preread TE_read(def) + #if !USE_NO_EOF + { + TE_read_pop pop + % Stack: len++ past* code + pop + /past exch def + 0 2 + % Stack: len++ garbage had_eof* + exit % exit(W1) + }ifelse + #endif + ASSERT_STACK(-str -str -int -int,(10)) + }{ + 0 % /code + }ifelse + exch + % Stack: len++ code past* + ASSERT_STACK(-str -str -int -int,(11)) + preread exch 2 copy + % Stack: len++ code preread0 past* preread past* + { 255 127 63 31 15 7 3 1 0 } % cAnd + exch get and + % Stack: len++ code preread0 past* preread&cAnd[past*] + /preread exch def % lsp->preread&=(1<<(8-lsp->past))-1; /* do PCLEAR */ + % Stack: len++ code preread0 past* + dup /past exch def + 8 sub bitshift INT_BIN(add,(or2)) + % Stack: len++ code*==code|(preread>>(8-past)) + ASSERT_STACK(-str -str -int,(12)) + #if !USE_LOWBITFIRST_FALSE + }ifelse % if: /LowBitFirst + #endif + % Stack: len++ code + ASSERT_STACK(-str -str -int,(13)) + + dup mClear INT_LT{ + /* Speed-up: process normal literal data code in `code` */ + % Stack: len++ code + ASSERT_STACK(-str -str -int,(15b)) + ASSERT_TRUE(dup 1 add mClear INT_LE,(code too high2)) /* /ioerror */ + ASSERT_TRUE(nentry 4095 INT_LE,(table full2)) /* /ioerror */ + prefix nentry 2 index put + suffix nentry 1 sub 2 index put + stack exch STACKSIZE_M1 exch put + % Stack: len++ + ASSERT_STACK(-str -str,(15c)) + /nentry nentry 1 add def + stack STACKSIZE_M1 1 getinterval + % Stack: len++ stackslice + 0 % /had_eof + ASSERT_STACK(-str -str -str -int,(20b)) + exit % exit(W1) + }if + + dup mEOD INT_GT{ + /* Process normal data code (either literal or above-mEOD) in `code` */ + % Stack: len++ code + ASSERT_STACK(-str -str -int,(15)) + ASSERT_TRUE(dup 1 add nentry INT_LE,(code too high)) /* /ioerror */ + ASSERT_TRUE(nentry 4095 INT_LE,(table full)) /* /ioerror */ + prefix nentry 2 index put + % ASSERT_TRUE(0 stacklen INT_EQ,(lsp->stacklen==0)) + % Stack: len++ code + stack exch dup STACKSIZE_M1 exch + nentry 1 sub + % Stack: len++ stack code STACKSIZE_M1 code nentry-1 + ASSERT_STACK(-str -str -aryb -int -int -int -int,(16)) + INT_EQ { + % the rightmost char of this entry will be equal to the leftmost + % side, as soon as we calculate the leftmost side + /gcode { stack STACKSIZE_M1 2 index put /gcode {} def } def + }if + %{ + % ASSERT_TRUE(1 index nentry 2 sub INT_LE,(code<lsp->nentry-1)) + % % /gcode { } def + %}ifelse + -1 0 + % Stack: len++ -{...} stack code STACKSIZE-1|STACKSIZE-2 -1 0 + { + % 1 index (code=) print === + % Stack: len -{...} stack code putidx + ASSERT_STACK(-str -str -aryb -int -int,(17)) + exch dup prefix exch get 2 copy + % Stack: len -{...} stack putidx code prefix[code] code prefix[code] + INT_EQ{pop exit}if % exit from inner for + % Stack: len -{...} stack putidx code prefix[code] + 4 copy pop suffix exch get + % Stack: len -{...} stack putidx code prefix[code] stack putidx suffix[code] + put + exch pop + exch pop + % Stack: len -{...} stack prefix[code] + }for + % Stack: len stack unused_putidx code + ASSERT_STACK(-str -str -aryb -int -int,(18)) + dup suffix exch get + % dup (sufcode=) print === + gcode + suffix nentry 1 sub 2 index put pop + % Stack: len stack unused_putidx suffix[code] + 3 copy put pop + % Stack: len stack unused_putidx + dup STACKSIZE exch sub + % Stack: len stack putidx STACKSIZE-putidx + ASSERT_STACK(-str -str -aryb -int -int,(19)) + getinterval + ASSERT_TRUE(1 index length 0 INT_NE,(len!=0)) + /nentry nentry 1 add def + % Stack: len++ stackslice + 0 % /had_eof + ASSERT_STACK(-str -str -str -int,(20)) + exit % exit(W1) + }if + + dup mEOD INT_EQ{ + % Stack: len++ code==mEOD + pop 0 1 + % Stack: len++ garbage had_eof* + ASSERT_STACK(-str -str -int -int,(14)) + exit % exit(W1) + }if + + ASSERT_TRUE(dup mClear INT_EQ,(code==mClear)) + pop Fclear + % Stack: len++ + ASSERT_STACK(-str -str,(21)) + }loop % /W1:WHILE(1) + % Stack: len++ stackslice|garbage had_eof* + ASSERT_TRUE(TYPE_STACK(-str -str -str -int) TYPE_STACK(-str -str -int -int -bool) BOOL_BIN(or,(ora4)),(stack leaving W2)) + } loop % /W2:WHILE(1) + % Stack: len++ + % Stack: reto rets(buffer-not-read) + ASSERT_STACK(-str -str,(22)) + length 1 index length exch sub + % Stack: reto reto.length-rets.length + 0 exch getinterval + % Stack: reto.pre(return-value) +} BIND_DEF % Flzwdecode_do + +#if USE_PIN +%/Fmain { +%} BIND_DEF +} % close the function defs section +%</Defs> + +%<Data> +%%BeginData: +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF +%</Data> +#else + +#if !USE_CURRENTFILE +% --- Main + +%** - Fmain - +/Fmain { + /mys 8192 string def + Flzwdecode_init + { mys Flzwdecode_do + % Stack: mys.pre + dup length 0 INT_EQ{exit}if + STDOUT exch writestring + } loop + had_eof 1 INT_EQ { + { STDIN read {pop}{exit}ifelse }loop + }if +} BIND_DEF +Fmain +#endif + +end % LZWDict +#endif + +%%EOF diff --git a/Build/source/utils/sam2p/l1zip.psm b/Build/source/utils/sam2p/l1zip.psm new file mode 100644 index 00000000000..af682f61c52 --- /dev/null +++ b/Build/source/utils/sam2p/l1zip.psm @@ -0,0 +1,1439 @@ +/*% +% l1zip.psm -- /FlateDecode image data implementation for /PSL1 +% by pts@fazekas.hu at Sun Sep 22 01:01:00 CEST 2002 +% formerly flatedecode.psm -- please run faltedecode_eps_helper.sh... +% by pts@fazekas.hu at Fri Sep 20 23:31:36 CEST 2002 +% -- Sat Sep 21 01:11:10 CEST 2002 +% doesn't work -- Sat Sep 21 02:52:36 CEST 2002 +% disallow preread==8, allow preread==0 WORKS -- Sat Sep 21 20:22:07 CEST 2002 +% derived from statecat.psm -- a stateful, faster minimalistic zcat (gzip -cd) +% implementation, implemented in pure PostScript LanguageLevel1 (Run +% through cpp (C preprocessor) to get the PostScript file +% statecat.psm by pts@fazekas.hu +% originally rcm.c +% original author: Ron McFarland <rcm@one.net>, 1996 +% formally muzcat.c (at Tue Dec 25 11:07:47 CET 2001) +% based on statecat.ps.3 by pts@fazekas.hu +% rewritten, restructured and extended at Tue Dec 25 21:00:33 CET 2001 +% translated to PostScript except fvWork at Tue Dec 25 23:11:31 CET 2001 +% translated to PostScript altogether at Thu Dec 27 01:10:58 CET 2001 +% translation works with `cat random.file.gz random.file.gz'' at Thu Dec 27 14:19:36 CET 2001 +% Thu Dec 27 18:37:03 CET 2001: +% statecat.ps: 1071960 ms user time (249.293 times slower than gunzip) +% function inlining at Thu Dec 27 21:51:45 CET 2001 +% shorter keywords at Thu Dec 27 23:52:46 CET 2001 +% at Sat Feb 23 17:05:43 CET 2002: +% statecat.ps originally: 5388 bytes +% after eliminate-NULLs trick: 5349 bytes +% after anti-32768... trick 5229 bytes +% 5041 +%*/ +/* +% Imp: more efficient optimize CFG_FMT_ZLIB_ONLY +% Imp: do `F closefile', `T closefile' in %<True> +% Not: don't inline TE_read for USE_HEXD (15*5 bytes for ACSO0g is not tolerable) +% OK : verify a85_getc for really eating EOD (~>) chars +% OK : find and catalogize `|' and other one-char abbrs +% OK : shorter operator names (i.e `E' for `def', as in test_vm_eps.eps) +% OK : shorter var names (such as `preread', `past') +% Not: make global vars numbered, not named... +% OK : make constU[]-3 a string, not an array +% OK : make constW, constP, constL strings, not arrays +% Imp: inline all except fvMktree (too long), fvFree (recursive) and fvWork (too long) +% OK : verify, examine StateCatDict (45) +% OK : find unused vars (such as `moo') in StateCatDict +% OK : is constM or 1<< faster?? (decided 1<<) +% OK : anti-`/z 42 eq', ensure `eq' compares numbers (INT_EQ) +% OK : verify if/ifelse for ENDIF +% OK : verify direction of `for's +% OK : eliminate `stopped' context because it catches errors +% OK : clear stack before `exit' +% OK : verify `/name' against `name'; grep m@/@ +% OK : verify that `}' is followed by correct if|ifelse|def|bind|stopped|loop|for +% +% Typical error: syntax: /^#/ +% Typical error: syntax: m@/ +\w@ +% Typical error: mispelling +% Typical error: missing `pop' at `dup ... eq{exit}if' +% Typical error: missing `for|if|...' after '}' +*/ + +#include "psmlib.psm" + +#if USE_A85D +#else + #if USE_HEXD + #else + #define USE_BINARY 1 + #endif +#endif + +#if USE_NO_BIND + #define BIND_DEF def +#else + #define BIND_DEF bind def +#endif + +/* --- .pin begins */ + +%<Head> +%!PS-Adobe-3.0`E +%%Inflater: pts@fazekas.hu l1zip.psm +%%Pages: 1 +`X%%DocumentData: `B +%%LanguageLevel: 1 +`I%%EndComments +%%Page: 1 1 +%</Head> + +%<Open> +save`s `R +%</Open> + +/* 88 dict dup /TokDict exch def begin */ +%<Abbr acount=26 xcount=62> +begin +%</Abbr> + +%<A x "load def"/> % best to make it first +%<A E def/> % best to make it second + +%<A + add/> +%<A , and/> +%<A - sub/> +%<A . lt/> +%<A : for/> +%<A ; getinterval/> +%<A = eq/> +%<A @ loop/> +%<A A currentfile/> +%<A H 32768/> /*!=LZW*/ +%<A J 32767/> /*!=LZW*/ +%<A O pop/> +%<A X exit/> +%<A a packedarray/> +%<A b bitshift/> +%<A c exch/> +%<A g get/> +%<A y copy/> +%<A i ifelse/> +%<A j if/> +%<A t put/> +%<A u dup/> +%<A ~ ne/> +#if 0 /* important in LZW, but not in Flate */ + %<A * gt/> + %<A L length/> + %<A r read/> + %<A s string/> +#endif +#if USE_A85D +%<D d a85_getc/> +%<D S xS/> +%<D D xD/> +%<D C xC/> +#endif +#if USE_HEXD +%<D d .hexd.un/> +%<A S readhexstring/> +%<D D .hexd.un/> +%<D C .hexd./> +#endif +#if USE_BINARY +%<D d .binary.un/> +#if USE_PALETTE +%<A S readstring/> +#endif +%<D D .binary.un/> +%<D C .binary.un/> +#endif + +#if USE_SHORT_NAMES +% Free for short names: *?\^_`| BFGIKLMNPQRTUVWYZ efhklmnopqrsvwz +% Numerical comments denote # calls or # accesses +% : B: TokSubs +%<D F Bary/> /* F must be overridden with array to avoid early TokSubs */ +% : G +%<D I fxIgnore8/> % ? + 3 +%<D K Sbuf/> +%<D L fvFree/> % 5 +%<D M fvMktree/> % 5 +%<D N .N./> +%<D P preread/> +%<D Q mQ/> % 6 +%<D R fxRead8/> % 6 +%<D T Gary/> /* T must be overridden with array to avoid early TokSubs */ +%<D U fvFree/> % 5 +%<D V fvMktree/> % 5 +%<D Y fxRead16/> % 7 /* formerly: C */ +%<D W oP/> % 4 +%<D Z .Z./> +%<D e oO/> % 7 +%<D f .f./> +%<D h .h./> +%<D k fxSkip/> % 4 +%<D l constZ19/> % 3 +%<D m mode/> +%<D n mF/> % 6 +%<D o .o./> +%<D p .p./> +%<D q .q./> +%<D r fvRead/> % 10 +%<D s past/> +%<D v .v./> +%<D w tY/> % 6 +%<D z Tvar/> +/* %<D z fxIgnore8z/> % 3 */ /* not a function anymore */ +%<D * fvWork/> % 1 +%<D _ fxRead8EOF/> % 1 +%<D ? Dvar/> +%<D | fvMain/> +#endif + +%<TokSubs name=B inlining=0/> + +#if USE_CURRENTFILE + #define STDIN currentfile +#endif + +%<Test> +#if USE_DEBUG2 +/FP /fileposition x +#endif + +#if USE_BINARY + {mark /F currentfile/FlateDecode filter def}stopped +#endif +#if USE_A85D + {mark /T currentfile/ASCII85Decode filter def /F T/FlateDecode filter def}stopped +#endif +#if USE_HEXD + {mark /T currentfile/ASCIIHexDecode filter def /F T/FlateDecode filter def}stopped +#endif +/Z exch def cleartomark +/G{`i}def % image, imagemask or `false 3 colorimage` +`w `h `b[1 0 0 -1 0 `h] +#if USE_TRUE +true +#else +Z +#endif +%</Test> + +%<S len=32768> +32768 string dup /Sbuf exch def +%</S> + +%<True> + fvMain +%</True> + +%<False> +F G +F closefile +#if !USE_BINARY +T closefile +#endif +%</False> + +#define ZZZ_ASET(aname,idx,b) aname idx b put +#define ZZZ_AREF(aname,idx) aname idx get +#define PASS +#define GLOBAL_VAR0(t,name) +#define SLOCAL_VAR0(t,name) +#define GLOBAL_VAR(t,name) /name null def +#define SLOCAL_VAR(t,name) /name null def +#define GLOBAL_ARRAY(t,name,size) /name size t def +#define LOCAL_VAR(a,b) + +#if 0 /* LINE_DEBUG */ +#define put (put:__LINE__) === put +#define get (get:__LINE__) === get +#endif + +%<Defs> +% Imp: F closefile, T closefile +/* We must define constants and global arrays first. */ + +#define NULL 0 +#define NODESIZE 1998 /* NODESIZE%3==0 */ +/** Binary (Huffman) tree of nodes. */ +GLOBAL_ARRAY(array,N,NODESIZE) +/** + * Contains the code word lengths used for Huffman code generation in + * fvMktree(). 320==288+32. 320 is large enough to hold both the code lengths + * of the literal--length (288) and the distance (32) Huffman trees -- and + * large enough to hold the auxilary Huffman tree (used for building the + * real tree) of length 19. + */ +GLOBAL_ARRAY(array,Z,320) +GLOBAL_ARRAY(array,Bary,17) +GLOBAL_ARRAY(array,Gary,17) +#if CFG_NO_VAR_S +#else +GLOBAL_ARRAY(string,Sbuf,32768) +#endif +/constZ19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 packedarray def +#if USE_HEXD + /C(.)def +#endif + +{ /* We start declaring functions inside the brace */ + +#define constW { 16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15 } /* 19 packedarray def */ +#define constU { 3 4 5 6 7 8 9 10 11 13 15 17 19 23 27 31 35 43 51 59 67 83 99 115 131 163 195 227 258 } /* 29 packedarray def */ +#define constP { 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 0 } /* 29 packedarray def */ +#define constQ { 1 2 3 4 5 7 9 13 17 25 33 49 65 97 129 193 257 385 513 769 1025 1537 2049 3073 4097 6145 8193 12289 16385 24577 } /* 30 packedarray def */ +#define constL { 0 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 } /* 30 packedarray def */ +#if 0 +#define constM { 0 1 3 7 15 31 63 127 255 511 1023 2047 4095 8191 } /* 14 packedarray def */ +#endif + +#if USE_A85D + GLOBAL_VAR0(SINT32,xS) /* Variable `xS' was formerly called: `sx' */ + GLOBAL_VAR0(SINT32,xD) /* Variable `xD' was formerly called: `dx' */ + GLOBAL_VAR0(SINT32,xC) /* Variable `xC' was formerly called: `c0' */ + /** - a85_getc <0..255|511> + * Reads a char from `currentfile' as /ASCII85Decode + */ + /a85_getc{ % Simple getchar() of ASCII85Decode filter :-)), formerly /d + PSM_A85_GETC + }BIND_DEF +#endif + +#if USE_NO_EOF + #define my_getchar() TE_read( ) + #define my_ignorechar() TE_read(pop) +#else + #define my_getchar() TE_read() {511}ifelse + #define my_ignorechar() TE_read(pop) if +#endif + + +/** Index of the first free node in <code>N</code>. */ +GLOBAL_VAR0(WORD,Dvar) + +GLOBAL_VAR0(WORD,Tvar) /* index (in S) of the first free position, [0..32767] */ + +/* GLOBAL_VAR(NODEN,no) -- unused */ +/* GLOBAL_VAR(WORD,roo) -- unused */ +/* GLOBAL_VAR(WORD,rf) -- unused */ +/* GLOBAL_VAR(WORD,moo) -- unused */ +/* GLOBAL_VAR(WORD,mo) -- unused */ +/* GLOBAL_VAR(WORD,oooo) -- unused */ +/* GLOBAL_VAR(WORD,x) -- unused */ +GLOBAL_VAR0(WORD,mQ) +GLOBAL_VAR0(WORD,mF) +GLOBAL_VAR0(WORD,o) +GLOBAL_VAR0(WORD,q) +GLOBAL_VAR0(WORD,mode) /* MODE_* */ +GLOBAL_VAR0(WORD,tY) /* FMT_*; formerly ty */ +GLOBAL_VAR0(WORD,oO) +GLOBAL_VAR0(WORD,oP) +GLOBAL_VAR0(WORD,f) +GLOBAL_VAR0(WORD,p) +GLOBAL_VAR0(WORD,v) +GLOBAL_VAR0(WORD,h) + + +#define AREF_S(idx) AREF(Sbuf,idx) +#define ASET_S(idx,val) ASET(Sbuf,idx,val) + +/* Reading Operations: + +-- fxRead8(): read a 8-bit byte at byte boundary +-- fxRead16z(): read a 16-bit word at byte boundary, MSB first (ZIP) +-- fxRead16(): read a 16-bit word at byte boundary, LSB first (normal) +-- fxSkip(): skip to next byte boundary +-- fxRead1(): read 1 bit (for Huffman) +-- fvRead(): read any amount of bits (0..13), LSB first +*/ + +/* Dat: FlateDecode bit packing order is: (b7*128+...+b0)+(b15*128+...+b8) + +/** char, 0..255 */ +SLOCAL_VAR0(WORD,preread) +/** -1..-8: bits of bufread[pos] already read */ +SLOCAL_VAR0(WORD,past) + +% static void fxInit(void) { +% /fxInit { +#define fxInit \ + /preread 0 def \ + /past -8 def +% }BIND_DEF + +/* #define ASSERT_PREREAD_NOT_EOF() preread 255 gt ASSERT_FALSE_POP((unexpected eof)) */ +#define ASSERT_NOT_EOF(val) ASSERT_TRUE(val dup 255 and eq,(non-EOF expected)) +#define ASSERT_PREREAD_NOT_EOF() ASSERT_NOT_EOF(preread) + +/** reads 0..13 bits */ +% static WORD fvRead(WORD arg) { +/fvRead { + DEBUG(dup (==> fvRead\() exch 42 string cvs concatstrings (\)\n) concatstrings) + DEBUG(( past=) past neg 42 string cvs concatstrings + ( preread=) preread 42 string cvs concatstrings + (\n) concatstrings concatstrings) + dup 0 INT_NE{ + ASSERT_PREREAD_NOT_EOF() + past + % Stack: arg -opast + dup preread exch bitshift exch % SHR + % Stack: arg preread>>opast opast + dup 3 index sub + % Stack: arg ret==:preread>>-opast -opast -past==:-opast-arg + dup -8 ge{ + /past exch def % BUG fixed at Thu Dec 27 14:53:53 CET 2001 + pop + % Stack: arg ret + }{ + ASSERT_TRUE(dup -9 le,(-past>=9)) + /preread my_getchar() def + ASSERT_PREREAD_NOT_EOF() + dup -16 ge{ /* _GT_ */ + 8 add /past exch def + 8 add + % Stack: arg ret==:preread>>opast 8-opast + preread exch bitshift % SHL + add + % Stack: arg ret'' + }{ + 16 add /past exch def + 8 add 2 copy + % Stack: arg retold 8-opast ret 8-opast + preread exch bitshift add % SHL + % Stack: arg retold 8-opast ret'' + /preread my_getchar() def % BUG fixed at Thu Dec 27 15:40:53 CET 2001 + ASSERT_TRUE(past -1 le,(-past>=1)) + ASSERT_TRUE(past -4 ge,(-past<=4)) + ASSERT_PREREAD_NOT_EOF() + exch 8 add preread exch bitshift add + % Stack: arg retold ret'' + exch pop + % Stack: arg ret'' + }ifelse + }ifelse + % Stack: arg ret + % exch constM exch get and % ret&=((1<<arg)-1); + % ^^^ BUG (re)-fixed at Thu Dec 27 14:50:49 CET 2001 + exch 1 exch bitshift 1 sub and + }if + DEBUG(dup (<-- fvRead=) exch 42 string cvs concatstrings (\n) concatstrings) + % (%stderr) (w) file (<fvRead\n) writestring + % fvRead(0)==0 implicitly assumed +}BIND_DEF + +% static WORD fxRead1(void) { +% /fxRead1{ +#define fxRead1 \ + ASSERT_PREREAD_NOT_EOF() \ + past dup -8 INT_EQ{ \ + pop \ + /preread my_getchar() def \ + /past -1 def \ + preread 1 and \ + /* Stack: ret */ \ + }{ \ + dup 1 sub /past exch def \ + preread exch bitshift 1 and \ + /* Stack: ret */ \ + }ifelse +% }BIND_DEF + +#if 0 /* old style past==0, inline only speed-critical functions */ + % static void fxSkip(void) { + % /fxSkip{ + #define fxSkip \ + past 0 INT_NE{ \ + ASSERT_PREREAD_NOT_EOF() \ + /preread my_getchar() def \ + /past 0 def \ + }if + % }BIND_DEF + + % static WORD fxRead16(void) { + % /fxRead16{ + #define fxRead16 \ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) \ + ASSERT_PREREAD_NOT_EOF() \ + preread \ + /* Stack: ret */ \ + my_getchar() dup /preread exch def \ + ASSERT_PREREAD_NOT_EOF() \ + 8 bitshift \ + add \ + /preread my_getchar() def + % }BIND_DEF + + % static WORD fxRead8(void) { + % /fxRead8{ + #define fxRead8 \ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) \ + ASSERT_PREREAD_NOT_EOF() \ + preread \ + /* Stack: ret */ \ + /preread my_getchar() def + % }BIND_DEF + + % static void fxIgnore8(WORD how_many_bytes) { + #define fxIgnore8 \ + ASSERT_TRUE(dup 0 gt,(fxIgnore8arg>0)) \ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) \ + ASSERT_PREREAD_NOT_EOF() \ + -1 2 {pop my_ignorechar()}for \ + /preread my_getchar() def + + #define fxIgnore8z \ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) \ + ASSERT_PREREAD_NOT_EOF() \ + dup 0 INT_NE{ \ + -1 2 {pop DEBUG2((fI8z)===) my_ignorechar()}for \ + /preread my_getchar() def \ + }{pop}ifelse + + % static WORD fxRead8EOF(void) { + % /fxRead8EOF{ + #define fxRead8EOF \ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) \ + preread \ + /* Stack: ret */ \ + /preread my_getchar() def + % }BIND_DEF +#else + #if 0 + /* old-style: past==0 */ + % static void fxSkip(void) { + /fxSkip{ + past 0 INT_NE{ + ASSERT_PREREAD_NOT_EOF() + /preread my_getchar() def + /past 0 def + }if + }BIND_DEF + % static WORD fxRead8(void) { + /fxRead8{ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) + ASSERT_PREREAD_NOT_EOF() + preread + /* Stack: ret */ + /preread my_getchar() def + }BIND_DEF + /fxIgnore8z{ + % Same as void fxIgnore8(WORD how_many_bytes), but allow 0 as arg + ASSERT_TRUE(past 0 INT_EQ,(past==0)) + ASSERT_PREREAD_NOT_EOF() + dup 0 INT_NE{ + -1 2 {pop DEBUG2((fI8z)===) my_ignorechar()}for + /preread my_getchar() def + }{pop}ifelse + }BIND_DEF + /fxRead8EOF{ + ASSERT_TRUE(past 0 INT_EQ,(past==0)) + preread + /* Stack: ret */ + /preread my_getchar() def + }BIND_DEF + #else + #define fxSkip /past -8 def + #define fxRead8 \ + ASSERT_TRUE(past -8 INT_EQ,(past==-8)) \ + my_getchar() ASSERT_NOT_EOF(dup) + % }BIND_DEF + #define fxRead8EOF \ + ASSERT_TRUE(past -8 INT_EQ,(past==-8)) \ + my_getchar() + % }BIND_DEF + #endif + + % static WORD fxRead16(void) { + /fxRead16{ + ASSERT_TRUE(past -8 INT_EQ,(past==-8)) + my_getchar() ASSERT_NOT_EOF(dup) + my_getchar() ASSERT_NOT_EOF(dup) + 8 bitshift add + }BIND_DEF + + % static void fxIgnore8(WORD how_many_bytes) { + /fxIgnore8{ + ASSERT_TRUE(dup 0 gt,(fxIgnore8arg>0)) + ASSERT_TRUE(past -8 INT_EQ,(past==-8)) + ASSERT_PREREAD_NOT_EOF() + {my_getchar() ASSERT_NOT_EOF(dup) pop }repeat + }BIND_DEF + #define fxIgnore8z fxIgnore8 +#endif + +#define fvReadq fvRead +/** Reads an uint16 from the ZIP file */ +#define fxRead16z fxRead16 + +/** + * Allocates a new node and initializes it with empty content. This function + * lets us get rid of the global variable F (which was buggily uninitialized + * in the original scm.c). + * @return pointer to the newly allocated node + * @whichcode -1 + */ +% DEFUN_0(NODEN,fvNalloc) +% /fvNalloc{ +#define fvNalloc \ + /* GLOBAL_REF(N) */ \ + /* GLOBAL_REF(Dvar) */ \ + /* LOCAL_VAR(NODEN,no) */ /* the first/next free node */ \ + /* FUNCODE */ \ + Dvar \ + /* Stack: no */ \ + ASSERT_TRUE(dup NODESIZE lt,(Dvar<NODESIZE)) \ + dup N exch get /Dvar exch def /* SET(Dvar,AREF(N,no)); % not free anymore */ \ + dup N exch NULL put /* ASET(N,no,NULL); */ /* clear; the other two fields are already cleared */ \ + /* Stack: no */ +% }BIND_DEF + +/** + * Frees the Huffman tree originating from <code>root</code> recursively. + * Used <code>I</code> as input only. + * Moved <code>I</code> into a argeter. + * @param arg root node index in N + */ +% DEFUN_1_VOID(fvFree,NODEN) +/fvFree{ + % GLOBAL_REF(N) + % GLOBAL_REF(Dvar) + N exch dup NULL INT_NE{ + 2 copy get fvFree + 2 copy 1 add get fvFree % fvFree(AREF(N,arg+1)); + 2 copy 1 add NULL put % ASET(N,arg+1,NULL); /* clear */ + 2 copy 2 add 0 put % ASET(N,arg+2,0); /* clear */ + 2 copy Dvar put % ASET(N,arg,Dvar); /* link to the beginning of the free list */ + /Dvar exch def pop % SET(Dvar,arg); /* set it free */ + }{ + % BUG fixed at Thu Dec 27 11:52:59 CET 2001 + pop pop + }ifelse +}BIND_DEF + +/** + * Goes down (descends) enough levels in the binary tree of (struct node)s. + * Reads numbers from input encoded as a Huffman tree represented by the + * (struct node)s. + * Called only from 2 places. + * Used <code>I</code> as both input and output, but the output is never used + * in the program. So I've put <code>I</code> to a argument. + * @param arg root is only for input + * @whichcode 3 + */ +% DEFUN_1(WORD,fvDescend,NODEN) +% /fvDescend{ +#define fvDescend \ + /* GLOBAL_REF(N) */ \ + /* FUNCODE */ \ + DEBUG(dup (==> fvDescend\() exch 42 string cvs concatstrings (\)\n) concatstrings) \ + N exch \ + { /* Stack: N arg */ \ + 2 copy get NULL INT_EQ{exit}if /* WHILE(NE(NULL,AREF(N,arg))) */ \ + 2 copy fxRead1 add get exch pop /* SET(arg,AREF(N,arg+fxRead1())); */ \ + }loop /* ENDWHILE */ \ + /* Stack: N arg */ \ + 2 add get \ + DEBUG(dup (<-- fvDescend=) exch 42 string cvs concatstrings (\n) concatstrings) \ + /* RETURN(fvDescend,AREF(N,arg+2)) */ /* arg->value; */ +% }BIND_DEF + +/** + * Allocates new (struct node)s. This is the Huffman tree + * builder. It reads the global array <code>Z</code>: the code lengths have + * been already stored there. + * Used <code>I</code> as output only, so I moved it to the return value. + * @param arg the number of entries (codes) of the Huffman tree to be built + * @return the root of the Huffman tree just built + * @whichcode 5 + */ +% DEFUN_1(NODEN,fvMktree,WORD) +/fvMktree{ % BUG fixed at Thu Dec 27 11:54:02 CET 2001 + % GLOBAL_REF(B) + % GLOBAL_REF(G) + % GLOBAL_REF(N) + % GLOBAL_REF(Z) + % LOCAL_VAR(WORD,moo) + % LOCAL_VAR(WORD,mQ) + % LOCAL_VAR(WORD,mo) + % LOCAL_VAR(WORD,mF) + % FUNCODE + constZ19 0 17 getinterval Bary copy pop % OK to copy packedarray -> array + % Stack: arg + Bary Z 0 1 4 index 1 sub + % Stack: arg Bary Z 0 1 arg-1 + { % Stack: arg Bary Z moo + 3 copy get + % Stack: arg Bary Z moo Bary Z[moo] + 2 copy get 1 add put + % Stack: arg Bary Z moo + pop + }for % WHILE(LT(moo,arg)) INCR(AREF(Bary,AREF(Z,moo))); INCR(moo); ENDWHILE + % Stack: arg Bary Z + pop 0 0 put % ASET(Bary,0,0); + Gary 0 0 put % ASET(Gary,0,0); + % Stack: arg + Gary Bary 0 1 15 % SET(moo,0); WHILE(LT(moo,16)) + { % Stack: arg Gary Bary moo + 2 copy get + % Stack: arg Gary Bary moo Bary[moo] + 3 index 2 index get + % Stack: arg Gary Bary moo Bary[moo] Gary[moo] + add dup add % BUG fixed at Thu Dec 27 15:05:51 CET 2001 + % Stack: arg Gary Bary moo 2*(Bary[moo]+Gary[moo]) + 3 index exch 2 index 1 add exch + % Stack: arg Gary Bary moo Gary moo+1 2*(Bary[moo]+Gary[moo]) + % ASET(Gary, moo+1,TWICE(AREF(Gary,moo)+AREF(Bary,moo))); + put pop + }for % BUG fixed at Thu Dec 27 14:59:52 CET 2001 + % Stack: arg Gary Bary + pop pop + /* Dat: anode is the ->left pointer of the Sentinel node */ + N 3 0 put % ASET(N,3,NULL); /* anode=NULL; */ + % Stack: arg + 1 sub 0 exch 1 exch{ % SET(moo,0); WHILE(LT(moo,arg)) + % Stack: moo + dup Z exch get dup 0 INT_NE{ % IF(NZ(AREF(Z,moo))) + % Stack: moo Z[moo] + % /* WORD o, f; */ /* struct node **f; */ + dup Gary exch get /mQ exch def % SET(mQ,AREF(Gary,AREF(Z,moo))); + % Stack: moo Z[moo] + dup Gary exch 2 copy + % Stack: moo Z[moo] Gary Z[moo] Gary Z[moo] + get 1 add put % INCR(AREF(Gary,AREF(Z,moo))); + % Stack: moo Z[moo] + /mF 3 def % SET(mF,3); /* mF=&anode; */ % BUG fixed at Thu Dec 27 12:03:31 CET 2001 + % SET(mo,AREF(Z,moo)); + 1 sub -1 0 + % Stack: moo Z[moo]-1 -1 0 + { % WHILE(NZ(mo)); DECR(mo); + % Stack: moo mo + N mF get NULL INT_EQ{ + N mF fvNalloc put + }if % IF(EQ(AREF(N,mF),NULL)); ASET(N,mF,fvNalloc NOARGS); ENDIF + 1 exch bitshift mQ and 0 INT_EQ{0}{1}ifelse + N mF get add + /mF exch def % SET(mF,AREF(N,mF)+TAND_P(mQ,SHL(1,mo))); + % Stack: moo + }for + N exch + % Stack: N moo + N mF 2 copy fvNalloc put % ASET(N,mF,fvNalloc NOARGS); + get 2 add + % Stack: N moo AREF(N,mF)+2 + exch put % ASET(N,AREF(N,mF)+2,moo); /* (*f)->value=moo; */ + % Stack: - + }{pop pop}ifelse % ENDIF + }for + % Stack: - + N 3 get +}BIND_DEF + + +#define FMT_ZLIB 120 +#define FMT_STOP 4 /* stop processing and flush STDIN */ +#if CFG_FMT_ZLIB_ONLYX +#else +#define FMT_ZIP_STORED 0 /* file is stored, not Deflated in ZIP file */ +#define FMT_GZIP 31 +#define FMT_NONE 3 +#define FMT_ZIP_DEFLATED 8 +#endif + +#define MODE_BOS 0 /* at beginning of (sub)file */ +#define MODE_MOB 1 /* at middle of a DEFLATE block */ +#define MODE_REP 2 /* printing a repeating string in a DEFLATE block */ +#define MODE_BOB 3 /* at the beginning of a block, just before BFINAL and BTYPE */ +#define MODE_COPY1 4 /* copying from input to output (a stored block) */ +#if CFG_FMT_ZLIB_ONLYX +#else +#define MODE_ZSTO 5 /* copying from input to output (FMT_ZIP_STORED) */ +#endif + +/** + * Root of the literal--length Huffman tree in <code>N</code> + * (see RFC 1951). Its length is at most 288 with values 0..287. Values + * 286 and 287 are invalid. A value in 0..255 means a literal byte, a + * value of 256 indicates end-of-block, and a + * value in 257..285 is a prefix (with 29 possible values) of a length + * in 3..258. See subsubsection 3.2.5 of RFC 1951. + */ +SLOCAL_VAR0(NODEN,v) +/** + * Root of the distance Huffman tree in <code>N</code> (see RFC 1951). + * Its length is at most 32 with values 0..31. Values 30 and 31 are invalid. + * A value of 0..29 is a prefix (with 30 possible values) of a distance in + * 1..32768. See subsubsection 3.2.5 of RFC 1951. + */ +SLOCAL_VAR0(NODEN,h) + + +#define SLIDEE dup 32767 INT_EQ{pop 0}{1 add}ifelse + +#if CFG_FMT_ZLIB_ONLY +#define fvAFB \ + DEBUG2((f0:__LINE__) ===only) DEBUG2(currentfile FP ===) \ + /mode MODE_BOS def \ + /tY FMT_STOP def /* force EOF */ \ + fxSkip \ + DEBUG2((f1:__LINE__) ===only) DEBUG2(currentfile FP ===) \ + 4 fxIgnore8z \ + DEBUG2((f2:__LINE__) ===only) DEBUG2(currentfile FP ===) +#else +% static void fvAFB(void) { +% /fvAFB{ /* after final block (BFINAL) */ +#define fvAFB \ + \ + /mode MODE_BOS def /* SET(mode,MODE_BOS); */ \ + fxSkip /* fxSkip(); */ \ + /* ^^^ skip till we reach byte boundary. fvRead! 0..7 bits */ \ + tY FMT_GZIP INT_EQ{ /* IF(EQ(tY,FMT_GZIP)) */ \ + /* CRC32 and ISIZE remaining */ \ + /* vvv IGNORE fxRead16(); IGNORE fxRead16(); IGNORE fxRead16(); IGNORE fxRead16(); */ \ + 8 \ + }{ \ + tY FMT_ZLIB INT_EQ{ /* ELSE_IF(EQ(tY,FMT_ZLIB)) */ \ + /* ADLER32 remaining */ \ + 4 \ + }{0}ifelse \ + }ifelse \ + fxIgnore8z +% }BIND_DEF +#endif /* CFG_FMT_ZLIB_ONLY */ + +/** Reads data from input, uncompresses and saves it to Sbuf. Sbuf.length==32768. + * Saves 32768 bytes into Sbuf unless EOF prevents it. After return, the caller + * may read Sbuf, but it may not modify it. + * @return length to be saved to Sbuf + */ +% static WORD fvWork(void) { +/fvWork{ + % GLOBAL_REF(J) + % GLOBAL_REF(Y) + % GLOBAL_REF(Tvar) + % GLOBAL_REF(N) + % GLOBAL_REF(Dvar) + { % `{'': establish fake loop context for return + mode MODE_REP INT_EQ{ % IF(EQ(mode,MODE_REP)) + ASSERT_TRUE(Tvar 0 INT_EQ,(Tvar==0)) + ASSERT_TRUE(f 258 le,(f<=258)) + % /* f==0 is OK now */ + Tvar oO + 1 1 f{ % WHILE(NZ(f)) -- inverse for + pop + % Stack: Tvar oO + Sbuf 3 copy exch get + % Stack: Tvar oO Sbuf Tvar S[oO] + put % ASET_S(Tvar,AREF_S(oO)); + SLIDEE % SLIDE(oO); + exch 1 add exch % INCR(Tvar); + % DECR(f); + }for % ENDWHILE + pop /Tvar exch def + /mode MODE_MOB def + }{ + mode MODE_COPY1 INT_EQ{ % ELSE_IF(EQ(mode,MODE_COPY1)) + % /* Now: f: copy count unsinged word16 */ + ASSERT_TRUE(Tvar 0 INT_EQ,(Tvar==0)) + % /* f==0 is OK now */ + f 32767 gt{ /* _GT_ */ % IF((unsigned short)f>=32768) + ASSERT_TRUE(f 32768 sub f 32767 and eq,((f&32767)==f-32768)) + /f f 32767 and def + 0 1 32767{ % WHILE(NE((unsigned short)Tvar,32768)) + Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8()); + % INCR(T); + % DECR(f); + }for % ENDWHILE + /Tvar 0 def % SET(Tvar,0); + % Stack: - + ASSERT_TRUE(mode MODE_COPY INT_EQ,(mode==MODE_COPY1)) + % bbb111 + 32768 exit % return (WORD)32768; outside loops + }{ % ELSE + Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for + pop + % Stack: Sbuf Tvar + 2 copy fxRead8 put % ASET_S(Tvar,fxRead8()); + 1 add % INCR(Tvar); + }for % ENDWHILE + /Tvar exch def pop + % /mode MODE_BOB def % SET(mode,MODE_BOB); % BUG fixed at Thu Dec 27 14:16:57 CET 2001 + o 0 INT_NE{ % IF(NZ(o)) + fvAFB % goto on_bos; SET(mode,MODE_BOS); + }{ % ELSE + /mode MODE_BOB def % SET(mode,MODE_BOB); % beginning of next block + }ifelse % ENDIF + }ifelse % ENDIF + } +#if CFG_FMT_ZLIB_ONLY + if +#else + {mode MODE_ZSTO INT_EQ{ % ELSE_IF(EQ(mode,MODE_ZSTO)) + % /* Now: f: copy count low unsinged word16, oP: high unsigned word16 */ + % /* Now: oo: 0..1 flag for decrementing oP */ + ASSERT_TRUE(Tvar 0 INT_EQ,(Tvar==0)) + % /* f==0 is OK now */ + f 32767 gt{ /* _GT_ */ % IF((unsigned short)f>=32768) + ASSERT_TRUE(f 32768 sub f 32767 and eq,((f&32767)==f-32768)) + /f f 32767 and def + 0 1 32767{ % WHILE(NE((unsigned short)Tvar,32768)) + Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8()); + % INCR(Tvar); + % DECR(f); + }for % ENDWHILE + /Tvar 0 def % SET(Tvar,0); + % Stack: - + ASSERT_TRUE(mode MODE_ZSTO INT_EQ,(mode==MODE_ZSTO)) + % bbb222 + 32768 exit % return (WORD)32768; outside loops + }{ + oP 0 INT_NE{ % ELSE_IF(NZ(oP)) + 0 1 32767{ % WHILE(NE((unsigned short)Tvar,32768)) + Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8()); + % INCR(Tvar); + % DECR(f); + }for % ENDWHILE + /Tvar 0 def % SET(Tvar,0); + % Stack: - + oO 0 INT_NE{ % IF(NZ(oO)) + /oP oP 1 sub def % DECR(oP); + /oO 0 def % SET(oO,0); + }{ % ELSE + /oO 1 def % SET(oO,1); + }ifelse + ASSERT_TRUE(mode MODE_ZSTO INT_EQ,(mode==MODE_ZSTO)) + % bbb333 + 32768 exit % return (WORD)32768; outside loops + }{ % ELSE + Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for + pop + % Stack: Sbuf Tvar + 2 copy fxRead8 put % ASET_S(Tvar,fxRead8()); + 1 add % INCR(Tvar); + }for % ENDWHILE + /Tvar exch def pop + /mode MODE_BOS def % SET(mode,MODE_BOS); + }ifelse % oO!=0 + }ifelse % f>=32768 + }if % MODE==MODE_ZSTO + }ifelse % MODE==MODE_COPY1 +#endif /* CFG_FMT_ZLIB_ONLY */ + }ifelse % MODE==MODE_REP + -1 exit % don''t return yet + }loop + % Stack: retval||-1 + + { % big-big MODE_MOB||MODE_BOB||MODE_BOS loop + #ifndef NDEBUG + % mode ===only ( big-big\n) print + #endif + ASSERT_TRUE(mode MODE_MOB INT_EQ mode MODE_BOB INT_EQ mode MODE_BOS INT_EQ or or,(MODE_MOB||MODE_BOB||MODE_BOS)) + + % Stack: retval||-1 + dup -1 INT_NE{%ccc999 + exit}if + mode MODE_MOB INT_EQ{ % IF(EQ(mode,MODE_MOB)); mode_mob: + ASSERT_TRUE(dup -1 INT_EQ,(was -1)) + pop % -1 + /** + * Uncompresses the data block with the Huffman codes set up. + * + * Reads at most 33 bits per entry. Unfortunately the block can be of + * arbitrary length (terminated by an entry of 256). + */ + % /* vvv reads 0..15 bits, see subsubsection 3.2.7 of RFC 1951 */ + { + % Dat: most of the time is spent inside fvDescend, fvRead and + % inside this loop + v fvDescend dup 256 INT_EQ{pop -1 exit}if % WHILE(NE(oo, 256)) + dup 257 lt{ % IF(LT(oO,257)) + % /* ^^^ BUG corrected */ + Sbuf exch Tvar exch put % ASET_S(Tvar,oO); + + % Stack: - + % vvv SLIDE(Tvar); /* Tvar++; Tvar&=32767; */ + % vvv if (Tvar==0) return (WORD)32768; /* remain in MODE_MOB */ + Tvar 32767 INT_EQ{ + /Tvar 0 def + % bbb444 + 32768 exit % return % in big-big-loop and MOB-loop + }if + /Tvar Tvar 1 add def + }{ % ELSE + 257 sub % SUB(oO,257); + % Stack: oO + dup constU exch get + exch constP exch get fvRead + add /f exch def % SET(f,AREF(constU,oO) + fvRead(AREF(constP,oO))); /* fvRead! 0..5 bits */ + ASSERT_TRUE(3 f le f 258 le and,(3<=f && f<=258)) + h fvDescend % SET(oO,fvDescend(h)); + dup constQ exch get + exch constL exch get fvRead + add % SET(oO,AREF(constQ,oO) + fvRead(AREF(constL,oO))); /* fvRead! 0..13 bits */ + Tvar exch sub 32767 and % /* oO = oO <= Tvar ? Tvar - oO : 32768 - oO + Tvar; */ + + f 32768 Tvar sub sub dup 0 lt{ % IF((unsigned short)f<32768-(unsigned short)Tvar) + pop + % Stack: oO + Tvar exch 1 1 f{ % WHILE(NZ(f)) -- inverse for + pop + % Stack: Tvar oO + Sbuf 3 copy exch get + % Stack: Tvar oO Sbuf Tvar S[oO] + put % ASET_S(Tvar,AREF_S(oO)); + SLIDEE % SLIDE(oO); + exch 1 add exch % INCR(Tvar); + % DECR(f); + }for % ENDWHILE + % Dat: oO doesn''t have to be remembered here + pop /Tvar exch def + % Stack: - + ASSERT_TRUE(Tvar 32768 lt,(Tvar<32768)) + }{ % ELSE + /f exch def % SUB(f,32768-Tvar); + % Stack: oO + Tvar 1 32767{ % WHILE(NE((unsigned short)Tvar,32768)) + % Stack: oO Tvar + exch + % Stack: Tvar oO + Sbuf 3 copy exch get + % Stack: Tvar oO Sbuf Tvar S[oO] + put % ASET_S(Tvar,AREF_S(oO)); + SLIDEE % SLIDE(oO); + exch pop % INCR(Tvar); + }for % ENDWHILE + /oO exch def + % Stack: - + /Tvar 0 def % SET(Tvar,0); + /mode MODE_REP def % SET(mode,MODE_REP); + % bbb555 + 32768 exit % return (WORD)32768; % in big-big-loop and MOB-loop + }ifelse % ENDIF + }ifelse % ENDIF + }loop % ENDWHILE + % Stack: retval||-1 + dup -1 INT_EQ{ % BUG fixed at Thu Dec 27 15:52:18 CET 2001 + v fvFree % fvFree(v); + h fvFree % fvFree(h); + o 0 INT_NE{ % IF(NZ(o)) + fvAFB % goto on_bos; SET(mode,MODE_BOS); + }{ % ELSE + /mode MODE_BOB def % SET(mode,MODE_BOB); % beginning of next block + }ifelse % ENDIF + }if + }if % ENDIF + % Stack: retval||-1 + dup -1 INT_NE{%ccc888 + exit}if pop + + DEBUG2((;)===) + + mode MODE_BOB INT_EQ{ % WHILE(EQ(mode,MODE_BOB)); mode_bob: + DEBUG(counttomark 42 string cvs) + DEBUG(( kope\n)) + % assert(mode==MODE_BOB); + /o fxRead1 def % SET(o,fxRead1()); /* BFINAL: 1 iff this is the last data block */ + /q 2 fvRead def % SET(q,fvRead(2)); /* BTYPE: block type; 0=stored, 1=fixed Huff, 2=dyn Huff */ + % #if NDEBUG + % #else + % fprintf(stderr, "MODE_BOB o=%d q=%d %ld\n", o, q, ftell(stdin)); + % #endif + DEBUG((MODE:BOB o=) o 42 string cvs + ( q=) q 42 string cvs + ( ) Stdin fileposition 42 string cvs + (\n) concatstrings concatstrings concatstrings + concatstrings concatstrings concatstrings) + ASSERT_TRUE(q 0 INT_EQ q 1 INT_EQ q 2 INT_EQ or or,(q==0 || q==1 || q==2)) + q 0 INT_NE{ % IF(NZ(q)) + /** + * Now: q==BTYPE, q==1 or q==2. (BTYPE==3 means error). Handles + * compressed data blocks, see subsubsection 3.2.5 of RFC 1951. + */ + q 1 INT_EQ{ % IF(EQ(q,1)) + /** + * Initializes the fixed Huffman codes for BTYPE==1. + */ + % /* WORD oO; */ + 287 -1 0{ % SET(oO,288); WHILE(NZ(oO)); DECR(oO); + Z exch dup 144 lt{8}{dup 256 lt{9} + {dup 280 lt{7}{8}ifelse}ifelse}ifelse put + /* ^^^ AREF(Z,oO) = oO < 144 ? 8 + : oO < 256 ? 9 + : oO < 280 ? 7 + : 8; */ + }for % ENDWHILE + /v 288 fvMktree def % SET(v,fvMktree(288)); + 0 1 31{Z exch 5 put}for % SET(f,0); WHILE(LT(f,32)) ASET(Z,f,5); INCR(f); ENDWHILE + /h 32 fvMktree def % SET(h,fvMktree(32)); + }{ % ELSE + /** + * Reads dynamic Huffman codes for BTYPE==2. + * + * Maximum read: 5+5+4+3*19+7*289 == 2094 bits + */ + ASSERT_TRUE(q 2 INT_EQ,(q==2)) + % /* WORD oO, oP, oPo, f, p, x, v; */ + /p 5 fvRead 257 add def % SET(p, fvRead(5) + 257); /* HLIT: 257..286 (287--289 are unused) */ + /oO 5 fvRead 1 add def % SET(oO, fvRead(5) + 1); /* HDIST: 1..32 */ + /v 4 fvRead 4 add def % SET(v, fvRead(4) + 4); /* HCLEN: 4..19 */ /* small v */ + constZ19 Z copy pop % WHILE(LT(oO,19)) ASET(Z,AREF(constW,oO), 0); INCR(oO); ENDWHILE + 0 1 v 1 sub{ + Z exch constW exch get 3 fvRead put % WHILE(LT(oO,v)) ASET(Z,AREF(constW,oO), fvRead(3)); INCR(oO); ENDWHILE /* small v */ + }for + % Stack: - (verified) + /v 19 fvMktree def % SET(v,fvMktree(19)); + /oP 0 def % SET(oP,0); + % Stack: - + Z 0 { % SET(oO,0); WHILE(LT(oO,p + oO)) + % Stack: Z oO + dup p oO add ge{exit}if + v fvDescend % SET(oPo,fvDescend(v)); + % Stack: Z oO oPo + dup 16 INT_EQ{ + pop oP /f 2 fvRead 3 add def % SET(oPo,oP); SET(f,3+fvRead(2)); + }{ + dup 17 INT_EQ{ + pop 0 /f 3 fvRead 3 add def % SET(oPo,0); SET(f,3+fvRead(3)); + }{ + dup 18 INT_EQ{ + pop 0 /f 7 fvRead 11 add def % SET(oPo,0); SET(f,11+fvRead(7)); + }{ + dup /oP exch def /f 1 def % SET(oP,oPo); SET(f,1); + }ifelse + }ifelse + }ifelse + % Stack: Z oO oPo + 1 1 f{ % SET(q,f); WHILE(NZ(q)) + pop % BUG fixed at Thu Dec 27 12:17:58 CET 2001 + 3 copy put % ASET(Z,oO,oPo); + exch 1 add exch % INCR(oO); + % DECR(q); + }for % ENDWHILE + pop % oPo, BUG fixed at Thu Dec 27 12:18:47 CET 2001 + }loop % ENDWHILE + % Stack: Z oO''==p+oO + pop pop + v fvFree % fvFree(v); + /v p fvMktree def % SET(v,fvMktree(p)); + % Stack: - + % /* vvv No need for array copy, just change/pass the pointer to Z... */ + oO 1 sub -1 0{ % SET(oO'',oO); WHILE(NZ(oO'')) DECR(oO''); + Z exch dup + % Stack: Z oO'' oO'' + p add Z exch get put % ASET(Z,oO'',AREF(Z,oO'' + p)); + }for % ENDWHILE + /h oO fvMktree def % SET(h,fvMktree(x)); + }ifelse % ENDIF + /mode MODE_MOB def % SET(mode,MODE_MOB); + % goto mode_mob; + }{ % ELSE /* inline: fv(..., 7); */ + + /** + * Copies a block of input to output (mostly) verbatim. This is for + * BTYPE==0, non-compressed block, subsubsection 3.2.4 of RFC 1951. + * (We need non-compressed because + * some blocks cannot be compressed effectively, so gzip inserts them + * as is.) + * @whichcode 7 + */ + fxSkip % fxSkip(); + % /* ^^^ skip till we reach byte boundary. fvRead! 0..7 bits */ + /f fxRead16 def % SET(f,fxRead16()); /* length of block: 0..65535 */ + % #if NDEBUG + % #else + % fprintf(stderr, "COPY1_BLK=%d Tvar=%d\n", f, Tvar); + % #endif + 2 fxIgnore8 % IGNORE fxRead16(); /* one's complement of length; ignored */ + + f 32768 Tvar sub sub dup 0 lt{ % IF((unsigned short)f<32768-(unsigned short)Tvar) + pop + Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for + pop + % Stack: Sbuf Tvar + 2 copy fxRead8 put % ASET_S(Tvar,fxRead8()); + 1 add % INCR(Tvar); + }for % ENDWHILE + /Tvar exch def pop + ASSERT_TRUE(mode MODE_BOB INT_EQ,(mode==MODE_BOB)) + ASSERT_TRUE(Tvar 32768 lt,(Tvar<32768)) + }{ % ELSE + % /* Even if f>=32768 */ + /f exch def % SUB(f,32768-Tvar); + Tvar 1 32767{ % WHILE(NE((unsigned short)Tvar,32768)) + Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8()); + % INCR(Tvar); + % DECR(f); + }for % ENDWHILE + /Tvar 0 def % SET(Tvar,0); + /mode MODE_COPY1 def % SET(mode,MODE_REP); + % bbb666 + DEBUG(counttomark 42 string cvs) + DEBUG(( whata\n)) + % trtr + ASSERT_TRUE(counttomark 0 eq,(seccounttomark==0)) + DEBUG((whatb\n)) + 32768 exit % return (WORD)32768; % exit from big-big loop + }ifelse % ENDIF + o 0 INT_NE{fvAFB}if % IF(NZ(o)); fvAFB(); ENDIF + DEBUG( counttomark 42 string cvs) + DEBUG((pikula\n)) + }ifelse % ENDIF + }if % ENDWHILE /* MODE_BOB */ + % Stack: - + + mode MODE_BOS INT_EQ{ + DEBUG(counttomark 42 string cvs) + DEBUG(( booski\n)) + DEBUG2((boost)===only) + DEBUG2(currentfile FP ===) + { + DEBUG(counttomark 42 string cvs) + DEBUG(( boosbe\n)) + tY FMT_STOP INT_EQ{ % WHILE(NE(tY,FMT_STOP)) + Tvar 0 INT_NE{ % /* Flush unwritten buffer. */ + Tvar% BUG fixed at Thu Dec 27 14:05:32 CET 2001 + /Tvar 0 def + % Stack: Tvar_old + }{0}ifelse + % ccc777 + exit % return % in big-big loop and BOS-loop + }if + % /* SET(oO,0); SET(oP,0); */ /* avoid GCC warnings */ + % /* fxInit(); */ /* assert(Y==0); SET(J,0); SET(Y,0); */ + /v NULL def /h NULL def % SET(v,NULL); SET(h,NULL); + % N 0 NULL put N 1 NULL put N 2 0 put % ASET(N,0,NULL); ASET(N,1,NULL); ASET(N,2,0); /* the NULL node is initially empty */ + % N 3 NULL put N 4 NULL put N 5 0 put % ASET(N,3,NULL); ASET(N,4,NULL); ASET(N,5,0); /* the Sentinel node is initially empty */ + constZ19 N copy pop % eliminate-NULLs trick: overwrites 1st >=6 elements of N + /Dvar 6 def % SET(Dvar,6); /* first free node is 6. `0' is NULL, `3' is Sentinel */ + 6{ % SET(o,Dvar); + dup NODESIZE ge{pop exit}if % WHILE (LT(o,NODESIZE)) + dup N exch dup 3 add put 1 add % ASET(N,o,o+3); INCR(o); /* next free node is next node */ + dup N exch NULL put 1 add % ASET(N,o,NULL); INCR(o); /* empty RIGHT */ + dup N exch 0 put 1 add % ASET(N,o,0); INCR(o); /* empty NVAL */ + }loop % ENDWHILE + % Stack: - + fxRead8EOF dup /tY exch def % SET(tY,fxRead8EOF()); /* read first byte of the header */ + % tY kkkkkkkkkk + dup 511 INT_EQ{ % IF(EQ(tY,511)) /* EOF */ + /tY FMT_STOP def % SET(tY,FMT_STOP); + }{ +#if CFG_FMT_ZLIB_ONLY + 1 fxIgnore8 % IGNORE fxRead8(); /* skip second header byte: 0x01 or 0x5e or 0x9c or 0xda */ +#else + dup FMT_ZLIB INT_EQ{ % ELSE_IF(EQ(tY,120)) /* ZLIB format */ + 1 fxIgnore8 % IGNORE fxRead8(); /* skip second header byte: 0x01 or 0x5e or 0x9c or 0xda */ + % /* SET(tY,FMT_ZLIB); */ + }{ + dup 80 INT_EQ{ % ELSE_IF(EQ(tY,80)) /* ZIP format */ + 1 fxIgnore8 % IGNORE fxRead8(); /* skip second header byte: 0x48 */ + /tY FMT_NONE def % SET(tY,FMT_NONE); + fxRead8 % SET(o,fxRead8()); + dup 3 INT_EQ{ % IF(EQ(o,3)) /* Local file header */ + % fxRead8 pop % IGNORE fxRead8(); /* skip: 0x04 */ + % fxRead16 pop % IGNORE fxRead16(); /* skip: version needed to extract file (0x0020) */ + % fxRead16 pop % IGNORE fxRead16(); /* LOCFLG flags */ + 5 fxIgnore8 + /tY fxRead8 def % SET(tY,fxRead8()); /* lower half of compression method */ + ASSERT_TRUE(tY FMT_ZIP_STORED INT_EQ tY FMT_ZIP_DEFLATED INT_EQ or,(ty==FMT_ZIP_STORED || ty==FMT_ZIP_DEFLATED)) + % ^^^ BUG fixed at Thu Dec 27 20:55:52 CET 2001 + % fxRead8 pop % IGNORE fxRead8(); /* upper half of compression method */ + % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* file modification time in MS-DOS format */ + % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* some kind of CRC-32 */ + 9 fxIgnore8 + /f fxRead16z def % SET(f, fxRead16z()); /* lower compressed file size */ + /oP fxRead16z def % SET(oP,fxRead16z()); /* higher compressed file size */ + 4 fxIgnore8 % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* uncompressed file size */ + fxRead16z % SET(oO,fxRead16z()); /* length of filename */ + fxRead16z add % SET(q,fxRead16z()); /* length of extra field */ + % WHILE(NZ(oO)) IGNORE fxRead8(); DECR(oO); ENDWHILE /* file name */ + % WHILE(NZ(q)) IGNORE fxRead8(); DECR(q); ENDWHILE /* extra field */ + % -1 1{fxRead8 pop}for + fxIgnore8z + }{ + dup 7 INT_EQ{ % ELSE_IF(EQ(o,7)) /* Extended local header of previous file in ZIP */ + % 1 1 13{fxRead8 pop}for % SET(o,0); WHILE(LT(o,13)) IGNORE fxRead8(); INCR(o); ENDWHILE /* BUGFIX: was 15 */ + 13 fxIgnore8 + }{ + dup 5 INT_EQ{ % ELSE_IF(EQ(o,5)) /* End of Central Directory Structure in ZIP */ + /* fprintf(stderr,"EOCDS\n"); */ + % 1 1 17{fxRead8 pop}for % SET(o,0); WHILE(LT(o,17)) IGNORE fxRead8(); INCR(o); ENDWHILE + 17 fxIgnore8 + fxRead16z % SET(o,fxRead16z()); /* CML: archive comment length */ + % -1 1{fxRead8 pop}for % WHILE (NZ(o)) IGNORE fxRead8(); DECR(o); ENDWHILE + fxIgnore8z + }{ + dup 1 INT_EQ{ % ELSE_IF(EQ(o,1)) /* Central Directory Structure */ + /* fprintf(stderr,"CDS\n"); */ + % 1 1 25{fxRead8 pop}for % SET(oO,0); WHILE(LT(oO,25)) IGNORE fxRead8(); INCR(oO); ENDWHILE + 25 fxIgnore8 + fxRead16z % SET(f,fxRead16z()); /* LEN: length of file name */ + fxRead16z add % SET(o,fxRead16z()); /* XLN: length of extra field */ + fxRead16z add % SET(q,fxRead16z()); /* CML: length of file comment */ + % fxRead16 pop fxRead16 pop fxRead16 pop + % fxRead16 pop fxRead16 pop fxRead16 pop + % ^^^ SET(oO,0); WHILE(LT(oO,12)) IGNORE fxRead8(); INCR(oO); ENDWHILE + 12 fxIgnore8 + fxIgnore8z + % ^^^ WHILE(NZ(f)) IGNORE fxRead8(); DECR(f); ENDWHILE /* file name */ + % WHILE(NZ(o)) IGNORE fxRead8(); DECR(o); ENDWHILE /* extra field */ + % WHILE(NZ(q)) IGNORE fxRead8(); DECR(q); ENDWHILE /* file comment */ + }if % o==1 + }ifelse % o==5 + }ifelse % o==7 + }ifelse % o==3 % ENDIF /* IF ZIP structure sub-type */ + % Stack: tY_old o + pop + }{ + dup 31 INT_EQ{ % ELSE_IF(EQ(tY,31)) /* gzip/RFC 1952 format */ + /* fprintf(stderr,"gzip!\n"); */ + /* SET(tY,FMT_GZIP); */ + /* The most simple gzip header (10 bytes): + * ID1 hex 0x1f == dec 31 == FMT_GZIP + * ID2 hex 0x8b + * CM hex 0x08 + * FLG hex 0x00 + * MTIME hex 0x00, 0x00, 0x00, 0x00 (1 Jan 1970, UNIX epoch) + * XFL hex 0x00 + * OS hex 0xff + * After that comes the compressed data stream. + * After that comes the CRC32 and ISIZE (byte aligned? ?) + */ + 2 fxIgnore8 % fxRead16 pop % IGNORE fxRead16(); /* ignore ID2 and CM */ + % kkkkkkkkkl + fxRead8 % SET(o,fxRead8()); /* FLG */ + % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* ignore MTIME */ + % fxRead16 pop % IGNORE fxRead16(); /* ignore XFL, OS */ + 6 fxIgnore8 + % Stack: o==FLG + dup 2 and 0 INT_NE{ % IF(TAND_P(o,2)) /* GCONT: skip part number of continuation */ + %fxRead16 pop % IGNORE fxRead16(); + 2 fxIgnore8 + }if % ENDIF + dup 4 and 0 INT_NE{ % IF(TAND_P(o,4)) /* ignore FEXTRA */ + fxRead16 fxIgnore8 + % 1 1 fxRead16{fxRead8 pop}for + % SET(q,fxRead16()); + % WHILE(NZ(q)) IGNORE fxRead8(); DECR(q); ENDWHILE + }if % ENDIF + dup 8 and 0 INT_NE{ % IF(TAND_P(o,8)) + {fxRead8 0 INT_EQ{exit}if}loop % WHILE(NZ(fxRead8())); PASS; ENDWHILE + }if % ENDIF /* ignore FNAME */ + dup 17 and 0 INT_NE{ % IF(TAND_P(o,16)) + {fxRead8 0 INT_EQ{exit}if}loop % WHILE(NZ(fxRead8())); PASS; ENDWHILE + }if % ENDIF /* ignore FCOMMENT */ + dup 32 and 0 INT_NE{ % IF(TAND_P(o,32)) /* skip encryption header */ + % fxRead16 pop fxRead16 pop fxRead16 pop + % fxRead16 pop fxRead16 pop fxRead16 pop + % SET(f,0); WHILE(LT(f,12)) IGNORE fxRead8(); INCR(f); ENDWHILE + 12 fxIgnore8 + }if % ENDIF + % Stack: tY o + pop + }if % tY==31 (gzip/RFC 1952 format) + }ifelse % tY==80 (ZIP format) + }ifelse % tY==FMT_ZLIB +#endif /* CFG_FMT_ZLIB_ONLY */ + }ifelse % tY==511 % ENDIF /* IF file format */ + % Stack: tY_old + pop + % /* fprintf(stderr,"tY=%d\n", tY); */ + % tY bbbbbc +#if CFG_FMT_ZLIB_ONLYX + /* FMT_ZIP_STORED can become alive somehow... */ + tY FMT_STOP INT_NE tY 3 INT_NE and{ + /mode MODE_BOB def % SET(mode,MODE_BOB); + -1 exit % goto mode_bob; + }if +#else + tY FMT_ZIP_STORED INT_EQ{ % IF(EQ(tY,FMT_ZIP_STORED)) + % /* fprintf(stderr,"ZIP_STORED oO=%d oP=%d\n", oO, oP); */ + /oO 0 def % SET(oO,0); + f 32768 Tvar sub sub dup 0 lt{ % IF((unsigned short)f<32768-(unsigned short)Tvar) + pop + Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for + pop + % Stack: Sbuf Tvar + 2 copy fxRead8 put % ASET_S(Tvar,fxRead8()); + 1 add % INCR(Tvar); + }for % ENDWHILE + /Tvar exch def pop + ASSERT_TRUE(Tvar 32768 lt,(Tvar<32768)) + oP 0 INT_NE{ + /mode MODE_ZSTO def + % ccc555 + Tvar exit % in big-big loop and BOS-loop + }if + % ^^^ IF(NZ(oP)); mode=MODE_ZSTO; return Tvar; ENDIF + ASSERT_TRUE(mode MODE_BOS INT_EQ,(mode==MODE_BOS)) + }{ % ELSE + % /* Even if f>=32768 */ + /f exch def % SUB(f,32768-Tvar); + Tvar 1 32767{ % WHILE(NE((unsigned short)Tvar,32768)) + Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8()); + % INCR(Tvar); + % DECR(f); + }for % ENDWHILE + /Tvar 0 def % SET(Tvar,0); + /mode MODE_ZSTO def % SET(mode,MODE_REP); + % bbb777 + 32768 exit % return (WORD)32768; % in big-big loop and BOS-loop + }ifelse % ENDIF + }{ + tY FMT_STOP INT_NE tY FMT_NONE INT_NE and{ + /mode MODE_BOB def % SET(mode,MODE_BOB); + -1 exit % goto mode_bob; + }if + }ifelse % ENDIF +#endif /* CFG_FMT_ZLIB_ONLY */ + }loop % ENDWHILE /* outermost WHILE(NE(tY,FMT_STOP)) */ + % Stack: retval + }{-1}ifelse % mode==MODE_BOS + % Stack: retval + }loop % big-big MODE_MOB||MODE_BOB||MODE_BOS loop + % Stack: retval +}BIND_DEF % ENDFUN + +% Stdin already set +#if 0 +% /fvInitAll{ +#define fvInitAll \ + fxInit \ + /tY FMT_NONE def \ + /mode MODE_BOS def \ + /Tvar 0 def /* make the round buffer empty */ \ + TE_init +% }BIND_DEF +#else +/fvMain{ + % /XXX + % STDIN read + % STDIN C readhexstring + % pop 0 get true_action + % TE_read(===) + + TE_init % must be called _before_ fxInit + fxInit + /tY FMT_NONE def + /mode MODE_BOS def + /Tvar 0 def + % /Tvar 0 def Tvar === quit + { Sbuf 0 fvWork getinterval } /G load exec + TE_read_eod % make sure that mEOD has been read +}BIND_DEF +#endif + +} /* We close the brace of declared functions */ +%</Defs> + +%<Data> +%%BeginData: +exec +`S +%%EndData +end restore showpage +%%Trailer +%%EOF +%</Data> + +%%EOF diff --git a/Build/source/utils/sam2p/main.hpp b/Build/source/utils/sam2p/main.hpp new file mode 100644 index 00000000000..c940ddac559 --- /dev/null +++ b/Build/source/utils/sam2p/main.hpp @@ -0,0 +1,18 @@ +/* main.hpp -- provide functions for the GUI + * by pts@fazekas.hu at 2002.12.28 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef MAIN_HPP +#define MAIN_HPP 1 + +#include "gensi.hpp" + +extern void init_applier(); +extern void init_loader(); +extern void init_sam2p_engine(char const*argv0); + +#endif diff --git a/Build/source/utils/sam2p/mapping.cpp b/Build/source/utils/sam2p/mapping.cpp new file mode 100644 index 00000000000..118d6d32ef5 --- /dev/null +++ b/Build/source/utils/sam2p/mapping.cpp @@ -0,0 +1,302 @@ +/* + * mapping.cpp -- associative array implementations + * by pts@fazekas.hu at Fri Mar 15 21:13:47 CET 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "mapping.hpp" +#include "error.hpp" +#include <string.h> +#include <stdlib.h> /* abort() */ + +/* --- */ + +bool Mapping::Gen::update(char const*key, slen_t keylen, char const*data) { + char *found_data=get(key, keylen); + if (found_data==NULLP) return true; + memcpy(found_data, data, datalen); + return false; +} + +/* --- */ + +bool Mapping::DoubleHash::obj_assert() { + assert(len <= used); + assert(minlen <= len); + assert(used <= maxused); + assert(maxused < alloced); + assert(alloced < (slen_t)-2); + /* Imp: re-count used and len */ + return true; +} + +bool Mapping::DoubleHash::set (char const* key, slen_t keylen, char const*data) { + assert(obj_assert()); + slen_t h1=vi_h1(key,keylen); + assert(h1<alloced); + Ary *p=ary+h1; + if (p->keylen==NEVER_USED) { added: + /* Dat: we shouldn't stop on p->keylen==DELETED */ + memcpy(p->keydata=new char[keylen+datalen], data, datalen); + memcpy(p->keydata+=datalen, key, p->keylen=keylen); len++; + //if (p->keylen==NEVER_USED && used++==maxused) { p->keylen=keylen; rehash(); } + // else { p->keylen=keylen; } + if (used++==maxused) rehash(); + assert(obj_assert()); + return true; /* new value added */ + } + if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) { updated: + memcpy(p->keydata-datalen, data, datalen); + return false; /* value updated */ + } + /* Not found for the 1st try. We have to walk. */ + slen_t h2=vi_h2(key,keylen); + assert(1<=h2 && h1<alloced); + while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */ + if (h1>=h2) { h1-=h2; p-=h2; } + else { h1+=alloced-h2; p+=alloced-h2; } + if (p->keylen==NEVER_USED) goto added; + if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) goto updated; + } +} +char*Mapping::DoubleHash::get (char const* key, slen_t keylen) { + assert(obj_assert()); + slen_t h1=vi_h1(key,keylen); + assert(h1<alloced); + Ary *p=ary+h1; + if (p->keylen==NEVER_USED) return (char*)NULLP; + if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) return p->keydata-datalen; + /* Not found for the 1st try. We have to walk. */ + slen_t h2=vi_h2(key,keylen); + assert(1<=h2 && h1<alloced); + /* Dat: assert(lnko(...)) better in vi_h2 */ + while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */ + if (h1>=h2) { h1-=h2; p-=h2; } + else { h1+=alloced-h2; p+=alloced-h2; } + if (p->keylen==NEVER_USED) return (char*)NULLP; + if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) return p->keydata-datalen; + } +} +bool Mapping::DoubleHash::deletee (char const* key, slen_t keylen) { + /* We must not set `p->keylen=NEVER_USED' in this method because this would + * ruin searches jumping on `p', but not coming from `p+h2'. So we just set + * `p->keylen=DELETED'. + */ + assert(obj_assert()); + slen_t h1=vi_h1(key,keylen); + assert(h1<alloced); + Ary *p=ary+h1; + if (p->keylen==NEVER_USED) return true; /* key to be deleted does not exist */ + if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) { found: + vi_dtor(p->keydata-datalen); + delete [] (p->keydata-datalen); + p->keylen=(slen_t)DELETED; + // p->keydata=(char*)NULLP; + if (len--==minlen) rehash(); + assert(obj_assert()); + return false; /* key-value pair deleted */ + } + /* Not found for the 1st try. We have to walk. */ + slen_t h2=vi_h2(key,keylen); + assert(1<=h2 && h1<alloced); + while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */ + if (h1>=h2) { h1-=h2; p-=h2; } + else { h1+=alloced-h2; p+=alloced-h2; } + if (p->keylen==(slen_t)NEVER_USED) return true; /* key to be deleted does not exist */ + if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) goto found; + } +} +void Mapping::DoubleHash::getFirst(char const*const*& key, slen_t &keylen, char *& data) { + assert(obj_assert()); + Ary *p=ary, *pend=p+alloced; + while (p!=pend && p->keylen>=(slen_t)-2) p++; + if (p==pend) { key=(char const*const*)NULLP; } + else { key=&p->keydata; data=p->keydata-datalen; keylen=p->keylen; } +} +void Mapping::DoubleHash::getNext (char const*const*& key, slen_t &keylen, char *& data) { + assert(obj_assert()); + /* vvv Dat: this operation is safe despite of the fact that it increases + * signedness off pointer target type ((char*) -> (Ary*)). + */ + Ary *p=PTS_align_cast(Ary*, + ( (char*)const_cast<char**>(key) + - ((char*)&((Ary*)0)->keydata-(char*)0) )), *pend=ary+alloced; + p++; + while (p!=pend && p->keylen>=(slen_t)-2) p++; + if (p==pend) { key=(char const*const*)NULLP; } + else { key=&p->keydata; data=p->keydata-datalen; keylen=p->keylen; } +} +void Mapping::DoubleHash::rehash() { + unsigned old_scale=scale; + slen_t old_alloced=alloced; +#ifndef NDEBUG + slen_t old_len=len; + slen_t old_used=used; +#endif + Ary *old_ary=ary; + // printf("rehash minlen=%u len=%u used=%u maxused=%u alloced=%u\n", minlen, len, used, maxused, alloced); + vi_scale(); + // printf("scaled minlen=%u len=%u used=%u maxused=%u alloced=%u\n", minlen, len, used, maxused, alloced); + // assert( minlen <= len); + if (scale==old_scale && used<=maxused) { assert(obj_assert()); return; } + Ary *pp=old_ary, *ppend=pp+old_alloced; + slen_t calclen=0, calcused=0; + ary=new Ary[alloced]; + // printf("alloced=%u\n", alloced); + memset(ary, '\377', sizeof(Ary)*alloced); /* fill with NEVER_USED */ + /* insert the old values to the new hash */ + for (; pp!=ppend; pp++) { + if (pp->keylen!=NEVER_USED) calcused++; + if (pp->keylen<(slen_t)-2) { + // printf("%u %u\n", (unsigned char)pp->keydata[0], (unsigned char)pp->keydata[1]); + calclen++; + slen_t h1=vi_h1(pp->keydata,pp->keylen); + assert(h1<alloced); + Ary *p=ary+h1; + assert(p->keylen!=DELETED); + if (p->keylen==NEVER_USED) { found: + p->keylen=pp->keylen; + p->keydata=pp->keydata; + continue; + } + assert(!(p->keylen==pp->keylen && 0==memcmp(p->keydata, pp->keydata, pp->keylen)) && "dupicate key"); + /* Not found for the 1st try. We have to walk. */ + slen_t h2=vi_h2(pp->keydata,pp->keylen); + assert(1<=h2 && h1<alloced); + while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */ + if (h1>=h2) { h1-=h2; p-=h2; } + else { h1+=alloced-h2; p+=alloced-h2; } + assert(p->keylen!=DELETED); + if (p->keylen==NEVER_USED) goto found; + assert(!(p->keylen==pp->keylen && 0==memcmp(p->keydata, pp->keydata, pp->keylen)) && "dupicate key"); + } /* WHILE */ + } + } /* NEXT */ + used=len=calclen; + assert(calclen==old_len); + assert(calcused==old_used); + assert(old_len==len); + assert(old_len==used); + assert(obj_assert()); + delete [] old_ary; +} +void Mapping::DoubleHash::clear() { + assert(obj_assert()); + Ary *pp=ary, *ppend=pp+alloced; + for (; pp!=ppend; pp++) if (pp->keylen<(slen_t)-2) { + vi_dtor(pp->keydata-datalen); /* this is quite fast */ + delete [] (pp->keydata-datalen); /* this is really slow for millions of values */ + pp->keylen=(slen_t)DELETED; + len--; + } + assert(len==0); + if (minlen!=0) rehash(); +} + +/* --- */ + +static slen_t const d15_primes[]= { + 0, 10, 13, 23, 37, 59, 89, 137, 211, 317, 479, 719, 1087, 1637, 2459, 3691, + 5557, 8353, 12539, 18839, 28277, 42433, 63659, + 95507UL, 143261UL, 214913UL, 322397UL, 483611UL, 725423UL, 1088159UL, 1632259UL, 2448389UL, + 3672593UL, 5508913UL, 8263373UL, 12395069UL, 18592631UL, 27888947UL, 41833427UL, + 62750147UL, 94125247UL, 141187901UL, 211781873UL, 317672813UL, 476509223UL, + 714763843UL, 1072145771UL, 1608218669UL, 2412328031UL, 3618492049UL, +#if SIZEOF_SLEN_T>=8 + 5427738097UL, 8141607167UL, 12212410753UL, 18318616157UL, 27477924239UL, + 41216886467UL, 61825329719UL, 92737994593UL, 139106991917UL, 208660487887UL, + 312990731839UL, 469486097807UL, 704229146717UL, 1056343720093UL, + 1584515580187UL, 2376773370313UL, 3565160055487UL, 5347740083243UL, + 8021610124867UL, 12032415187319UL, 18048622780987UL, 27072934171487UL, + 40609401257291UL, 60914101885951UL, 91371152828947UL, 137056729243439UL, + 205585093865189UL, 308377640797829UL, 462566461196803UL, + 693849691795229UL, 1040774537692907UL, 1561161806539393UL, + 2341742709809177UL, 3512614064713777UL, 5268921097070759UL, + 7903381645606193UL, 11855072468409349UL, 17782608702614033UL, + 26673913053921061UL, 40010869580881603UL, 60016304371322423UL, + 90024456556983643UL, 135036684835475519UL, 202555027253213279UL, + 303832540879819943UL, 455748811319729951UL, 683623216979594929UL, + 1025434825469392417UL, 1538152238204088631UL, 2307228357306132983UL, + 3460842535959199481UL, 5191263803938799269UL, +#endif + 0 +}; + +void Mapping::DoubleHash15::vi_scale() { +#if 0 + // <lloced=63659 used=59671 maxused=59670 + // alloced=1637 used=59671 maxused=1534 + + // <lloced=1637 used=1535 maxused=1534 + // |lloced=2459 used=1535 maxused=1534 + // |lloced=1637 used=1535 maxused=1534 + // alloced=1637 used=1535 maxused=1534 + + + printf("<lloced=%u used=%u maxused=%u\n", alloced, used, maxused); + if (len<minlen) { again: + /* assert(used==minlen-1); */ + assert(scale>=1); + alloced=(d15_primes+2)[--scale]; + if (scale>1) minlen=(d15_primes+2)[scale-2]; + else if (scale==1) minlen=10; + else minlen=0; + if (len<minlen) goto again; + } else if (used>maxused) { + assert(used==maxused+1); + if ((alloced=(d15_primes+2)[++scale])==0) abort(); /* Imp: better overflow reporting */ + if (scale>1) minlen=(d15_primes+2)[scale-2]; + else if (scale==1) minlen=10; + else minlen=0; + // if (len<minlen) minlen=len; + } else assert(0); + printf("|lloced=%u used=%u maxused=%u\n", alloced, used, maxused); + if (alloced<=4000U) maxused=(alloced*15)>>4; + else maxused=(alloced>>4)*15; + if (used>maxused) printf("alloced=%u used=%u maxused=%u\n", alloced, used, maxused); +#endif + + /* Dat: we respect only `len', not used. */ + /* Imp: make calculation of scale relative to previous one */ + + scale=0; while (1) { + // printf("xscale=%u\n", scale); + if (0==(alloced=(d15_primes+2)[scale])) { assert(0); abort(); } /* Imp: better overflow reporting */ + if (alloced<=4000U) maxused=(alloced*15)>>4; + else maxused=(alloced>>4)*15; /* avoid overflows */ + if (len<=maxused) break; /* _not_ used<=maxused, because of rehash() */ + scale++; + } + minlen=(d15_primes)[scale]; + // printf("ret alloced=%u used=%u maxused=%u\n", alloced, used, maxused); +} +slen_t Mapping::DoubleHash15::vi_h1(register char const*key, register slen_t keylen) { + register slen_t hval=0, m=alloced; + while (keylen--!=0) hval=((hval<<8)+*key++)%m; + /* Imp: make this accurate and faster (the `%' operation is rather slow) */ + return hval; +} +slen_t Mapping::DoubleHash15::vi_h2(char const*key, slen_t keylen) { + register slen_t hval=0, m=alloced-1; + while (keylen--!=0) hval=((hval<<8)+*key++)%m; + /* Imp: make this accurate and faster (the `%' operation is rather slow) */ + return hval+1; +} +void Mapping::DoubleHash15::vi_dtor(char *) {} + +Mapping::DoubleHash15::DoubleHash15(slen_t datalen_) { + ary=new Ary[alloced=(d15_primes+2)[scale=0]]; + memset(ary, '\377', sizeof(Ary)*alloced); /* fill with NEVER_USED */ + datalen=datalen_; + len=used=minlen=0; + maxused=(alloced>>4)*15; +} +Mapping::DoubleHash15::~DoubleHash15() { + clear(); + delete [] ary; +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/mapping.hpp b/Build/source/utils/sam2p/mapping.hpp new file mode 100644 index 00000000000..cee76d2bf1d --- /dev/null +++ b/Build/source/utils/sam2p/mapping.hpp @@ -0,0 +1,153 @@ +/* mapping.hpp -- an associative array that maps strings into arbitrary fixed-length values + * by pts@fazekas.hu at Sat Mar 23 16:01:55 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef MAPPING_HPP +#define MAPPING_HPP 1 + +#include "config2.h" +#include "gensi.hpp" + +class Mapping { + /** A mapping is an assicative array whose keys are arbitrary binary strings + * and its values are arbirary fixed-length data. The Mapping class is + * abstract. The longest key which can be stored in a Mapping::Gen has + * length `(slen_t)-3'. The caller must verify that she doesn't try to + * call us with a longer string. + */ + class Gen { + public: + /** Returns the length of one data value (same for all values, determined + * at construction of Gen). + */ + inline slen_t getDataLen() const { return datalen; } + /** Returns the number of keys currently in this Mapping. */ + inline slen_t getLength() const { return len; } + /** Returns the number of key positions allocated for this Mapping. This + * number may or may not have meaning, depending on the implementation. + */ + inline slen_t getAlloced() const { return len; } + /** + * Updates or extends the mapping with the specified key/value pair. + * @param data must point to an area of length getDataLen(). That + * area will be copied (memcpy()) by set(). + * @return true if key previously hasn't existed + */ + virtual bool set(char const*key, slen_t keylen, char const*data) =0; + /** @return the address of the data that corresponds to param + * `key', or NULLP if `key' was not found. The returned value is valid + * until the next modification (.set(), deletee() methods). + */ + virtual char* get(char const*key, slen_t keylen) =0; + /** + * Updates mapping with the specified key/value pair. Leaves it unchanged + * if the specified key doesn't exist. Calls get() and memcpy() to do the + * job. + * @param data must point to an area of length getDataLen(). That + * area will be copied by set(). + * @return true if key previously hasn't existed + */ + bool update(char const*key, slen_t keylen, char const*data); + + /** Calls get to do the job. */ + inline bool exists(char const*key, slen_t keylen) { return NULLP!=get(key, keylen); } + + /** + * Deletes the specified `key' from the mapping. + * @param data must point to an area of length getDataLen(). That + * area will be copied by set(). + * @return true if key previously hasn't existed + */ + virtual bool deletee(char const*key, slen_t keylen) =0; + + /** The user must ensure that she isn't updating the mapping while walking. + * @param key (out) is set to NULLP on empty mapping. + */ + virtual void getFirst(char const*const*& key, slen_t &keylen, char *& data) =0; + /** The user must ensure that she isn't updating the mapping while walking. + * @param key (out) is set to NULLP if there are no more elements + */ + virtual void getNext (char const*const*& key, slen_t &keylen, char *& data) =0; + + protected: + slen_t datalen, len, alloced; + }; + + /** Double hashing. Still abstract. */ + class DoubleHash: public Gen { + public: + /** If it modifies `scale', then it must modify alloced, may modify minlen + * and maxused, and must not modify anything else. If it does not modify + * `scale', it must not modify anything else. After it returns, + * obj_assert() must hold. Must not copy or (re)allocate memory, + * rehashing is not done by vi_scale(). rehash() calls vi_scale(), and + * rehash() does the real reallocation. + */ + virtual void vi_scale() =0; + /** First hash function. Must return a value in 0..alloced-1 */ + virtual slen_t vi_h1(char const*key, slen_t keylen) =0; + /** Second hash function. Must return a value in 1..alloced-1, which is + * realatively prime to the value returned by vi_h2(). + */ + virtual slen_t vi_h2(char const*key, slen_t keylen) =0; + /** Destruct and free resources used by data. Called by deletee(). */ + virtual void vi_dtor(char *data) =0; + + /** Called by set() and deletee() ?? */ + virtual bool set (char const* key, slen_t keylen, char const*data); + virtual char*get (char const* key, slen_t keylen); + virtual bool deletee (char const* key, slen_t keylen); + virtual void getFirst(char const*const*&key, slen_t &keylen, char *& data); + virtual void getNext (char const*const*&key, slen_t &keylen, char *& data); + /** Delete everything. */ + void clear(); + protected: + void rehash(); + /** @return true */ + bool obj_assert(); + /** `keylen==(slen_t)-1' indicates a place never used, + * `keylen==(slen_t)-2' indicates a deleted place + * Before changing the value of NEVER_USED, please update the memset(...) + * in rehash(). + */ + BEGIN_STATIC_ENUM1(slen_t) NEVER_USED=(slen_t)-1, DELETED=(slen_t)-2 END_STATIC_ENUM() + // static const slen_t NEVER_USED=(slen_t)-1, DELETED=(slen_t)-2; + struct Ary { + slen_t keylen; + /** key is located at keydata, data is located keydata-datalen */ + char *keydata; + } *ary; + /* The minimum number of keys before rehashing. */ + slen_t minlen; + /* The maximum number of keys before rehashing. */ + slen_t maxused; + /* The number of used places. A place is used unless it is NEVER_USED */ + slen_t used; + /** Used by the implementor of vi_scale. */ + unsigned scale; + }; + + /** Simple prime modulus double hashing with a factor of around 1.5 + * between `alloced' scales. This class is not abstract anymore. + */ + class DoubleHash15: public DoubleHash { + public: + DoubleHash15(slen_t datalen_); + virtual ~DoubleHash15(); + virtual void vi_scale(); + /** @return key % Prime */ + virtual slen_t vi_h1(char const*key, slen_t keylen); + /** @return (key % (Prime-1))+1 */ + virtual slen_t vi_h2(char const*key, slen_t keylen); + /** No-op. */ + virtual void vi_dtor(char *data); + }; + public: + typedef DoubleHash15 H; +}; + +#endif diff --git a/Build/source/utils/sam2p/minips.cpp b/Build/source/utils/sam2p/minips.cpp new file mode 100644 index 00000000000..3351f6fbdef --- /dev/null +++ b/Build/source/utils/sam2p/minips.cpp @@ -0,0 +1,1081 @@ +/* + * minips.cpp + * by pts@fazekas.hu at Sat Mar 9 21:33:35 CET 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "minips.hpp" +#include "error.hpp" +#include "gensio.hpp" +#if USE_DICT_MAPPING +#if OBJDEP +# warning REQUIRES: mapping.o +#endif +#include "mapping.hpp" +#endif +#include <stdio.h> /* sscanf() */ +#include <string.h> /* memset() */ + +static inline bool is_ps_white(char c) { + return c=='\n' || c=='\r' || c=='\t' || c==' ' || c=='\f' || c=='\0'; +} + +static inline bool is_ps_name(char c) { + /* Dat: we differ from PDF since we do not treat the hashmark (`#') special + * in names. + * Dat: we differ from PostScript since we accept names =~ /[!-~]/ + */ + return c>='!' && c<='~' + && c!='/' && c!='%' && c!='{' && c!='}' && c!='<' && c!='>' + && c!='[' && c!=']' && c!='(' && c!=')'; + /* Dat: PS avoids: /{}<>()[]% \n\r\t\000\f\040 */ +} + +/** @param b: assume null-terminated @return true on erro + * @return false on error + */ +static inline bool toInteger(SimBuffer::Flat const&b, signed long &ret) { + int n=0; /* BUGFIX?? found by __CHECKER__ */ + // b.term0(); + return sscanf(b(), "%li%n", &ret, &n)<1 || b[n]!='\0'; +} + +static inline bool toHex(char const*s, unsigned long &ret) { + int n=0; + return sscanf(s, "%lx%n", &ret, &n)<1 || s[n]!='\0'; +} + +static inline bool toHex3(char const*s, char ret[3]) { + unsigned long l; + if (toHex(s, l)) return true; + ret[0]=((l>>8)&15)*17; ret[1]=((l>>4)&15)*17; ret[2]=(l&15)*17; + return false; +} + +static inline bool toHex6(char const*s, char ret[3]) { + unsigned long l; + if (toHex(s, l)) return true; + ret[0]=(l>>16)&255; ret[1]=(l>>8)&255; ret[2]=l&255; + return false; +} + +/** @param b: assume null-terminated @return true on error */ +static inline bool toReal(SimBuffer::Flat const&b, double &ret) { + int n; + char c; + // b.term0(); + /* Dat: glibc accepts "12e", "12E", "12e+" and "12E-" */ + return sscanf(b(), "%lf%n", &ret, &n)<1 + || (c=b[n-1])=='e' || c=='E' || c=='+' || c=='-' || b[n]!='\0'; +} + +/** This is not correct if blen cuts the real number into two strings. + * @param b: assume null-terminated @return true on error + */ +static inline bool toReal(char const *b, slen_t blen, double &ret) { + int n; + char c; + // b.term0(); + /* Dat: glibc accepts "12e", "12E", "12e+" and "12E-" */ + return sscanf(b, "%lf%n", &ret, &n)<1 + || (c=b[n-1])=='e' || c=='E' || c=='+' || c=='-' || (slen_t)n!=blen; +} + +MiniPS::Tokenizer::Tokenizer(GenBuffer::Readable& in_): in(in_), ungot(NO_UNGOT) { +} +int MiniPS::Tokenizer::yylex() { + int c=0; /* dummy initialization */ + bool hi; + unsigned hv; + slen_t nest, len; + signed long l; + double d; + Real::metric_t metric; + char saved; + + if (ungot==EOFF) return EOFF; + if (ungot!=NO_UNGOT) { c=ungot; ungot=NO_UNGOT; goto again; } + again_getcc: + c=in.vi_getcc(); + again: + switch (c) { + case -1: eof: + return ungot=EOFF; + case '\n': case '\r': case '\t': case ' ': case '\f': case '\0': + goto again_getcc; + case '%': /* one-line comment */ + while ((c=in.vi_getcc())!='\n' && c!='\r' && c!=-1) ; + if (c==-1) goto eof; + goto again_getcc; + case '{': case '[': + return '['; + case '}': case ']': + return ']'; + case ')': goto err; + case '>': + if (in.vi_getcc()!='>') goto err; + return '>'; + case '<': + if ((c=in.vi_getcc())==-1) { uf_hex: Error::sev(Error::EERROR) << "miniPS: unfinished hexstr" << (Error*)0; } + if (c=='<') return '<'; + if (c=='~') Error::sev(Error::EERROR) << "miniPS: a85str unsupported" << (Error*)0; + tv.bb=&b; b.clear(); + hi=true; + while (c!='>') { + if ((hv=b.hexc2n(c))!=16) { + if (hi) { b << (char)(hv<<4); hi=false; } + else { b.end_()[-1]|=hv; hi=true; } + } else if (!is_ps_white(c)) Error::sev(Error::EERROR) << "miniPS: syntax error in hexstr" << (Error*)0; + if ((c=in.vi_getcc())==-1) goto uf_hex; + } + /* This is correct even if an odd number of hex digits have arrived */ + return '('; + case '(': + tv.bb=&b; b.clear(); + nest=1; + while ((c=in.vi_getcc())!=-1) { redo: + if (c==')' && --nest==0) return '('; + if (c!='\\') { if (c=='(') nest++; b << (char)c; continue; } + /* read a backslash */ + switch (c=in.vi_getcc()) { + case -1: goto uf_str; + case 'n': b << '\n'; break; + case 'r': b << '\r'; break; + case 't': b << '\t'; break; + case 'b': b << '\010'; break; /* \b and \a conflict between -ansi and -traditional */ + case 'f': b << '\f'; break; + default: + if (c<'0' || c>'7') { b << (char)c; break; } + hv=c-'0'; /* read at most 3 octal chars */ + if ((c=in.vi_getcc())==-1) goto uf_str; + if (c<'0' || c>'7') { b << (char)hv; goto redo; } + hv=8*hv+(c-'0'); + if ((c=in.vi_getcc())==-1) goto uf_str; + if (c<'0' || c>'7') { b << (char)hv; goto redo; } + b << (char)(8*hv+(c-'0')); + } /* SWITCH */ + } /* WHILE */ + uf_str: Error::sev(Error::EERROR) << "miniPS: unfinished str" << (Error*)0; + case '/': + /* fall-through, b will begin with '/' */ + default: /* /nametype, /integertype or /realtype */ + tv.bb=&b; b.clear(); + b.clear(); b << (char)c; + while ((c=in.vi_getcc())!=-1 && is_ps_name(c)) b << (char)c; + ungot=c==-1?EOFF:c; + if (b[0]=='/') return '/'; + b.term0(); + /* Dat: we don't support base-n number such as `16#100' == 256 in PostScript */ + if (!toInteger(b, l)) { tv.i=l; return '1'; } + /* Dat: call toInteger _before_ toReal */ + // if (!toReal(b, tv.d)) { fprintf(stderr,"%f;\n", tv.d); } + /* assert(tv.bb!=NULLP); */ + len=b.getLength(); + if (!toReal(b, d)) { /* tv.bb is also valid */ + tv.r=new Real(d, b(), len); + return '.'; + } + if (len>2 && (metric=Real::str2metric(b()+len-2))!=Real::ME_COUNT) { + saved=b[len-2]; + b[len-2]='\0'; + if (!toReal(b, d)) { + tv.r=new Real(d, b(), len-2); + tv.r->setMetric(metric); + return ':'; /* Real with metric */ + } + b[len-2]=saved; + } + return 'E'; /* /nametype */ + } + err: + Error::sev(Error::EERROR) << "miniPS: syntax error" << (Error*)0; + goto again_getcc; /* notreached */ +} + +/* --- */ + +#if 0 +inline static unsigned typerr() { assert(0); return 0; } +#endif + +unsigned MiniPS::getType(VALUE v) { + return (v&1)!=0 ? T_INTEGER + : v>Qmax_ ? RVALUE(v)->getType() + : v==Qnull ? T_NULL+0/*avoid gcc-3.0 ld bug*/ + : T_BOOLEAN; +} +char const* MiniPS::getTypeStr(unsigned u) { + static char const* strs[]= { (char const*)NULLP, "null", "boolean", "integer", "real", "string", "array", "dict", "name", "Ename", "void" }; + // return strs[getType(v)]; + return strs[u]; +} +void MiniPS::delete0(VALUE v) { + if (isDirect(v)) return; + Value *vp=RVALUE(v); + unsigned ty=vp->getType(); + if (ty==T_DICT) RDICT(v)->free(); + else if (ty==T_ARRAY) RARRAY(v)->free(); + else if (ty==T_VOID) ; + else if (vp->hasPtr()) delete [] (char*)vp->begin_(); + delete vp; /* BUGFIX at Sat Sep 7 12:50:13 CEST 2002 */ +} +void MiniPS::dump(VALUE v, unsigned indent) { + Files::FILEW sout(stdout); + dump(sout, v, indent); +} +void MiniPS::dump(GenBuffer::Writable& out_, VALUE v, unsigned indent) { + if (v==Qnull) out_ << "null"; + else if (v==Qtrue) out_ << "true"; + else if (v==Qfalse) out_ << "false"; + else if ((v&1)!=0) out_ << (v/2); /* prints a signed integer */ + else { + Value *vp=RVALUE(v); + unsigned ty=vp->getType(); + if (ty==T_STRING) { + SimBuffer::Static s((char*)vp->begin_(), vp->getLength()); + SimBuffer::B b; + b.appendDumpPS(s, true); + out_ << b; + } else if (ty==T_SNAME || ty==T_ENAME) { + out_.vi_write((char*)vp->begin_(), vp->getLength()); + } else if (ty==T_REAL) { + RREAL(v)->dump(out_); + } else if (ty==T_ARRAY) { + if (!vp->isDumping()) { /* Imp: thread-safe locking */ + RARRAY(v)->dump(out_, indent); + } else out_ << "[...]"; + } else if (ty==T_DICT) { + if (!vp->isDumping()) { /* Imp: thread-safe locking */ + RDICT(v)->dump(out_, indent); + } else out_ << "<<...>>"; + } else assert(0 && "unknown MiniPS type"); + } +} + +/* --- */ + +/* Sat Sep 7 12:30:19 CEST 2002 */ +const double MiniPS::Real::me_factor[MiniPS::Real::ME_COUNT]={ + 1.0L, /* 1 bp = 1 bp (big point) */ + 72.0L, /* 1 in = 72 bp (inch) */ + 72.0L/72.27, /* 1 pt = 72/72.27 bp (point) */ + 12.0L*72.0/72.27, /* 1 pc = 12*72/72.27 bp (pica) */ + 1238.0L/1157.0*72.0/72.27, /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */ + 12.0L*1238.0/1157.0*72.0/72.27, /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */ + 72.0L/72.27/65536.0, /* 1 sp = 72/72.27/65536 bp (scaled point) */ + 72.0L/2.54, /* 1 cm = 72/2.54 bp (centimeter) */ + 7.2L/2.54, /* 1 mm = 7.2/2.54 bp (millimeter) */ +}; +/* Sat Sep 7 12:30:19 CEST 2002 */ +char const* const MiniPS::Real::me_psfactor[MiniPS::Real::ME_COUNT]={ + "", /* 1 bp = 1 bp (big point) */ + " 72 mul", /* 1 in = 72 bp (inch) */ + " 72 mul 72.27 div", /* 1 pt = 72/72.27 bp (point) */ + " 864 mul 72.27 div", /* 1 pc = 12*72/72.27 bp (pica) */ + " 891.36 mul 836.164 div", /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */ + " 10696.32 mul 836.164 div", /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */ + " 0.72 mul 47362.8672 div", /* 1 sp = 72/72.27/65536 bp (scaled point) */ + " 72 mul 2.54 div", /* 1 cm = 72/2.54 bp (centimeter) */ + " 720 mul 254 div", /* 1 mm = 7.2/2.54 bp (millimeter) */ +}; +MiniPS::Real::Real(double d_, char const*ptr_, ii_t len_): d(d_), metric(0), dumpPS(false) { + ty=T_REAL; + char *p=new char[len_+1]; + memcpy(ptr=p, ptr_, len=len_); + p[len_]='\0'; +} +void MiniPS::Real::dump(GenBuffer::Writable &out_, bool dumpPS_force) { + char buf[64]; /* Imp: should be enough?? */ + if (metric!=0 && (dumpPS_force || dumpPS)) { + sprintf(buf, "%"PTS_CFG_PRINTFGLEN"g%s", d, me_psfactor[metric]); + } else { + sprintf(buf, "%"PTS_CFG_PRINTFGLEN"g", d*me_factor[metric]); + } + out_ << buf; +} +MiniPS::Real::metric_t MiniPS::Real::str2metric(char const str[2]) { + switch (str[0]) { + case 'b': if (str[1]=='p') return ME_bp; break; + case 'i': if (str[1]=='n') return ME_in; break; + case 'p': if (str[1]=='t') return ME_pt; + if (str[1]=='c') return ME_pc; break; + case 'd': if (str[1]=='d') return ME_dd; break; + case 'c': if (str[1]=='c') return ME_cc; + if (str[1]=='m') return ME_cm; break; + case 's': if (str[1]=='p') return ME_sp; break; + case 'm': if (str[1]=='m') return ME_mm; break; + } + return ME_COUNT; +} +bool MiniPS::Real::isDimen(char const *str) { + double d; + slen_t len=strlen(str); + if (!toReal(str, len, d)) return true; + return len>2 && str2metric(str+len-2)!=ME_COUNT && !toReal(str, len-2, d); +} + +MiniPS::String::String(char const*ptr_, ii_t len_) { + char *p=new char[len_+1]; + memcpy(ptr=p, ptr_, len=len_); + p[len_]='\0'; + ty=T_STRING; +} +void MiniPS::String::replace(char const*ap, slen_t alen, char const*bp, slen_t blen) { + char *p=new char[alen+blen+1]; + memcpy(p, ap, alen); + memcpy(p+alen, bp, blen); + p[alen+blen]='\0'; + delete [] (char*)ptr; + ptr=p; +} + +MiniPS::Sname::Sname(char const*ptr_, ii_t len_) { + param_assert(len_>=1 && ptr_[0]=='/'); + char *p=new char[len_+1]; + memcpy(ptr=p, ptr_, len=len_); + p[len_]='\0'; + ty=T_SNAME; +} +bool MiniPS::Sname::equals(Sname const&other) { + return len==other.len && 0==memcmp(ptr, other.ptr, len); +} +bool MiniPS::Sname::equals(char const*other) { + return 0==strcmp(1+(char*)ptr, other); +} + +MiniPS::Ename::Ename(char const*ptr_, ii_t len_) { + param_assert(len_>=1 && ptr_[0]!='/'); + char *p=new char[len_+1]; + memcpy(ptr=p, ptr_, len=len_); + p[len_]='\0'; + ty=T_ENAME; +} +bool MiniPS::Ename::equals(Ename const&other) { + return len==other.len && 0==memcmp(ptr, other.ptr, len); +} +bool MiniPS::Ename::equals(char const*other, slen_t otherlen) { + return (slen_t)len==otherlen && 0==memcmp(ptr, other, otherlen); +} +bool MiniPS::Ename::equals(char const*other) { + return 0==strcmp((char*)ptr, other); +} + +MiniPS::Array::Array() { + alloced=16; + ptr=new VALUE[alloced=16]; + len=0; + ty=T_ARRAY; +} +void MiniPS::Array::free() { + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) delete0(*p++); + delete [] (VALUE*)ptr; +} +void MiniPS::Array::push(VALUE v) { + if (len==alloced) extend(len+1); + ((VALUE*)ptr)[len++]=v; +} +MiniPS::VALUE MiniPS::Array::get(ii_t index) { + return (index<0 || index>=len) ? Qundef : ((VALUE*)ptr)[index]; +} +void MiniPS::Array::set(ii_t index, VALUE val) { + param_assert(index>=0 && index<len); + MiniPS::delete0(((VALUE*)ptr)[index]); + ((VALUE*)ptr)[index]=val; +} +void MiniPS::Array::dump(GenBuffer::Writable &out_, unsigned indent) { + dumping=true; + if (len==0) { + out_ << "[]"; + } else if (len==1) { + out_ << "[ "; + MiniPS::dump(out_, ((VALUE*)ptr)[0], indent); + out_ << " ]"; + } else { + indent+=2; + char *spaces=new char[indent]; + memset(spaces, ' ', indent); + // spaces[indent]='\n'; + out_ << "[ % " << len << " elements\n"; + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + out_.vi_write(spaces, indent); + MiniPS::dump(out_, *p++, indent); + /*if(p!=pend)*/ out_ << "\n"; + } + out_.vi_write(spaces, indent-=2); + out_ << "]"; + } + dumping=false; +} +void MiniPS::Array::extend(ii_t newlen) { + if (newlen<=alloced) return; + ii_t newalloced=alloced; + assert(alloced>=0); + while (newlen>newalloced) newalloced<<=1; + VALUE *newptr=new VALUE[newalloced]; + memcpy(newptr, ptr, len*sizeof(VALUE)); + delete [] (VALUE*)ptr; + ptr=newptr; + alloced=newalloced; + /* len remains unchanged */ +} +void MiniPS::Array::getFirst(VALUE *&val) { + if (len==0) { val=(VALUE*)NULLP; return; } + val=(VALUE*)ptr; +} +void MiniPS::Array::getNext(VALUE *&val) { + val++; + if (len+(VALUE*)ptr==val) val=(VALUE*)NULLP; +} + +#if USE_DICT_MAPPING +MiniPS::Dict::Dict() { /* Sun Mar 24 21:02:41 CET 2002 */ + ptr=(void*)new Mapping::H(sizeof(VALUE)+1); + /* hash value format: a VALUE, and a flag (0 or 1) indicating touchedness */ + len=0; /* meaningless */ + ty=T_DICT; +} +void MiniPS::Dict::free() { + char const*const* keyy; slen_t keylen; VALUE *val; bool touched; + getFirst(keyy, keylen, val, touched); + while (keyy!=(char const*const*)NULLP) { + MiniPS::delete0(*val); + getNext(keyy, keylen, val, touched); + } + delete (Mapping::H*)ptr; +} +void MiniPS::Dict::put(char const*key, VALUE val) { + put(key,strlen(key),val); +} +MiniPS::VALUE MiniPS::Dict::push(char const*keys, slen_t keylen, VALUE val) { + if (keys[0]=='/') { keys++; keylen--; } + char *has=((Mapping::H*)ptr)->get(keys,keylen); + VALUE ret=Qundef; + if (has!=(char const*)NULLP) { + memcpy(&ret, has, sizeof(VALUE)); + // printf("found=/%s.\n", keys); + /* No delete0(); deliberately. */ + memcpy(has, &val, sizeof(VALUE)); has[sizeof(VALUE)]=0; + } else { + char tmp[sizeof(VALUE)+1]; + memcpy(tmp, &val, sizeof(VALUE)); + tmp[sizeof(VALUE)]=0; + ((Mapping::H*)ptr)->set(keys,keylen,tmp); + } + return ret; +} +void MiniPS::Dict::put(char const*keys, slen_t keylen, VALUE val) { + if (keys[0]=='/') { keys++; keylen--; } + char *has=((Mapping::H*)ptr)->get(keys,keylen); + if (has!=NULLP) { + VALUE ret=Qundef; memcpy(&ret, has, sizeof(VALUE)); + MiniPS::delete0(ret); + memcpy(has, &val, sizeof(VALUE)); has[sizeof(VALUE)]=0; + } else { + char tmp[sizeof(VALUE)+1]; + memcpy(tmp, &val, sizeof(VALUE)); + tmp[sizeof(VALUE)]=0; + ((Mapping::H*)ptr)->set(keys,keylen,tmp); + } +} +MiniPS::VALUE MiniPS::Dict::get(char const*keys, slen_t keylen) { + if (keys[0]=='/') { keys++; keylen--; } + char *has=((Mapping::H*)ptr)->get(keys,keylen); + VALUE ret=Qundef; if (has!=NULLP) memcpy(&ret, has, sizeof(VALUE)); + return ret; +} +MiniPS::VALUE MiniPS::Dict::get1(char const*keys, slen_t keylen) { + if (keys[0]=='/') { keys++; keylen--; } + char *has=((Mapping::H*)ptr)->get(keys,keylen); + VALUE ret=Qundef; if (has!=NULLP) { memcpy(&ret, has, sizeof(VALUE)); has[sizeof(VALUE)]=1; } + return ret; +} +void MiniPS::Dict::untouch(char const*keys, slen_t keylen) { + if (keys[0]=='/') { keys++; keylen--; } + char *has=((Mapping::H*)ptr)->get(keys,keylen); + if (has!=NULLP) has[sizeof(VALUE)]=0; +} +void MiniPS::Dict::getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) { + char *has; + // key=(char const*const*)NULLP;return; + ((Mapping::H*)ptr)->getFirst(key, keylen, has); + if (key==(char const*const*)NULLP) return; + val=PTS_align_cast(VALUE*,has); + touched=has[sizeof(VALUE)]!=0; +} +void MiniPS::Dict::getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) { + char *has; + ((Mapping::H*)ptr)->getNext(key, keylen, has); + if (key==(char const*const*)NULLP) return; + val=PTS_align_cast(VALUE*,has); + touched=has[sizeof(VALUE)]!=0; +} +void MiniPS::Dict::dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters) { + dumping=true; + slen_t len=((Mapping::H*)ptr)->getLength(); + if (len==0) { + if (dump_delimiters) out_ << "<<>>"; + } else { + char const*const* keyy; slen_t keylen; VALUE *val; bool touched; + indent+=2; + char *spaces=new char[indent]; + memset(spaces, ' ', indent); + // spaces[indent]='\n'; + if (dump_delimiters) out_ << "<< % " << len << " key(s)\n"; + getFirst(keyy, keylen, val, touched); + while (keyy!=(char const*const*)NULLP) { + out_.vi_write(spaces, indent); + out_.vi_putcc('/'); + out_.vi_write(*keyy, keylen); /* Imp: PDF #...-quoting */ + out_ << " "; + MiniPS::dump(out_, *val, indent); + out_.vi_putcc('\n'); + getNext(keyy, keylen, val, touched); + } + if (dump_delimiters) { out_.vi_write(spaces, indent-=2); out_ << ">>"; } + } + dumping=false; +} +void MiniPS::Dict::extend(ii_t) {} + +#else /* a MiniPS::Dict implementation with linear search */ +MiniPS::Dict::Dict() { + alloced=16; + ptr=new VALUE[alloced=16]; + len=0; + ty=T_DICT; +} +void MiniPS::Dict::free() { + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) delete0(*p++); + delete [] (VALUE*)ptr; +} +void MiniPS::Dict::put(char const*key, VALUE val) { + return put(key,strlen(key),val); +} +MiniPS::VALUE MiniPS::Dict::push(char const*keys, slen_t keylen, VALUE val) { + // param_assert(key[0]=='/'); + if (keys[0]=='/') { keys++; keylen--; } + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + if (MiniPS::RENAME(p[0]&~1)->equals(key,keylen)) { + VALUE v=p[1]; + p[1]=val; return v; + } + p+=2; + } + if (len==alloced) extend(len+2); + ((VALUE*)ptr)[len++]=(MiniPS::VALUE)new Ename(keys,keylen); + ((VALUE*)ptr)[len++]=val; + return Qundef; +} +void MiniPS::Dict::put(char const*keys, slen_t keylen, VALUE val) { + // param_assert(key[0]=='/'); + if (keys[0]=='/') { keys++; keylen--; } + //void MiniPS::Dict::put(VALUE key, VALUE val) { + //param_assert(MiniPS::getType(key)==T_ENAME); + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + if (MiniPS::RENAME(p[0]&~1)->equals(keys,keylen)) { + MiniPS::delete0(p[1]); + p[1]=val; + return; + } + p+=2; + } + if (len==alloced) extend(len+2); + ((VALUE*)ptr)[len++]=(MiniPS::VALUE)new Ename(keys,keylen); + ((VALUE*)ptr)[len++]=val; +} +MiniPS::VALUE MiniPS::Dict::get(char const*key, slen_t keylen) { + if (key[0]=='/') { key++; keylen--; } + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + //printf("for=%s trying=%s.\n", key, MiniPS::RENAME(p[0]&~1)->begin_()); + if (MiniPS::RENAME(p[0]&~1)->equals(key, keylen)) return p[1]; + p+=2; + } + return Qundef; +} +MiniPS::VALUE MiniPS::Dict::get1(char const*key, slen_t keylen) { + if (key[0]=='/') { key++; keylen--; } + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + //printf("for=%s trying=%s.\n", key, MiniPS::RENAME(p[0]&~1)->begin_()); + if (MiniPS::RENAME(p[0]&~1)->equals(key,keylen)) { + /* dirty, black magic */ p[0]|=1; + return p[1]; + } + p+=2; + } + return Qundef; +} +void MiniPS::Dict::untouch(char const*key, slen_t keylen) { + if (key[0]=='/') { key++; keylen--; } + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + if (MiniPS::RENAME(p[0]&~1)->equals(key,keylen)) { p[0]&=~1; return; } + p+=2; + } +} +void MiniPS::Dict::getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) { + // assert(MiniPS::getType(((VALUE*)ptr)[0])==T_ENAME); + if (len==0) { key=(char const*const*)NULLP; return; } + assert(ptr!=NULLP); + Ename *skey=(Ename*)(((VALUE*)ptr)[0]&~1); + key=(char**)&skey->ptr; + keylen=skey->len; + val=((VALUE*)ptr)+1; + touched=(((VALUE*)ptr)[0]&1)!=0; +} +void MiniPS::Dict::getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) { + val+=2; + if (len+(VALUE*)ptr==(VALUE*)val-1) { key=(char const*const*)NULLP; return; } + Ename *skey=RENAME(val[-1]&~1); + // assert(MiniPS::getType((VALUE)skey)==T_ENAME); + key=(char**)&skey->ptr; + keylen=skey->len; + touched=(val[-1]&1)!=0; +} + +#if 0 /* obsolete */ +void MiniPS::Dict::getFirst(VALUE *&key, VALUE *&val) { + if (len==0) { key=val=(VALUE*)NULLP; return; } + assert(ptr!=NULLP); + key=(VALUE*)ptr; + val=key+1; +} +void MiniPS::Dict::getNext(VALUE *&key, VALUE *&val) { + key+=2; + if (len+(VALUE*)ptr==key) key=val=(VALUE*)NULLP; + else val=key+1; +} +#endif + +void MiniPS::Dict::dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters) { + assert(len>=0 && (len&1)==0); + if (len==0) { + if (dump_delimiters) out_ << "<<>>"; + } else { + indent+=2; + char *spaces=new char[indent]; + memset(spaces, ' ', indent); + // spaces[indent]='\n'; + if (dump_delimiters) out_ << "<< % " << (len/2) << " key(s)\n"; + VALUE *p=(VALUE*)ptr, *pend=p+len; + while (p!=pend) { + out_.vi_write(spaces, indent); + MiniPS::dump(out_, *p++, indent); + out_ << " "; + MiniPS::dump(out_, *p++, indent); + /*if(p!=pend)*/ out_.vi_putcc('\n'); // out_ << "\n"; + } + if (dump_delimiters) { out_.vi_write(spaces, indent-=2); out_ << ">>"; } + } +} +void MiniPS::Dict::extend(ii_t newlen) { + if (newlen<=alloced) return; + ii_t newalloced=alloced; + assert(alloced>=0); + while (newlen>newalloced) newalloced<<=1; + VALUE *newptr=new VALUE[newalloced]; + memcpy(newptr, ptr, len*sizeof(VALUE)); + delete [] (VALUE*)ptr; + ptr=newptr; + alloced=newalloced; + /* len remains unchanged */ +} +#endif + +/* --- */ + +MiniPS::Parser::Parser(char const *filename_) { + FILE *ff; + ff=(filename_[0]=='-' && filename_[1]=='\0')? stdin: fopen(filename_, "r"); /* not "rb" */ + if (ff==NULLP) Error::sev(Error::EERROR) << "MiniPS::Parser: cannot open file: " << FNQ(filename_) << (Error*)0; + f=(FILEP)ff; + rd=new Files::FILER(ff); + tok=new Tokenizer(*rd); + master=(Parser*)NULLP; + free_level=4; + unread=Tokenizer::NO_UNGOT; + depth=0; + specRuns=(MiniPS::Dict*)NULLP; + specRunsDelete=false; +} +MiniPS::Parser::Parser(FILEP f_) { + f=f_; + rd=new Files::FILER(PTS_align_cast(FILE*,f_)); + tok=new Tokenizer(*rd); + master=(Parser*)NULLP; + free_level=3; + unread=Tokenizer::NO_UNGOT; + depth=0; + specRuns=(MiniPS::Dict*)NULLP; + specRunsDelete=false; +} +MiniPS::Parser::Parser(GenBuffer::Readable *rd_) { + f=(FILEP)NULLP; + rd=rd_; + tok=new Tokenizer(*rd); + master=(Parser*)NULLP; + free_level=2; + unread=Tokenizer::NO_UNGOT; + depth=0; + specRuns=(MiniPS::Dict*)NULLP; + specRunsDelete=false; +} +MiniPS::Parser::Parser(Tokenizer *tok_) { + master=(Parser*)NULLP; + f=(FILEP)NULLP; + rd=(GenBuffer::Readable*)NULLP; + tok=tok_; + master=(Parser*)NULLP; + free_level=0; + unread=Tokenizer::NO_UNGOT; + depth=0; + specRuns=(MiniPS::Dict*)NULLP; + specRunsDelete=false; +} +MiniPS::Parser::Parser(Parser *master_) { + f=(FILEP)NULLP; + rd=(GenBuffer::Readable*)NULLP; + tok=(Tokenizer*)NULLP; + master=master_; + free_level=1; + unread=Tokenizer::NO_UNGOT; + depth=0; + specRuns=(MiniPS::Dict*)NULLP; + specRunsDelete=false; +} +MiniPS::Parser::~Parser() { + /* We delete the master here! */ + if (master!=NULLP) delete master; /* recursive ~Parser() call */ + if (free_level>=2) delete tok; + if (free_level>=3) delete rd; + if (free_level>=4) fclose(PTS_align_cast(FILE*,f)); + if (specRunsDelete) delete0((VALUE)specRuns); +} +void MiniPS::Parser::addSpecRun(char const* filename_, GenBuffer::Readable *rd_) { + if (specRuns==NULLP) { + specRunsDelete=true; + specRuns=new MiniPS::Dict(); + } + specRuns->put(filename_, (MiniPS::VALUE)new MiniPS::Void(rd_)); +} +void MiniPS::Parser::setSpecRuns(MiniPS::Dict *newSpecRuns) { + if (newSpecRuns!=specRuns) { + if (specRunsDelete) delete0((VALUE)specRuns); + specRunsDelete=false; + specRuns=newSpecRuns; + } +} +void MiniPS::Parser::setDepth(unsigned depth_) { + if (depth_>=MAX_DEPTH) Error::sev(Error::EERROR) << "MiniPS::Parser: `run' inclusion too deep" << (Error*)0; + depth=depth_; +} +MiniPS::VALUE MiniPS::Parser::parse1(int closer, int sev) { + char *beg=0; slen_t len=0; /* pacify g++-2.91 */ + Real::metric_t metric; Real *r=0; /* pacify g++-2.91 */ + VALUE v, w; + if (master!=NULLP) { + from_master: + /* vvv EOF_ALLOWED means: the master cannot close our open '>' or ']' */ + if ((v=master->parse1(EOF_ALLOWED, sev))!=Qundef) return v; + delete master; + master=(Parser*)NULLP; + // fprintf(stderr, "closed master\n"); + } + // return parse1_real(closer); + + int i=0; + if (unread!=Tokenizer::NO_UNGOT) { + i=unread; + unread=Tokenizer::NO_UNGOT; + } else i=tok->yylex(); + + // fprintf(stderr, "i=%d i='%c'\n", i, i); + + switch (i) { + case Tokenizer::EOFF: case ']': case '>': + if (closer==i) return Qundef; /* EOF */ + Error::sev((Error::level_t)sev) << "MiniPS::Parser: premature EOF (early closer: " << (int)i << ')' << (Error*)0; + return Qerror; /* parse error */ + case '(': { + beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + VALUE v=(VALUE)new String(beg, len); /* Imp: resolve memory leak here */ + i=tok->yylex(); + beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + if (i!='E' || len!=3 || 0!=memcmp(beg,"run",3)) { unread=i; return v; } + /* Process external file inclusion */ + assert(master==NULLP); + /* Imp: prevent infinite recursion */ + if (specRuns!=NULLP && Qundef!=(w=specRuns->get(RSTRING(v)->begin_(), RSTRING(v)->getLength()))) + master=new Parser((GenBuffer::Readable*)RVOID(w)->getPtr()); + else master=new Parser(RSTRING(v)->getCstr()); + master->setDepth(depth+1); + master->setSpecRuns(specRuns); + goto from_master; + } + case '/': + beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + return (VALUE)new Sname(beg, len); + case ':': /* Real with metric */ + return (VALUE)tok->lastTokVal().r; + case '.': + // fprintf(stderr, "d=%g\n", tok->lastTokVal().d); + // fprintf(stderr, "b=(%s)\n", tok->lastTokVal().b()); + // assert(tok->lastTokVal().bb!=NULLP); + // beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + // r=new Real(tok->lastTokVal().d, beg, len); + r=tok->lastTokVal().r; + i=tok->yylex(); + beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + if (i!='E' || len!=2 || (metric=Real::str2metric(beg))==Real::ME_COUNT) { + unread=i; + } else { + r->setMetric(metric); + } + return (VALUE)r; + case '1': + i=tok->yylex(); + beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + if (i!='E' || len!=2 || (metric=Real::str2metric(beg))==Real::ME_COUNT) { + unread=i; + return Qinteger(tok->lastTokVal().i); + } else { /* integer with metric is auto-converted to Real */ + r=new Real(tok->lastTokVal().i, beg, len); + r->setMetric(metric); + } + return (VALUE)r; + case 'E': { + beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength(); + // fprintf(stderr, "L=%d\n", bb->getLength()); + // assert(0); + tok->lastTokVal().bb->term0(); + if (0==strcmp(beg,"true")) return Qtrue; + if (0==strcmp(beg,"false")) return Qfalse; + if (0==strcmp(beg,"null")) return Qnull; + if (closer==EOF_ILLEGAL_POP && 0==strcmp(beg,"pop")) return Qpop; + Error::sev((Error::level_t)sev) << "MiniPS::Parser: unknown Ename: " << (*tok->lastTokVal().bb) << (Error*)0; + return Qerror; + } + case '[': { + Array *ap=new Array(); + VALUE v; + while (Qundef!=(v=parse1(']', sev))) { if (v==Qerror) return Qerror; ap->push(v); } + return (VALUE)ap; + } + case '<': { + Dict *ap=new Dict(); + VALUE key, val; + while (1) { + if (Qundef==(key=parse1('>', sev))) break; + if (key==Qerror) return Qerror; + if (getType(key)!=T_SNAME) { + Error::sev(Error::EERROR) << "MiniPS::Parser: dict key must be a /name" << (Error*)0; + return Qerror; + } + val=parse1(EOF_ILLEGAL_POP, sev); /* No EOF allowed here */ + if (val==Qerror) return Qerror; + if (val!=Qpop) { + // if (Qundef!=ap->push(RSNAME(key)->begin_(),RSNAME(key)->getLength(),val)) Error::sev(Error::EERROR) << "MiniPS::Parser: duplicate dict key" << (Error*)0; + /* ^^^ should free if non-fatal error */ + if (Qundef!=(v=ap->push(RSNAME(key)->begin_(),RSNAME(key)->getLength(),val))) { + Error::sev(Error::WARNING) << "MiniPS::Parser: overriding previous dict key: " << RSNAME(key)->begin_() << (Error*)0; + MiniPS::delete0(v); + } + } + MiniPS::delete0(key); + } + return (VALUE)ap; + } + default: + assert(0); + } + return Qerror; /* NOTREACHED */ +} + +void MiniPS::scanf_dict(VALUE job, bool show_warnings, ...) { + va_list ap; + Dict *dict=RDICT(job); + char *key; + unsigned ty; + char hex3[3]; + VALUE default_, *dst, got; + if (getType(job)!=T_DICT) Error::sev(Error::EERROR) << "scanf_dict: dict expected" << (Error*)0; + PTS_va_start(ap, show_warnings); + // "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile, + // "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile, + // "Profile", MiniPS::T_ARRAY, MiniPS::Qundef, &Profiles, + // NULLP + while (NULLP!=(key=va_arg(ap, char*))) { + slen_t keylen=strlen(key); + if (*key=='/') key++; + ty=va_arg(ap, unsigned); + default_=va_arg(ap, VALUE); + dst=va_arg(ap, VALUE*); + got=(show_warnings) ? dict->get1(key,keylen) : dict->get(key,keylen); + if (got==Qundef) { + got = (ty==S_SENUM) ? RDICT(default_)->get(" ",1) /* get the default value */ + : (ty==S_FUNC) ? ((VALUE(*)(VALUE))default_)(Qundef) + : default_; + if (got==Qundef) Error::sev(Error::EERROR) << "scanf_dict: required key missing: /" << key << (Error*)0; + /* type of default value is unchecked deliberately */ + } else switch (ty) { + case S_RGBSTR: + /* Dat: red is: (\377\0\0), (#f00), (#ff0000) */ + if (getType(got)!=T_STRING || !( + RSTRING(got)->getLength()==3 /* Imp: `transparent -red' shouldn't work */ + || RSTRING(got)->getLength()==4 && RSTRING(got)->begin_()[0]=='#' && !toHex3(RSTRING(got)->begin_()+1, hex3) && (got=(VALUE)new String(hex3, 3), true) + || RSTRING(got)->getLength()==7 && RSTRING(got)->begin_()[0]=='#' && !toHex6(RSTRING(got)->begin_()+1, hex3) && (got=(VALUE)new String(hex3, 3), true) + || RSTRING(got)->getLength()==6 && !toHex6(RSTRING(got)->begin_(), hex3) && (got=(VALUE)new String(hex3, 3), true) + )) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be an RGB color triplet" << (Error*)0; + break; + case S_SENUM: + if (getType(got)!=T_SNAME) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be an enum value (name)" << (Error*)0; + got=RDICT(default_)->get(RSNAME(got)->begin_(),RSNAME(got)->getLength()); + if (got==Qundef) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be a valid enum value" << (Error*)0; + break; + case S_FUNC: + got=((VALUE(*)(VALUE))default_)(got); + if (got==Qundef) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " has invalid value" << (Error*)0; + break; + case S_UINTEGER: + if ((got&1)==0 || got<Qinteger(0)) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be a non-negative integer" << (Error*)0; + break; + case S_ANY: + break; + case S_PINTEGER: + if ((got&1)==0 || got<=Qinteger(0)) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be a positive integer" << (Error*)0; + break; + case S_NUMBER: + if ((got&1)==0 && getType(got)!=T_REAL) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be real or integer" << (Error*)0; + break; + case S_PNUMBER: + if ((got&1)==0 && getType(got)!=T_REAL) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be real or integer" << (Error*)0; + if ((got&1)!=0 && got<=Qinteger(0) + || getType(got)==T_REAL && RREAL(got)->getBp()<=0 + ) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be positive" << (Error*)0; + break; + default: + if (getType(got)!=ty) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must have type " << getTypeStr(ty) << (Error*)0; + } + *dst=got; + } + va_end(ap); + if (show_warnings) { + // VALUE *keyy, *val; + char const*const* keyy; slen_t keylen; VALUE *val; bool touched; + dict->getFirst(keyy, keylen, val, touched); + // fprintf(stderr, "> %p\n", keyy); + PTS_va_start(ap, show_warnings); + while (keyy!=(char const*const*)NULLP) { + // fprintf(stderr, "untouch len=%u\n", keylen); + // fprintf(stderr, "untouching key=(%s)\n", *keyy); + if (!touched) Error::sev(Error::WARNING) << "scanf_dict: ignoring unknown key /" << SimBuffer::Static(*keyy,keylen) << (Error*)0; + else dict->untouch(*keyy, keylen); /* undo get1 */ + dict->getNext(keyy, keylen, val, touched); + } + va_end(ap); + } +} + +void MiniPS::setDumpPS(MiniPS::VALUE v, bool g) { + /* Sat Sep 7 13:18:35 CEST 2002 */ + if (getType(v)==T_REAL) RREAL(v)->setDumpPS(g); +} + +bool MiniPS::isZero(MiniPS::VALUE v) { + /* Sat Sep 7 15:12:54 CEST 2002 */ + switch (getType(v)) { + case T_REAL: return RREAL(v)->getBp()==0; + case T_INTEGER: return int2ii(v)==0; + } + Error::sev(Error::EERROR) << "isZero: number expected" << (Error*)0; + return false; /* NOTREACHED */ +} + +bool MiniPS::isEq(MiniPS::VALUE v, double d) { + double dif=0; + switch (getType(v)) { + case T_REAL: dif=RREAL(v)->getBp()-d; break; + case T_INTEGER: dif=int2ii(v)-d; break; + default: Error::sev(Error::EERROR) << "isEq: number expected" << (Error*)0; + } + if (dif<0.0) dif=-dif; + /* fprintf(stderr,"dif=%g g=%d\n", dif, (dif<0.000001)); */ + return (dif<0.000001); /* Imp: ... */ +} + +void MiniPS::dumpScale(GenBuffer::Writable &out, VALUE v) { + double d=0; + switch (getType(v)) { + case T_REAL: d=RREAL(v)->getBp(); break; + case T_INTEGER: + if (int2ii(v)%72==0) { out << (int2ii(v)/72); return; } + d=int2ii(v); break; + default: Error::sev(Error::EERROR) << "dumpScale: number expected" << (Error*)0; + } + char buf[64]; /* Dat: enough */ + sprintf(buf, "%"PTS_CFG_PRINTFGLEN"g", d/72.0); + out << buf; +} + +void MiniPS::dumpAdd3(GenBuffer::Writable &out, MiniPS::VALUE m, MiniPS::VALUE a, MiniPS::VALUE b, MiniPS::VALUE c, MiniPS::VALUE sub, unsigned rounding) { + long ll; + #if 1 + /* Sat Sep 7 15:30:28 CEST 2002 */ + bool no_real_real=true; + double d=0, dd; + long l=0; + if (getType(m)==T_REAL && isEq(m,72)) /* Imp: not so exact comparison */ + m=Qinteger(72); + MiniPS::VALUE t[5], *tt; + t[0]=a; t[1]=m; t[2]=b; t[3]=c; t[4]=sub; + for (tt=t;tt<t+5;tt++) switch (getType(*tt)) { + case T_REAL: + dd=RREAL(*tt)->getBp(); + doadd: + if (no_real_real) { + d=l; + no_real_real=false; + } + if (tt==t+1) { + if (dd==0.0 || d==0.0) { no_real_real=true; l=0; d=0.0; } + else d*=dd/72; + } else if (tt==t+4) d-=dd; + else d+=dd; + break; + case T_INTEGER: + ll=int2ii(*tt); + if (tt==t+1) { + if (ll%72==0) l*=ll/72; + else { dd=ll; goto doadd; } + } else if (tt==t+4) l-=ll; + else l+=ll; + break; + default: Error::sev(Error::EERROR) << "dumpAdd3: numbers expected" << (Error*)0; + } + if (no_real_real) { out << l; return; } + #else + /* Sat Sep 7 15:16:12 CEST 2002 */ + ... + #endif + if (rounding!=0) { + ll=(long)d; + if ((double)ll<d) ll++; + assert((double)ll>=d); /* Imp: verify possible rounding errors */ + out << (rounding>=2 && ll<0 ? 0 : ll); + } else { + char buf[64]; /* Dat: enough */ + sprintf(buf, "%"PTS_CFG_PRINTFGLEN"g", d); + out << buf; + } +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/minips.hpp b/Build/source/utils/sam2p/minips.hpp new file mode 100644 index 00000000000..a833f28bd26 --- /dev/null +++ b/Build/source/utils/sam2p/minips.hpp @@ -0,0 +1,327 @@ +/* minips.hpp -- mini-PostScript parser and structure builder + * by pts@fazekas.hu at Sat Mar 9 21:33:04 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef MINIPS_HPP +#define MINIPS_HPP 1 + +#include "config2.h" +#include "gensi.hpp" +#include "error.hpp" + +class MiniPS { + public: + #if SIZEOF_VOID_P <= SIZEOF_INT + typedef signed int ii_t; + #elif SIZEOF_VOID_P <= SIZEOF_LONG + typedef signed long ii_t; + #elif SIZEOF_VOID_P <= SIZEOF_CFG_LONGEST + typedef signed PTS_CFG_LONGEST ii_t; + #else + #error No integral data type to hold a ptr. + #endif + + class Real; + + /*union*/ struct TokVal { + SimBuffer::B *bb; + ii_t i; + /* double d; */ + /*MiniPS::*/Real *r; + }; + /** minips tokenizer */ + class Tokenizer { + public: + BEGIN_STATIC_ENUM1(int) EOFF=-1, NO_UNGOT=-2 END_STATIC_ENUM() + Tokenizer(GenBuffer::Readable& in_); + /** Reads and returns next token. + * Token types are named for their first character: + * '1': integertype: 31 bits signed (-1073741824 .. 1073741823) is + * guaranteed. VALUED + * '.': realtype (NOT implemented), double guaranteed. VALUED + * 'E': Ename (name without a slash). VALUED + * '/': Sname (name beginning with a slash). VALUED + * '(': stringtype (also with `<hexadecimal>') VALUED + * '[': beginning-of-array (also with `{') + * ']': end-of-array (also with '}') + * '<': beginning-of-dict (`<<') + * '>': end-of-dict (`>>') + * -1: EOF + */ + int yylex(); + inline TokVal const& lastTokVal() const { return tv; } + protected: + /** Data for last token read. */ + TokVal tv; + SimBuffer::B b; + GenBuffer::Readable& in; + /* NO_UNGOT for nothing, EOFF for EOF, 0..255 otherwise */ + int ungot; + }; + + /* This is somewhat similar to Ruby */ + typedef ii_t VALUE; + /** Qundef is the undefined hash key or array elements. It is an _invalid_ VALUE! */ + BEGIN_STATIC_ENUM1(VALUE) Qfalse=0, Qtrue=2, Qnull=4, Qundef=6, Qpop=8, Qerror=10, Qmax_=10 END_STATIC_ENUM() + + BEGIN_STATIC_ENUM1(unsigned) T_NULL=1, T_BOOLEAN=2, T_INTEGER=3, T_REAL=4, + T_STRING=5, T_ARRAY=6, T_DICT=7, T_SNAME=8, T_ENAME=9, T_VOID=10, + S_SENUM=20, /* must be a dict-member; meta-type used by scanf_dict() */ + S_FUNC=21, /* call a function to determine; meta-type used by scanf_dict() */ + S_UINTEGER=22, /* non-negative integer; meta-type used by scanf_dict() */ + S_ANY=23, /* anything; meta-type used by scanf_dict() */ + S_PINTEGER=24, /* positive integer; meta-type used by scanf_dict() */ + S_RGBSTR=25, /* an optional 3-byte string, representing an RGB color triplet */ + S_NUMBER=26, /* real or integer */ + S_PNUMBER=27 /* positive real or integer */ + END_STATIC_ENUM() + + /** No virtual methods because of special types. MiniPS composite values + * really _contain_ their components; one Value has exactly one reference: + * its container component. + */ + class Value { public: + inline ii_t getLength() const { return len; } + inline ii_t getType() const { return ty; } + inline bool hasPtr() const { return ptr!=NULLP; } + inline bool isDumping() const { return dumping; } + inline char const* getCstr() const { return (char const*)ptr; } + inline char* begin_() const { return (char*)ptr; } + inline char const* operator()() const { return (char const*)ptr; } + protected: + ii_t len; void *ptr; unsigned char ty; bool dumping; + }; + /** ptr contains a `void*'. Won't be freed. */ + class Void: public Value { public: + inline Void(void *ptr_) { ptr=ptr_; ty=T_VOID; } + inline void *getPtr() const { return ptr; } + }; + /** Always null-terminated. */ + class String: public Value { public: + /** Copies from ptr_ */ + String(char const*ptr_, ii_t len_); + /** Replaces (this) with a copy of (a).(b) */ + void replace(char const*ap, slen_t alen, char const*bp, slen_t blen); + }; + class Sname: public Value { public: + /** ptr_ must begin with '/' */ + Sname(char const*ptr_, ii_t len_); + bool equals(Sname const&other); + bool equals(char const*other); + }; + class Ename: public Value { public: + Ename(char const*ptr_, ii_t len_); + bool equals(Ename const&other); + bool equals(char const*other); + bool equals(char const*other, slen_t otherlen); + }; + class Real: public Value { public: + typedef unsigned char metric_t; + inline Real(double d_): d(d_), metric(0), dumpPS(false) { ty=T_REAL; ptr=(char*)NULLP; } + /** Also supply a string representation of the value (to avoid possible + * loss of precision when converting string -> double -> string). + */ + Real(double d_, char const*ptr_, ii_t len_); + // inline bool isZero() const { return d==0.0; } + inline double getBp() const { return d*me_factor[metric]; } + inline void setDumpPS(bool g) { dumpPS=g; } + inline void setMetric(metric_t metric_) { metric=metric_; } + /** Return true iff the specified null-terminated string is a valid + * dimen. + */ + static bool isDimen(char const *); + void dump(GenBuffer::Writable &out_, bool dumpPS_force=false); + /** @return ME_count on invalid */ + static metric_t str2metric(char const str[2]); + BEGIN_STATIC_ENUM1(metric_t) + ME_bp=0, /* 1 bp = 1 bp (big point) */ + ME_in=1, /* 1 in = 72 bp (inch) */ + ME_pt=2, /* 1 pt = 72/72.27 bp (point) */ + ME_pc=3, /* 1 pc = 12*72/72.27 bp (pica) */ + ME_dd=4, /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */ + ME_cc=5, /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */ + ME_sp=6, /* 1 sp = 72/72.27/65536 bp (scaled point) */ + ME_cm=7, /* 1 cm = 72/2.54 bp (centimeter) */ + ME_mm=8, /* 1 mm = 7.2/2.54 bp (millimeter) */ + ME_COUNT=9 + END_STATIC_ENUM() + protected: + double d; + /* vvv metric added at Sat Sep 7 12:26:08 CEST 2002 */ + metric_t metric; + /** Allow PostScript operators such as `div' to appear in the dump */ + bool dumpPS; + /** Factor to convert to bp */ + static const double me_factor[ME_COUNT]; + /** PostScript code to do multiplication by me_factor */ + static char const* const me_psfactor[ME_COUNT]; + }; + class Array: public Value { public: + Array(); + void free(); + void dump(GenBuffer::Writable &out_, unsigned indent); + void push(VALUE v); + VALUE get(ii_t index); + /** Cannot extend. Calls delete0() when overwriting an element */ + void set(ii_t index, VALUE val); + /** val: out */ + void getFirst(VALUE *&val); + /** val: in_out */ + void getNext(VALUE *&val); + protected: + ii_t alloced; + void extend(ii_t newlen); + }; + /** Keys must be Snames here! (i.e no integer keys allowed). The current + * implementation does a linear string search :-(. Dat: might not work + * on extremely long keys if slen_t can hold a larger integer than + * ii_t. + */ + class Dict: public Value { public: + Dict(); + void free(); + void dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters=true); + /** @return val or Qundef */ + VALUE get(char const*key, slen_t keylen); + /** A hack: get and touch. */ + VALUE get1(char const*key, slen_t keylen); + void untouch(char const*key, slen_t keylen); + /** Can extend. */ + void put(char const*key, VALUE val); + /** Calls delete0() when overwriting an element */ + void put(char const*key, slen_t keylen, VALUE val); + /** @return old value for key `key', or Qundef */ + VALUE push(char const*key, slen_t keylen, VALUE val); + /** key: out, val: out */ + void getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched); + /** key: in_out, val: in_out */ + void getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched); + // void getFirst(VALUE *&key, VALUE *&val); + // void getNext(VALUE *&key, VALUE *&val); + protected: + ii_t alloced; + void extend(ii_t newlen); + }; + + static inline Value* RVALUE(VALUE v) { return static_cast<Value*>((void*)v); } + static inline Void* RVOID(VALUE v) { return static_cast<Void*>((void*)v); } + static inline Array* RARRAY(VALUE v) { return static_cast<Array*>((void*)v); } + static inline String* RSTRING(VALUE v){ return static_cast<String*>((void*)v); } + static inline Dict* RDICT(VALUE v) { return static_cast<Dict*>((void*)v); } + static inline Real* RREAL(VALUE v) { return static_cast<Real*>((void*)v); } + static inline Sname* RSNAME(VALUE v) { return static_cast<Sname*>((void*)v); } + static inline Ename* RENAME(VALUE v) { return static_cast<Ename*>((void*)v); } + static inline bool isDirect(VALUE v) { return (v&1)!=0 || v<=Qmax_; } + /** T_NULL .. T_DICT */ + static unsigned getType(VALUE v); + /** "null" .. "dict", "name" (T_SNAME), "ename" (T_ENAME, non-std-PS) */ + static char const* getTypeStr(unsigned u); + static void delete0(VALUE v); + /** The current implementation dumps dict keys in order of insertion, but + * this is very likely to change soon to an _arbitrary_ order. + */ + static void dump(GenBuffer::Writable& out_, VALUE v, unsigned indent=0); + static void dump(VALUE v, unsigned indent=0); + static inline VALUE Qinteger(ii_t v) { return (v<<1)+1; } + static inline ii_t int2ii(VALUE v) { return v>>1; } + /** Fortunate coincidence that 2x+1>0 <=> x>0 */ + static inline bool isPositive(VALUE v) { return v>0; } + static inline VALUE undef2null(VALUE v) { return v==Qundef ? Qnull : v; } + // static SimBuffer::B scale72(VALUE v, double d); + + class Parser { + /** Define this to avoid including <stdio.h> */ + typedef class _anon_filet_ {} *FILEP; + public: + BEGIN_STATIC_ENUM1(int) EOF_ALLOWED=Tokenizer::EOFF, EOF_ILLEGAL=-2, EOF_ILLEGAL_POP=-3 END_STATIC_ENUM() + /** Maximum depth of `run' file inclusions. */ + BEGIN_STATIC_ENUM1(unsigned) MAX_DEPTH=17 END_STATIC_ENUM() + Parser(char const *filename_); + /** The caller is responsible for closing the FILE* */ + Parser(FILEP f_); + Parser(GenBuffer::Readable *rd_); + Parser(Tokenizer *tok_); + ~Parser(); + /** Allocates and returns. Qundef is returned on EOF + * @param closer: EOF_ILLEGAL, EOF_ALLOWED, '>' or ']' + */ + VALUE parse1(int closer=EOF_ILLEGAL, int sev=Error::EERROR); + void setDepth(unsigned depth_); + /** Sets special filename for the `run' operator. `run' will read that + * special file from param `rd_', and then it will call rd_->vi_rewind(). + * Example usage: .addSpecRun("%stdin", new Files::FileR(stdin)); + */ + void addSpecRun(char const* filename_, GenBuffer::Readable *rd_); + /*MiniPS::*/Dict *getSpecRuns() const { return specRuns; } + /** Does not copy the dict, but sets the pointer. */ + void setSpecRuns(/*MiniPS::*/Dict *); + protected: + Parser(Parser *master_); + // VALUE parse1_real(int closer); + /* 0=nothing, 1=master 2=tok, 3=tok+rd, 4=tok+rd+f */ + unsigned free_level; + Parser *master; + Tokenizer *tok; + GenBuffer::Readable *rd; + FILEP f; + int unread; + unsigned depth; + /*MiniPS::*/Dict *specRuns; + /** Should MiniPS::delete0() be called on specRuns upon destruction of + * (this)? + */ + bool specRunsDelete; + }; + + /** Assumes that param `job' is a dict, extracts its elements into ..., + * emits errors for elements (not found and having default==Qundef), emits + * warnings for elements found in `job', but undescribed in `...' (only + * if show_warnings==true). Example: + * + * MiniPS::scanf_dict(job, true, + * "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile, + * "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile, + * "Profiles", MiniPS::T_ARRAY, MiniPS::Qundef, &Profiles + * NULLP + * ); + */ + static void scanf_dict(VALUE job, bool show_warnings, ...); + static void setDumpPS(VALUE v, bool g); + /** @param v must be T_REAL or T_INTEGER */ + static bool isZero(VALUE v); + /** @param v must be T_REAL or T_INTEGER + * @return true iff v==i + */ + static bool isEq(VALUE v, double d); + /** Dumps the human-readable real or integer value of the sum (m/72)*a+b+c-sub + * to `out'. + * @param rounding 0: nothing. 1: round the sum _up_ to integers. 2: + * round the sum _up_ to non-negative integers + * @param a must be T_REAL or T_INTEGER + * @param b must be T_REAL or T_INTEGER + * @param c must be T_REAL or T_INTEGER + * @param sub must be T_REAL or T_INTEGER + */ + static void dumpAdd3(GenBuffer::Writable &out, VALUE m, VALUE a, VALUE b, VALUE c, VALUE sub, unsigned rounding=0); + static void dumpScale(GenBuffer::Writable &out, VALUE v); +}; + +/* Fri Aug 16 17:07:14 CEST 2002 */ +#if 0 /* doesn't work because MiniPS::VALUE is really an `int', so there will be an ambiguous overload */ +inline GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::VALUE v) { + MiniPS::dump(out_, v); + return out_; +} +#endif +inline GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::Value *v) { + MiniPS::dump(out_, (MiniPS::VALUE)v); + return out_; +} + +// GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::Value *v) { + +#endif diff --git a/Build/source/utils/sam2p/mkdist.sh b/Build/source/utils/sam2p/mkdist.sh new file mode 100644 index 00000000000..acce18e4395 --- /dev/null +++ b/Build/source/utils/sam2p/mkdist.sh @@ -0,0 +1,59 @@ +#! /bin/bash -- +# +# mkdist.sh by pts@fazekas.hu at Wed Mar 6 09:09:01 CET 2002 +# added debian/changelog support at Fri Mar 5 19:37:45 CET 2004 +# based on mkdist.sh of autotrace +# +# + +if [ -f debian/changelog ]; then :; else + echo "$0: missing: debian/changelog" >&2 + exit 2 +fi +if [ -f files ]; then :; else + echo "$0: missing: files" >&2 + exit 3 +fi +PRO_VER="`<debian/changelog perl -ne 'print"$1-$2"if/^(\S+) +[(]([-.\w]+?)(?:-\d+)?[)] +\w+;/;last'`" +if [ "$PRO_VER" ]; then :; else + echo "$0: couldn't determine version from debian/changelog" >&2 + exit 4 +fi +if [ -e "$PRO_VER" ]; then + echo "$0: $PRO_VER already exists, remove it first" >&2 + exit 5 +fi + +if [ $# -gt 0 ]; then + TGZ_NAME="$1.tar.gz"; shift +else + TGZ_NAME="$PRO_VER.tar.gz" +fi + +set -e # exit on error +rm -f "../$TGZ_NAME" +mkdir "$PRO_VER" +echo "$PRO_VER" +(IFS=' +'; exec tar -c -- `cat files` "$@") | +(cd "$PRO_VER" && exec tar -xv) +# ^^^ tar(1) magically calls mkdir(2) etc. + +# vvv Dat: don't include sam2p-.../ in the filenames of the .tar.gz +#(IFS=' +#'; cd "$PRO_VER" && exec tar -czf "../../$TGZ_NAME" -- `cat ../files` "$@") + +# vvv Dat: do include sam2p-.../ in the filenames of the .tar.gz +(IFS=' +'; export PRO_VER; exec tar -czf "../$TGZ_NAME" -- `perl -pe '$_="$ENV{PRO_VER}/$_"' files` "$@") + +rm -rf "$PRO_VER" +set +e + +if [ -s "../$TGZ_NAME" ]; then :; else + echo "$0: failed to create dist: ../$TGZ_NAME" >&2 + exit 6 +fi +(cd ..; echo "Created dist: `pwd`/$TGZ_NAME" >&2) + +# __EOF__ diff --git a/Build/source/utils/sam2p/out_gif.cpp b/Build/source/utils/sam2p/out_gif.cpp new file mode 100644 index 00000000000..50899feb100 --- /dev/null +++ b/Build/source/utils/sam2p/out_gif.cpp @@ -0,0 +1,341 @@ +/* out_gif.cpp + * by pts@fazekas.hu at Sat Mar 23 11:02:36 CET 2002 + */ + +#include "image.hpp" + +#if USE_OUT_GIF +#include <string.h> +#include <stdio.h> + +/**** pts ****/ +#ifdef __cplusplus +# define AALLOC(var,len,itemtype) var=new itemtype[len] +# define AFREE(expr) delete [] (expr) +#else +# include <stdlib.h> /* malloc(), free() */ +# define AALLOC(var,len,itemtype) var=(itemtype*)malloc(len*sizeof(itemtype)); +# define AFREE(expr) free((expr)) +#endif +#define HasLZW HAVE_LZW /* Imp: or USE_BUILTIN_LZW? */ +#define True true +#define False false + +/* The code of GIFEncodeImage is based on an early version of ImageMagick. */ +static unsigned int GIFEncodeImage(GenBuffer::Writable& out, char const*ppbeg, register char const*ppend, const unsigned int data_size) +{ +#define MaxCode(number_bits) ((1 << (number_bits))-1) +#define MaxHashTable 5003 +#define MaxGIFBits 12 +#if defined(HasLZW) +#define MaxGIFTable (1 << MaxGIFBits) +#else +#define MaxGIFTable max_code +#endif +#define GIFOutputCode(code) \ +{ \ + /* \ + Emit a code. \ + */ \ + if (bits > 0) \ + datum|=((long) code << bits); \ + else \ + datum=(long) code; \ + bits+=number_bits; \ + while (bits >= 8) \ + { \ + /* \ + Add a character to current packet. \ + */ \ + packet[byte_count++]=(unsigned char) (datum & 0xff); \ + if (byte_count >= 254) \ + { \ + packet[-1]=byte_count; \ + out.vi_write((char*)packet-1, byte_count+1); \ + byte_count=0; \ + } \ + datum>>=8; \ + bits-=8; \ + } \ + if (free_code > max_code) \ + { \ + number_bits++; \ + if (number_bits == MaxGIFBits) \ + max_code=MaxGIFTable; \ + else \ + max_code=MaxCode(number_bits); \ + } \ +} + + int + bits, + byte_count, + i, + next_pixel, + number_bits; + + long + datum; + + register int + displacement, + k; + + register char const*pp; + + short + clear_code, + end_of_information_code, + free_code, + *hash_code, + *hash_prefix, + index, + max_code, + waiting_code; + + unsigned char + *packet, + *hash_suffix; + + /* + Allocate encoder tables. + */ + AALLOC(packet,257,unsigned char); + AALLOC(hash_code,MaxHashTable,short); + AALLOC(hash_prefix,MaxHashTable,short); + AALLOC(hash_suffix,MaxHashTable,unsigned char); + if ((packet == (unsigned char *) NULL) || (hash_code == (short *) NULL) || + (hash_prefix == (short *) NULL) || + (hash_suffix == (unsigned char *) NULL)) + return(False); + packet++; + /* Now: packet-1 == place for byte_count */ + /* + Initialize GIF encoder. + */ + number_bits=data_size; + max_code=MaxCode(number_bits); + clear_code=((short) 1 << (data_size-1)); + end_of_information_code=clear_code+1; + free_code=clear_code+2; + byte_count=0; + datum=0; + bits=0; + for (i=0; i < MaxHashTable; i++) + hash_code[i]=0; + GIFOutputCode(clear_code); + /* + Encode pixels. + */ + /**** pts ****/ + pp=ppbeg; + waiting_code=*(unsigned char const*)pp++; /* unsigned char BUGFIX at Sun Dec 8 13:17:00 CET 2002 */ + + while (pp!=ppend) { + /* + Probe hash table. + */ + index=*(unsigned char const*)pp++; + k=(int) ((int) index << (MaxGIFBits-8))+waiting_code; + if (k >= MaxHashTable) + k-=MaxHashTable; +#if defined(HasLZW) + if (hash_code[k] > 0) + { + if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == index)) + { + waiting_code=hash_code[k]; + continue; + } + if (k == 0) + displacement=1; + else + displacement=MaxHashTable-k; + next_pixel=False; + for ( ; ; ) + { + k-=displacement; + if (k < 0) + k+=MaxHashTable; + if (hash_code[k] == 0) + break; + if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == index)) + { + waiting_code=hash_code[k]; + next_pixel=True; + break; + } + } + if (next_pixel != False) /* pacify VC6.0 */ + continue; + } +#endif + GIFOutputCode(waiting_code); + // printf("wc=%u\n", waiting_code); + if (free_code < MaxGIFTable) + { + hash_code[k]=free_code++; + hash_prefix[k]=waiting_code; + hash_suffix[k]=index; + } + else + { + /* + Fill the hash table with empty entries. + */ + for (k=0; k < MaxHashTable; k++) + hash_code[k]=0; + /* + Reset compressor and issue a clear code. + */ + free_code=clear_code+2; + GIFOutputCode(clear_code); + number_bits=data_size; + max_code=MaxCode(number_bits); + } + waiting_code=index; +#if 0 /**** pts ****/ + if (QuantumTick(i,image) && (image->previous == (Image2 *) NULL)) + ProgressMonitor(SaveImageText,i,image->packets); +#endif + } + /* + Flush out the buffered code. + */ + GIFOutputCode(waiting_code); + GIFOutputCode(end_of_information_code); + if (bits > 0) + { + /* + Add a character to current packet. + */ + packet[byte_count++]=(unsigned char) (datum & 0xff); + if (byte_count >= 254) + { + packet[-1]=byte_count; + out.vi_write((char*)packet-1, byte_count+1); + byte_count=0; + } + } + /* + Flush accumulated data. + */ + if (byte_count > 0) + { + packet[-1]=byte_count; + out.vi_write((char*)packet-1, byte_count+1); + } + /* + Free encoder memory. + */ + AFREE(hash_suffix); + AFREE(hash_prefix); + AFREE(hash_code); + AFREE(packet-1); + return pp==ppend; +} + +/** This isn't a complete GIF writer. For example, it doesn't support + * animation or multiple sub-images. But it supports transparency and + * compression. Only works when . The user should call + * packPal() first to ensure img->getBpc()==8, and to get a minimal palette. + */ +void out_gif_write(GenBuffer::Writable& out, Image::Indexed *img) { + /* Tested and proven to work at Sat Mar 23 13:11:41 CET 2002 */ + unsigned i, c, bits_per_pixel; + signed transp; + char hd[19]; + + assert(img->getBpc()==8); /* 1 palette entry == 8 bits */ + + transp=img->getTransp(); + memcpy(hd, transp!=-1 ? "GIF89a" : "GIF87a", 6); + i=img->getWd(); hd[6]=i; hd[7]=i>>8; + i=img->getHt(); hd[8]=i; hd[9]=i>>8; + + // transp=-1; /* With this, transparency will be ignored */ + c=img->getNcols(); + bits_per_pixel=1; while (((c-1)>>bits_per_pixel)!=0) bits_per_pixel++; + /* ^^^ (c-1) BUGFIX at Mon Oct 20 15:18:24 CEST 2003 */ + /* 63 -> 6, 64 -> 6, 65 -> 7 */ + // if (bits_per_pixel>1) bits_per_pixel--; /* BUGFIX at Wed Apr 30 15:55:27 CEST 2003 */ /* BUGFIX at Mon Oct 20 15:18:14 CEST 2003 */ + // fprintf(stderr, "GIF89 write transp=%d ncols=%d bpp=%d\n", transp, c, bits_per_pixel); + assert(1<=bits_per_pixel && bits_per_pixel<=8); + c=3*((1<<bits_per_pixel)-c); + /* Now: c is the number of padding bytes */ + + hd[10]= 0x80 /* have global colormap */ + | ((8-1) << 4) /* color resolution: bpc==8 */ + | (bits_per_pixel-1); /* size of global colormap */ + hd[11]=0; /* background color: currently unused */ + hd[12]=0; /* reversed */ + out.vi_write(hd, 13); + + // out.vi_write("\xFF\x00\x00" "\x00\xFF\x00" "\x00\x00\xFF", 9); + + out.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); /* write colormap */ + if (c!=0) { + char *padding=new char[(unsigned char)c]; /* BUGFIX at Fri Oct 17 18:05:09 CEST 2003 */ + memset(padding, '\0', (unsigned char)c); /* Not automatic! */ + out.vi_write(padding, (unsigned char)c); + delete [] padding; + } + + if (transp!=-1) { + /* Write Graphics Control extension. Only GIF89a */ + hd[0]=0x21; hd[1]=(char)0xf9; hd[2]=0x04; + hd[3]=transp!=-1; /* dispose==0 */ + hd[4]=hd[5]=0; /* delay==0 */ + hd[6]=transp; /* transparent color index -- or 255 */ + hd[7]=0; + out.vi_write(hd, 8); + } + + /* Write image header */ + hd[8]=','; + hd[ 9]=hd[10]=0; /* left */ + hd[11]=hd[12]=0; /* top */ + i=img->getWd(); hd[13]=i; hd[14]=i>>8; + i=img->getHt(); hd[15]=i; hd[16]=i>>8; + hd[17]=0; /* no interlace, no local colormap, no bits in local colormap */ + + if ((c=bits_per_pixel)<2) c=4; + hd[18]=c; /* compression bits_per_pixel */ + out.vi_write(hd+8, 11); + +#if 0 + printf("GIFEncodeImage out r r+%u %u; off=%u\n", img->getRlen()*img->getHt(), c+1, img->getRowbeg()-img->getHeadp()); + FILE *f=fopen("tjo.dat","wb"); + fprintf(f, "P6 %u %u 255\n", img->getWd(), img->getHt()); + // fwrite(img->getRowbeg(), 1, img->getRlen()*img->getHt(), f); + for (unsigned u=0; u<img->getRlen()*img->getHt(); u++) { + char *p=img->getHeadp()+3* *(unsigned char*)(img->getRowbeg()+u); + putc(p[0],f); + putc(p[1],f); + putc(p[2],f); + } +#endif + + i=GIFEncodeImage(out, img->getRowbeg(), img->getRowbeg()+img->getRlen()*img->getHt(), c+1); +#if 0 + { char buf[500000]; + FILE *f=fopen("tjo.dat","rb"); + int got=fread(buf, 1, sizeof(buf), f); + assert(got==486109); + assert(got==img->getRlen()*img->getHt()); + i=GIFEncodeImage(out, buf, buf+img->getRlen()*img->getHt(), c+1); + } +#endif + assert(i!=0); + + /* Write trailer */ + hd[0]=0; hd[1]=';'; + out.vi_write(hd, 2); +} +#else +#include <stdlib.h> +void out_gif_write(GenBuffer::Writable&, Image::Indexed *) { + assert(0); + abort(); +} +#endif diff --git a/Build/source/utils/sam2p/ps_tiny.c b/Build/source/utils/sam2p/ps_tiny.c new file mode 100644 index 00000000000..9e0b0acadc8 --- /dev/null +++ b/Build/source/utils/sam2p/ps_tiny.c @@ -0,0 +1,873 @@ +#define DUMMY \ +set -ex; \ +gcc -O3 -s -DNDEBUG=1 -DNO_CONFIG=1 -ansi -pedantic -Wunused \ + -Wall -W -Wstrict-prototypes -Wtraditional -Wnested-externs -Winline \ + -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wmissing-prototypes \ + -Wmissing-declarations ps_tiny.c -o ps_tiny; \ +exit +/* ps_tiny.c -- read .pin files, write short PostScript code + * by pts@fazekas.hu at Sat Aug 24 12:46:14 CEST 2002 + * -- Sat Aug 24 18:23:08 CEST 2002 + * -- Sat Aug 24 23:47:02 CEST 2002 + * -- Mon Sep 2 11:28:19 CEST 2002 + * %<B added -- Thu Sep 19 09:23:00 CEST 2002 + * v0.02 WORKS for flatedecode.psm -- Sun Sep 22 00:39:54 CEST 2002 + * DEVEL + */ + +/* + * Imp: extensive documentation + * Imp: verify acount + xcount + * Imp: uncompressed méretellenõrzés + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> /* exit() */ + +#if NO_CONFIG + #include <assert.h> + #if SIZEOF_INT>=4 + typedef unsigned slen_t; + typedef int slendiff_t; + # define SLEN_P "" + #else + typedef unsigned long slen_t; + typedef long slendiff_t; + # define SLEN_P "l" + #endif + typedef char sbool; + #if ';'!=59 || 'a'!=97 + # error ASCII system is required to compile this program + #endif +#else + #include "config2.h" /* by sam2p... */ + typedef bool sbool; +#endif +#if OBJDEP +# warning PROVIDES: ps_tiny_main +#endif + +#define ULE(a,b) (((a)+0U)<=((b)+0U)) +#define ISWSPACE(i,j) ((i j)==32 || ULE(i-9,13-9) || i==0) + +#define PROGNAME "ps_tiny" +#define VERSION "0.02" + +/* --- Data */ + +#define SBUFSIZE 4096 + +/** Data area holding strings; */ +char sbuf[SBUFSIZE], *sbufb; + +#define WORDSSIZE 127 + +/** Pointers inside sbuf, indexed by chars, [0..31] are special */ +char const* words[WORDSSIZE]; + +static void sbuff(void) { + unsigned i; + sbuf[0]='\0'; + sbufb=sbuf+1; + for (i=0;i<WORDSSIZE;i++) words[i]=sbuf; +} + +/** @return -1 or the word found */ +static int findword(char const*word) { + unsigned i=32; + while (i<WORDSSIZE && 0!=strcmp(word,words[i])) i++; + return i==WORDSSIZE ? -1 : (int)i; +} + +/** @return -1 or the word found */ +static int findword_stripslash(char const*word) { + unsigned i=32; + assert(word[0]!='/'); + while (i<WORDSSIZE && 0!=strcmp(word,words[i]+(words[i][0]=='/'))) i++; + return i==WORDSSIZE ? -1 : (int)i; +} + +/* --- Reading */ + +/** Current byte offset in input. (from 0) */ +slen_t curofs; + +/** Current line in input. (from 1) */ +slen_t curline; + +/** Offset of the leftmost char of current line in input. (from 0) */ +slen_t leftofs; + +/** Current position in input override format string */ +char const* ifmt; + +/** Input override string list */ +char const* const* ilist; + +/** Current position in current item of ilist */ +char const* iitem; + +/** Char unget */ +int ilast; + +static void rewindd(void) { ifmt=0; curofs=leftofs=0; curline=1; } + +static void setifmt(char const *ifmt_, char const* const* ilist_) { + ifmt=ifmt_; + ilist=ilist_; + iitem=""; + ilast=-1; +} + +static void noifmt(void) { ifmt=0; } + +static int getcc(void) { + int c; + if (ifmt!=0) { + nextitem: + if (ilast>=0) { c=ilast; ilast=-1; } + else if (iitem[0]!='\0') c=*iitem++; + else if (ifmt[0]=='$') { iitem=*ilist++; ifmt++; goto nextitem; } + else if (ifmt[0]=='\0') c=-1; /* EOF forever */ + else c=*ifmt++; + /* fprintf(stderr, "igetcc()='%c'\n", c); */ + } else { + if ((c=getchar())=='\n') { leftofs=curofs; curline++; } + curofs++; + } + return c; +} + +static void ungetcc(int c) { + if (ifmt!=0) { + assert(ilast<0); + ilast=c; + } else { + if (c=='\n') curline--; + if (c>=0) { curofs--; ungetc(c,stdin); } + } +} + +static void erri(char const*msg1, char const*msg2) { + fprintf(stderr, "%s: error at %"SLEN_P"u.%"SLEN_P"u.%"SLEN_P"u: %s%s\n", + PROGNAME, curline, curofs-leftofs+1, curofs, msg1, msg2?msg2:""); + exit(3); +} + +static void setword(int c, char const*word, int slash) { + slen_t len; + assert(slash==0 || slash==1); + if (words[c][0]!='\0') erri("abbr letter already used",0); + if (sbuf+SBUFSIZE-sbufb+0U<(len=strlen(word))+slash+1U) erri("words overflow",0); + /* fprintf(stderr,"setword(%d,\"%s\");\n", c, word); */ + words[c]=sbufb; + if (slash) *sbufb++='/'; + strcpy(sbufb, word); + sbufb+=len+1; + /* assert(c<3 || findword(word)==c); */ +} + +/** So a long string from ps_tiny --copy <bts2.ttt will fit */ +/* #define IBUFSIZE 512 */ +#define IBUFSIZE 32000 + +/** Input buffer for several operations. */ +char ibuf[IBUFSIZE]; +/** Position after last valid char in ibuf */ +char *ibufb; + +typedef slendiff_t psint_t; + +#if 0 +static psint_t getint(void) { + int c, sgn=1; + psint_t v, w; + while (ISWSPACE(c,=getcc())) ; + if (c=='-') { c=getcc(); sgn=-1; } + if (!ULE(c-'0','9'-'0')) erri("integer expected",0); /* Dat: EOF err */ + v=sgn*(c-'0'); + while (ULE((c=getcc())-'0','9'-'0')) { + if ((w=10*v+sgn*(c-'0'))/10!=v) erri("integer overflow",0); + /* ^^^ Dat: overflow check is ok between -MAX-1 .. MAX */ + v=w; + } + ungetcc(c); + return v; +} + +static psint_t getuint(void) { + psint_t v=getint(); + if (v<0) erri("nonnegative integer expected",0); + return v; +} +#endif + +static /*inline*/ sbool is_ps_white(int/*char*/ c) { + return c=='\n' || c=='\r' || c=='\t' || c==' ' || c=='\f' || c=='\0'; +} + +static /*inline*/ sbool is_ps_name(int/*char*/ c) { + /* Dat: we differ from PDF since we do not treat the hashmark (`#') special + * in names. + * Dat: we differ from PostScript since we accept names =~ /[!-~]/ + */ + return c>='!' && c<='~' + && c!='/' && c!='%' && c!='{' && c!='}' && c!='<' && c!='>' + && c!='[' && c!=']' && c!='(' && c!=')'; + /* Dat: PS avoids: /{}<>()[]% \n\r\t\000\f\040 */ +} + +/** Definition chosen rather arbitrarily by pts */ +static sbool is_wordx(char const *s) { + if (!ULE(*s-'A','Z'-'A') && !ULE(*s-'a','z'-'a') && *s!='.') return 0; + /* && !ULE(*s-'0','9'-'0') && *s!='-') return 0; */ + while (*++s!='\0') if (!is_ps_name(*s)) return 0; + return 1; +} + +/** @param b: assume null-terminated @return true on error */ +static /*inline*/ sbool toInteger(char *s, psint_t *ret) { + int n=0; /* BUGFIX?? found by __CHECKER__ */ + return sscanf(s, "%"SLEN_P"i%n", ret, &n)<1 || s[n]!='\0'; +} + +/** @param b: assume null-terminated @return true on error */ +static /*inline*/ sbool toReal(char *s, double *ret) { + int n; + char c; + /* Dat: glibc accepts "12e", "12E", "12e+" and "12E-" */ + return sscanf(s, "%lf%n", ret, &n)<1 + || (c=s[n-1])=='e' || c=='E' || c=='+' || c=='-' || s[n]!='\0'; +} + +/** Returns a PostScript token ID, puts token into buf */ +static char gettok(void) { + /* Derived from MiniPS::Tokenizer::yylex() of sam2p-0.37 */ + int c=0; /* dummy initialization */ + sbool hi; + unsigned hv=0; /* =0: pacify G++ 2.91 */ + slen_t nest; + char *ibufend=ibuf+IBUFSIZE; + ibufb=ibuf; + +#if 0 + if (ungot==EOFF) return EOFF; + if (ungot!=NO_UNGOT) { c=ungot; ungot=NO_UNGOT; goto again; } +#endif + again_getcc: + c=getcc(); + /* again: */ + switch (c) { + case -1: eof: + return 0; /*ungot=EOFF */; + case '\n': case '\r': case '\t': case ' ': case '\f': case '\0': + goto again_getcc; + case '%': /* one-line comment */ + if ((c=getcc())=='<') { /* XMLish tag */ + char ret='<'; + if ((c=getcc())=='/') { ret='>'; c=getcc(); } /* close tag */ + if (!ULE(c-'A','Z'-'A')) erri("invalid tag",0); /* catch EOF */ + (ibufb=ibuf)[0]=c; ibufb++; + while (ULE((c=getcc())-'A','Z'-'A') || ULE(c-'a','z'-'a')) { + if (ibufb==ibufend-1) erri("tag too long",0); + *ibufb++=c; + } + if (c<0) erri("unfinished tag",0); + *ibufb='\0'; + ungetcc(c); + return ret; + } + while (c!='\n' && c!='\r' && c!=-1) c=getcc(); + if (c==-1) goto eof; + goto again_getcc; + case '{': case '[': + *ibufb++=c; + return '['; + case '}': case ']': + *ibufb++=c; + return ']'; + case '>': + if (getcc()!='>') goto err; + *ibufb++='>'; *ibufb++='>'; + return ']'; + case '<': + if ((c=getcc())==-1) { uf_hex: erri("unfinished hexstr",0); } + if (c=='<') { + *ibufb++='<'; *ibufb++='<'; + return '['; + } + if (c=='~') erri("a85str unsupported",0); + hi=1; + while (c!='>') { + if (ULE(c-'0','9'-'0')) hv=c-'0'; + else if (ULE(c-'a','f'-'a')) hv=c-'a'+10; + else if (ULE(c-'A','F'-'A')) hv=c-'A'+10; + else if (is_ps_white(c)) hv=16; + else erri("syntax error in hexstr",0); + if (hv==16) ; + else if (!hi) { ibufb[-1]|=hv; hi=1; } + else if (ibufb==ibufend) erri("hexstr literal too long",0); + else { *ibufb++=(char)(hv<<4); hi=0; } + if ((c=getcc())==-1) goto uf_hex; + } + /* This is correct even if an odd number of hex digits have arrived */ + return '('; + case '(': + nest=1; + while ((c=getcc())!=-1) { + if (c==')' && --nest==0) return '('; + if (c!='\\') { if (c=='(') nest++; } + else switch (c=getcc()) { /* read a backslash escape */ + case -1: goto uf_str; + case 'n': c='\n'; break; + case 'r': c='\r'; break; + case 't': c='\t'; break; + case 'b': c='\010'; break; /* \b and \a conflict between -ansi and -traditional */ + case 'f': c='\f'; break; + default: + if (!ULE(c-'0','7'-'0')) break; + hv=c-'0'; /* read at most 3 octal chars */ + if ((c=getcc())==-1) goto uf_str; + if (c<'0' || c>'7') { ungetcc(c); c=hv; } + hv=8*hv+(c-'0'); + if ((c=getcc())==-1) goto uf_str; + if (c<'0' || c>'7') { ungetcc(c); c=hv; } + c=(char)(8*hv+(c-'0')); + } /* SWITCH */ + if (ibufb==ibufend) erri("str literal too long",0); + /* putchar(c); */ + *ibufb++=c; + } /* WHILE */ + /* if (c==')') return '('; */ + uf_str: erri("unfinished str",0); + case ')': goto err; + case '/': + *ibufb++='/'; + while (ISWSPACE(c,=getcc())) ; + /* ^^^ `/ x' are two token in PostScript, but here we overcome the C + * preprocessor's feature of including whitespace. + */ + /* fall-through, b will begin with '/' */ + default: /* /nametype, /integertype or /realtype */ + *ibufb++=c; + while ((c=getcc())!=-1 && is_ps_name(c)) { + if (ibufb==ibufend) erri("token too long",0); + *ibufb++=c; + } + ungetcc(c); + if (ibuf[0]=='/') return '/'; + /* Imp: optimise numbers?? */ + if (ibufb!=ibufend) { + psint_t l; + double d; + *ibufb='\0'; + /* Dat: we don't support base-n number such as `16#100' == 256 in real PostScript */ + if (!toInteger(ibufb, &l)) return '1'; /* throw away integer value */ + /* Dat: call toInteger _before_ toReal */ + if (!toReal(ibufb, &d)) return '.'; + } + return 'E'; /* executable /nametype */ + } + err: + erri("syntax error, token expected",0); + goto again_getcc; /* notreached */ +} + +static void getotag(char const*tag) { +#if 0 /* This code segment cannot ignore comments */ + char const *p=tag; + int c; + while (ISWSPACE(c,=getcc())) ; + if (c!='%' || (c=getcc())!='<') erri("tag expected: ", tag); + while (ISWSPACE(c,=getcc())) ; + while (p[0]!='\0') { + if (c!=*p++) erri("this tag expected: ", tag); + c=getcc(); + } + ungetcc(c); +#else + if (gettok()!='<' || 0!=strcmp(ibuf,tag)) erri("tag expected: ", tag); +#endif +} + +static void gettagbeg(void) { + int c; + while (ISWSPACE(c,=getcc())) ; + if (c!='>') erri("`>' expected",0); +} + +static void gettagend(void) { + int c; + while (ISWSPACE(c,=getcc())) ; + if (c!='/') erri("`/>' expected",0); + while (ISWSPACE(c,=getcc())) ; + if (c!='>') erri("`/>' expected",0); +} + +static void getkey(char const *key) { + char const *p=key; + int c; + while (ISWSPACE(c,=getcc())) ; + while (p[0]!='\0') { + if (c!=*p++) erri("this key expected: ", key); + c=getcc(); + } + while (ISWSPACE(c,)) c=getcc(); + if (c!='=') erri("key `=' expected", 0); +} + + +/** Loads a value into ibuf, '\0'-terminated. */ +static void getval(void) { + sbool g=1; + char *ibufend1=ibuf+IBUFSIZE-1, c; + ibufb=ibuf; + while (ISWSPACE(c,=getcc())) ; + while (1) { + if (c=='"') g=!g; + else if (g && (ISWSPACE(c,) || c=='/' || c=='>')) { ungetcc(c); break; } + else if (c<0) erri("unfinished tag val",0); + else if (c==0) erri("\\0 disallowed in tag val",0); + else if (ibufb==ibufend1) erri("tag val too long",0); + else *ibufb++=c; + c=getcc(); + } /* WHILE */ + *ibufb='\0'; +} + +static psint_t getuintval(void) { + psint_t ret; + getval(); + /* fprintf(stderr, "[%s]\n", ibuf); */ + if (toInteger(ibuf, &ret) || ret<0) erri("tag val must be nonnegative integer",0); + return ret; +} + +/* --- Writing */ + +/** Maximum number of characters in a line. */ +#define MAXLINE 78 + +/** Number of characters already written into this line. (from 0) */ +slen_t wcolc; + +/** Last token was a self-closing one */ +sbool wlastclosed; + +static void prepare(void) { wcolc=0; wlastclosed=1; } + +static void newline(void) { + if (wcolc!=0) { + putchar('\n'); + wcolc=0; wlastclosed=1; + } else assert(wlastclosed); +} + +/** 2: "\\n"; 1: "\n" */ +static int pstrq_litn_pp=2; + +/** @return the byte length of a string as a quoted PostScript ASCII string + * literal + */ +static slen_t pstrqlen(register char const* p, char const* pend) { + slen_t olen=2; /* '(' and ')' */ + char c; + p=ibuf; pend=ibufb; while (p!=pend) { + if ((c=*(unsigned char const*)p++)=='\r' || c=='\t' || c=='\010' || c=='\f' || c=='(' || c==')') olen+=2; + else if (c=='\n') olen+=pstrq_litn_pp; + else if (c>=32 && c<=126) olen++; + else if (c>=64 || p==pend || ULE(*p-'0','7'-'0')) olen+=4; + else if (c>=8) olen+=3; + else olen+=2; + } + return olen; +} + +/** Prints the specified string as a quoted PostScript ASCII string literal. + * Does not modify wcolc etc. + */ +static void pstrqput(register char const* p, char const* pend) { + char c; + putchar('('); + p=ibuf; pend=ibufb; while (p!=pend) { + if ((ULE((c=*(unsigned char const*)p++)-32, 126-32) && c!='(' && c!=')') + || (c=='\n' && pstrq_litn_pp==1) + ) { putchar(c); continue; } + putchar('\\'); + if (c=='\n') putchar('n'); + else if (c=='\r') putchar('r'); + else if (c=='\t') putchar('t'); + else if (c=='\010') putchar('b'); + else if (c=='\f') putchar('f'); + else if (c=='(') putchar('('); /* BUGFIX at Tue Feb 22 00:22:19 CET 2005 */ + else if (c==')') putchar(')'); + else if (c>=64 || p==pend || ULE(*p-'0','7'-'0')) { + putchar((c>>6&7)+'0'); + putchar((c>>3&7)+'0'); + putchar(( c&7)+'0'); + } else if (c>=8) { + putchar((c>>3) +'0'); + putchar(( c&7)+'0'); + } else putchar(c+'0'); + } + putchar(')'); +} + +static int copy_longstr_warn_p=1; + +/** Copies PostScript code from input to output. Strips comments, superfluous + * whitespace etc., substitutes words etc. + * @param tag may be NULL, this signals: copy till EOF, doesn't substitute + * words + */ +static void copy(char const*tag) { + int c; + slen_t len, olen; + while (1) switch (gettok()) { + case 0: + if (tag) erri("eof before close tag: ", tag); + return; + case '[': case ']': + if (wcolc+(len=ibufb-ibuf)>MAXLINE) newline(); + wlastclosed=1; + write: + if (len>MAXLINE) fprintf(stderr, "%s: warning: output line too long\n", PROGNAME); + fwrite(ibuf, 1, len, stdout); wcolc+=len; + break; + case '/': + if ((len=ibufb-ibuf)<IBUFSIZE && tag && !(*ibufb='\0') && (c=findword(ibuf))>=0) { + ibuf[0]='/'; + ibuf[1]=c; + ibufb=ibuf+2; + len=2; + } + if (wcolc+len>MAXLINE) newline(); + wlastclosed=0; + goto write; + case '<': erri("tag unexpected",0); + case '>': + if (!tag) erri("close tag unexpected",0); + if (strlen(tag)!=(len=ibufb-ibuf) || 0!=memcmp(ibuf,tag,len)) erri("this close tag expected: ", tag); + /* wlastclosed is left unmodified */ + gettagbeg(); + return; + case '(': + olen=pstrqlen(ibuf,ibufb); + if (wcolc+olen>MAXLINE) newline(); + if (olen>MAXLINE && copy_longstr_warn_p) fprintf(stderr, "%s: warning: output string too long\n", PROGNAME); + /* putchar(ibuf[1]); */ + wcolc+=olen; pstrqput(ibuf,ibufb); + wlastclosed=1; + break; + default: /* case '1': case '.': case 'E': */ + /* fprintf(stderr,"fw(%s) %c\n", ibuf, findword("32768")); */ + if ((len=ibufb-ibuf)<IBUFSIZE && tag && !(*ibufb='\0') && (c=findword_stripslash(ibuf))>=0) { + ibuf[0]=c; + ibufb=ibuf+1; + len=1; + } + if (wcolc+len+!wlastclosed>MAXLINE) newline(); + else if (!wlastclosed) { putchar(' '); wcolc++; } + wlastclosed=0; + goto write; + } +} + +/** Prefix chars: 32..41 ' '..')' */ +static void cprefix(slen_t olen) { + slen_t plen; + if (0==olen) erri("empty token",""); + if (olen>11) erri("compressed token too long (>11)",""); + plen=olen+(olen>1)+(olen==7); + if (wcolc+(wcolc==0)+plen>MAXLINE) newline(); + if (wcolc==0) { putchar('%'); wcolc=1; } + if (plen>=MAXLINE) fprintf(stderr, "%s: warning: output line too long\n", PROGNAME); + if (olen==7) { putchar(8+30); putchar(' '); wcolc+=2; } /* Dat: ASCII 37=='%' */ + else if (olen>1) { putchar(olen+30); wcolc++; } +} + +/** Copies PostScript code from input to output. Strips comments, superfluous + * whitespace etc., substitutes words etc. Output is not valid PostScript code, + * but it needs decompression (i.e adding spaces to words). Ignores var + * `wlastclosed' (sets it to 1 by calling newline()). + */ +static void compress0(char const*tag) { + int c; + slen_t len, olen; + newline(); + while (1) switch (gettok()) { + case 0: erri("eof before close tag: ", tag); + case '[': case ']': + len=ibufb-ibuf; + write: + cprefix(len); + fwrite(ibuf, 1, len, stdout); wcolc+=len; + break; + case '/': + if ((len=ibufb-ibuf)<IBUFSIZE && !(*ibufb='\0') && (c=findword(ibuf))>=0) { + /* erri("possibly stupid redef: ", ibuf); */ + ibuf[0]='/'; + ibuf[1]=c; + ibufb=ibuf+2; + len=2; + } + goto write; + case '<': erri("tag unexpected",0); + case '>': + if (strlen(tag)!=(len=ibufb-ibuf) || 0!=memcmp(ibuf,tag,len)) erri("this close tag expected: ", tag); + /* wlastclosed is left unmodified */ + fputs((wcolc+2>MAXLINE) ? "\n% %%" : "%%", stdout); + newline(); + gettagbeg(); + return; + case '(': + cprefix(olen=pstrqlen(ibuf,ibufb)); + wcolc+=olen; pstrqput(ibuf,ibufb); + break; + default: /* case '1': case '.': case 'E': */ + if ((len=ibufb-ibuf)<IBUFSIZE && !(*ibufb='\0') && (c=findword_stripslash(ibuf))>=0) { + ibuf[0]=c; + ibufb=ibuf+1; + len=1; + } + goto write; + } +} + +/** by pts@fazekas.hu at Fri Sep 6 11:34:57 CEST 2002. Copies data from stdin + * to stdout till close tag %</tag>. (Note that it isn't safe to copy data of + * the ASCII85Encode filter this way + */ +static void copydata(char const*tag) { + int c; + while (ISWSPACE(c,=getcc())) ; + /* ungetcc(c); */ + while (1) { + if (c<0) erri("missing close tag: ", tag); + if (c!='%') { putchar(c); c=getcc(); continue; } + if ((c=getcc())=='<') { + if ((c=getcc())=='/') { + while (tag[0]!='\0') { + if ((c=getcc())!=*tag++) erri("this close tag expected: ", tag); + } + while (ISWSPACE(c,=getcc())) ; + if (c!='>') erri("`>' expected", 0); + break; + } else { + putchar('%'); + putchar('<'); + } + } else { + putchar('%'); + } + } +} + +/* --- Main */ + +int main(int argc, char**argv) { + slen_t acount, xcount, inlining, slen; + char tmp[40]; + (void)argc; + + /* freopen("t.pin","rb",stdin); */ + + sbuff(); + rewindd(); + prepare(); + if (argv[0] && argv[1] && 0==strcmp(argv[1],"--copy")) { + copy_longstr_warn_p=0; + pstrq_litn_pp=1; + copy((char const*)0); + return 0; + } + + { char tok=gettok(); + slen_t len; + len=ibufb-ibuf; + if (tok=='<' && len==4 && 0==memcmp(ibuf, "Head", 4)) { + gettagbeg(); + copydata("Head"); + getotag("Open"); + } else if (tok=='<' && len==4 && 0==memcmp(ibuf, "Open", 4)) { + } else erri("tag %<Head or %<Open expected",0); + } + gettagbeg(); + copy("Open"); + + getotag("Abbr"); + getkey("acount"); acount=getuintval(); + getkey("xcount"); xcount=getuintval(); + sprintf(tmp,"%"SLEN_P"u dict%%</I>", acount+xcount); + setifmt(tmp,0); copy("I"); noifmt(); + gettagbeg(); + +#define E_RANGE 3 +#define E_SYNTAX 4 +#define E_COMPRESS 5 + copy("Abbr"); + setword(E_RANGE, ")range", 0); + setword(E_SYNTAX, ")syntax", 0); + setword(E_COMPRESS, ")compress", 0); + { int c; + for (c=7;c<32;c++) words[c]=words[E_RANGE]; + for (c=32;c<42;c++) words[c]=words[E_COMPRESS]; + for (c=47;c<58;c++) words[c]=words[E_SYNTAX]; /* Name:'/', Number:'0'..'9' */ + words[0U+'<']=words[0U+'>']= /* Hex */ + words[0U+'[']=words[0U+']']= /* Bracket */ + words[0U+'{']=words[0U+'}']= /* Brace */ + words[E_SYNTAX]; + for (c=127;c<WORDSSIZE;c++) words[c]=words[E_RANGE]; + } + + { char tok; + slen_t len; + int c; + char ct[2]; + char const* ilist_[3]; + psint_t i; + sbool g; + while (1) { + tok=gettok(); len=ibufb-ibuf; + if (tok=='<' && len==1 && 0==memcmp(ibuf, "A", 1)) { + while (ISWSPACE(c,=getcc())) ; + if (c<32 || c>=WORDSSIZE) erri("invalid %<A letter",0); + ct[0]=c; ct[1]='\0'; ilist_[0]=ct; + getval(); + if (is_wordx(ibuf)) { + setword(c, ibuf, 0); + ilist_[1]=words[c]; words[c]=sbuf; /* temp hide */ + ilist_[2]=words[0][0]=='\0' ? "load def" : words[0]; + setifmt("/$ /$ $%</I>", ilist_); + if (words[1][0]=='\0' && 0==strcmp(ibuf,"def")) setword(1, ct, 0); + } else { + g=toInteger(ibuf, &i); /* need braces? */ + if (g) { words[2]=sbuf; c=2; } + setword(c, ibuf, 0); /* temp save */ + ilist_[1]=words[c]; words[c]=sbuf; /* temp hide */ + ilist_[2]=words[1][0]=='\0' ? "def" : words[1]; + setifmt(g ? "/$ { $\n} $%</I>" : "/$ $\n $%</I>", ilist_); + if (words[0][0]=='\0' && 0==strcmp(ibuf,"load def")) setword(0, ct, 0); + } + copy("I"); + noifmt(); + words[c]=ilist_[1]; + } else if (tok=='<' && len==1 && 0==memcmp(ibuf, "D", 1)) { + /* define both /x and x */ + while (ISWSPACE(c,=getcc())) ; + if (c<32 || c>=WORDSSIZE) erri("invalid %<D letter",0); + ct[0]=c; ct[1]='\0'; ilist_[0]=ct; + getval(); + if (!is_wordx(ibuf)) erri("body for %<D must be a single word",0); + setword(c, ibuf, 1); + } else if (tok=='<' && len==7 && 0==memcmp(ibuf, "TokSubs", 7)) { + break; + } else erri("tag %<TokSubs or %<A or %<D expected",0); + gettagend(); + } + words[2]=sbuf; /* Imp: free chars */ + } + + getkey("name"); getval(); setword(2, ibuf, 0); + if (ibufb-ibuf==1 && words[(unsigned char)ibuf[0]]!=sbuf) erri("abbr used as %<TokSubs name= : ",ibuf); + getkey("inlining"); inlining=getuintval(); + gettagend(); + { char const* ilist_[2]; ilist_[0]=ilist_[1]=words[2]; + setifmt(inlining!=0 ? "/${mark exch{dup xcheck{dup type/arraytype eq{$}{dup type/nametype eq{dup currentdict exch known{load dup dup type/arraytype eq exch xcheck and{$ aload pop}if}if}if}ifelse}if}forall counttomark array astore exch pop cvx}bind def%</I>" + :"/$ {\n" + "mark exch{\n" + "dup xcheck{\n" + "dup type/arraytype eq{$}{\n" + "dup type/nametype eq{\n" + "dup currentdict exch known {load}if\n" + "}if\n" + "}ifelse\n" + "}if\n" + "}forall\n" + "counttomark array astore exch pop cvx\n" + "} bind def%</I>", ilist_); + copy("I"); noifmt(); + } + + getotag("Test"); + gettagbeg(); + copy("Test"); + + getotag("S"); + getkey("len"); slen=getuintval(); /* Imp: verify slen for overruns */ + gettagbeg(); + setifmt("{%</I>",0); copy("I"); noifmt(); /*}*/ + copy("S"); + + { char const* ilist_[2]; ilist_[0]=ilist_[1]=words[2]; + setifmt( + "0\n" + "{ % Stack: <dst-str> <i>\n" + " currentfile read pop\n" + " dup 37 eq{% '%'\n" + " pop currentfile read pop\n" + " dup 37 eq{pop pop exit}if % exit when '%%'\n" + " }if\n" + " % Stack: <dst-str> <i> <char-read>\n" + " dup 42 lt{\n" + " 30 sub\n" + " % Stack: <dst-str> <i> <repeat-count>\n" + " dup 0 gt{\n" + " 3 copy getinterval\n" + " % Stack: <dst-str> <i> <repeat-count> <sub-dst-str>\n" + " currentfile exch readstring pop pop\n" + " % Stack: <dst-str> <i> <repeat-count>\n" + " add 1 add\n" + " }{pop}ifelse % skip newlines, tabs etc.\n" + " }{\n" + " 3 copy put\n" + " pop 2 add % \\0 as space\n" + " }ifelse\n" + " % Stack: <dst-str> <new-i>\n" + "}$ bind loop\n" + "% Stack: <dst-str>\n" + "cvx exec $ bind exec\n" /* CONST, VAR és CODE futtatása */ + "currentfile token pop pop\n" /* A %%BeginData utáni exec beolvasása */ + "%</I>\n", ilist_); + copy("I"); noifmt(); + } + + getotag("True"); + gettagbeg(); + copy("True"); + + setifmt("}{currentfile token pop pop%</I>",0); + copy("I"); noifmt(); + + getotag("False"); + gettagbeg(); + copy("False"); + + setifmt("}ifelse%</I>",0); + copy("I"); noifmt(); + + getotag("Defs"); + gettagbeg(); + compress0("Defs"); + + { char tok=gettok(); + slen_t len; + len=ibufb-ibuf; + if (tok=='<' && len==4 && 0==memcmp(ibuf, "Data", 4)) { + gettagbeg(); + copydata("Data"); + } else if (tok=='<' && len==4 && 0==memcmp(ibuf, "Fini", 4)) { + fputs("%%BeginData:\nexec\n`S\n%%EndData\n",stdout); + getotag("Fini"); + gettagbeg(); + copy("Fini"); + newline(); + fputs("%%Trailer\n%%EOF\n", stdout); + } else erri("tag %<Data or %<Fini expected",0); + } + + if (gettok()!=0) erri("premature EOF",0); + + return 0; +} diff --git a/Build/source/utils/sam2p/psmlib.psm b/Build/source/utils/sam2p/psmlib.psm new file mode 100644 index 00000000000..7ebc93a08ce --- /dev/null +++ b/Build/source/utils/sam2p/psmlib.psm @@ -0,0 +1,199 @@ +/* psmlib.psm -- utilites for writing PostScript code with the help of + * cpp, the C preprocessor + * compiled by pts@fazekas.hu at Fri Sep 20 23:38:32 CEST 2002 + */ + +#if USE_A85D +#else + #if USE_HEXD + #else + #define USE_BINARY 1 + #endif +#endif + +#if USE_INDEXED2 + #define USE_PALETTE 1 +#else + #if USE_TRANSPARENT8 + #define USE_PALETTE 1 + #endif +#endif + +#if USE_NO_BIND + #define BIND_DEF def +#else + #define BIND_DEF bind def +#endif + + +#if NDEBUG + #define DEBUG(msg) + #define ASSERT_TRUE_POP(str) pop + #define ASSERT_FALSE_POP(str) pop + #define ASSERT_TRUE(what,str) + #define ASSERT_INT() + #define INT_EQ eq + #define INT_NE ne + #define INT_LE le + #define INT_GT gt + #define INT_LT lt + #define BOOL_BIN(op,message) op + #define INT_BIN(op,message) op + #define DEBUGFORCE(msg) + #define ASSERT_STACK(list,message) +#else + /-str /stringtype def + /-aryb /stringtype def % byte array + /-ary /arraytype def + /-int /integertype def + /-bool /booleantype def + /-dict /dicttype def + /handleerror.orig /handleerror load def + /handleerror { + (%stderr) (w) file + dup (!!!Fatal: GS error: ) writestring + dup $error /errorname get write==only + dup ( in ) writestring + dup $error /command get write==only + dup ( at ) writestring + dup $error /position get write==only + dup (.\n) writestring + flushfile flush + handleerror.orig + quit + }bind def + #define ASSERT_TRUE_POP(str) not{ str InternalError }if + #define ASSERT_FALSE_POP(str) { str InternalError }if + #define ASSERT_TRUE(what,str) what not{ str InternalError }if + #define ASSERT_INT(str) dup type/integertype ne{str InternalError}if + #define ASSERT_BOOL(str) dup type/booleantype ne{str InternalError}if + /DumpStack { % - DumpStack - + (Stack: ) print % from bottom to top + count 1 sub -1 0{ + index + dup type /stringtype eq {pop ()}if + ===only + ( ) print + } for + (.\n) print + }bind def + + /TypeStack { % <list> TypeStack <bool> + dup length count 2 sub eq { + true exch count 2 add 1 index length 1 sub 0 exch 1 exch + % Stack: ... true ary count(...)+5 0 1 ary.length-1 + { + % Stack: ... true ary count* i + 2 index exch get 2 copy exch + % Stack: ... true ary count* ary[i] ary[i] count* + index type + % Stack: ... true ary count* ary[i] ary[i] stackitem.type + ne{ + pop pop pop pop + % Stack: ... + false 0 0 + exit + }if + pop 1 sub + % Stack: ... true ary count*-1 + } for + % Stack: ... true|false ary count* + pop pop + }{ + pop false + }ifelse + ASSERT_BOOL((TypeStack-bool)) + }bind def + /InternalError { % <str> FatalError - + (%stderr) (w) file dup dup + (Internal muZCat Error: ) writestring + 2 index writestring + dup (.\n) writestring + flushfile + pop + quit + }bind def + /Stderr (%stderr) (w) file def + #ifdef DEBUGMSG + #define DEBUG(msg) msg Stderr exch writestring Stderr flushfile + #else + #define DEBUG(msg) + #endif + #define DEBUGFORCE(msg) msg Stderr exch writestring Stderr flushfile + #define INT_EQ ASSERT_INT((eq2int)) exch ASSERT_INT((eq1int)) exch eq + #define INT_NE ASSERT_INT((ne2int)) exch ASSERT_INT((ne1int)) exch ne + #define INT_LE ASSERT_INT((le2int)) exch ASSERT_INT((le1int)) exch le + #define INT_GT ASSERT_INT((gt2int)) exch ASSERT_INT((gt1int)) exch gt + #define INT_LT ASSERT_INT((lt2int)) exch ASSERT_INT((lt1int)) exch lt + #define BOOL_BIN(op,message) ASSERT_BOOL(message) exch ASSERT_BOOL(message) exch op + #define INT_BIN(op,message) ASSERT_INT(message) exch ASSERT_INT(message) exch op + #define ASSERT_STACK(list,message) TYPE_STACK(list) not{ DumpStack (assert stack: ) message concatstrings InternalError }if + #define TYPE_STACK(list) [ list ] TypeStack +#endif + +/* at Sat Sep 21 19:07:59 CEST 2002 */ +#if USE_DEBUG2 + #define DEBUG2(x) x +#else + #define DEBUG2(x) +#endif + +/* revised, A85D/read_eod at Sun Sep 22 00:27:13 CEST 2002 */ +/* Sample usage: + * { TE_read(===) % action to do with normal char + * #if !USE_NO_EOF + * { TE_read_pop exit } ifelse % action to do on EOF + * #endif + * } loop + */ +#if USE_A85D + #define TE_read_eod a85_getc ASSERT_TRUE(dup 511 eq,(EOD expected)) pop + #define TE_init /xS 32 def /xD 0 def /xC 0 def + #if USE_NO_EOF + #define TE_read(true_action) a85_getc true_action + #define PSM_A85_GETC \ + {27 xS ge{exit}if STDIN read pop \ + dup 122 eq{/xS 27 def/xD 0 def/xC 0 def}{dup 117 gt{ \ + STDIN read{pop}if/xS 54 xS sub def}{dup 33 ge{xS 32 eq{dup/xC exch def/xD -1670420001 def}{dup 117 sub{1 85 \ + 7225 614125}xS 28 sub get mul xD add/xD exch def}ifelse/xS xS 1 sub def}if}ifelse}ifelse pop}loop xS 22 eq{511}{xC \ + 1868977 mul xD add xS 24 and neg bitshift 23 xS lt{xC 3 mul add}if 255 and/xS xS 3 eq{32}{xS 7 mod 3 \ + eq{22}{xS 8 sub}ifelse}ifelse def}ifelse + /** TE_readstring(str) <substr> */ + #define TE_readstring(str) dup length 1 sub 0 exch 1 exch{a85_getc 3 copy put pop pop}for + #else + #define TE_read(true_action) a85_getc dup 256 INT_LT { true_action } + #define TE_read_pop pop + /* #define TE_read_eod TE_read() { ASSERT_TRUE(false,(EOD expected)) } ifelse */ + #define PSM_A85_GETC \ + {27 xS ge{exit}if STDIN read not{511}if \ + dup 122 eq{/xS 27 def/xD 0 def/xC 0 def}{dup 117 gt{ \ + STDIN read{pop}if/xS 54 xS sub def}{dup 33 ge{xS 32 eq{dup/xC exch def/xD -1670420001 def}{dup 117 sub{1 85 \ + 7225 614125}xS 28 sub get mul xD add/xD exch def}ifelse/xS xS 1 sub def}if}ifelse}ifelse pop}loop xS 22 eq{511}{xC \ + 1868977 mul xD add xS 24 and neg bitshift 23 xS lt{xC 3 mul add}if 255 and/xS xS 3 eq{32}{xS 7 mod 3 \ + eq{22}{xS 8 sub}ifelse}ifelse def}ifelse + #endif +#endif +#if USE_HEXD + #define TE_init + #if USE_NO_EOF + #define TE_read(true_action) STDIN C readhexstring pop 0 get true_action + #define TE_read_eod STDIN read pop pop /* read '>' */ + #define TE_readstring(str) STDIN str readhexstring pop + #else + #error PostScript op readhexstring cannot detect EOD! + #define TE_read(true_action) STDIN C readhexstring { 0 get true_action } + #define TE_read_pop + #define TE_read_eod + #endif +#endif +#if USE_BINARY + #define TE_init + #define TE_read_eod + #if USE_NO_EOF + #define TE_read(true_action) STDIN read pop true_action + #define TE_readstring(str) STDIN str readstring pop + #else + #define TE_read(true_action) STDIN read { true_action } + #define TE_read_pop + #endif +#endif diff --git a/Build/source/utils/sam2p/pts_defl.c b/Build/source/utils/sam2p/pts_defl.c new file mode 100644 index 00000000000..fe72772bb75 --- /dev/null +++ b/Build/source/utils/sam2p/pts_defl.c @@ -0,0 +1,3671 @@ +#define DUMMY \ +set -ex; \ +${CC:-gcc} -DNDEBUG=1 -DPTS_DEFL_MAIN -O3 -ansi \ + -Wall -W -Wstrict-prototypes -Wtraditional -Wnested-externs -Winline \ + -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wmissing-prototypes \ + -Wmissing-declarations pts_defl.c -o flateenc; \ +exit +/* + * pts_defl.c -- C source file ZIP compression ripped from linux-2.6.8.1 + * by pts@fazekas.hu at Tue Jan 18 15:19:06 CET 2005 + * + * This ZIP compression (ZIP == PostScript /FlateEncode compression filter + * (ZLIB RFC 1950)) routine has been ripped from the Linux kernel 2.6.8.1 + * (directory lib/zlib_deflate), which has been ripped from ZLIB 1.1.3 + * + * To have a UNIX filter program (stdin -> stdout), compile zipfilt.c + * + * Dat: the exported symbols are: zlib_deflate zlib_deflateEnd + * zlib_deflateInit_ zlib_deflateInit2_ zlib_deflateParams + * zlib_deflate_workspacesize + * + */ + +/* ---- <rip> by pts */ + +/* +++ deflate.c */ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-1996 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +#if 0 /**** pts ****/ +# include <linux/module.h> +#endif + +/**** pts ****/ +#if OBJDEP /* sam2p */ +# warning PROVIDES: pts_defl +#endif +#if HAVE_CONFIG2_H /* sam2p */ +# include "config2.h" +#endif + +/* #include <linux/zutil.h> */ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: pts_defl.c,v 1.5 2005/01/18 16:05:16 pts Exp $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#if 0 /**** pts ****/ +# include <linux/zlib.h> +#else +# include "pts_defl.h" +#endif +#if 0 /**** pts ****/ +# include <linux/string.h> +# include <linux/errno.h> +# include <linux/kernel.h> +#endif + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +/*#include <linux/zconf.h>*/ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: pts_defl.c,v 1.5 2005/01/18 16:05:16 pts Exp $ */ + +/*#ifndef _ZCONF_H*/ +/*#define _ZCONF_H*/ + +#ifndef NULLP /**** pts ****/ +#define NULLP ((void*)0) /* Imp: g++, with const */ +#endif + +#if 0 /**** pts ****/ /* Dat: `inline' is not ANSI C */ +# define ZINLINE inline +#else +# define ZINLINE +#endif +#define ZSTATIC static /**** pts ****/ + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# define MAX_MEM_LEVEL 8 +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + + /* Type declarations */ + +typedef unsigned char Byte; /* 8 bits */ +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ +typedef void *voidp; + +/*#endif*/ /* _ZCONF_H */ + +/* end of linux/zconf.h */ + +#if 0 +#define ZLIB_VERSION "1.1.3" +#endif + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +#if 0 +struct zlib_internal_state; /**** pts ****/ /* Dat: was: internal_state */ + +typedef struct z_stream_s { + Byte *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Byte *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULLP if no error */ + struct zlib_internal_state *state; /* not visible by applications */ + + void *workspace; /* memory allocated for this stream */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return NULLP if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ +#endif +typedef z_stream *z_streamp; + + /* constants */ + +#if 0 +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_PACKET_FLUSH 2 +#define Z_SYNC_FLUSH 3 +#define Z_FULL_FLUSH 4 +#define Z_FINISH 5 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ +#endif + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#if 0 +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ +#endif + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + + /* basic functions */ + +extern const char * zlib_zlibVersion (void); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +extern int zlib_deflate_workspacesize (void); +/* + Returns the number of bytes that needs to be allocated for a per- + stream workspace. A pointer to this number of bytes should be + returned in stream->workspace before calling zlib_deflateInit(). +*/ + +/* +extern int deflateInit (z_streamp strm, int level); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to NULLP, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +extern int zlib_deflate (z_streamp strm, int flush); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULLP), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +extern int zlib_deflateEnd (z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +extern int zlib_inflate_workspacesize (void); +/* + Returns the number of bytes that needs to be allocated for a per- + stream workspace. A pointer to this number of bytes should be + returned in stream->workspace before calling zlib_inflateInit(). +*/ + +/* +extern int zlib_inflateInit (z_streamp strm); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, and workspace must be initialized before by + the caller. If next_in is not NULLP and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to NULLP, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +extern int zlib_inflate (z_streamp strm, int flush); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULLP), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +extern int zlib_inflateEnd (z_streamp strm); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +extern int deflateInit2 (z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +extern int zlib_deflateSetDictionary (z_streamp strm, + const Byte *dictionary, + uInt dictLength); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULLP dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +extern int zlib_deflateCopy (z_streamp dest, z_streamp source); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULLP). msg is left unchanged in both source and + destination. +*/ + +extern int zlib_deflateReset (z_streamp strm); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULLP). +*/ + +extern int zlib_deflateParams (z_streamp strm, int level, int strategy); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +extern int inflateInit2 (z_streamp strm, int windowBits); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +extern int zlib_inflateSetDictionary (z_streamp strm, + const Byte *dictionary, + uInt dictLength); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULLP dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +extern int zlib_inflateSync (z_streamp strm); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +extern int zlib_inflateReset (z_streamp strm); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULLP). +*/ + +extern int zlib_inflateIncomp (z_stream *strm); +/* + This function adds the data at next_in (avail_in bytes) to the output + history without performing any output. There must be no pending output, + and the decompressor must be expecting to see the start of a block. + Calling this function is equivalent to decompressing a stored block + containing the data at next_in (except that the data is not output). +*/ + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +extern int zlib_deflateInit_ (z_streamp strm, int level, + const char *version, int stream_size); +extern int zlib_inflateInit_ (z_streamp strm, + const char *version, int stream_size); +extern int zlib_deflateInit2_ (z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +extern int zlib_inflateInit2_ (z_streamp strm, int windowBits, + const char *version, int stream_size); +#if 0 /**** pts ****/ +#define zlib_deflateInit(strm, level) \ + zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define zlib_inflateInit(strm) \ + zlib_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define zlib_inflateInit2(strm, windowBits) \ + zlib_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#endif + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct zlib_internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +extern const char * zlib_zError (int err); +extern int zlib_inflateSyncPoint (z_streamp z); +extern const uLong * zlib_get_crc_table (void); + +/**** pts ****/ +#define max(a,b) ((a)<(b) ? (b) : (a)) + + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + + /* functions */ + +typedef uLong (*check_func) (uLong check, const Byte *buf, + uInt len); + + + /* checksum functions */ + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULLP, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, NULLP, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ +static ZINLINE uLong zlib_adler32(uLong adler, + const Byte *buf, + uInt len) +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULLP) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} + +#endif /* _Z_UTIL_H */ + +/* end of zutil.h */ + +/* #include "defutil.h" */ + +#define Assert(err, str) +#define Trace(dummy) +#define Tracev(dummy) +#define Tracecv(err, dummy) +#define Tracevv(dummy) + + + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} tree_desc; + +typedef ush Pos; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct deflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Byte *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Byte *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Byte *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Pos *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Pos *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uch *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ush *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + ulg compressed_len; /* total bit length of compressed file */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG_ZLIB + ulg bits_sent; /* bit length of the compressed data */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} deflate_state; + +typedef struct deflate_workspace { + /* State memory for the deflator */ + deflate_state deflate_memory; + Byte window_memory[2 * (1 << MAX_WBITS)]; + Pos prev_memory[1 << MAX_WBITS]; + Pos head_memory[1 << (MAX_MEM_LEVEL + 7)]; + char overlay_memory[(1 << (MAX_MEM_LEVEL + 6)) * (sizeof(ush)+2)]; +} deflate_workspace; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +ZSTATIC void zlib_tr_init (deflate_state *s); +ZSTATIC int zlib_tr_tally (deflate_state *s, unsigned dist, unsigned lc); +ZSTATIC ulg zlib_tr_flush_block (deflate_state *s, char *buf, ulg stored_len, + int eof); +ZSTATIC void zlib_tr_align (deflate_state *s); +ZSTATIC void zlib_tr_stored_block (deflate_state *s, char *buf, ulg stored_len, + int eof); +ZSTATIC void zlib_tr_stored_type_only (deflate_state *); + + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +static ZINLINE unsigned bi_reverse(unsigned code, /* the value to invert */ + int len) /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +static ZINLINE void bi_flush(deflate_state *s) +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +static ZINLINE void bi_windup(deflate_state *s) +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG_ZLIB + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + + +/* end of defutil.h */ + +#if USE_ZLIB_MEM +# include <string.h> /* memcpy(), memset() */ +# define zmemcpy(a,b,c) memcpy(a,b,c) +# define zmemset(a,b,c) memset(a,b,c) +#else +static void *zmemcpy(void * dest,const void *src,unsigned count) { + char *tmp = (char *) dest; + char const *s = (char const*) src; + while (count--) *tmp++ = *s++; + return dest; +} +static void *zmemset(void * s,int c,unsigned count) { + char *xs = (char *) s; + while (count--) *xs++ = c; + return s; +} +#endif + + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) (deflate_state *s, int flush); +/* Compression function. Returns the block state after the call. */ + +static void fill_window (deflate_state *s); +static block_state deflate_stored (deflate_state *s, int flush); +static block_state deflate_fast (deflate_state *s, int flush); +static block_state deflate_slow (deflate_state *s, int flush); +static void lm_init (deflate_state *s); +static void putShortMSB (deflate_state *s, uInt b); +static void flush_pending (z_streamp strm); +static int read_buf (z_streamp strm, Byte *buf, unsigned size); +static uInt longest_match (deflate_state *s, IPos cur_match); + +#ifdef DEBUG_ZLIB +static void check_match (deflate_state *s, IPos start, IPos match, + int length); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +static const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int zlib_deflateInit_( + z_streamp strm, + int level, + const char *version, + int stream_size +) +{ + return zlib_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, + DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int zlib_deflateInit2_( + z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy, + const char *version, + int stream_size +) +{ + deflate_state *s; + int noheader = 0; + static char* my_version = ZLIB_VERSION; + deflate_workspace *mem; + + ush *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == NULLP || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == NULLP) return Z_STREAM_ERROR; + + strm->msg = (char*)NULLP; /**** pts ****/ + + if (level == Z_DEFAULT_COMPRESSION) level = 6; + + mem = (deflate_workspace *) strm->workspace; + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) &(mem->deflate_memory); + strm->state = (struct zlib_internal_state *)s; + s->strm = strm; + + s->data_type=strm->data_type; /**** pts ****/ /* BUGFIX at Tue Jan 18 16:01:08 CET 2005 */ /* Imp: report this bugfix to the Linux kernel */ + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Byte *) mem->window_memory; + s->prev = (Pos *) mem->prev_memory; + s->head = (Pos *) mem->head_memory; + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ush *) mem->overlay_memory; + s->pending_buf = (uch *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return zlib_deflateReset(strm); +} + +#if 0 /**** pts ****/ +/* ========================================================================= */ +int zlib_deflateSetDictionary( + z_streamp strm, + const Byte *dictionary, + uInt dictLength +) +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == NULLP || strm->state == NULLP || dictionary == NULLP) + return Z_STREAM_ERROR; + + s = (deflate_state *) strm->state; + if (s->status != INIT_STATE) return Z_STREAM_ERROR; + + strm->adler = zlib_adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy((char *)s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} +#endif + +/* ========================================================================= */ +int zlib_deflateReset( + z_streamp strm +) +{ + deflate_state *s; + + if (strm == NULLP || strm->state == NULLP) + return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = (char*)NULLP; + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + zlib_tr_init(s); + lm_init(s); + + return Z_OK; +} + +#if 0 /**** pts ****/ +/* ========================================================================= */ +int zlib_deflateParams( + z_streamp strm, + int level, + int strategy +) +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == NULLP || strm->state == NULLP) return Z_STREAM_ERROR; + s = (deflate_state *) strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = zlib_deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} +#endif + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +static void putShortMSB( + deflate_state *s, + uInt b +) +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +static void flush_pending( + z_streamp strm +) +{ + deflate_state *s = (deflate_state *) strm->state; + unsigned len = s->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + if (strm->next_out != NULLP) { + zmemcpy(strm->next_out, s->pending_out, len); + strm->next_out += len; + } + s->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; + } +} + +/* ========================================================================= */ +int zlib_deflate( + z_streamp strm, + int flush +) +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == NULLP || strm->state == NULLP || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) strm->state; + + if ((strm->next_in == NULLP && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + return Z_STREAM_ERROR; + } + if (strm->avail_out == 0) return Z_BUF_ERROR; + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + return Z_BUF_ERROR; + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + return Z_BUF_ERROR; + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + zlib_tr_align(s); + } else if (flush == Z_PACKET_FLUSH) { + /* Output just the 3-bit `stored' block type value, + but not a zero length. */ + zlib_tr_stored_type_only(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + zlib_tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int zlib_deflateEnd( + z_streamp strm +) +{ + int status; + deflate_state *s; + + if (strm == NULLP || strm->state == NULLP) return Z_STREAM_ERROR; + s = (deflate_state *) strm->state; + + status = s->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + strm->state = (struct zlib_internal_state*)NULLP; /**** pts ****/ + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +#if 0 /**** pts ****/ +/* ========================================================================= + * Copy the source state to the destination state. + */ +int zlib_deflateCopy ( + z_streamp dest, + z_streamp source +) +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ush *overlay; + deflate_workspace *mem; + + + if (source == NULLP || dest == NULLP || source->state == NULLP) { + return Z_STREAM_ERROR; + } + + ss = (deflate_state *) source->state; + + *dest = *source; + + mem = (deflate_workspace *) dest->workspace; + + ds = &(mem->deflate_memory); + + dest->state = (struct zlib_internal_state *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Byte *) mem->window_memory; + ds->prev = (Pos *) mem->prev_memory; + ds->head = (Pos *) mem->head_memory; + overlay = (ush *) mem->overlay_memory; + ds->pending_buf = (uch *) overlay; + + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} +#endif + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +static int read_buf( + z_streamp strm, + Byte *buf, + unsigned size +) +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!((deflate_state *)(strm->state))->noheader) { + strm->adler = zlib_adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +static void lm_init( + deflate_state *s +) +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +static uInt longest_match( + deflate_state *s, + IPos cur_match /* current match */ +) +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Byte *scan = s->window + s->strstart; /* current string */ + register Byte *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Pos *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Byte *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ush*)scan; + register ush scan_end = *(ush*)(scan+best_len-1); +#else + register Byte *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ush*)(match+best_len-1) != scan_end || + *(ush*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + *(ush*)(scan+=2) == *(ush*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ush*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return best_len; + return s->lookahead; +} + +#ifdef DEBUG_ZLIB +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +static void check_match( + deflate_state *s, + IPos start, + IPos match, + int length +) +{ + /* check that the match is indeed a match */ + if (memcmp((char *)s->window + match, + (char *)s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +static void fill_window( + deflate_state *s +) +{ + register unsigned n, m; + register Pos *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy((char *)s->window, (char *)s->window+wsize, + (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + zlib_tr_flush_block(s, (s->block_start >= 0L ? \ + (char *)&s->window[(unsigned)s->block_start] : \ + (char *)/****pts****/NULLP), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +static block_state deflate_stored( + deflate_state *s, + int flush +) +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +static block_state deflate_fast( + deflate_state *s, + int flush +) +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + bflush = zlib_tr_tally(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + bflush = zlib_tr_tally (s, 0, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +static block_state deflate_slow( + deflate_state *s, + int flush +) +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + bflush = zlib_tr_tally(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + if (zlib_tr_tally (s, 0, s->window[s->strstart-1])) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + zlib_tr_tally (s, 0, s->window[s->strstart-1]); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +int zlib_deflate_workspacesize(void) +{ + return sizeof(deflate_workspace); +} + +/* +++ trees.c */ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-1996 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* From: trees.c,v 1.11 1996/07/24 13:41:06 me Exp $ */ + +/* #include "deflate.h" */ +#if 0 /**** pts ****/ +# include <linux/zutil.h> +# include "defutil.h" +# ifdef DEBUG_ZLIB +# include <ctype.h> +# endif +#endif + + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +static const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +static const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +static const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +static ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see zlib_tr_init + * below). + */ + +static ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +static uch dist_code[512]; +/* distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +static uch length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +static int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +static int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULLP */ + const int *extra_bits; /* extra bits for each code or NULLP */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +static static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +static static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +static static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +static void tr_static_init (void); +static void init_block (deflate_state *s); +static void pqdownheap (deflate_state *s, ct_data *tree, int k); +static void gen_bitlen (deflate_state *s, tree_desc *desc); +static void gen_codes (ct_data *tree, int max_code, ush *bl_count); +static void build_tree (deflate_state *s, tree_desc *desc); +static void scan_tree (deflate_state *s, ct_data *tree, int max_code); +static void send_tree (deflate_state *s, ct_data *tree, int max_code); +static int build_bl_tree (deflate_state *s); +static void send_all_trees (deflate_state *s, int lcodes, int dcodes, + int blcodes); +static void compress_block (deflate_state *s, ct_data *ltree, + ct_data *dtree); +static void set_data_type (deflate_state *s); +static unsigned bi_reverse (unsigned value, int length); +static void bi_windup (deflate_state *s); +static void bi_flush (deflate_state *s); +static void copy_block (deflate_state *s, char *buf, unsigned len, + int header); + +#ifndef DEBUG_ZLIB +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG_ZLIB */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +#define d_code(dist) \ + ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. dist_code[256] and dist_code[257] are never + * used. + */ + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG_ZLIB +static void send_bits (deflate_state *s, int value, int length); + +static void send_bits( + deflate_state *s, + int value, /* value to send */ + int length /* number of bits */ +) +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG_ZLIB */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG_ZLIB */ + +/* =========================================================================== + * Initialize the various 'constant' tables. In a multi-threaded environment, + * this function may be called by two threads concurrently, but this is + * harmless since both invocations do exactly the same thing. + */ +static void tr_static_init(void) +{ + static int static_init_done; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; +} + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +ZSTATIC void zlib_tr_init( + deflate_state *s +) +{ + tr_static_init(); + + s->compressed_len = 0L; + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG_ZLIB + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +static void init_block( + deflate_state *s +) +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +static void pqdownheap( + deflate_state *s, + ct_data *tree, /* the tree to restore */ + int k /* node to move down */ +) +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +static void gen_bitlen( + deflate_state *s, + tree_desc *desc /* the tree descriptor */ +) +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const int *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +static void gen_codes( + ct_data *tree, /* the tree to decorate */ + int max_code, /* largest code with non zero frequency */ + ush *bl_count /* number of codes at each bit length */ +) +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +static void build_tree( + deflate_state *s, + tree_desc *desc /* the tree descriptor */ +) +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (max(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +static void scan_tree( + deflate_state *s, + ct_data *tree, /* the tree to be scanned */ + int max_code /* and its largest code of non zero frequency */ +) +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +static void send_tree( + deflate_state *s, + ct_data *tree, /* the tree to be scanned */ + int max_code /* and its largest code of non zero frequency */ +) +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +static int build_bl_tree( + deflate_state *s +) +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +static void send_all_trees( + deflate_state *s, + int lcodes, /* number of codes for each tree */ + int dcodes, /* number of codes for each tree */ + int blcodes /* number of codes for each tree */ +) +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +ZSTATIC void zlib_tr_stored_block( + deflate_state *s, + char *buf, /* input block */ + ulg stored_len, /* length of input block */ + int eof /* true if this is the last block for a file */ +) +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; + + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* Send just the `stored block' type code without any length bytes or data. + */ +ZSTATIC void zlib_tr_stored_type_only( + deflate_state *s +) +{ + send_bits(s, (STORED_BLOCK << 1), 3); + bi_windup(s); + s->compressed_len = (s->compressed_len + 3) & ~7L; +} + + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +ZSTATIC void zlib_tr_align( + deflate_state *s +) +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); + s->compressed_len += 10L; + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. This function + * returns the total compressed length for the file so far. + */ +ZSTATIC ulg zlib_tr_flush_block( + deflate_state *s, + char *buf, /* input block, or NULLP if too old */ + ulg stored_len, /* length of input block */ + int eof /* true if this is the last block for a file */ +) +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + /* If compression failed and this is the first and last block, + * and if the .zip file can be seeked (to rewrite the local header), + * the whole file is transformed into a stored file: + */ +#ifdef STORED_FILE_OK +# ifdef FORCE_STORED_FILE + if (eof && s->compressed_len == 0L) { /* force stored file */ +# else + if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) { +# endif + /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ + if (buf == (char*)0) error ("block vanished"); + + copy_block(s, buf, (unsigned)stored_len, 0); /* without header */ + s->compressed_len = stored_len << 3; + s->method = STORED; + } else +#endif /* STORED_FILE_OK */ + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULLP is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + zlib_tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); + s->compressed_len += 3 + s->static_len; + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + s->compressed_len += 3 + s->opt_len; + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + init_block(s); + + if (eof) { + bi_windup(s); + s->compressed_len += 7; /* align on byte boundary */ + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); + + return s->compressed_len >> 3; +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +ZSTATIC int zlib_tr_tally( + deflate_state *s, + unsigned dist, /* distance of matched string */ + unsigned lc /* match length-MIN_MATCH or unmatched char (if dist==0) */ +) +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "zlib_tr_tally: bad match"); + + s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0xfff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +static void compress_block( + deflate_state *s, + ct_data *ltree, /* literal tree */ + ct_data *dtree /* distance tree */ +) +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +static void set_data_type( + deflate_state *s +) +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +static void copy_block( + deflate_state *s, + char *buf, /* the input data */ + unsigned len, /* its length */ + int header /* true if block header must be written */ +) +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG_ZLIB + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG_ZLIB + s->bits_sent += (ulg)len<<3; +#endif + /* bundle up the put_byte(s, *buf++) calls */ + zmemcpy(&s->pending_buf[s->pending], buf, len); + s->pending += len; +} + +/* end of deftree.c */ + +/* ---- </rip> by pts */ + +#if PTS_DEFL_MAIN + +/* + * Usage: flateenc [-<level>] < <inputfile> > <outputfile> + * <level> is one of: 0: no compression; 1: low & fast; 9: high & slow + */ + +#include "pts_defl.h" +#include <unistd.h> /* read(), write() */ +#include <stdio.h> +#include <stdlib.h> /* abort() */ + +int main(int argc, char **argv) { + char ibuf[4096], obuf[6000]; /* Dat: 4096->6000 should be enough */ + char workspace[sizeof(deflate_workspace)]; /* Dat: as returned by zlib_deflate_workspacesize in ZLIB 1.1.3 */ + int got, zgot; + /** Compression level: 0..9 or Z_DEFAULT_COMPRESSION */ + int level=Z_DEFAULT_COMPRESSION; + z_stream zs; + (void)argc; + if (argv && argv[0] && argv[1] && argv[1][0]=='-' && argv[1][1]>='0' && argv[1][1]<='9') + level=argv[1][1]-'0'; + /* printf("ws=%d\n", zlib_deflate_workspacesize()); */ + if (zlib_deflate_workspacesize()+(unsigned)0<sizeof(workspace)) abort(); + zs.total_in=0; + zs.total_out=0; + zs.workspace=workspace; + zs.msg=(char*)NULLP; + zs.state=(struct zlib_internal_state*)NULLP; + zs.data_type=Z_UNKNOWN; /* Imp: do we have to initialize it? */ + if (Z_OK!=zlib_deflateInit(&zs, level)) abort(); + while (0<(got=read(0, ibuf, sizeof(ibuf)))) { + zs.next_in=ibuf; zs.avail_in=got; + zs.next_out=obuf; zs.avail_out=sizeof(obuf); + if (Z_OK!=zlib_deflate(&zs, 0)) abort(); +#ifdef DEBUG_PTS_DEFL + fprintf(stderr, "ai=%d ao=%d no=%d\n", zs.avail_in, zs.avail_out, (char*)zs.next_out-obuf); +#endif + if (0!=zs.avail_in) abort(); + got=sizeof(obuf)-zs.avail_out; + if (got>0 && got!=write(1, zs.next_out-got, got)) abort(); + } + if (0!=got) abort(); + do { /* flush all output */ + zs.next_in=NULL; zs.avail_in=0; + zs.next_out=obuf; zs.avail_out=sizeof(obuf); + if (Z_STREAM_END!=(zgot=zlib_deflate(&zs, Z_FINISH)) && Z_OK!=zgot) abort(); +#ifdef DEBUG_PTS_DEFL + fprintf(stderr, "ai=%d ao=%d flush\n", zs.avail_in, zs.avail_out); +#endif + got=sizeof(obuf)-zs.avail_out; + if (got>0 && got!=write(1, zs.next_out-got, got)) abort(); + } while (zgot==Z_OK); + if (Z_OK!=zlib_deflateEnd(&zs)) abort(); + return 0; +} + +#endif diff --git a/Build/source/utils/sam2p/pts_defl.h b/Build/source/utils/sam2p/pts_defl.h new file mode 100644 index 00000000000..86390b77111 --- /dev/null +++ b/Build/source/utils/sam2p/pts_defl.h @@ -0,0 +1,95 @@ +/* + * pts_defl.h -- C header file ZIP compression ripped from linux-2.6.8.1 + * by pts@fazekas.hu at Tue Jan 18 15:19:06 CET 2005 + * + * This ZIP compression (ZIP == PostScript /FlateEncode compression filter + * (ZLIB RFC 1950)) routine has been ripped from the Linux kernel 2.6.8.1 + * (directory lib/zlib_deflate), which has been ripped from ZLIB 1.1.3 + * + * This is a minimal .h file, to avoid namespace pollution. + * See more in the beginning of pts_defl.c + * For documentation comments, see pts_defl.c + * + */ + +#ifndef PTS_DEFL_H +#define PTS_DEFL_H + +#define PTS_DEFL_RIPPED_ZLIB 1 + +/** Must be at least zlib_deflate_workspacesize(): 267946 on Linux i386 */ +#define ZLIB_DEFLATE_WORKSPACESIZE_MIN 270000 + +#define ZLIB_VERSION "1.1.3" + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_PACKET_FLUSH 2 +#define Z_SYNC_FLUSH 3 +#define Z_FULL_FLUSH 4 +#define Z_FINISH 5 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +struct zlib_internal_state; /**** pts ****/ /* Dat: was: internal_state */ + +typedef struct z_stream_s { + unsigned char *next_in; /* next input byte */ + unsigned int avail_in; /* number of bytes available at next_in */ + unsigned long total_in; /* total nb of input bytes read so far */ + + unsigned char *next_out; /* next output byte should be put there */ + unsigned int avail_out; /* remaining free space at next_out */ + unsigned long total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULLP if no error */ + struct zlib_internal_state *state; /* not visible by applications */ + + void *workspace; /* memory allocated for this stream */ + + int data_type; /* best guess about the data type: ascii or binary */ + unsigned long adler; /* adler32 value of the uncompressed data */ + unsigned long reserved; /* reserved for future use */ +} z_stream; + +extern int zlib_deflate_workspacesize (void); +extern int zlib_deflate (z_stream* strm, int flush); +extern int zlib_deflateEnd (z_stream* strm); +extern int zlib_deflateParams (z_stream* strm, int level, int strategy); + +extern int zlib_deflateInit_ (z_stream* strm, int level, + const char *version, int stream_size); +extern int zlib_deflateInit2_ (z_stream* strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +#define zlib_deflateInit(strm, level) \ + zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) + +#endif diff --git a/Build/source/utils/sam2p/pts_fax.c b/Build/source/utils/sam2p/pts_fax.c new file mode 100644 index 00000000000..39a1f6819eb --- /dev/null +++ b/Build/source/utils/sam2p/pts_fax.c @@ -0,0 +1,3221 @@ +/* + * pts_fax.c -- a compact CCITTFax compressor and uncompressor) implementation + * compiled by pts@fazekas.hu at Sun Jul 7 19:51:42 CEST 2002 + * + * algorithm ripped from GNU Ghostscript, implementation and (C): + * +Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All +rights reserved. + +GNU Ghostscript is free software; you can redistribute it and/or +modify it under the terms of version 2 of the GNU General Public +License as published by the Free Software Foundation. + +GNU Ghostscript 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 so you can know your rights and responsibilities. +It should be in a file named doc/COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA +02111-1307, USA. + */ + +#include "pts_fax.h" +#if 0 /* doesn't work in C++ */ +# define intern static +# define impl static +# define intern_const static const +# define impl_const static const +#else +# define intern static +# define impl static +# define intern_const extern const +# define impl_const const +#endif +/* #define cxxintern extern */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +/* misc_types.h by pts@fazekas.hu at Sat Jul 6 19:20:17 CEST 2002 */ +#ifndef MISC_TYPES_H +#define MISC_TYPES_H 1 + +/* #include "config2.h" */ + +#define BEGIN do { +#define END } while (0) +#ifndef DO_NOTHING +# define DO_NOTHING BEGIN END +#endif + +# define if_debug0(c,s) DO_NOTHING +# define if_debug1(c,s,a1) DO_NOTHING +# define if_debug2(c,s,a1,a2) DO_NOTHING +# define if_debug3(c,s,a1,a2,a3) DO_NOTHING +# define if_debug4(c,s,a1,a2,a3,a4) DO_NOTHING +# define if_debug5(c,s,a1,a2,a3,a4,a5) DO_NOTHING +# define if_debug6(c,s,a1,a2,a3,a4,a5,a6) DO_NOTHING +# define if_debug7(c,s,a1,a2,a3,a4,a5,a6,a7) DO_NOTHING +# define if_debug8(c,s,a1,a2,a3,a4,a5,a6,a7,a8) DO_NOTHING +# define if_debug9(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9) DO_NOTHING +# define if_debug10(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) DO_NOTHING +# define if_debug11(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) DO_NOTHING +# define if_debug12(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) DO_NOTHING + +/* to the one that all the compilers seem to have.... */ +#ifndef min +# define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef max +# define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/* Define a standard way to round values to a (constant) modulus. */ +#define ROUND_DOWN(value, modulus)\ + ( (modulus) & ((modulus) - 1) ? /* not a power of 2 */\ + (value) - (value) % (modulus) :\ + (value) & -(modulus) ) +#define ROUND_UP(value, modulus)\ + ( (modulus) & ((modulus) - 1) ? /* not a power of 2 */\ + ((value) + ((modulus) - 1)) / (modulus) * (modulus) :\ + ((value) + ((modulus) - 1)) & -(modulus) ) + +#define countof(a) (sizeof(a) / sizeof((a)[0])) + +#define gs_alloc_bytes(a, n, c) ss->xalloc_(n) +#define gs_free_object(a, ptr, c) ss->free_(ptr) + +#endif /* gstypes.h */ +/* end of former misc_types.h */ + +/* gsbittab.h */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Interface to tables for bit operations */ + +#ifndef gsbittab_INCLUDED +# define gsbittab_INCLUDED + +/* + * Generate tables for transforming 2, 4, 6, or 8 bits. + */ +#define btab2_(v0,v2,v1)\ + v0,v1+v0,v2+v0,v2+v1+v0 +#define bit_table_2(v0,v2,v1) btab2_(v0,v2,v1) +#define btab4_(v0,v8,v4,v2,v1)\ + btab2_(v0,v2,v1), btab2_(v4+v0,v2,v1),\ + btab2_(v8+v0,v2,v1), btab2_(v8+v4+v0,v2,v1) +#define bit_table_4(v0,v8,v4,v2,v1) btab4_(v0,v8,v4,v2,v1) +#define btab6_(v0,v20,v10,v8,v4,v2,v1)\ + btab4_(v0,v8,v4,v2,v1), btab4_(v10+v0,v8,v4,v2,v1),\ + btab4_(v20+v0,v8,v4,v2,v1), btab4_(v20+v10+v0,v8,v4,v2,v1) +#define bit_table_6(v0,v20,v10,v8,v4,v2,v1) btab6_(v0,v20,v10,v8,v4,v2,v1) +#define bit_table_8(v0,v80,v40,v20,v10,v8,v4,v2,v1)\ + btab6_(v0,v20,v10,v8,v4,v2,v1), btab6_(v40+v0,v20,v10,v8,v4,v2,v1),\ + btab6_(v80+v0,v20,v10,v8,v4,v2,v1), btab6_(v80+v40+v0,v20,v10,v8,v4,v2,v1) + +/* + * byte_reverse_bits[B] = the unsigned char B with the order of bits reversed. + */ +intern_const unsigned char byte_reverse_bits[256]; + +/* + * byte_right_mask[N] = a unsigned char with N trailing 1s, 0 <= N <= 8. + */ +intern_const unsigned char byte_right_mask[9]; + +/* + * byte_count_bits[B] = the number of 1-bits in a unsigned char with value B. + */ +intern_const unsigned char byte_count_bits[256]; + +/* + * byte_bit_run_length_N[B], for 0 <= N <= 7, gives the length of the + * run of 1-bits starting at bit N in a unsigned char with value B, + * numbering the bits in the unsigned char as 01234567. If the run includes + * the low-order bit (i.e., might be continued into a following unsigned char), + * the run length is increased by 8. + */ +intern_const unsigned char + byte_bit_run_length_0[256], byte_bit_run_length_1[256], + byte_bit_run_length_2[256], byte_bit_run_length_3[256], + byte_bit_run_length_4[256], byte_bit_run_length_5[256], + byte_bit_run_length_6[256], byte_bit_run_length_7[256]; + +/* + * byte_bit_run_length[N] points to byte_bit_run_length_N. + * byte_bit_run_length_neg[N] = byte_bit_run_length[-N & 7]. + */ +intern_const unsigned char *const byte_bit_run_length[8]; +intern_const unsigned char *const byte_bit_run_length_neg[8]; + +/* + * byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters + * denote the individual bits of the unsigned char. + */ +intern_const unsigned char byte_acegbdfh_to_abcdefgh[256]; + +#endif /* gsbittab_INCLUDED */ + +/* end of former gsbittab.h */ + +/* shc.h */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Common definitions for filters using Huffman coding */ + +#ifndef shc_INCLUDED +# define shc_INCLUDED + +/* #include "gsbittab.h" */ + +#define hc_bits_size (SIZEOF_INT * 8) +#define s_hce_init_inline(ss)\ + ((ss)->bits = 0, (ss)->bits_left = hc_bits_size) +#define s_hcd_init_inline(ss)\ + ((ss)->bits = 0, (ss)->bits_left = 0) + +/* + * These definitions are valid for code lengths up to 16 bits + * and non-negative decoded values up to 15 bits. + * + * We define 3 different representations of the code: encoding tables, + * decoding tables, and a definition table which can be generated easily + * from frequency information and which in turn can easily generate + * the encoding and decoding tables. + * + * The definition table has two parts: a list of the number of i-bit + * codes for each i >= 1, and the decoded values corresponding to + * the code values in increasing lexicographic order (which will also + * normally be decreasing code frequency). Calling these two lists + * L[1..M] and V[0..N-1] respectively, we have the following invariants: + * - 1 <= M <= max_hc_length, N >= 2. + * - L[0] = 0. + * - for i=1..M, L[i] >= 0. + * - sum(i=1..M: L[i]) = N. + * - sum(i=1..M: L[i] * 2^-i) = 1. + * - V[0..N-1] are a permutation of the integers 0..N-1. + */ +#define max_hc_length 16 +typedef struct hc_definition_s { + unsigned short *counts; /* [0..M] */ + unsigned int num_counts; /* M */ + unsigned short *values; /* [0..N-1] */ + unsigned int num_values; /* N */ +} hc_definition; + +/**** pts ****/ +struct stream_hc_state_s; +/* definition moved to pts_fax.h */ + +/* ------ Encoding tables ------ */ + +/* Define the structure for the encoding tables. */ +typedef struct hce_code_s { + unsigned short code; + unsigned short code_length; +} hce_code; + +#define hce_entry(c, len) { c, len } + +typedef struct hce_table_s { + unsigned int count; + hce_code *codes; +} hce_table; + +#define hce_bits_available(n)\ + (ss->bits_left >= (n) || wlimit - q > ((n) - ss->bits_left - 1) >> 3) + +/* ------ Encoding utilities ------ */ + +/* + * Put a code on the output. The client is responsible for ensuring + * that q does not exceed pw->limit. + */ + +#ifdef DEBUG +# define hc_print_value(code, clen)\ + (gs_debug_c('W') ?\ + (dlprintf2("[W]0x%x,%d\n", code, clen), 0) : 0) +# define hc_print_value_then(code, clen) hc_print_value(code, clen), +#else +# define hc_print_value(code, clen) 0 +# define hc_print_value_then(code, clen) /* */ +#endif +#define hc_print_code(rp) hc_print_value((rp)->code, (rp)->code_length) + +/* Declare variables that hold the encoder state. */ +#define hce_declare_state\ + register unsigned int bits;\ + register int bits_left + +/* Load the state from the stream. */ +/* Free variables: ss, bits, bits_left. */ +#define hce_load_state()\ + bits = ss->bits, bits_left = ss->bits_left + +/* Store the state back in the stream. */ +/* Free variables: ss, bits, bits_left. */ +#define hce_store_state()\ + ss->bits = bits, ss->bits_left = bits_left + +/* Put a code on the stream. */ +intern void hc_put_code_proc _((bool, unsigned char *, unsigned int)); + +#define hc_put_value(ss, q, code, clen)\ + (hc_print_value_then(code, clen)\ + ((bits_left -= (clen)) >= 0 ?\ + (bits += (code) << bits_left) :\ + (hc_put_code_proc((ss)->FirstBitLowOrder,\ + q += hc_bits_size >> 3,\ + (bits + ((code) >> -bits_left))),\ + bits = (code) << (bits_left += hc_bits_size)))) +#define hc_put_code(ss, q, cp)\ + hc_put_value(ss, q, (cp)->code, (cp)->code_length) + +/* + * Force out the final bits to the output. + * Note that this does a store_state, but not a load_state. + */ +intern unsigned char *hc_put_last_bits_proc _((struct stream_hc_state_s *, unsigned char *, unsigned int, int)); + +#define hc_put_last_bits(ss, q)\ + hc_put_last_bits_proc(ss, q, bits, bits_left) + +/* ------ Decoding tables ------ */ + +/* + * Define the structure for the decoding tables. + * First-level nodes are either leaves, which have + * value = decoded value + * code_length <= initial_bits + * or non-leaves, which have + * value = the index of a sub-table + * code_length = initial_bits + the number of additional dispatch bits + * Second-level nodes are always leaves, with + * code_length = the actual number of bits in the code - initial_bits. + */ + +typedef struct hcd_code_s { + short value; + unsigned short code_length; +} hcd_code; + +typedef struct hcd_table_s { + unsigned int count; + unsigned int initial_bits; + hcd_code *codes; +} hcd_table; + +/* Declare variables that hold the decoder state. */ +#define hcd_declare_state\ + register const unsigned char *p;\ + const unsigned char *rlimit;\ + unsigned int bits;\ + int bits_left + +/* Load the state from the stream. */ +/* Free variables: pr, ss, p, rlimit, bits, bits_left. */ +#define hcd_load_state()\ + p = pr->ptr,\ + rlimit = pr->limit,\ + bits = ss->bits,\ + bits_left = ss->bits_left + +/* Store the state back in the stream. */ +/* Put back any complete bytes into the input buffer. */ +/* Free variables: pr, ss, p, bits, bits_left. */ +#define hcd_store_state()\ + pr->ptr = p -= (bits_left >> 3),\ + ss->bits = bits >>= (bits_left & ~7),\ + ss->bits_left = bits_left &= 7 + +/* Macros to get blocks of bits from the input stream. */ +/* Invariants: 0 <= bits_left <= bits_size; */ +/* bits [bits_left-1..0] contain valid data. */ + +#define hcd_bits_available(n)\ + (bits_left >= (n) || rlimit - p > ((n) - bits_left - 1) >> 3) +/* For hcd_ensure_bits, n must not be greater than 8. */ +#define HCD_ENSURE_BITS_ELSE(n)\ + if (bits_left >= n)\ + DO_NOTHING;\ + else HCD_MORE_BITS_ELSE +#define hcd_ensure_bits(n, outl)\ + BEGIN HCD_ENSURE_BITS_ELSE(n) goto outl; END + +/* Load more bits into the buffer. */ +#define HCD_MORE_BITS_1_ELSE\ + if (p < rlimit) {\ + int c = *++p;\ +\ + if (ss->FirstBitLowOrder)\ + c = byte_reverse_bits[c];\ + bits = (bits << 8) + c, bits_left += 8;\ + } else +#if hc_bits_size == 16 +# define HCD_MORE_BITS_ELSE HCD_MORE_BITS_1_ELSE +#else /* hc_bits_size >= 32 */ +# define HCD_MORE_BITS_ELSE\ + if (rlimit - p >= 3) {\ + if (ss->FirstBitLowOrder)\ + bits = (bits << 24) + ((unsigned int)byte_reverse_bits[p[1]] << 16) + ((unsigned int)byte_reverse_bits[p[2]] << 8) + byte_reverse_bits[p[3]];\ + else\ + bits = (bits << 24) + ((unsigned int)p[1] << 16) + ((unsigned int)p[2] << 8) + p[3];\ + bits_left += 24, p += 3;\ + } else HCD_MORE_BITS_1_ELSE +#endif +#define hcd_more_bits(outl)\ + BEGIN HCD_MORE_BITS_ELSE goto outl; END + +#define hcd_peek_bits(n) ((bits >> (bits_left - (n))) & ((1 << (n)) - 1)) + +/* hcd_peek_var_bits requires bits_left <= 8. */ +#define hcd_peek_var_bits(n)\ + ((bits >> (bits_left - (n))) & byte_right_mask[n]) + +/* hcd_peek_bits_left requires bits_left <= 8. */ +#define hcd_peek_bits_left()\ + (bits & byte_right_mask[bits_left]) + +#define hcd_skip_bits(n) (bits_left -= (n)) + +#endif /* shc_INCLUDED */ + +/* end of former shc.h */ + +/* scf.h */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Common definitions for CCITTFax encoding and decoding filters */ + +#ifndef scf_INCLUDED +# define scf_INCLUDED + +/* #include "shc.h" */ + +/* + * The CCITT Group 3 (T.4) and Group 4 (T.6) fax specifications map + * run lengths to Huffman codes. White and black have different mappings. + * If the run length is 64 or greater, two or more codes are needed: + * - One or more 'make-up' codes for 2560 pixels; + * - A 'make-up' code that encodes the multiple of 64; + * - A 'termination' code for the remainder. + * For runs of 63 or less, only the 'termination' code is needed. + */ + +/* ------ Encoding tables ------ */ + +/* + * The maximum possible length of a scan line is determined by the + * requirement that 3 runs have to fit into the stream buffer. + * A run of length N requires approximately ceil(N / 2560) makeup codes, + * hence 1.5 * ceil(N / 2560) bytes. Taking the largest safe stream + * buffer size as 32K, we arrive at the following maximum width: + */ +#if SIZEOF_INT > 2 +# define cfe_max_width (2560 * 32000 * 2 / 3) +#else +# define cfe_max_width (max_int - 40) /* avoid overflows */ +#endif +/* The +5 in cfe_max_code_bytes is a little conservative. */ +#define cfe_max_code_bytes(width) ((width) / 2560 * 3 / 2 + 5) + +typedef hce_code cfe_run; + +/* Codes common to 1-D and 2-D encoding. */ +/* The decoding algorithms know that EOL is 0....01. */ +#define run_eol_code_length 12 +#define run_eol_code_value 1 +intern_const cfe_run cf_run_eol; +typedef struct cf_runs_s { + cfe_run termination[64]; + cfe_run make_up[41]; +} cf_runs; +intern_const cf_runs + cf_white_runs, cf_black_runs; +intern_const cfe_run cf_uncompressed[6]; +intern_const cfe_run cf_uncompressed_exit[10]; /* indexed by 2 x length of */ + + /* white run + (1 if next run black, 0 if white) */ +/* 1-D encoding. */ +intern_const cfe_run cf1_run_uncompressed; + +/* 2-D encoding. */ +intern_const cfe_run cf2_run_pass; + +#define cf2_run_pass_length 4 +#define cf2_run_pass_value 0x1 +#define cf2_run_vertical_offset 3 +intern_const cfe_run cf2_run_vertical[7]; /* indexed by b1 - a1 + offset */ +intern_const cfe_run cf2_run_horizontal; + +#define cf2_run_horizontal_value 1 +#define cf2_run_horizontal_length 3 +intern_const cfe_run cf2_run_uncompressed; + +/* 2-D Group 3 encoding. */ +intern_const cfe_run cf2_run_eol_1d; +intern_const cfe_run cf2_run_eol_2d; + +/* ------ Decoding tables ------ */ + +typedef hcd_code cfd_node; + +#define run_length value + +/* + * The value in the decoding tables is either a white or black run length, + * or a (negative) exceptional value. + */ +#define run_error (-1) +#define run_zeros (-2) /* EOL follows, possibly with more padding first */ +#define run_uncompressed (-3) +/* 2-D codes */ +#define run2_pass (-4) +#define run2_horizontal (-5) + +#define cfd_white_initial_bits 8 +#define cfd_white_min_bits 4 /* shortest white run */ +/* intern_const cfd_node cf_white_decode[]; */ + +#define cfd_black_initial_bits 7 +#define cfd_black_min_bits 2 /* shortest black run */ +/* intern_const cfd_node cf_black_decode[]; */ + +#define cfd_2d_initial_bits 7 +#define cfd_2d_min_bits 4 /* shortest non-H/V 2-D run */ +/* intern_const cfd_node cf_2d_decode[]; */ + +#define cfd_uncompressed_initial_bits 6 /* must be 6 */ +/* intern_const cfd_node cf_uncompressed_decode[]; */ + +/* ------ Run detection macros ------ */ + +/* + * For the run detection macros: + * white_byte is 0 or 0xff for BlackIs1 or !BlackIs1 respectively; + * data holds p[-1], inverted if !BlackIs1; + * count is the number of valid bits remaining in the scan line. + */ + +/* Aliases for bit processing tables. */ +#define cf_byte_run_length byte_bit_run_length_neg +#define cf_byte_run_length_0 byte_bit_run_length_0 + +/* Skip over white pixels to find the next black pixel in the input. */ +/* Store the run length in rlen, and update data, p, and count. */ +/* There are many more white pixels in typical input than black pixels, */ +/* and the runs of white pixels tend to be much longer, so we use */ +/* substantially different loops for the two cases. */ + +#define skip_white_pixels(data, p, count, white_byte, rlen)\ +BEGIN\ + rlen = cf_byte_run_length[count & 7][data ^ 0xff];\ + if ( rlen >= 8 ) { /* run extends past unsigned char boundary */\ + if ( white_byte == 0 ) {\ + if ( p[0] ) { data = p[0]; p += 1; rlen -= 8; }\ + else if ( p[1] ) { data = p[1]; p += 2; }\ + else {\ + while ( !(p[2] | p[3] | p[4] | p[5]) )\ + p += 4, rlen += 32;\ + if ( p[2] ) {\ + data = p[2]; p += 3; rlen += 8;\ + } else if ( p[3] ) {\ + data = p[3]; p += 4; rlen += 16;\ + } else if ( p[4] ) {\ + data = p[4]; p += 5; rlen += 24;\ + } else /* p[5] */ {\ + data = p[5]; p += 6; rlen += 32;\ + }\ + }\ + } else {\ + if ( p[0] != 0xff ) { data = (unsigned char)~p[0]; p += 1; rlen -= 8; }\ + else if ( p[1] != 0xff ) { data = (unsigned char)~p[1]; p += 2; }\ + else {\ + while ( (p[2] & p[3] & p[4] & p[5]) == 0xff )\ + p += 4, rlen += 32;\ + if ( p[2] != 0xff ) {\ + data = (unsigned char)~p[2]; p += 3; rlen += 8;\ + } else if ( p[3] != 0xff ) {\ + data = (unsigned char)~p[3]; p += 4; rlen += 16;\ + } else if ( p[4] != 0xff ) {\ + data = (unsigned char)~p[4]; p += 5; rlen += 24;\ + } else /* p[5] != 0xff */ {\ + data = (unsigned char)~p[5]; p += 6; rlen += 32;\ + }\ + }\ + }\ + rlen += cf_byte_run_length_0[data ^ 0xff];\ + }\ + count -= rlen;\ +END + +/* Skip over black pixels to find the next white pixel in the input. */ +/* Store the run length in rlen, and update data, p, and count. */ + +#define skip_black_pixels(data, p, count, white_byte, rlen)\ +BEGIN\ + rlen = cf_byte_run_length[count & 7][data];\ + if ( rlen >= 8 ) {\ + if ( white_byte == 0 )\ + for ( ; ; p += 4, rlen += 32 ) {\ + if ( p[0] != 0xff ) { data = p[0]; p += 1; rlen -= 8; break; }\ + if ( p[1] != 0xff ) { data = p[1]; p += 2; break; }\ + if ( p[2] != 0xff ) { data = p[2]; p += 3; rlen += 8; break; }\ + if ( p[3] != 0xff ) { data = p[3]; p += 4; rlen += 16; break; }\ + }\ + else\ + for ( ; ; p += 4, rlen += 32 ) {\ + if ( p[0] ) { data = (unsigned char)~p[0]; p += 1; rlen -= 8; break; }\ + if ( p[1] ) { data = (unsigned char)~p[1]; p += 2; break; }\ + if ( p[2] ) { data = (unsigned char)~p[2]; p += 3; rlen += 8; break; }\ + if ( p[3] ) { data = (unsigned char)~p[3]; p += 4; rlen += 16; break; }\ + }\ + rlen += cf_byte_run_length_0[data];\ + }\ + count -= rlen;\ +END + +#endif /* scf_INCLUDED */ + +/* end of former scf.h */ + +#if USE_BUILTIN_FAXE +#if OBJDEP +# warning PROVIDES: pts_faxe +#endif +/* scfe.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* CCITTFax encoding filter */ +/* #include "config2.h" */ +/* #include "scf.h" */ +/* #include "scfx.h" */ + +/* ------ Macros and support routines ------ */ + +/* Statistics */ + +#ifdef DEBUG + +typedef struct stats_runs_s { + unsigned long termination[64]; + unsigned long make_up[41]; +} stats_runs_t; +static stats_runs_t stats_white_runs, stats_black_runs; + +#define COUNT_RUN(tab, i) (tab)[i]++; + +static void +print_run_stats(const stats_runs_t * stats) +{ + int i; + unsigned long total; + + for (i = 0, total = 0; i < 41; i++) + dprintf1(" %lu", stats->make_up[i]), + total += stats->make_up[i]; + dprintf1(" total=%lu\n\t", total); + for (i = 0, total = 0; i < 64; i++) + dprintf1(" %lu", stats->termination[i]), + total += stats->termination[i]; + dprintf1(" total=%lu\n", total); +} + +#else /* !DEBUG */ + +#define COUNT_RUN(cnt, i) DO_NOTHING + +#endif /* DEBUG */ + +/* Put a run onto the output stream. */ +/* Free variables: q, bits, bits_left. */ + +#define CF_PUT_RUN(ss, lenv, rt, stats)\ +BEGIN\ + cfe_run rr;\ +\ + if ( lenv >= 64 ) {\ + hce_store_state();\ + q = cf_put_long_run(ss, q, lenv, &rt);\ + hce_load_state();\ + lenv &= 63;\ + }\ + rr = rt.termination[lenv];\ + COUNT_RUN(stats.termination, lenv);\ + hc_put_value(ss, q, rr.code, rr.code_length);\ +END + +static unsigned char * +cf_put_long_run(stream_CFE_state * ss, unsigned char * q, int lenv, const cf_runs * prt) +{ + hce_declare_state; + cfe_run rr; + +#ifdef DEBUG + stats_runs_t *pstats = + (prt == &cf_white_runs ? &stats_white_runs : &stats_black_runs); + +#endif + + hce_load_state(); + while (lenv >= 2560 + 64) { + rr = prt->make_up[40]; + COUNT_RUN(pstats->make_up, 40); + hc_put_value(ss, q, rr.code, rr.code_length); + lenv -= 2560; + } + rr = prt->make_up[lenv >> 6]; + COUNT_RUN(pstats->make_up, lenv >> 6); + hc_put_value(ss, q, rr.code, rr.code_length); + hce_store_state(); + return q; +} + +#define CF_PUT_WHITE_RUN(ss, lenv)\ + CF_PUT_RUN(ss, lenv, cf_white_runs, stats_white_runs) + +#define CF_PUT_BLACK_RUN(ss, lenv)\ + CF_PUT_RUN(ss, lenv, cf_black_runs, stats_black_runs) + +/* ------ CCITTFaxEncode ------ */ + +/* private_st_CFE_state(); */ + +static void s_CFE_release _((stream_state *)); + +/* Set default parameter values. */ +static void +s_CFE_set_defaults(register stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + + s_CFE_set_defaults_inline(ss); +} + +/* Initialize CCITTFaxEncode filter */ +static int +s_CFE_init(register stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + int columns = ss->Columns; + + /* + * The worst case for encoding is alternating white and black pixels. + * For 1-D encoding, the worst case is 9 bits per 2 pixels; for 2-D + * (horizontal), 12 bits per 2 pixels. To fill out a scan line, + * we may add up to 6 12-bit EOL codes. + */ + /**** pts: added UL ****/ + int code_bytes = + ((columns * (ss->K == 0 ? 9UL : 12UL)) >> 4) + 20; /* add slop */ + int raster = ss->raster = + ROUND_UP((columns + 7) >> 3, ss->DecodedByteAlign); + + s_hce_init_inline(ss); + ss->lbuf = ss->lprev = ss->lcode = 0; /* in case we have to release */ + if (columns > cfe_max_width) + return PTSFAX_ERRC; +/****** WRONG ******/ + /* Because skip_white_pixels can look as many as 4 bytes ahead, */ + /* we need to allow 4 extra bytes at the end of the row buffers. */ + ss->lbuf = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFE lbuf"); + ss->lcode = (unsigned char*)gs_alloc_bytes(st->memory, code_bytes, "CFE lcode"); + if (ss->lbuf == 0 || ss->lcode == 0) { + s_CFE_release(st); + return PTSFAX_ERRC; +/****** WRONG ******/ + } + if (ss->K != 0) { + ss->lprev = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFE lprev"); + if (ss->lprev == 0) { + s_CFE_release(st); + return PTSFAX_ERRC; +/****** WRONG ******/ + } + /* Clear the initial reference line for 2-D encoding. */ + /* Make sure it is terminated properly. */ + ss->memset_(ss->lprev, (ss->BlackIs1 ? 0 : 0xff), raster); + if (columns & 7) + ss->lprev[raster - 1] ^= 0x80 >> (columns & 7); + else + ss->lprev[raster] = ~ss->lprev[0]; + } + ss->read_count = raster; + ss->write_count = 0; + ss->k_left = (ss->K > 0 ? 1 : ss->K); + ss->max_code_bytes = code_bytes; + return 0; +} + +/* Release the filter. */ +static void +s_CFE_release(stream_state * st) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + + gs_free_object(st->memory, ss->lprev, "CFE lprev(close)"); + gs_free_object(st->memory, ss->lcode, "CFE lcode(close)"); + gs_free_object(st->memory, ss->lbuf, "CFE lbuf(close)"); +} + +/* Flush the buffer */ +static void cf_encode_1d _((stream_CFE_state *, const unsigned char *, + stream_cursor_write *)); +static void cf_encode_2d _((stream_CFE_state *, const unsigned char *, + stream_cursor_write *, const unsigned char *)); +static int +s_CFE_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_CFE_state *const ss = (stream_CFE_state *) st; + const unsigned char *rlimit = pr->limit; + unsigned char *wlimit = pw->limit; + int raster = ss->raster; + unsigned char end_mask = 1 << (-ss->Columns & 7); + int status = 0; + + for (;;) { + stream_cursor_write w; + + if_debug2('w', "[w]CFE: read_count = %d, write_count=%d,\n", + ss->read_count, ss->write_count); + if_debug6('w', " pr = 0x%lx(%d)0x%lx, pw = 0x%lx(%d)0x%lx\n", + (unsigned long) pr->ptr, (int)(rlimit - pr->ptr), (unsigned long) rlimit, + (unsigned long) pw->ptr, (int)(wlimit - pw->ptr), (unsigned long) wlimit); + if (ss->write_count) { + /* Copy more of an encoded line to the caller. */ + int wcount = wlimit - pw->ptr; + int ccount = min(wcount, ss->write_count); + + ss->memcpy_(pw->ptr + 1, ss->lcode + ss->code_bytes - ss->write_count, + ccount); + pw->ptr += ccount; + if ((ss->write_count -= ccount) > 0) { + status = 1; + break; + } + } + if (ss->read_count) { + /* Copy more of an unencoded line from the caller. */ + int rcount = rlimit - pr->ptr; + int ccount = min(rcount, ss->read_count); + + if (rcount == 0 && last) + break; + ss->memcpy_(ss->lbuf + raster - ss->read_count, + pr->ptr + 1, ccount); + pr->ptr += ccount; + if ((ss->read_count -= ccount) != 0) + break; + } + /* + * We have a full scan line in lbuf. Ensure that it ends with + * two polarity changes. + */ + { + unsigned char *end = ss->lbuf + raster - 1; + unsigned char end_bit = *end & end_mask; + unsigned char not_bit = end_bit ^ end_mask; + + *end &= -end_mask; + if (end_mask == 1) + end[1] = (end_bit ? 0x40 : 0x80); + else if (end_mask == 2) + *end |= not_bit >> 1, end[1] = end_bit << 7; + else + *end |= (not_bit >> 1) | (end_bit >> 2); + } + /* + * Write the output directly to the caller's buffer if it's large + * enough, otherwise to our own buffer. + */ + if (wlimit - pw->ptr >= ss->max_code_bytes) { + w = *pw; + } else { + w.ptr = ss->lcode - 1; + w.limit = w.ptr + ss->max_code_bytes; + } +#ifdef DEBUG + if (ss->K > 0) { + if_debug1('w', "[w]new row, k_left=%d\n", + ss->k_left); + } else { + if_debug0('w', "[w]new row\n"); + } +#endif + /* + * Write an EOL (actually a "beginning of line") if requested. + */ + if (ss->EndOfLine) { + const cfe_run *rp = + (ss->K <= 0 ? &cf_run_eol : + ss->k_left > 1 ? &cf2_run_eol_2d : + &cf2_run_eol_1d); + cfe_run run; + + hce_declare_state; + + hce_load_state(); + if (ss->EncodedByteAlign) { + run = *rp; + /* Pad the run on the left */ + /* so it winds up unsigned char-aligned. */ + run.code_length += + (bits_left - run_eol_code_length) & 7; + if (run.code_length > 16) /* <= 23 */ + bits_left -= run.code_length & 7, + run.code_length = 16; + rp = &run; + } + hc_put_code(ss, w.ptr, rp); + hce_store_state(); + } else if (ss->EncodedByteAlign) + ss->bits_left &= ~7; + /* Encode the line. */ + if (ss->K == 0) + cf_encode_1d(ss, ss->lbuf, &w); /* pure 1-D */ + else if (ss->K < 0) + cf_encode_2d(ss, ss->lbuf, &w, ss->lprev); /* pure 2-D */ + else if (--(ss->k_left)) /* mixed, use 2-D */ + cf_encode_2d(ss, ss->lbuf, &w, ss->lprev); + else { /* mixed, use 1-D */ + cf_encode_1d(ss, ss->lbuf, &w); + ss->k_left = ss->K; + } + /* + * If we didn't write directly to the client's buffer, schedule + * the output data to be written. + */ + if (w.limit == wlimit) + pw->ptr = w.ptr; + else + ss->write_count = ss->code_bytes = w.ptr - (ss->lcode - 1); + if (ss->K != 0) { + /* In 2-D modes, swap the current and previous scan lines. */ + unsigned char *temp = ss->lbuf; + + ss->lbuf = ss->lprev; + ss->lprev = temp; + } + /* Note that the input buffer needs refilling. */ + ss->read_count = raster; + } + /* + * When we exit from the loop, we know that write_count = 0, and + * there is no line waiting to be processed in the input buffer. + */ + if (last && status == 0) { + const cfe_run *rp = + (ss->K > 0 ? &cf2_run_eol_1d : &cf_run_eol); + int i = (!ss->EndOfBlock ? 0 : ss->K < 0 ? 2 : 6); + unsigned int bits_to_write = + hc_bits_size - ss->bits_left + i * rp->code_length; + unsigned char *q = pw->ptr; + + hce_declare_state; + + if (0U+(wlimit - q) < (bits_to_write + 7) >> 3) { /* PTS_UNSIGNED */ + status = 1; + goto out; + } + hce_load_state(); + if (ss->EncodedByteAlign) + bits_left &= ~7; + while (--i >= 0) + hc_put_code(ss, q, rp); + /* Force out the last unsigned char or bytes. */ + pw->ptr = hc_put_last_bits((stream_hc_state *) ss, q); + } + out: + if_debug9('w', "[w]CFE exit %d: read_count = %d, write_count = %d,\n pr = 0x%lx(%d)0x%lx; pw = 0x%lx(%d)0x%lx\n", + status, ss->read_count, ss->write_count, + (unsigned long) pr->ptr, (int)(rlimit - pr->ptr), (unsigned long) rlimit, + (unsigned long) pw->ptr, (int)(wlimit - pw->ptr), (unsigned long) wlimit); +#ifdef DEBUG + if (pr->ptr > rlimit || pw->ptr > wlimit) { + lprintf("Pointer overrun!\n"); + status = PTSFAX_ERRC; + } + if (gs_debug_c('w') && status == 1) { + dlputs("[w]white runs:"); + print_run_stats(&stats_white_runs); + dlputs("[w]black runs:"); + print_run_stats(&stats_black_runs); + } +#endif + return status; +} + +/* Encode a 1-D scan line. */ +static void +cf_encode_1d(stream_CFE_state * ss, const unsigned char * lbuf, stream_cursor_write * pw) +{ + unsigned int count = ss->raster << 3; + unsigned char *q = pw->ptr; + int end_count = -ss->Columns & 7; + int rlen; + + hce_declare_state; + const unsigned char *p = lbuf; + unsigned char invert = (ss->BlackIs1 ? 0 : 0xff); + + /* Invariant: data = p[-1] ^ invert. */ + unsigned int data = *p++ ^ invert; + + hce_load_state(); + while (count != 0U+end_count) { /* PTS_UNSIGNED */ + /* Parse a white run. */ + skip_white_pixels(data, p, count, invert, rlen); + CF_PUT_WHITE_RUN(ss, rlen); + if (count == 0U+end_count) /* PTS_UNSIGNED */ + break; + /* Parse a black run. */ + skip_black_pixels(data, p, count, invert, rlen); + CF_PUT_BLACK_RUN(ss, rlen); + } + hce_store_state(); + pw->ptr = q; +} + +/* Encode a 2-D scan line. */ +static void +cf_encode_2d(stream_CFE_state * ss, const unsigned char * lbuf, stream_cursor_write * pw, + const unsigned char * lprev) +{ + unsigned char invert_white = (ss->BlackIs1 ? 0 : 0xff); + unsigned char invert = invert_white; + unsigned int count = ss->raster << 3; + int end_count = -ss->Columns & 7; + const unsigned char *p = lbuf; + unsigned char *q = pw->ptr; + unsigned int data = *p++ ^ invert; + + hce_declare_state; + /* + * In order to handle the nominal 'changing white' at the beginning of + * each scan line, we need to suppress the test for an initial black bit + * in the reference line when we are at the very beginning of the scan + * line. To avoid an extra test, we use two different mask tables. + */ + static const unsigned char initial_count_bit[8] = + { + 0, 1, 2, 4, 8, 0x10, 0x20, 0x40 + }; + static const unsigned char further_count_bit[8] = + { + 0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40 + }; + const unsigned char *count_bit = initial_count_bit; + + hce_load_state(); + while (count != 0U+end_count) { /* PTS_UNSIGNED */ + /* + * If invert == invert_white, white and black have their + * correct meanings; if invert == ~invert_white, + * black and white are interchanged. + */ + unsigned int a0 = count; + unsigned int a1; + +#define b1 (a1 - diff) /* only for printing */ + int diff; + unsigned int prev_count = count; + const unsigned char *prev_p = p - lbuf + lprev; + unsigned char prev_data = prev_p[-1] ^ invert; + int rlen; + + /* Find the a1 and b1 transitions. */ + skip_white_pixels(data, p, count, invert, rlen); + a1 = count; + if ((prev_data & count_bit[prev_count & 7])) { + /* Look for changing white first. */ + skip_black_pixels(prev_data, prev_p, prev_count, invert, rlen); + } + count_bit = further_count_bit; /* no longer at beginning */ + pass: + if (prev_count != 0U+end_count) /* PTS_UNSIGNED */ + skip_white_pixels(prev_data, prev_p, prev_count, invert, rlen); + diff = a1 - prev_count; /* i.e., logical b1 - a1 */ + /* In all the comparisons below, remember that count */ + /* runs downward, not upward, so the comparisons are */ + /* reversed. */ + if (diff <= -2) { + /* Could be a pass mode. Find b2. */ + if (prev_count != 0U+ end_count) /* PTS_UNSIGNED */ + skip_black_pixels(prev_data, prev_p, + prev_count, invert, rlen); + if (prev_count > a1) { + /* Use pass mode. */ + if_debug4('W', "[W]pass: count = %d, a1 = %d, b1 = %d, new count = %d\n", + a0, a1, b1, prev_count); + hc_put_value(ss, q, cf2_run_pass_value, cf2_run_pass_length); + a0 = prev_count; + goto pass; + } + } + /* Check for vertical coding. */ + if (diff <= 3 && diff >= -3) { + /* Use vertical coding. */ + const cfe_run *cp = &cf2_run_vertical[diff + 3]; + + if_debug5('W', "[W]vertical %d: count = %d, a1 = %d, b1 = %d, new count = %d\n", + diff, a0, a1, b1, count); + hc_put_code(ss, q, cp); + invert = ~invert; /* a1 polarity changes */ + data ^= 0xff; + continue; + } + /* No luck, use horizontal coding. */ + if (count != 0U+end_count) /* PTS_UNSIGNED */ + skip_black_pixels(data, p, count, invert, rlen); /* find a2 */ + hc_put_value(ss, q, cf2_run_horizontal_value, + cf2_run_horizontal_length); + a0 -= a1; + a1 -= count; + if (invert == invert_white) { + if_debug3('W', "[W]horizontal: white = %d, black = %d, new count = %d\n", + a0, a1, count); + CF_PUT_WHITE_RUN(ss, a0); + CF_PUT_BLACK_RUN(ss, a1); + } else { + if_debug3('W', "[W]horizontal: black = %d, white = %d, new count = %d\n", + a0, a1, count); + CF_PUT_BLACK_RUN(ss, a0); + CF_PUT_WHITE_RUN(ss, a1); +#undef b1 + } + } + hce_store_state(); + pw->ptr = q; +} + +/* Stream template */ +const stream_template s_CFE_template = { + /*0, &st_CFE_state*/ s_CFE_init, s_CFE_process, 1, 1, + s_CFE_release, s_CFE_set_defaults, 0 +}; +/* end of former scfe.c */ + +/* scfetab.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Tables for CCITTFaxEncode filter */ +/* #include "scommon.h" */ /* for scf.h */ +/* #include "scf.h" */ + +/* We make this a separate file so that it can be used by */ +/* the program that generates the tables for the CCITTFaxDecode filter. */ + +/* ------ Run encoding tables ------ */ + +/* Abbreviate hce_entry to make the file smaller. */ +#define RUN(c,len) hce_entry(c,len) + +/* Define the end-of-line code. */ +/* Code in scfd.c and scfdgen.c knows that the run value is 1. */ +impl_const cfe_run cf_run_eol = +RUN(run_eol_code_value, run_eol_code_length); + +/* Define the 1-D code that signals uncompressed data. */ +impl_const cfe_run cf1_run_uncompressed = +RUN(0xf, 12); + +/* Define the 2-D run codes. */ +impl_const cfe_run cf2_run_pass = +RUN(cf2_run_pass_value, cf2_run_pass_length); +impl_const cfe_run cf2_run_vertical[7] = +{ + RUN(0x3, 7), + RUN(0x3, 6), + RUN(0x3, 3), + RUN(0x1, 1), + RUN(0x2, 3), + RUN(0x2, 6), + RUN(0x2, 7) +}; +impl_const cfe_run cf2_run_horizontal = +RUN(cf2_run_horizontal_value, cf2_run_horizontal_length); +impl_const cfe_run cf2_run_uncompressed = +RUN(0xf, 10); + +/* EOL codes for Group 3 2-D. */ +/* Code in scfd.c knows that these are 0...01x. */ +impl_const cfe_run cf2_run_eol_1d = +RUN((run_eol_code_value << 1) + 1, run_eol_code_length + 1); +impl_const cfe_run cf2_run_eol_2d = +RUN((run_eol_code_value << 1) + 0, run_eol_code_length + 1); + +/* White run codes. */ +impl_const cf_runs cf_white_runs = +{ + { /* Termination codes */ + RUN(0x35, 8), RUN(0x7, 6), RUN(0x7, 4), RUN(0x8, 4), + RUN(0xb, 4), RUN(0xc, 4), RUN(0xe, 4), RUN(0xf, 4), + RUN(0x13, 5), RUN(0x14, 5), RUN(0x7, 5), RUN(0x8, 5), + RUN(0x8, 6), RUN(0x3, 6), RUN(0x34, 6), RUN(0x35, 6), + RUN(0x2a, 6), RUN(0x2b, 6), RUN(0x27, 7), RUN(0xc, 7), + RUN(0x8, 7), RUN(0x17, 7), RUN(0x3, 7), RUN(0x4, 7), + RUN(0x28, 7), RUN(0x2b, 7), RUN(0x13, 7), RUN(0x24, 7), + RUN(0x18, 7), RUN(0x2, 8), RUN(0x3, 8), RUN(0x1a, 8), + RUN(0x1b, 8), RUN(0x12, 8), RUN(0x13, 8), RUN(0x14, 8), + RUN(0x15, 8), RUN(0x16, 8), RUN(0x17, 8), RUN(0x28, 8), + RUN(0x29, 8), RUN(0x2a, 8), RUN(0x2b, 8), RUN(0x2c, 8), + RUN(0x2d, 8), RUN(0x4, 8), RUN(0x5, 8), RUN(0xa, 8), + RUN(0xb, 8), RUN(0x52, 8), RUN(0x53, 8), RUN(0x54, 8), + RUN(0x55, 8), RUN(0x24, 8), RUN(0x25, 8), RUN(0x58, 8), + RUN(0x59, 8), RUN(0x5a, 8), RUN(0x5b, 8), RUN(0x4a, 8), + RUN(0x4b, 8), RUN(0x32, 8), RUN(0x33, 8), RUN(0x34, 8) + }, + { /* Make-up codes */ + RUN(0, 0) /* dummy */ , RUN(0x1b, 5), RUN(0x12, 5), RUN(0x17, 6), + RUN(0x37, 7), RUN(0x36, 8), RUN(0x37, 8), RUN(0x64, 8), + RUN(0x65, 8), RUN(0x68, 8), RUN(0x67, 8), RUN(0xcc, 9), + RUN(0xcd, 9), RUN(0xd2, 9), RUN(0xd3, 9), RUN(0xd4, 9), + RUN(0xd5, 9), RUN(0xd6, 9), RUN(0xd7, 9), RUN(0xd8, 9), + RUN(0xd9, 9), RUN(0xda, 9), RUN(0xdb, 9), RUN(0x98, 9), + RUN(0x99, 9), RUN(0x9a, 9), RUN(0x18, 6), RUN(0x9b, 9), + RUN(0x8, 11), RUN(0xc, 11), RUN(0xd, 11), RUN(0x12, 12), + RUN(0x13, 12), RUN(0x14, 12), RUN(0x15, 12), RUN(0x16, 12), + RUN(0x17, 12), RUN(0x1c, 12), RUN(0x1d, 12), RUN(0x1e, 12), + RUN(0x1f, 12) + } +}; + +/* Black run codes. */ +impl_const cf_runs cf_black_runs = +{ + { /* Termination codes */ + RUN(0x37, 10), RUN(0x2, 3), RUN(0x3, 2), RUN(0x2, 2), + RUN(0x3, 3), RUN(0x3, 4), RUN(0x2, 4), RUN(0x3, 5), + RUN(0x5, 6), RUN(0x4, 6), RUN(0x4, 7), RUN(0x5, 7), + RUN(0x7, 7), RUN(0x4, 8), RUN(0x7, 8), RUN(0x18, 9), + RUN(0x17, 10), RUN(0x18, 10), RUN(0x8, 10), RUN(0x67, 11), + RUN(0x68, 11), RUN(0x6c, 11), RUN(0x37, 11), RUN(0x28, 11), + RUN(0x17, 11), RUN(0x18, 11), RUN(0xca, 12), RUN(0xcb, 12), + RUN(0xcc, 12), RUN(0xcd, 12), RUN(0x68, 12), RUN(0x69, 12), + RUN(0x6a, 12), RUN(0x6b, 12), RUN(0xd2, 12), RUN(0xd3, 12), + RUN(0xd4, 12), RUN(0xd5, 12), RUN(0xd6, 12), RUN(0xd7, 12), + RUN(0x6c, 12), RUN(0x6d, 12), RUN(0xda, 12), RUN(0xdb, 12), + RUN(0x54, 12), RUN(0x55, 12), RUN(0x56, 12), RUN(0x57, 12), + RUN(0x64, 12), RUN(0x65, 12), RUN(0x52, 12), RUN(0x53, 12), + RUN(0x24, 12), RUN(0x37, 12), RUN(0x38, 12), RUN(0x27, 12), + RUN(0x28, 12), RUN(0x58, 12), RUN(0x59, 12), RUN(0x2b, 12), + RUN(0x2c, 12), RUN(0x5a, 12), RUN(0x66, 12), RUN(0x67, 12) + }, + { /* Make-up codes. */ + RUN(0, 0) /* dummy */ , RUN(0xf, 10), RUN(0xc8, 12), RUN(0xc9, 12), + RUN(0x5b, 12), RUN(0x33, 12), RUN(0x34, 12), RUN(0x35, 12), + RUN(0x6c, 13), RUN(0x6d, 13), RUN(0x4a, 13), RUN(0x4b, 13), + RUN(0x4c, 13), RUN(0x4d, 13), RUN(0x72, 13), RUN(0x73, 13), + RUN(0x74, 13), RUN(0x75, 13), RUN(0x76, 13), RUN(0x77, 13), + RUN(0x52, 13), RUN(0x53, 13), RUN(0x54, 13), RUN(0x55, 13), + RUN(0x5a, 13), RUN(0x5b, 13), RUN(0x64, 13), RUN(0x65, 13), + RUN(0x8, 11), RUN(0xc, 11), RUN(0xd, 11), RUN(0x12, 12), + RUN(0x13, 12), RUN(0x14, 12), RUN(0x15, 12), RUN(0x16, 12), + RUN(0x17, 12), RUN(0x1c, 12), RUN(0x1d, 12), RUN(0x1e, 12), + RUN(0x1f, 12) + } +}; + +/* Uncompressed codes. */ +impl_const cfe_run cf_uncompressed[6] = +{ + RUN(1, 1), + RUN(1, 2), + RUN(1, 3), + RUN(1, 4), + RUN(1, 5), + RUN(1, 6) +}; + +/* Uncompressed exit codes. */ +impl_const cfe_run cf_uncompressed_exit[10] = +{ + RUN(2, 8), RUN(3, 8), + RUN(2, 9), RUN(3, 9), + RUN(2, 10), RUN(3, 10), + RUN(2, 11), RUN(3, 11), + RUN(2, 12), RUN(3, 12) +}; + +#if 0 +/* Some C compilers insist on having executable code in every file.... */ +void scfetab_dummy _((void)); /* for picky compilers */ +void +scfetab_dummy(void) +{ +} +#endif + +/* end of former scfetab.c */ + +#endif /* USE_BUILTIN_FAXE */ + +#if USE_BUILTIN_FAXD +#if OBJDEP +# warning PROVIDES: pts_faxd +#endif +/* scfdtab.c; must be before scfd.c */ +/* #include "scommon.h" */ /* for scf.h */ +/* #include "scf.h" */ + +/* White decoding table. */ +impl_const cfd_node cf_white_decode[] = { + { 256, 12 }, + { 272, 12 }, + { 29, 8 }, + { 30, 8 }, + { 45, 8 }, + { 46, 8 }, + { 22, 7 }, + { 22, 7 }, + { 23, 7 }, + { 23, 7 }, + { 47, 8 }, + { 48, 8 }, + { 13, 6 }, + { 13, 6 }, + { 13, 6 }, + { 13, 6 }, + { 20, 7 }, + { 20, 7 }, + { 33, 8 }, + { 34, 8 }, + { 35, 8 }, + { 36, 8 }, + { 37, 8 }, + { 38, 8 }, + { 19, 7 }, + { 19, 7 }, + { 31, 8 }, + { 32, 8 }, + { 1, 6 }, + { 1, 6 }, + { 1, 6 }, + { 1, 6 }, + { 12, 6 }, + { 12, 6 }, + { 12, 6 }, + { 12, 6 }, + { 53, 8 }, + { 54, 8 }, + { 26, 7 }, + { 26, 7 }, + { 39, 8 }, + { 40, 8 }, + { 41, 8 }, + { 42, 8 }, + { 43, 8 }, + { 44, 8 }, + { 21, 7 }, + { 21, 7 }, + { 28, 7 }, + { 28, 7 }, + { 61, 8 }, + { 62, 8 }, + { 63, 8 }, + { 0, 8 }, + { 320, 8 }, + { 384, 8 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 10, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 11, 5 }, + { 27, 7 }, + { 27, 7 }, + { 59, 8 }, + { 60, 8 }, + { 288, 9 }, + { 290, 9 }, + { 18, 7 }, + { 18, 7 }, + { 24, 7 }, + { 24, 7 }, + { 49, 8 }, + { 50, 8 }, + { 51, 8 }, + { 52, 8 }, + { 25, 7 }, + { 25, 7 }, + { 55, 8 }, + { 56, 8 }, + { 57, 8 }, + { 58, 8 }, + { 192, 6 }, + { 192, 6 }, + { 192, 6 }, + { 192, 6 }, + { 1664, 6 }, + { 1664, 6 }, + { 1664, 6 }, + { 1664, 6 }, + { 448, 8 }, + { 512, 8 }, + { 292, 9 }, + { 640, 8 }, + { 576, 8 }, + { 294, 9 }, + { 296, 9 }, + { 298, 9 }, + { 300, 9 }, + { 302, 9 }, + { 256, 7 }, + { 256, 7 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 2, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 128, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 8, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 9, 5 }, + { 16, 6 }, + { 16, 6 }, + { 16, 6 }, + { 16, 6 }, + { 17, 6 }, + { 17, 6 }, + { 17, 6 }, + { 17, 6 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 14, 6 }, + { 14, 6 }, + { 14, 6 }, + { 14, 6 }, + { 15, 6 }, + { 15, 6 }, + { 15, 6 }, + { 15, 6 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 64, 5 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { 7, 4 }, + { -2, 3 }, + { -2, 3 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -3, 4 }, + { 1792, 3 }, + { 1792, 3 }, + { 1984, 4 }, + { 2048, 4 }, + { 2112, 4 }, + { 2176, 4 }, + { 2240, 4 }, + { 2304, 4 }, + { 1856, 3 }, + { 1856, 3 }, + { 1920, 3 }, + { 1920, 3 }, + { 2368, 4 }, + { 2432, 4 }, + { 2496, 4 }, + { 2560, 4 }, + { 1472, 1 }, + { 1536, 1 }, + { 1600, 1 }, + { 1728, 1 }, + { 704, 1 }, + { 768, 1 }, + { 832, 1 }, + { 896, 1 }, + { 960, 1 }, + { 1024, 1 }, + { 1088, 1 }, + { 1152, 1 }, + { 1216, 1 }, + { 1280, 1 }, + { 1344, 1 }, + { 1408, 1 } +}; + +/* Black decoding table. */ +impl_const cfd_node cf_black_decode[] = { + { 128, 12 }, + { 160, 13 }, + { 224, 12 }, + { 256, 12 }, + { 10, 7 }, + { 11, 7 }, + { 288, 12 }, + { 12, 7 }, + { 9, 6 }, + { 9, 6 }, + { 8, 6 }, + { 8, 6 }, + { 7, 5 }, + { 7, 5 }, + { 7, 5 }, + { 7, 5 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 6, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 1, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 3, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { 2, 2 }, + { -2, 4 }, + { -2, 4 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -3, 5 }, + { 1792, 4 }, + { 1792, 4 }, + { 1984, 5 }, + { 2048, 5 }, + { 2112, 5 }, + { 2176, 5 }, + { 2240, 5 }, + { 2304, 5 }, + { 1856, 4 }, + { 1856, 4 }, + { 1920, 4 }, + { 1920, 4 }, + { 2368, 5 }, + { 2432, 5 }, + { 2496, 5 }, + { 2560, 5 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 18, 3 }, + { 52, 5 }, + { 52, 5 }, + { 640, 6 }, + { 704, 6 }, + { 768, 6 }, + { 832, 6 }, + { 55, 5 }, + { 55, 5 }, + { 56, 5 }, + { 56, 5 }, + { 1280, 6 }, + { 1344, 6 }, + { 1408, 6 }, + { 1472, 6 }, + { 59, 5 }, + { 59, 5 }, + { 60, 5 }, + { 60, 5 }, + { 1536, 6 }, + { 1600, 6 }, + { 24, 4 }, + { 24, 4 }, + { 24, 4 }, + { 24, 4 }, + { 25, 4 }, + { 25, 4 }, + { 25, 4 }, + { 25, 4 }, + { 1664, 6 }, + { 1728, 6 }, + { 320, 5 }, + { 320, 5 }, + { 384, 5 }, + { 384, 5 }, + { 448, 5 }, + { 448, 5 }, + { 512, 6 }, + { 576, 6 }, + { 53, 5 }, + { 53, 5 }, + { 54, 5 }, + { 54, 5 }, + { 896, 6 }, + { 960, 6 }, + { 1024, 6 }, + { 1088, 6 }, + { 1152, 6 }, + { 1216, 6 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 64, 3 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 13, 1 }, + { 23, 4 }, + { 23, 4 }, + { 50, 5 }, + { 51, 5 }, + { 44, 5 }, + { 45, 5 }, + { 46, 5 }, + { 47, 5 }, + { 57, 5 }, + { 58, 5 }, + { 61, 5 }, + { 256, 5 }, + { 16, 3 }, + { 16, 3 }, + { 16, 3 }, + { 16, 3 }, + { 17, 3 }, + { 17, 3 }, + { 17, 3 }, + { 17, 3 }, + { 48, 5 }, + { 49, 5 }, + { 62, 5 }, + { 63, 5 }, + { 30, 5 }, + { 31, 5 }, + { 32, 5 }, + { 33, 5 }, + { 40, 5 }, + { 41, 5 }, + { 22, 4 }, + { 22, 4 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 14, 1 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 15, 2 }, + { 128, 5 }, + { 192, 5 }, + { 26, 5 }, + { 27, 5 }, + { 28, 5 }, + { 29, 5 }, + { 19, 4 }, + { 19, 4 }, + { 20, 4 }, + { 20, 4 }, + { 34, 5 }, + { 35, 5 }, + { 36, 5 }, + { 37, 5 }, + { 38, 5 }, + { 39, 5 }, + { 21, 4 }, + { 21, 4 }, + { 42, 5 }, + { 43, 5 }, + { 0, 3 }, + { 0, 3 }, + { 0, 3 }, + { 0, 3 } +}; + +/* 2-D decoding table. */ +impl_const cfd_node cf_2d_decode[] = { + { 128, 11 }, + { 144, 10 }, + { 6, 7 }, + { 0, 7 }, + { 5, 6 }, + { 5, 6 }, + { 1, 6 }, + { 1, 6 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -4, 4 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { -5, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 4, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { 3, 1 }, + { -2, 4 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -1, 0 }, + { -3, 3 } +}; + +/* Uncompresssed decoding table. */ +impl_const cfd_node cf_uncompressed_decode[] = { + { 64, 12 }, + { 5, 6 }, + { 4, 5 }, + { 4, 5 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 3, 4 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { 0, 1 }, + { -1, 0 }, + { -1, 0 }, + { 8, 6 }, + { 9, 6 }, + { 6, 5 }, + { 6, 5 }, + { 7, 5 }, + { 7, 5 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 4, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 5, 4 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 2, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 3, 3 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 0, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 }, + { 1, 2 } +}; + +#if 0 +/* Dummy executable code to pacify compilers. */ +void scfdtab_dummy _((void)); +void +scfdtab_dummy() +{ +} +#endif +/* end of former scfdtab.c */ +/* scfd.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* CCITTFax decoding filter */ +/* #include "gstypes.h" */ +/* #include "scf.h" */ +/* #include "scfx.h" */ + +/* Utility procedures */ +int stream_move _((stream_cursor_read *, stream_cursor_write *)); /* in stream.c */ + +/* ------ CCITTFaxDecode ------ */ + +/* private_st_CFD_state(); */ + +/* Set default parameter values. */ +static void +s_CFD_set_defaults(register stream_state * st) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + + s_CFD_set_defaults_inline(ss); +} + +/* Initialize CCITTFaxDecode filter */ +static int +s_CFD_init(stream_state * st) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + int raster = ss->raster = + ROUND_UP((ss->Columns + 7) >> 3, ss->DecodedByteAlign); + unsigned char white = (ss->BlackIs1 ? 0 : 0xff); + + s_hcd_init_inline(ss); + /* Because skip_white_pixels can look as many as 4 bytes ahead, */ + /* we need to allow 4 extra bytes at the end of the row buffers. */ + ss->lbuf = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFD lbuf"); + ss->lprev = 0; + if (ss->lbuf == 0) + return PTSFAX_ERRC; +/****** WRONG ******/ + if (ss->K != 0) { + ss->lprev = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFD lprev"); + if (ss->lprev == 0) + return PTSFAX_ERRC; +/****** WRONG ******/ + /* Clear the initial reference line for 2-D encoding. */ + ss->memset_(ss->lbuf, white, raster); + /* Ensure that the scan of the reference line will stop. */ + ss->lbuf[raster] = 0xa0; + } + ss->k_left = min(ss->K, 0); + ss->run_color = 0; + ss->damaged_rows = 0; + ss->skipping_damage = false; + ss->cbit = 0; + ss->uncomp_run = 0; + ss->rows_left = (ss->Rows <= 0 || ss->EndOfBlock ? -1 : ss->Rows + 1); + ss->rpos = ss->wpos = raster - 1; + ss->eol_count = 0; + ss->invert = white; + ss->min_left = 1; + return 0; +} + +/* Release the filter. */ +static void +s_CFD_release(stream_state * st) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + + gs_free_object(st->memory, ss->lprev, "CFD lprev(close)"); + gs_free_object(st->memory, ss->lbuf, "CFD lbuf(close)"); +} + +/* Declare the variables that hold the state. */ +#define cfd_declare_state\ + hcd_declare_state;\ + register unsigned char *q;\ + int qbit +/* Load the state from the stream. */ +#define cfd_load_state()\ + hcd_load_state(),\ + q = ss->lbuf + ss->wpos, qbit = ss->cbit +/* Store the state back in the stream. */ +#define cfd_store_state()\ + hcd_store_state(),\ + ss->wpos = q - ss->lbuf, ss->cbit = qbit + +/* Macros to get blocks of bits from the input stream. */ +/* Invariants: 0 <= bits_left <= bits_size; */ +/* bits [bits_left-1..0] contain valid data. */ + +#define avail_bits(n) hcd_bits_available(n) +#define ensure_bits(n, outl) hcd_ensure_bits(n, outl) +#define peek_bits(n) hcd_peek_bits(n) +#define peek_var_bits(n) hcd_peek_var_bits(n) +#define skip_bits(n) hcd_skip_bits(n) + +/* Get a run from the stream. */ +#ifdef DEBUG +# define IF_DEBUG(expr) expr +#else +# define IF_DEBUG(expr) DO_NOTHING +#endif +#define get_run(decode, initial_bits, min_bits, runlen, str, locl, outl)\ + BEGIN\ + const cfd_node *np;\ + int clen;\ +\ + HCD_ENSURE_BITS_ELSE(initial_bits) {\ + /* We might still have enough bits for the specific code. */\ + if (bits_left < min_bits) goto outl;\ + np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];\ + if ((clen = np->code_length) > bits_left) goto outl;\ + goto locl;\ + }\ + np = &decode[peek_bits(initial_bits)];\ + if ((clen = np->code_length) > initial_bits) {\ + IF_DEBUG(unsigned int init_bits = peek_bits(initial_bits));\ + if (!avail_bits(clen)) goto outl;\ + clen -= initial_bits;\ + skip_bits(initial_bits);\ + ensure_bits(clen, outl); /* can't goto outl */\ + np = &decode[np->run_length + peek_var_bits(clen)];\ + if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,\ + (init_bits << np->code_length) +\ + peek_var_bits(np->code_length),\ + initial_bits + np->code_length,\ + np->run_length);\ + skip_bits(np->code_length);\ + } else {\ + locl: if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\ + peek_var_bits(clen), clen, np->run_length);\ + skip_bits(clen);\ + }\ + runlen = np->run_length;\ + END + +/* Skip data bits for a white run. */ +/* rlen is either less than 64, or a multiple of 64. */ +#define skip_data(rlen, makeup_label)\ + if ( (qbit -= rlen) < 0 )\ + { q -= qbit >> 3, qbit &= 7;\ + if ( rlen >= 64 ) goto makeup_label;\ + } + +/* Invert data bits for a black run. */ +/* If rlen >= 64, execute makeup_action: this is to handle */ +/* makeup codes efficiently, since these are always a multiple of 64. */ +#define invert_data(rlen, black_byte, makeup_action, d)\ + if ( rlen > qbit )\ + { *q++ ^= (1 << qbit) - 1;\ + rlen -= qbit;\ + switch ( rlen >> 3 )\ + {\ + case 7: /* original rlen possibly >= 64 */\ + if ( rlen + qbit >= 64 ) goto d;\ + *q++ = black_byte;\ + case 6: *q++ = black_byte;\ + case 5: *q++ = black_byte;\ + case 4: *q++ = black_byte;\ + case 3: *q++ = black_byte;\ + case 2: *q++ = black_byte;\ + case 1: *q = black_byte;\ + rlen &= 7;\ + if ( !rlen ) { qbit = 0; break; }\ + q++;\ + case 0: /* know rlen != 0 */\ + qbit = 8 - rlen;\ + *q ^= 0xff << qbit;\ + break;\ + default: /* original rlen >= 64 */\ +d: ss->memset_(q, black_byte, rlen >> 3);\ + q += rlen >> 3;\ + rlen &= 7;\ + if ( !rlen ) qbit = 0, q--;\ + else qbit = 8 - rlen, *q ^= 0xff << qbit;\ + makeup_action;\ + }\ + }\ + else\ + qbit -= rlen,\ + *q ^= ((1 << rlen) - 1) << qbit + +/* Buffer refill for CCITTFaxDecode filter */ +static int cf_decode_eol _((stream_CFD_state *, stream_cursor_read *)); +static int cf_decode_1d _((stream_CFD_state *, stream_cursor_read *)); +static int cf_decode_2d _((stream_CFD_state *, stream_cursor_read *)); +static int cf_decode_uncompressed _((stream_CFD_state *, stream_cursor_read *)); +static int +s_CFD_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_CFD_state *const ss = (stream_CFD_state *) st; + int wstop = ss->raster - 1; + int eol_count = ss->eol_count; + int k_left = ss->k_left; + int rows_left = ss->rows_left; + int status = 0; + + (void)last; /**** pts ****/ + +#ifdef DEBUG + const unsigned char *rstart = pr->ptr; + const unsigned char *wstart = pw->ptr; + +#endif + + top: +#ifdef DEBUG + { + hcd_declare_state; + hcd_load_state(); + if_debug8('w', "\ +[w]CFD_process top: eol_count=%d, k_left=%d, rows_left=%d\n\ + bits=0x%lx, bits_left=%d, read %u, wrote %u%s\n", + eol_count, k_left, rows_left, + (unsigned long) bits, bits_left, + (unsigned int) (p - rstart), (unsigned int) (pw->ptr - wstart), + (ss->skipping_damage ? ", skipping damage" : "")); + } +#endif + if (ss->skipping_damage) { /* Skip until we reach an EOL. */ + hcd_declare_state; + int skip; + + status = 0; + do { + switch ((skip = cf_decode_eol(ss, pr))) { + default: /* not EOL */ + hcd_load_state(); + skip_bits(-skip); + hcd_store_state(); + continue; + case 0: /* need more input */ + goto out; + case 1: /* EOL */ + { /* Back up over the EOL. */ + hcd_load_state(); + bits_left += run_eol_code_length; + hcd_store_state(); + } + ss->skipping_damage = false; + } + } + while (ss->skipping_damage); + ss->damaged_rows++; + } + /* + * Check for a completed input scan line. This isn't quite as + * simple as it seems, because we could have run out of input data + * between a makeup code and a 0-length termination code, or in a + * 2-D line before a final horizontal code with a 0-length second + * run. There's probably a way to think about this situation that + * doesn't require a special check, but I haven't found it yet. + */ + if (ss->wpos == wstop && ss->cbit <= (-ss->Columns & 7) && + (k_left == 0 ? !(ss->run_color & ~1) : ss->run_color == 0) + ) { /* Check for completed data to be copied to the client. */ + /* (We could avoid the extra copy step for 1-D, but */ + /* it's simpler not to, and it doesn't cost much.) */ + if (ss->rpos < ss->wpos) { + stream_cursor_read cr; + + cr.ptr = ss->lbuf + ss->rpos; + cr.limit = ss->lbuf + ss->wpos; + status = stream_move(&cr, pw); + ss->rpos = cr.ptr - ss->lbuf; + if (status) + goto out; + } + if (rows_left > 0 && --rows_left == 0) { + status = EOFC; + goto out; + } + if (ss->K != 0) { + unsigned char *prev_bits = ss->lprev; + + ss->lprev = ss->lbuf; + ss->lbuf = prev_bits; + if (ss->K > 0) + k_left = (k_left == 0 ? ss->K : k_left) - 1; + } + ss->rpos = ss->wpos = -1; + ss->eol_count = eol_count = 0; + ss->cbit = 0; + ss->invert = (ss->BlackIs1 ? 0 : 0xff); + ss->memset_(ss->lbuf, ss->invert, wstop + 1); + ss->run_color = 0; + /* + * If EndOfLine is true, we want to include the unsigned char padding + * in the string of initial zeros in the EOL. If EndOfLine + * is false, we aren't sure what we should do.... + */ + if (ss->EncodedByteAlign & !ss->EndOfLine) + ss->bits_left &= ~7; + } + /* If we're between scan lines, scan for EOLs. */ + if (ss->wpos < 0) { + while ((status = cf_decode_eol(ss, pr)) > 0) { + if_debug0('w', "[w]EOL\n"); + /* If we are in a Group 3 mixed regime, */ + /* check the next bit for 1- vs. 2-D. */ + if (ss->K > 0) { + hcd_declare_state; + hcd_load_state(); + ensure_bits(1, out); /* can't fail */ + k_left = (peek_bits(1) ? 0 : 1); + skip_bits(1); + hcd_store_state(); + } + ++eol_count; + /* + * According to Adobe, the decoder should always check for + * the EOD sequence, regardless of EndOfBlock: the Red Book's + * documentation of EndOfBlock is wrong. + */ + if (eol_count == (ss->K < 0 ? 2 : 6)) { + status = EOFC; + goto out; + } + } + if (status == 0) /* input empty while scanning EOLs */ + goto out; + switch (eol_count) { + case 0: + if (ss->EndOfLine) { /* EOL is required, but none is present. */ + status = PTSFAX_ERRC; + goto check; + } + case 1: + break; + default: + status = PTSFAX_ERRC; + goto check; + } + } + /* Now decode actual data. */ + if (k_left < 0) { + if_debug0('w', "[w2]new row\n"); + status = cf_decode_2d(ss, pr); + } else if (k_left == 0) { + if_debug0('w', "[w1]new row\n"); + status = cf_decode_1d(ss, pr); + } else { + if_debug1('w', "[w1]new 2-D row, %d left\n", k_left); + status = cf_decode_2d(ss, pr); + } + if_debug3('w', "[w]CFD status = %d, wpos = %d, cbit = %d\n", + status, ss->wpos, ss->cbit); + check:switch (status) { + case 1: /* output full */ + goto top; + case PTSFAX_ERRC: + /* Check for special handling of damaged rows. */ + if (ss->damaged_rows >= ss->DamagedRowsBeforeError || + !(ss->EndOfLine && ss->K >= 0) + ) + break; + /* Substitute undamaged data if appropriate. */ +/****** NOT IMPLEMENTED YET ******/ + { + ss->wpos = wstop; + ss->cbit = -ss->Columns & 7; + ss->run_color = 0; + } + ss->skipping_damage = true; + goto top; + default: + ss->damaged_rows = 0; /* finished a good row */ + } + out:ss->k_left = k_left; + ss->rows_left = rows_left; + ss->eol_count = eol_count; + return status; +} + +/* + * Decode a leading EOL, if any. + * If an EOL is present, skip over it and return 1; + * if no EOL is present, read no input and return -N, where N is the + * number of initial bits that can be skipped in the search for an EOL; + * if more input is needed, return 0. + * Note that if we detected an EOL, we know that we can back up over it; + * if we detected an N-bit non-EOL, we know that at least N bits of data + * are available in the buffer. + */ +static int +cf_decode_eol(stream_CFD_state * ss, stream_cursor_read * pr) +{ + hcd_declare_state; + int zeros; + int look_ahead; + + hcd_load_state(); + for (zeros = 0; zeros < run_eol_code_length - 1; zeros++) { + ensure_bits(1, out); + if (peek_bits(1)) + return -(zeros + 1); + skip_bits(1); + } + /* We definitely have an EOL. Skip further zero bits. */ + look_ahead = (ss->K > 0 ? 2 : 1); + for (;;) { + ensure_bits(look_ahead, back); + if (peek_bits(1)) + break; + skip_bits(1); + } + skip_bits(1); + hcd_store_state(); + return 1; + back: /* + * We ran out of data while skipping zeros. + * We know we are at a unsigned char boundary, and have just skipped + * at least run_eol_code_length - 1 zeros. However, + * bits_left may be 1 if look_ahead == 2. + */ + bits &= (1 << bits_left) - 1; + bits_left += run_eol_code_length - 1; + hcd_store_state(); + out:return 0; +} + +/* Decode a 1-D scan line. */ +static int +cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr) +{ + cfd_declare_state; + unsigned char black_byte = (ss->BlackIs1 ? 0xff : 0); + int end_bit = -ss->Columns & 7; + unsigned char *stop = ss->lbuf - 1 + ss->raster; + int run_color = ss->run_color; + int status; + int bcnt; + + cfd_load_state(); + if_debug1('w', "[w1]entry run_color = %d\n", ss->run_color); + if (ss->run_color > 0) + goto db; + else + goto dw; +#define q_at_stop() (q >= stop && (qbit <= end_bit || q > stop)) + top:run_color = 0; + if (q_at_stop()) + goto done; + dw: /* Decode a white run. */ + get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits, + bcnt, "[w1]white", dwl, out0); + if (bcnt < 0) { /* exceptional situation */ + switch (bcnt) { + case run_uncompressed: /* Uncompressed data. */ + cfd_store_state(); + bcnt = cf_decode_uncompressed(ss, pr); + if (bcnt < 0) + return bcnt; + cfd_load_state(); + if (bcnt) + goto db; + else + goto dw; + /*case run_error: */ + /*case run_zeros: *//* Premature end-of-line. */ + default: + status = PTSFAX_ERRC; + goto out; + } + } + skip_data(bcnt, dwx); + if (q_at_stop()) { + run_color = 0; /* not inside a run */ + goto done; + } + run_color = 1; + db: /* Decode a black run. */ + get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits, + bcnt, "[w1]black", dbl, out1); + if (bcnt < 0) { /* All exceptional codes are invalid here. */ +/****** WRONG, uncompressed IS ALLOWED ******/ + status = PTSFAX_ERRC; + goto out; + } + /* Invert bits designated by black run. */ + invert_data(bcnt, black_byte, goto dbx, idb); + goto top; + dwx: /* If we run out of data after a makeup code, */ + /* note that we are still processing a white run. */ + run_color = -1; + goto dw; + dbx: /* If we run out of data after a makeup code, */ + /* note that we are still processing a black run. */ + run_color = 2; + goto db; + done:if (q > stop || qbit < end_bit) + status = PTSFAX_ERRC; + else + status = 1; + out:cfd_store_state(); + ss->run_color = run_color; + if_debug1('w', "[w1]exit run_color = %d\n", run_color); + return status; + out0: /* We already set run_color to 0 or -1. */ + status = 0; + goto out; + out1: /* We already set run_color to 1 or 2. */ + status = 0; + goto out; +} + +/* Decode a 2-D scan line. */ +static int +cf_decode_2d(stream_CFD_state * ss, stream_cursor_read * pr) +{ + cfd_declare_state; + unsigned char invert_white = (ss->BlackIs1 ? 0 : 0xff); + unsigned char black_byte = ~invert_white; + unsigned char invert = ss->invert; + int end_count = -ss->Columns & 7; + unsigned int raster = ss->raster; + unsigned char *q0 = ss->lbuf; + unsigned char *prev_q01 = ss->lprev + 1; + unsigned char *endptr = q0 - 1 + raster; + int init_count = raster << 3; + register int count; + int rlen; + int status; + + cfd_load_state(); + count = ((endptr - q) << 3) + qbit; + endptr[1] = 0xa0; /* a unsigned char with some 0s and some 1s, */ + /* to ensure run scan will stop */ + if_debug1('W', "[w2]raster=%d\n", raster); + switch (ss->run_color) { + case -2: + ss->run_color = 0; + goto hww; + case -1: + ss->run_color = 0; + goto hbw; + case 1: + ss->run_color = 0; + goto hwb; + case 2: + ss->run_color = 0; + goto hbb; + /*case 0: */ + } + top:if (count <= end_count) { + status = (count < end_count ? PTSFAX_ERRC : 1); + goto out; + } + /* If invert == invert_white, white and black have their */ + /* correct meanings; if invert == ~invert_white, */ + /* black and white are interchanged. */ + if_debug1('W', "[w2]%4d:\n", count); +#ifdef DEBUG + /* Check the invariant between q, qbit, and count. */ + { + int pcount = (endptr - q) * 8 + qbit; + + if (pcount != count) + dlprintf2("[w2]Error: count=%d pcount=%d\n", + count, pcount); + } +#endif + /* + * We could just use get_run here, but we can do better. However, + * we must be careful to handle the case where the very last codes + * in the input stream are 1-bit "vertical 0" codes: we can't just + * use ensure_bits(3, ...) and go to get more data if it fails. + */ + ensure_bits(3, out3); +#define vertical_0 (countof(cf2_run_vertical) / 2) + switch (peek_bits(3)) { + default /*4..7*/ : /* vertical(0) */ +v0: skip_bits(1); + rlen = vertical_0; + break; + case 2: /* vertical(+1) */ + skip_bits(3); + rlen = vertical_0 + 1; + break; + case 3: /* vertical(-1) */ + skip_bits(3); + rlen = vertical_0 - 1; + break; + case 1: /* horizontal */ + skip_bits(3); + if (invert == invert_white) + goto hww; + else + goto hbb; + case 0: /* everything else */ + get_run(cf_2d_decode, cfd_2d_initial_bits, cfd_2d_min_bits, + rlen, "[w2]", d2l, out0); + /* rlen may be run2_pass, run_uncompressed, or */ + /* 0..countof(cf2_run_vertical)-1. */ + if (rlen < 0) + switch (rlen) { + case run2_pass: + break; + case run_uncompressed: + { + int which; + + cfd_store_state(); + which = cf_decode_uncompressed(ss, pr); + if (which < 0) { + status = which; + goto out; + } + cfd_load_state(); +/****** ADJUST count ******/ + invert = (which ? ~invert_white : invert_white); + } + goto top; + default: /* run_error, run_zeros */ + status = PTSFAX_ERRC; + goto out; + } + } + /* Interpreting the run requires scanning the */ + /* previous ('reference') line. */ + { + int prev_count = count; + unsigned char prev_data; + int dlen; + static const unsigned char count_bit[8] = + {0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40}; + unsigned char *prev_q = prev_q01 + (q - q0); + int plen; + + if (!(count & 7)) + prev_q++; /* because of skip macros */ + prev_data = prev_q[-1] ^ invert; + /* Find the b1 transition. */ + if ((prev_data & count_bit[prev_count & 7]) && + (prev_count < init_count || invert != invert_white) + ) { /* Look for changing white first. */ + if_debug1('W', " data=0x%x", prev_data); + skip_black_pixels(prev_data, prev_q, + prev_count, invert, plen); + if (prev_count < end_count) /* overshot */ + prev_count = end_count; + if_debug1('W', " b1 other=%d", prev_count); + } + if (prev_count != end_count) { + if_debug1('W', " data=0x%x", prev_data); + skip_white_pixels(prev_data, prev_q, + prev_count, invert, plen); + if (prev_count < end_count) /* overshot */ + prev_count = end_count; + if_debug1('W', " b1 same=%d", prev_count); + } + /* b1 = prev_count; */ + if (rlen == run2_pass) { /* Pass mode. Find b2. */ + if (prev_count != end_count) { + if_debug1('W', " data=0x%x", prev_data); + skip_black_pixels(prev_data, prev_q, + prev_count, invert, plen); + if (prev_count < end_count) /* overshot */ + prev_count = end_count; + } + /* b2 = prev_count; */ + if_debug2('W', " b2=%d, pass %d\n", + prev_count, count - prev_count); + } else { /* Vertical coding. */ + /* Remember that count counts *down*. */ + prev_count += rlen - vertical_0; /* a1 */ + if_debug2('W', " vertical %d -> %d\n", + rlen - vertical_0, prev_count); + } + /* Now either invert or skip from count */ + /* to prev_count, and reset count. */ + if (invert == invert_white) { /* Skip data bits. */ + q = endptr - (prev_count >> 3); + qbit = prev_count & 7; + } else { /* Invert data bits. */ + dlen = count - prev_count; + invert_data(dlen, black_byte, DO_NOTHING, idd); + } + count = prev_count; + if (rlen >= 0) /* vertical mode */ + invert = ~invert; /* polarity changes */ + } + goto top; + out3: + if (bits_left > 0 && peek_bits(1)) { + /* This is a 1-bit "vertical 0" code, which we can still process. */ + goto v0; + } + /* falls through */ + out0:status = 0; + /* falls through */ + out:cfd_store_state(); + ss->invert = invert; + return status; + /* + * We handle horizontal decoding here, so that we can + * branch back into it if we run out of input data. + */ + /* White, then black. */ + hww:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits, + rlen, " white", wwl, outww); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + skip_data(rlen, hww); + /* Handle the second half of a white-black horizontal code. */ + hwb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits, + rlen, " black", wbl, outwb); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + invert_data(rlen, black_byte, goto hwb, ihwb); + goto top; + outww:ss->run_color = -2; + goto out0; + outwb:ss->run_color = 1; + goto out0; + /* Black, then white. */ + hbb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits, + rlen, " black", bbl, outbb); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + invert_data(rlen, black_byte, goto hbb, ihbb); + /* Handle the second half of a black-white horizontal code. */ + hbw:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits, + rlen, " white", bwl, outbw); + if ((count -= rlen) < end_count) { + status = PTSFAX_ERRC; + goto out; + } + skip_data(rlen, hbw); + goto top; + outbb:ss->run_color = 2; + goto out0; + outbw:ss->run_color = -1; + goto out0; +} + +#if 1 /*************** */ +static int +cf_decode_uncompressed(stream_CFD_state * ss, stream_cursor_read * pr) +{ + (void)ss; + (void)pr; + /**** pts ****/ + return PTSFAX_ERRC; +} +#else /*************** */ + +/* Decode uncompressed data. */ +/* (Not tested: no sample data available!) */ +/****** DOESN'T CHECK FOR OVERFLOWING SCAN LINE ******/ +static int +cf_decode_uncompressed(stream * s) +{ + cfd_declare_state; + const cfd_node *np; + int clen, rlen; + + cfd_load_state(); + while (1) { + ensure_bits(cfd_uncompressed_initial_bits, NOOUT); + np = &cf_uncompressed_decode[peek_bits(cfd_uncompressed_initial_bits)]; + clen = np->code_length; + rlen = np->run_length; + if (clen > cfd_uncompressed_initial_bits) { /* Must be an exit code. */ + break; + } + if (rlen == cfd_uncompressed_initial_bits) { /* Longest representable white run */ + if_debug1('W', "[wu]%d\n", rlen); + if ((qbit -= cfd_uncompressed_initial_bits) < 0) + qbit += 8, q++; + } else { + if_debug1('W', "[wu]%d+1\n", rlen); + if (qbit -= rlen < 0) + qbit += 8, q++; + *q ^= 1 << qbit; + } + skip_bits(clen); + } + clen -= cfd_uncompressed_initial_bits; + skip_bits(cfd_uncompressed_initial_bits); + ensure_bits(clen, NOOUT); + np = &cf_uncompressed_decode[rlen + peek_var_bits(clen)]; + rlen = np->run_length; + skip_bits(np->code_length); + if_debug1('w', "[wu]exit %d\n", rlen); + if (rlen >= 0) { /* Valid exit code, rlen = 2 * run length + next polarity */ + if ((qbit -= rlen >> 1) < 0) + qbit += 8, q++; + rlen &= 1; + } + out: +/******* WRONG ******/ + cfd_store_state(); + return rlen; +} + +#endif /*************** */ + +/* Move as much data as possible from one buffer to another. */ +/* Return 0 if the input became empty, 1 if the output became full. */ +int +stream_move(stream_cursor_read * pr, stream_cursor_write * pw) +{ + unsigned int rcount = pr->limit - pr->ptr; + unsigned int wcount = pw->limit - pw->ptr; + unsigned int count; + int status; + + if (rcount <= wcount) + count = rcount, status = 0; + else + count = wcount, status = 1; + + /**** pts ****/ /* Dat: memcpy should be enough instead of memmove */ + #if 0 + memmove(pw->ptr + 1, pr->ptr + 1, count); + pr->ptr += count; + pw->ptr += count; + #else + while (count--!=0) *++pw->ptr=*++pr->ptr; + #endif + return status; +} + + +#if 1 /**** pts ****/ +/* Stream template */ +const stream_template s_CFD_template = +{/*0, &st_CFD_state*/ s_CFD_init, s_CFD_process, 1, 1, s_CFD_release, + s_CFD_set_defaults, 0 +}; +#endif + +/* end of former scfd.c */ + + +#endif /* USE_BUILTIN_FAXD */ + +#if USE_BUILTIN_FAXE || USE_BUILTIN_FAXD +/* shc.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Support code for shc.h */ +/* #include "scommon.h" */ +/* #include "shc.h" */ +/* #include "scfx.h" */ /**** pts ****/ /* struct stream_hc_state_s */ + +/* ------ Encoding ------ */ + +/* Empty the 1-word buffer onto the output stream. */ +/* q has already been incremented. */ +static void +hc_put_code_proc(bool reverse_bits, unsigned char * q, unsigned int cw) +{ +#define cb(n) ((unsigned char)(cw >> (n * 8))) + if (reverse_bits) { +#if hc_bits_size > 16 + q[-3] = byte_reverse_bits[cb(3)]; + q[-2] = byte_reverse_bits[cb(2)]; +#endif + q[-1] = byte_reverse_bits[cb(1)]; + q[0] = byte_reverse_bits[cb(0)]; + } else { +#if hc_bits_size > 16 + q[-3] = cb(3); + q[-2] = cb(2); +#endif + q[-1] = cb(1); + q[0] = cb(0); + } +#undef cb +} + +/* Put out any final bytes. */ +/* Note that this does a store_state, but not a load_state. */ +static unsigned char * +hc_put_last_bits_proc(stream_hc_state * ss, unsigned char * q, unsigned int bits, int bits_left) +{ + while (bits_left < hc_bits_size) { + unsigned char c = (unsigned char) (bits >> (hc_bits_size - 8)); + + if (ss->FirstBitLowOrder) + c = byte_reverse_bits[c]; + *++q = c; + bits <<= 8; + bits_left += 8; + } + ss->bits = bits; + ss->bits_left = bits_left; + return q; +} + +/* end of former shc.c */ + + +/* gsbittab.c */ +/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */ +/* Tables for bit operations */ +/* #include "gstypes.h" */ +/* #include "gsbittab.h" */ + +/* ---------------- Byte processing tables ---------------- */ + +/* + * byte_reverse_bits[B] = the unsigned char B with the order of bits reversed. + */ +impl_const unsigned char byte_reverse_bits[256] = { + bit_table_8(0, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80) +}; + +/* + * byte_right_mask[N] = a unsigned char with N trailing 1s, 0 <= N <= 8. + */ +impl_const unsigned char byte_right_mask[9] = { + 0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff +}; + +/* + * byte_count_bits[B] = the number of 1-bits in a unsigned char with value B. + */ +impl_const unsigned char byte_count_bits[256] = { + bit_table_8(0, 1, 1, 1, 1, 1, 1, 1, 1) +}; + +/* ---------------- Scanning tables ---------------- */ + +/* + * byte_bit_run_length_N[B], for 0 <= N <= 7, gives the length of the + * run of 1-bits starting at bit N in a unsigned char with value B, + * numbering the bits in the unsigned char as 01234567. If the run includes + * the low-order bit (i.e., might be continued into a following unsigned char), + * the run length is increased by 8. + */ + +#define t8(n) n,n,n,n,n+1,n+1,n+2,n+11 +#define r8(n) n,n,n,n,n,n,n,n +#define r16(n) r8(n),r8(n) +#define r32(n) r16(n),r16(n) +#define r64(n) r32(n),r32(n) +#define r128(n) r64(n),r64(n) +impl_const unsigned char byte_bit_run_length_0[256] = { + r128(0), r64(1), r32(2), r16(3), r8(4), t8(5) +}; +impl_const unsigned char byte_bit_run_length_1[256] = { + r64(0), r32(1), r16(2), r8(3), t8(4), + r64(0), r32(1), r16(2), r8(3), t8(4) +}; +impl_const unsigned char byte_bit_run_length_2[256] = { + r32(0), r16(1), r8(2), t8(3), + r32(0), r16(1), r8(2), t8(3), + r32(0), r16(1), r8(2), t8(3), + r32(0), r16(1), r8(2), t8(3) +}; +impl_const unsigned char byte_bit_run_length_3[256] = { + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2), + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2), + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2), + r16(0), r8(1), t8(2), r16(0), r8(1), t8(2) +}; +impl_const unsigned char byte_bit_run_length_4[256] = { + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), + r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), +}; + +#define rr8(a,b,c,d,e,f,g,h)\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\ + a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h +impl_const unsigned char byte_bit_run_length_5[256] = { + rr8(0, 0, 0, 0, 1, 1, 2, 11) +}; +impl_const unsigned char byte_bit_run_length_6[256] = { + rr8(0, 0, 1, 10, 0, 0, 1, 10) +}; +impl_const unsigned char byte_bit_run_length_7[256] = { + rr8(0, 9, 0, 9, 0, 9, 0, 9) +}; + +/* Pointer tables indexed by bit number. */ + +impl_const unsigned char *const byte_bit_run_length[8] = { + byte_bit_run_length_0, byte_bit_run_length_1, + byte_bit_run_length_2, byte_bit_run_length_3, + byte_bit_run_length_4, byte_bit_run_length_5, + byte_bit_run_length_6, byte_bit_run_length_7 +}; +impl_const unsigned char *const byte_bit_run_length_neg[8] = { + byte_bit_run_length_0, byte_bit_run_length_7, + byte_bit_run_length_6, byte_bit_run_length_5, + byte_bit_run_length_4, byte_bit_run_length_3, + byte_bit_run_length_2, byte_bit_run_length_1 +}; + +/* + * byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters + * denote the individual bits of the unsigned char. + */ +impl_const unsigned char byte_acegbdfh_to_abcdefgh[256] = { + bit_table_8(0, 0x80, 0x20, 0x08, 0x02, 0x40, 0x10, 0x04, 0x01) +}; + +#if 0 +/* Some C compilers insist on having executable code in every file.... */ +void gsbittab_dummy _((void)); /* for picky compilers */ +void +gsbittab_dummy(void) +{ +} +#endif + +/* end of former gsbittab.c */ +#endif /* USE_BUILTIN_FAXE || USE_BUILTIN_FAXD */ + +/* end of pts_fax.c */ diff --git a/Build/source/utils/sam2p/pts_fax.h b/Build/source/utils/sam2p/pts_fax.h new file mode 100644 index 00000000000..fcf17fc1422 --- /dev/null +++ b/Build/source/utils/sam2p/pts_fax.h @@ -0,0 +1,513 @@ +/* + * pts_fax.h -- a compact CCITTFax compressor and uncompressor) interface + * compiled by pts@fazekas.hu at Sun Jul 7 19:51:42 CEST 2002 + * + * For usage example, see fax_test.c. + * + * algorithm ripped from GNU Ghostscript, implementation and (C): + * +Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All +rights reserved. + +GNU Ghostscript is free software; you can redistribute it and/or +modify it under the terms of version 2 of the GNU General Public +License as published by the Free Software Foundation. + +GNU Ghostscript 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 so you can know your rights and responsibilities. +It should be in a file named doc/COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA +02111-1307, USA. + */ + +/*$Id: pts_fax.h,v 1.4 2005/07/20 21:15:08 pts Exp $ */ +/* CCITTFax filter state definition */ +/* Requires strimpl.h */ + +#ifndef PTS_FAX_H +# define PTS_FAX_H 1 + +#ifdef __GNUC__ +#pragma interface +#endif + +/* #include "scommon.h" */ +/*$Id: pts_fax.h,v 1.4 2005/07/20 21:15:08 pts Exp $ */ +/* Definitions common to stream clients and implementors */ + +/* #ifndef scommon_DEFINED */ +/* # define scommon_DEFINED */ + +/**** pts ****/ +#if 0 +#include "gsmemory.h" +#include "gsstype.h" /* for extern_st */ +#endif + +/**** pts ****/ +#include "config2.h" +/* ^^^ should #define SIZEOF_INT + * ^^^ should #define _, and ___ + * ^^^ should #define? USE_BULITIN_FAXD + * ^^^ should #define? USE_BULITIN_FAXE + * ^^^ should define const + */ +#if 0 /* example for Linux i386 gcc 2.95: */ + #define SIZEOF_INT 4 + #if ((defined(__STDC__) || defined(__PROTOTYPES__)) && !defined(NO_PROTO)) || defined(__cplusplus) + # define _(args) args + # define OF(args) args + # define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */ + #else + # define _(args) () + # define OF(args) () + # define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */ + #endif + #define USE_BUILTIN_FAXE 1 + #define USE_BUILITN_FAXD 1 +#endif + +typedef void (*gssss_memset_t)(void *s, int c, unsigned n); /* Imp: not `unsigned' len */ +/** The function must not return out of memory. */ +typedef void* (*gssss_xalloc_t)(unsigned len); /* Imp: not `unsigned' len */ +typedef void (*gssss_free_t)(void *ptr); +typedef void (*gssss_memcpy_t)(void *dest, const void *src, unsigned len); /* Imp: not `unsigned' len */ + +/* + * There are three major structures involved in the stream package. + * + * A stream is an "object" that owns a buffer, which it uses to implement + * unsigned char-oriented sequential access in a standard way, and a set of + * procedures that handle things like buffer refilling. See stream.h + * for more information about streams. + */ +#ifndef stream_DEFINED +# define stream_DEFINED +typedef struct stream_s stream; + +#endif +/* + * A stream_state records the state specific to a given variety of stream. + * The buffer processing function of a stream maintains this state. + */ +typedef struct stream_state_s stream_state; + +/* + * A stream_template provides the information needed to create a stream. + * The client must fill in any needed setup parameters in the appropriate + * variety of stream_state, and then call the initialization function + * provided by the template. See strimpl.h for more information about + * stream_templates. + */ +typedef struct stream_template_s stream_template; + +/* + * The stream package works with bytes, not chars. + * This is to ensure unsigned representation on all systems. + * A stream currently can only be read or written, not both. + * Note also that the read procedure returns an int, not a char or a unsigned char; + * we use negative values to indicate exceptional conditions. + * (We cast these values to int explicitly, because some compilers + * don't do this if the other arm of a conditional is a unsigned char.) + */ +/* End of data */ +#define PTSFAX_EOFC ((int)(-1)) +/* Error */ +#define PTSFAX_ERRC ((int)(-2)) +/* Interrupt */ +/* #define INTC ((int)(-3)) */ +/****** INTC IS NOT USED YET ******/ +/* Callout */ +/* #define CALLC ((int)(-4)) */ +#define max_stream_exception 4 +/* The following hack is needed for initializing scan_char_array in iscan.c. */ +#define stream_exception_repeat(x) x, x, x, x + +/* + * Define cursors for reading from or writing into a buffer. + * We lay them out this way so that we can alias + * the write pointer and the read limit. + */ +typedef struct stream_cursor_read_s { + const unsigned char *ptr; + const unsigned char *limit; + unsigned char *_skip; +} stream_cursor_read; +typedef struct stream_cursor_write_s { + const unsigned char *_skip; + unsigned char *ptr; + unsigned char *limit; +} stream_cursor_write; +typedef union stream_cursor_s { + stream_cursor_read r; + stream_cursor_write w; +} stream_cursor; + +/* + * Define the prototype for the procedures known to both the generic + * stream code and the stream implementations. + */ + +/* Initialize the stream state (after the client parameters are set). */ +#define stream_proc_init(proc)\ + int proc _((stream_state *)) + +/* Process a buffer. See strimpl.h for details. */ +#define stream_proc_process(proc)\ + int proc _((stream_state *, stream_cursor_read *,\ + stream_cursor_write *, bool)) + +/* Release the stream state when closing. */ +#define stream_proc_release(proc)\ + void proc _((stream_state *)) + +/* Initialize the client parameters to default values. */ +#define stream_proc_set_defaults(proc)\ + void proc _((stream_state *)) + +/* Reinitialize any internal stream state. Note that this does not */ +/* affect buffered data. We declare this as returning an int so that */ +/* it can be the same as the init procedure; however, reinit cannot fail. */ +#define stream_proc_reinit(proc)\ + int proc _((stream_state *)) + +/* Report an error. Note that this procedure is stored in the state, */ +/* not in the main stream structure. */ +#define stream_proc_report_error(proc)\ + int proc _((stream_state *, const char *)) +stream_proc_report_error(s_no_report_error); + +/* + * Some types of streams have the ability to read their parameters from + * a parameter list, and to write all (or only the non-default) + * parameters to a parameter list. Since these are not virtual + * procedures for the stream (they operate on stream_state structures + * even if no actual stream has been created), we name them differently. + */ +#define stream_state_proc_get_params(proc, state_type)\ + int proc _((gs_param_list *plist, const state_type *ss, bool all)) +#define stream_state_proc_put_params(proc, state_type)\ + int proc _((gs_param_list *plist, state_type *ss)) + +/* + * Define a generic stream state. If a processing procedure has no + * state of its own, it can use stream_state; otherwise, it must + * create a "subclass". There is a hack in stream.h to allow the stream + * itself to serve as the "state" of a couple of heavily used stream types. + * + * In order to simplify the structure descriptors for concrete streams, + * we require that the generic stream state not contain any pointers + * to garbage-collectable storage. + */ +#define STREAM_MAX_ERROR_STRING 79 +#define stream_state_common\ + const stream_template *template_; /**** pts C++ */\ + gssss_memset_t memset_;\ + gssss_xalloc_t xalloc_;\ + gssss_free_t free_;\ + gssss_memcpy_t memcpy_;\ + /* gs_memory_t *memory; */ /**** pts ****/ \ + stream_proc_report_error((*report_error));\ + int min_left; /* required bytes for lookahead */ \ + char error_string[STREAM_MAX_ERROR_STRING + 1] +struct stream_state_s { + stream_state_common; +}; + +/* extern_st(st_stream_state); */ /**** pts ****/ +#define public_st_stream_state() /* in stream.c */\ + gs_public_st_simple(st_stream_state, stream_state, "stream_state") + +/**** pts ****/ +/* original strimpl.h coming */ +/*$Id: pts_fax.h,v 1.4 2005/07/20 21:15:08 pts Exp $ */ +/* Definitions for stream implementors */ +/* Requires stdio.h */ + +/* + * The 'process' procedure does the real work of the stream. + * It must process as much input information (from pr->ptr + 1 through + * pr->limit) as it can, subject to space available for output + * (pw->ptr + 1 through pw->limit), updating pr->ptr and pw->ptr. + * + * The procedure return value must be one of: + * PTSFAX_EOFC - an end-of-data pattern was detected in the input, + * or no more input can be processed for some other reason (e.g., + * the stream was told only to read a certain amount of data). + * PTSFAX_ERRC - a syntactic error was detected in the input. + * 0 - more input data is needed. + * 1 - more output space is needed. + * If the procedure returns PTSFAX_EOFC, it can assume it will never be called + * again for that stream. + * + * If the procedure is called with last = 1, this is an indication that + * no more input will ever be supplied (after the input in the current + * buffer defined by *pr); the procedure should produce as much output + * as possible, including an end-of-data marker if applicable. In this + * case: + * - If the procedure returns 1, it may be called again (also with + * last = 1). + * - If the procedure returns any other value other than 1, the + * procedure will never be called again for that stream. + * - If the procedure returns 0, this is taken as equivalent to + * returning PTSFAX_EOFC. + * - If the procedure returns PTSFAX_EOFC (or 0), the stream's end_status + * is set to PTSFAX_EOFC, meaning no more writing is allowed. + * + * Note that these specifications do not distinguish input from output + * streams. This is deliberate: The processing procedures should work + * regardless of which way they are oriented in a stream pipeline. + * (The PostScript language does take a position as whether any given + * filter may be used for input or output, but this occurs at a higher level.) + * + * The value returned by the process procedure of a stream whose data source + * or sink is external (i.e., not another stream) is interpreted slightly + * differently. For an external data source, a return value of 0 means + * "no more input data are available now, but more might become available + * later." For an external data sink, a return value of 1 means "there is + * no more room for output data now, but there might be room later." + * + * It appears that the Adobe specifications, read correctly, require that when + * the process procedure of a decoding filter has filled up the output + * buffer, it must still peek ahead in the input to determine whether or not + * the next thing in the input stream is EOD. If the next thing is an EOD (or + * end-of-data, indicated by running out of input data with last = true), the + * process procedure must return PTSFAX_EOFC; if the next thing is definitely not + * an EOD, the process procedure must return 1 (output full) (without, of + * course, consuming the non-EOD datum); if the procedure cannot determine + * whether or not the next thing is an EOD, it must return 0 (need more input). + * Decoding filters that don't have EOD (for example, NullDecode) can use + * a simpler algorithm: if the output buffer is full, then if there is more + * input, return 1, otherwise return 0 (which is taken as PTSFAX_EOFC if last + * is true). All this may seem a little awkward, but it is needed in order + * to have consistent behavior regardless of where buffer boundaries fall -- + * in particular, if a buffer boundary falls just before an EOD. It is + * actually quite easy to implement if the main loop of the process + * procedure tests for running out of input rather than for filling the + * output: with this structure, exhausting the input always returns 0, + * and discovering that the output buffer is full when attempting to store + * more output always returns 1. + * + * Even this algorithm for handling end-of-buffer is not sufficient if an + * EOD falls just after a buffer boundary, but the generic stream code + * handles this case: the process procedures need only do what was just + * described. + */ + +/* + * The set_defaults procedure in the template has a dual purpose: it sets + * default values for all parameters that the client can set before calling + * the init procedure, and it also must initialize all pointers in the + * stream state to a value that will be valid for the garbage collector + * (normally 0). The latter implies that: + * + * Any stream whose state includes additional pointers (beyond those + * in stream_state_common) must have a set_defaults procedure. + */ + +/* + * Note that all decoding filters that require an explicit EOD in the + * source data must have an init procedure that sets min_left = 1. + * This effectively provides a 1-unsigned char lookahead in the source data, + * which is required so that the stream can close itself "after reading + * the last unsigned char of data" (per Adobe specification), as noted above. + */ + +/* + * Define a template for creating a stream. + * + * The meaning of min_in_size and min_out_size is the following: + * If the amount of input information is at least min_in_size, + * and the available output space is at least min_out_size, + * the process procedure guarantees that it will make some progress. + * (It may make progress even if this condition is not met, but this is + * not guaranteed.) + */ +struct stream_template_s { + + /* Define the structure type for the stream state. */ + /* gs_memory_type_ptr_t stype; */ /**** pts ****/ + + /* Define an optional initialization procedure. */ + stream_proc_init((*init)); + + /* Define the processing procedure. */ + /* (The init procedure can reset other procs if it wants.) */ + stream_proc_process((*process)); + + /* Define the minimum buffer sizes. */ + unsigned int min_in_size; /* minimum size for process input */ + unsigned int min_out_size; /* minimum size for process output */ + + /* Define an optional releasing procedure. */ + stream_proc_release((*release)); + + /* Define an optional parameter defaulting and pointer initialization */ + /* procedure. */ + stream_proc_set_defaults((*set_defaults)); + + /* Define an optional reinitialization procedure. */ + stream_proc_reinit((*reinit)); + +}; + + +#if 0 +/* Hex decoding utility procedure */ +typedef enum { + hex_ignore_garbage = 0, + hex_ignore_whitespace = 1, + hex_ignore_leading_whitespace = 2 +} hex_syntax; +int s_hex_process _((stream_cursor_read *, stream_cursor_write *, int *, hex_syntax)); /* in sstring.c */ +#endif +/* end of former strimpl.h */ +/* #endif */ /* scommon_INCLUDED */ +/* end of former scommon.h */ + + + +/* ------ Common state ------ */ + +/* + * Define the common stream state for Huffman-coded filters. + * Invariants when writing: + * 0 <= bits_left <= hc_bits_size; + * Only the leftmost (hc_bits_size - bits_left) bits of bits + * contain valid data. + */ +#define stream_hc_state_common\ + stream_state_common;\ + /* The client sets the following before initialization. */\ + bool FirstBitLowOrder;\ + /* The following are updated dynamically. */\ + unsigned int bits; /* most recent bits of input or */\ + /* current bits of output */\ + int bits_left /* # of valid low bits (input) or */\ + /* unused low bits (output) in above, */\ + /* 0 <= bits_left <= 7 */ +typedef struct stream_hc_state_s { + stream_hc_state_common; +} stream_hc_state; + +/* Common state */ +#define stream_CF_state_common\ + stream_hc_state_common;\ + /* The client sets the following before initialization. */\ + bool Uncompressed;\ + int K;\ + bool EndOfLine;\ + bool EncodedByteAlign;\ + int Columns;\ + int Rows;\ + bool EndOfBlock;\ + bool BlackIs1;\ + int DamagedRowsBeforeError; /* (Decode only) */\ + /*bool FirstBitLowOrder;*/ /* in stream_hc_state_common */\ + int DecodedByteAlign;\ + /* The init procedure sets the following. */\ + unsigned int raster;\ + unsigned char *lbuf; /* current scan line buffer */\ + /* (only if decoding or 2-D encoding) */\ + unsigned char *lprev; /* previous scan line buffer (only if 2-D) */\ + /* The following are updated dynamically. */\ + int k_left /* number of next rows to encode in 2-D */\ + /* (only if K > 0) */ +typedef struct stream_CF_state_s { + stream_CF_state_common; +} stream_CF_state; + +/* Define common default parameter setting. */ +#define s_CF_set_defaults_inline(ss)\ + ((ss)->Uncompressed = false,\ + (ss)->K = 0,\ + (ss)->EndOfLine = false,\ + (ss)->EncodedByteAlign = false,\ + (ss)->Columns = 1728,\ + (ss)->Rows = 0,\ + (ss)->EndOfBlock = true,\ + (ss)->BlackIs1 = false,\ + /* Added by Adobe since the Red Book */\ + (ss)->DamagedRowsBeforeError = 0, /* always set, for s_CF_get_params */\ + (ss)->FirstBitLowOrder = false,\ + /* Added by us */\ + (ss)->DecodedByteAlign = 1,\ + /* Clear pointers */\ + (ss)->lbuf = 0, (ss)->lprev = 0) + +/* CCITTFaxEncode */ +typedef struct stream_CFE_state_s { + stream_CF_state_common; + /* The init procedure sets the following. */ + int max_code_bytes; /* max # of bytes for an encoded line */ + unsigned char *lcode; /* buffer for encoded output line */ + /* The following change dynamically. */ + int read_count; /* # of bytes to copy into lbuf */ + int write_count; /* # of bytes to copy out of lcode */ + int code_bytes; /* # of occupied bytes in lcode */ +} stream_CFE_state; + +#define private_st_CFE_state() /* in scfe.c */\ + gs_private_st_ptrs3(st_CFE_state, stream_CFE_state, "CCITTFaxEncode state",\ + cfe_enum_ptrs, cfe_reloc_ptrs, lbuf, lprev, lcode) +#define s_CFE_set_defaults_inline(ss)\ + (s_CF_set_defaults_inline(ss), (ss)->lcode = 0) +#if USE_BUILTIN_FAXE +/**** pts ****/ +#if SIZEOF_INT > 2 +# define cfe_max_width (2560 * 32000 * 2 / 3) +#else +# define cfe_max_width ((int)((unsigned)-1/2 - 40)) /* avoid overflows */ +#endif +#ifdef __cplusplus +extern "C" +#else +extern +#endif +const stream_template s_CFE_template; +#endif + +/* CCITTFaxDecode */ +typedef struct stream_CFD_state_s { + stream_CF_state_common; + int cbit; /* bits left to fill in current decoded */ + /* unsigned char at lbuf[wpos] (0..7) */ + int rows_left; /* number of rows left */ + int rpos; /* rptr for copying lbuf to client */ + int wpos; /* rlimit/wptr for filling lbuf or */ + /* copying to client */ + int eol_count; /* number of EOLs seen so far */ + unsigned char invert; /* current value of 'white' */ + /* for 2-D decoding */ + int run_color; /* -1 if processing white run, */ + /* 0 if between runs but white is next, */ + /* 1 if between runs and black is next, */ + /* 2 if processing black run */ + int damaged_rows; /* # of consecutive damaged rows preceding */ + /* the current row */ + bool skipping_damage; /* true if skipping a damaged row looking */ + /* for EOL */ + /* The following are not used yet. */ + int uncomp_run; /* non-0 iff we are in an uncompressed */ + /* run straddling a scan line (-1 if white, */ + /* 1 if black) */ + int uncomp_left; /* # of bits left in the run */ + int uncomp_exit; /* non-0 iff this is an exit run */ + /* (-1 if next run white, 1 if black) */ +} stream_CFD_state; + +#define private_st_CFD_state() /* in scfd.c */\ + gs_private_st_ptrs2(st_CFD_state, stream_CFD_state, "CCITTFaxDecode state",\ + cfd_enum_ptrs, cfd_reloc_ptrs, lbuf, lprev) +#define s_CFD_set_defaults_inline(ss)\ + s_CF_set_defaults_inline(ss) +#if USE_BUILTIN_FAXD +extern const stream_template s_CFD_template; +#endif + +#endif /* pts_fax.h */ diff --git a/Build/source/utils/sam2p/pts_lzw.c b/Build/source/utils/sam2p/pts_lzw.c new file mode 100644 index 00000000000..43142effb89 --- /dev/null +++ b/Build/source/utils/sam2p/pts_lzw.c @@ -0,0 +1,1487 @@ +#define DUMMY \ +set -ex; \ +g++ -DNDEBUG=1 -O3 -ansi -pedantic \ + -Wall -W -Wstrict-prototypes -Wtraditional -Wnested-externs -Winline \ + -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wmissing-prototypes \ + -Wmissing-declarations pts_lzw.c -c; \ +exit +/* pts_lzw.c -- a real, effective implementation of PostScript + * LanguageLevel2 and PDF /LZWEncode and /LZWDecode filters (same as the LZW + * compression used in TIFF raster image files) + * + * based on tif_lzw.c in libtiff-v3.4beta037 by Sam Leffler and Silicon Graphics. + * by pts@fazekas.hu at Sun Dec 30 15:04:19 CET 2001 + * encoding and decoding works at Sun Dec 30 17:05:23 CET 2001 + * modified for sam2p at Mon Mar 4 00:21:59 CET 2002 + * + * Note that the LZW compression (but not uncompression) is patented by + * Unisys (patent number #4,558,302), so use this program at your own legal + * risk! + * + * Predictors and PostScript LanguageLevel3 filter options are not supported. + * + * Test: linux-2.2.8.tar.gz + * -- uncompressed: 58 388 480 bytes + * -- LZWEncode (lzw_codec.c): 26 518 397 bytes (uncompression OK) + * -- FlateEncode (almost gzip): 13 808 890 bytes (uncompression: zcat) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* Imp: check #ifdef _WINDOWS */ +/* Dat: a strip is an interval of rows. Each strip -- probably except for the + * last -- has a same number of rows. Strips are useful for TIFF writers + * to better organize data in memory or disk. + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#if _MSC_VER > 1000 +# undef __PROTOTYPES__ +# define __PROTOTYPES__ 1 +# pragma warning(disable: 4127) /* conditional expression is constant */ +# pragma warning(disable: 4244) /* =' : conversion from 'int ' to 'unsigned char ', possible loss of data */ +#endif + + +/* Original: /d1/sam/tiff/libtiff/RCS/tif_lzw.c,v 1.73 1997/08/29 21:45:54 sam Exp */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/**** pts ****/ +#if OBJDEP +# warning PROVIDES: pts_lzw +#endif +#define LZW_SUPPORT 1 +#if 0 /* conflicts with some system defs */ +typedef unsigned short u_short; +typedef unsigned char u_char; +typedef unsigned long u_long; +#endif +#define TO_RDONLY 1 +#define _TIFFmalloc malloc +#define _TIFFfree free +#define _TIFFmemset memset +#include <stdlib.h> +#include <string.h> + +/* + * ``Library-private'' definitions. + */ + +/* + * TIFF I/O Library Definitions. + */ +/* + * Tag Image File Format (TIFF) + * + * Based on Rev 6.0 from: + * Developer's Desk + * Aldus Corporation + * 411 First Ave. South + * Suite 200 + * Seattle, WA 98104 + * 206-622-5500 + */ +#define TIFF_VERSION 42 + +/* + * NB: In the comments below, + * - items marked with a + are obsoleted by revision 5.0, + * - items marked with a ! are introduced in revision 6.0. + * - items marked with a % are introduced post revision 6.0. + * - items marked with a $ are obsoleted by revision 6.0. + */ + +/* --- */ + +/* + * This define can be used in code that requires + * compilation-related definitions specific to a + * version or versions of the library. Runtime + * version checking should be done based on the + * string returned by TIFFGetVersion. + */ +#define TIFFLIB_VERSION 19970127 /* January 27, 1997 */ + +/* + * The following typedefs define the intrinsic size of + * data types used in the *exported* interfaces. These + * definitions depend on the proper definition of types + * in tiff.h. Note also that the varargs interface used + * to pass tag types and values uses the types defined in + * tiff.h directly. + * + * NB: ttag_t is unsigned int and not unsigned short because + * ANSI C requires that the type before the ellipsis be a + * promoted type (i.e. one of int, unsigned int, pointer, + * or double) and because we defined pseudo-tags that are + * outside the range of legal Aldus-assigned tags. + * NB: tsize_t is int32 and not uint32 because some functions + * return -1. + * NB: toff_t is not off_t for many reasons; TIFFs max out at + * 32-bit file offsets being the most important + */ + +#ifndef NULL +#define NULL 0 +#endif + +typedef struct pts_lzw_state TIFF; +#include "pts_lzw.h" + +/**** pts ****/ +static int TIFFInitLZW(TIFF*); +static void TIFFError(char const*a, char const*b); +#if 0 /**** pts ****/ +static void TIFFWarning(char const*a, char const*b, int c); +void TIFFWarning(char const*a, char const*b, int c) { + fprintf(stderr, "Warning: %s: ", a); + fprintf(stderr, b, c); + fprintf(stderr, "\n"); +} +#endif +static int TIFFAppendTo(TIFF*, tidataval_t*, tsize_t); /* tif_write.h */ +#if 0 +static void TIFFReverseBits(unsigned char *, unsigned long); +#endif + +#ifdef LZW_SUPPORT +/* + * TIFF Library. + * Rev 5.0 Lempel-Ziv & Welch Compression Support + * + * This code is derived from the compress program whose code is + * derived from software contributed to Berkeley by James A. Woods, + * derived from original work by Spencer Thomas and Joseph Orost. + * + * The original Berkeley copyright notice appears below in its entirety. + */ + +#include <assert.h> +/* #include <stdio.h> */ + +/* + * Internal version of TIFFFlushData that can be + * called by ``encodestrip routines'' w/o concern + * for infinite recursion. + */ +static int +TIFFFlushData1(TIFF* tif) +{ + if (tif->tif_rawcc > 0) { +#if 0 + if (tif->tif_revbits_p) + TIFFReverseBits((unsigned char *)tif->tif_rawdata, + tif->tif_rawcc); +#endif + if (!TIFFAppendTo(tif, + /* isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, */ + tif->tif_rawdata, tif->tif_rawcc)) + return (0); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + } + return (1); +} + + + +/* + * NB: The 5.0 spec describes a different algorithm than Aldus + * implements. Specifically, Aldus does code length transitions + * one code earlier than should be done (for real LZW). + * Earlier versions of this library implemented the correct + * LZW algorithm, but emitted codes in a bit order opposite + * to the TIFF spec. Thus, to maintain compatibility w/ Aldus + * we interpret MSB-LSB ordered codes to be images written w/ + * old versions of this library, but otherwise adhere to the + * Aldus "off by one" algorithm. + * + * Future revisions to the TIFF spec are expected to "clarify this issue". + */ +#define LZW_COMPAT /* include backwards compatibility code */ +/* + * Each strip of data is supposed to be terminated by a CODE_EOI. + * If the following #define is included, the decoder will also + * check for end-of-strip w/o seeing this code. This makes the + * library more robust, but also slower. + */ +#define LZW_CHECKEOS /* include checks for strips w/o EOI code */ +#undef LZW_CHECKEOS /**** pts ****/ + +#define MAXCODE(n) ((1L<<(n))-1) +/* + * The TIFF spec specifies that encoded bit + * strings range from 9 to 12 bits. + */ +#define BITS_MIN 9 /* start with 9 bits */ +#define BITS_MAX 12 /* max of 12 bit strings */ +/* predefined codes */ +#define CODE_CLEAR 256 /* code to clear string table */ +#define CODE_EOI 257 /* end-of-information code */ +#define CODE_FIRST 258 /* first free code entry */ +#define CODE_MAX MAXCODE(BITS_MAX) +#define HSIZE 9001L /* 91% occupancy */ +#define HSHIFT (13-8) +#ifdef LZW_COMPAT +/* NB: +1024 is for compatibility with old files */ +#define CSIZE (MAXCODE(BITS_MAX)+1024L) +#else +#define CSIZE (MAXCODE(BITS_MAX)+1L) +#endif + +/* + * State block for each open TIFF file using LZW + * compression/decompression. Note that the predictor + * state block must be first in this data structure. + */ +typedef struct { +#if 0 /****pts****/ + TIFFPredictorState predict; /* predictor super class */ +#endif + + unsigned short nbits; /* # of bits/code */ + unsigned short maxcode; /* maximum code for lzw_nbits */ + unsigned short free_ent; /* next free entry in hash table */ + long nextdata; /* next bits of i/o */ + long nextbits; /* # of valid bits in lzw_nextdata */ +} LZWBaseState; + +#define lzw_nbits base.nbits +#define lzw_maxcode base.maxcode +#define lzw_free_ent base.free_ent +#define lzw_nextdata base.nextdata +#define lzw_nextbits base.nextbits + +/* + * Decoding-specific state. + */ +typedef struct code_ent { + struct code_ent *next; + unsigned short length; /* string len, including this token */ + unsigned char value; /* data value */ + unsigned char firstchar; /* first token of string */ +} code_t; + +typedef int (*decodeFunc)(TIFF*, tidataval_t*, tsize_t); + +typedef struct { + LZWBaseState base; + long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */ + long dec_restart; /* restart count */ +#ifdef LZW_CHECKEOS + long dec_bitsleft; /* available bits in raw data */ +#endif + decodeFunc dec_decode; /* regular or backwards compatible */ + code_t* dec_codep; /* current recognized code */ + code_t* dec_oldcodep; /* previously recognized code */ + code_t* dec_free_entp; /* next free entry */ + code_t* dec_maxcodep; /* max available entry */ + code_t* dec_codetab; /* kept separate for small machines */ +} LZWDecodeState; + +/* + * Encoding-specific state. + */ +typedef unsigned short hcode_t; /* codes fit in 16 bits */ +typedef struct { + long hash; + hcode_t code; +} hash_t; + +typedef struct { + LZWBaseState base; + int enc_oldcode; /* last code encountered */ + long enc_checkpoint; /* point at which to clear table */ +#define CHECK_GAP 10000 /* enc_ratio check interval */ + long enc_ratio; /* current compression ratio */ + long enc_incount; /* (input) data bytes encoded */ + long enc_outcount; /* encoded (output) bytes */ + tidataval_t* enc_rawlimit; /* bound on tif_rawdata buffer */ + hash_t* enc_hashtab; /* kept separate for small machines */ +} LZWEncodeState; + +#define LZWState(tif) ((LZWBaseState*) (void*) (tif)->tif_data) +#define DecoderState(tif) ((LZWDecodeState*)(void*) LZWState(tif)) +#define EncoderState(tif) ((LZWEncodeState*)(void*) LZWState(tif)) +/* ^^^ Dat: (void*) -> suppress gcc warning from -Wcast-align */ + +static void cl_hash(LZWEncodeState*); + +#if 0 /**** pts ****/ /* LZW decoder is not needed */ + +static int LZWDecode(TIFF*, tidataval_t*, tsize_t); +#ifdef LZW_COMPAT +static int LZWDecodeCompat(TIFF*, tidataval_t*, tsize_t); +#endif + +/* + * LZW Decoder. + */ + +#ifdef LZW_CHECKEOS +/* + * This check shouldn't be necessary because each + * strip is suppose to be terminated with CODE_EOI. + */ +#define NextCode(_tif, _sp, _bp, _code, _get) { \ + if ((_sp)->dec_bitsleft < nbits) { \ + TIFFWarning(_tif->tif_name, \ + "LZWDecode: Strip %d not terminated with EOI code", \ + /*_tif->tif_curstrip*/ 0); \ + _code = CODE_EOI; \ + } else { \ + _get(_sp,_bp,_code); \ + (_sp)->dec_bitsleft -= nbits; \ + } \ +} +#else +#define NextCode(tif, sp, bp, code, get) get(sp, bp, code) +#endif + +static int +LZWSetupDecode(TIFF* tif) +{ + LZWDecodeState* sp = DecoderState(tif); + static const char module[] = " LZWSetupDecode"; + int code; + + assert(sp != NULL); + if (sp->dec_codetab == NULL) { + sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); + if (sp->dec_codetab == NULL) { + TIFFError(module, "No space for LZW code table"); + return (0); + } + /* + * Pre-load the table. + */ + for (code = 255; code >= 0; code--) { + sp->dec_codetab[code].value = code; + sp->dec_codetab[code].firstchar = code; + sp->dec_codetab[code].length = 1; + sp->dec_codetab[code].next = NULL; + } + } + return (1); +} + +/* + * Setup state for decoding a strip. + */ +static int +LZWPreDecode(TIFF* tif) +{ + LZWDecodeState *sp = DecoderState(tif); + + assert(sp != NULL); + /* + * Check for old bit-reversed codes. + */ + if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { +#ifdef LZW_COMPAT + if (!sp->dec_decode) { + TIFFWarning(tif->tif_name, + "Old-style LZW codes, convert file %d", 0); +#if 0 /**** pts ****/ + /* + * Override default decoding methods with + * ones that deal with the old coding. + * Otherwise the predictor versions set + * above will call the compatibility routines + * through the dec_decode method. + */ + tif->tif_decoderow = LZWDecodeCompat; + tif->tif_decodestrip = LZWDecodeCompat; + tif->tif_decodetile = LZWDecodeCompat; + /* + * If doing horizontal differencing, must + * re-setup the predictor logic since we + * switched the basic decoder methods... + */ + (*tif->tif_setupdecode)(tif); +#endif + LZWSetupDecode(tif); + sp->dec_decode = LZWDecodeCompat; + } + sp->lzw_maxcode = MAXCODE(BITS_MIN); +#else /* !LZW_COMPAT */ + if (!sp->dec_decode) { + TIFFError(tif->tif_name, + "Old-style LZW codes not supported"); + sp->dec_decode = LZWDecode; + } + return (0); +#endif/* !LZW_COMPAT */ + } else { + sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; + sp->dec_decode = LZWDecode; + } + sp->lzw_nbits = BITS_MIN; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; + + sp->dec_restart = 0; + sp->dec_nbitsmask = MAXCODE(BITS_MIN); +#ifdef LZW_CHECKEOS + sp->dec_bitsleft = tif->tif_rawcc << 3; +#endif + sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; + /* + * Zero entries that are not yet filled in. We do + * this to guard against bogus input data that causes + * us to index into undefined entries. If you can + * come up with a way to safely bounds-check input codes + * while decoding then you can remove this operation. + */ + _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); + sp->dec_oldcodep = &sp->dec_codetab[-1]; + sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; + return (1); +} + +/* + * Decode a "hunk of data". + */ +#define GetNextCode(sp, bp, code) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + } \ + code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \ + nextbits -= nbits; \ +} + +static void +codeLoop(TIFF* tif) +{ + TIFFError(tif->tif_name, + "LZWDecode: Bogus encoding, loop in the code table; scanline %d" + /*,tif->tif_row*/); +} + +static int +LZWDecode(TIFF* tif, tidataval_t* op0, tsize_t occ0) +{ + LZWDecodeState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + unsigned char *bp; + hcode_t code; + int len; + long nbits, nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; + + assert(sp != NULL); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; + + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ && codep); + if (codep) { + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + } + return occ0-occ; + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue, occ -= residue; + tp = op; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = t; + } while (--residue && codep); + sp->dec_restart = 0; + } + + bp = (unsigned char *)tif->tif_rawcp; /* reading from here */ + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0 && bp<tif->tif_rawend /**** pts ****/) { + NextCode(tif, sp, bp, code, GetNextCode); + #if 0 + if (bp>tif->tif_rawend) fprintf(stderr, "over %d\n", tif->tif_rawend-bp); + assert(bp<=tif->tif_rawend); + #endif + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + free_entp = sp->dec_codetab + CODE_FIRST; + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask-1; + +#if 1 /**** pts ****/ + NextCode(tif, sp, bp, code, GetNextCode); + if (code == CODE_EOI) + break; + *op++ = code, occ--; + oldcodep = sp->dec_codetab + code; /* ! */ +#endif + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + assert(&sp->dec_codetab[0] <= free_entp && free_entp < &sp->dec_codetab[CSIZE]); + free_entp->next = oldcodep; + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask-1; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep && codep->length > occ); + if (codep) { + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + if (codep) { + codeLoop(tif); + return -1; + } + } + break; + } + len = codep->length; + tp = op + len; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = t; + } while (codep && tp > op); + if (codep) { + codeLoop(tif); + return -1; + /* break; */ + } + op += len, occ -= len; + } else + *op++ = code, occ--; + } + + tif->tif_rawcp = (tidataval_t*) bp; + sp->lzw_nbits = (unsigned short) nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + +#if 0 /**** pts ****/ + if (occ > 0) { + TIFFError(tif->tif_name, + "LZWDecode: Not enough data at scanline %d (short %d bytes)" + /*,tif->tif_row, occ*/); + return (0); + } +#endif + return occ0-occ; +} + +#ifdef LZW_COMPAT +/* + * Decode a "hunk of data" for old images. + */ +#define GetNextCodeCompat(sp, bp, code) { \ + nextdata |= (unsigned long) *(bp)++ << nextbits; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata |= (unsigned long) *(bp)++ << nextbits; \ + nextbits += 8; \ + } \ + code = (hcode_t)(nextdata & nbitsmask); \ + nextdata >>= nbits; \ + nextbits -= nbits; \ +} + +static int +LZWDecodeCompat(TIFF* tif, tidataval_t* op0, tsize_t occ0) +{ + LZWDecodeState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + unsigned char *bp; + int code, nbits; + long nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; + + assert(0); + assert(sp != NULL); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; + + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ); + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + return occ0-occ; + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue, occ -= residue; + tp = op; + do { + *--tp = codep->value; + codep = codep->next; + } while (--residue); + sp->dec_restart = 0; + } + + bp = (unsigned char *)tif->tif_rawcp; + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0 && bp<tif->tif_rawend) { + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + free_entp = sp->dec_codetab + CODE_FIRST; + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask; + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + *op++ = code, occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + assert(&sp->dec_codetab[0] <= free_entp && free_entp < &sp->dec_codetab[CSIZE]); + free_entp->next = oldcodep; + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep->length > occ); + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + break; + } + op += codep->length, occ -= codep->length; + tp = op; + do { + *--tp = codep->value; + } while (0!=(codep = codep->next)); + } else + *op++ = code, occ--; + } + + tif->tif_rawcp = (tidataval_t*) bp; + sp->lzw_nbits = nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + +#if 0 /**** pts ****/ + if (occ > 0) { + TIFFError(tif->tif_name, + "LZWDecodeCompat: Not enough data at scanline %d (short %d bytes)" + /*,tif->tif_row, occ*/); + return (0); + } +#endif + return occ0-occ; +} +#endif /* LZW_COMPAT */ + +#endif /**** pts ****/ + +/* --- */ + +/* + * LZW Encoding. + */ + +static int +LZWSetupEncode(TIFF* tif) +{ + LZWEncodeState* sp = EncoderState(tif); + static const char module[] = "LZWSetupEncode"; + + assert(sp != NULL); + sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t)); + if (sp->enc_hashtab == NULL) { + TIFFError(module, "No space for LZW hash table"); + return (0); + } + return (1); +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +LZWPreEncode(TIFF* tif) +{ + LZWEncodeState *sp = EncoderState(tif); + + assert(sp != NULL); + sp->lzw_nbits = BITS_MIN; + sp->lzw_maxcode = MAXCODE(BITS_MIN); + sp->lzw_free_ent = CODE_FIRST; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; + sp->enc_checkpoint = CHECK_GAP; + sp->enc_ratio = 0; + sp->enc_incount = 0; + sp->enc_outcount = 0; + /* + * The 4 here insures there is space for 2 max-sized + * codes in LZWEncode and LZWPostDecode. + */ + sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4; + cl_hash(sp); /* clear hash table */ + sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */ + return (1); +} + +#define CALCRATIO(sp, rat) { \ + if (incount > 0x007fffff) { /* NB: shift will overflow */\ + rat = outcount >> 8; \ + rat = (rat == 0 ? 0x7fffffff : incount/rat); \ + } else \ + rat = (incount<<8) / outcount; \ +} +#define PutNextCode(op, c) { \ + nextdata = (nextdata << nbits) | c; \ + nextbits += nbits; \ + *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ + nextbits -= 8; \ + if (nextbits >= 8) { \ + *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ + nextbits -= 8; \ + } \ + outcount += nbits; \ +} + +/* + * Encode a chunk of pixels. + * + * Uses an open addressing double hashing (no chaining) on the + * prefix code/next character combination. We do a variant of + * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's + * relatively-prime secondary probe. Here, the modular division + * first probe is gives way to a faster exclusive-or manipulation. + * Also do block compression with an adaptive reset, whereby the + * code table is cleared when the compression ratio decreases, + * but after the table fills. The variable-length output codes + * are re-sized at this point, and a CODE_CLEAR is generated + * for the decoder. + */ +static int +LZWEncode(TIFF* tif, tidataval_t* bp, tsize_t cc) +{ + register LZWEncodeState *sp = EncoderState(tif); + register long fcode; + register hash_t *hp; + register int h, c; + hcode_t ent; + long disp; + long incount, outcount, checkpoint; + long nextdata, nextbits; + int free_ent, maxcode, nbits; + tidataval_t* op, *limit; + + if (sp == NULL) + return (0); + /* + * Load local state. + */ + incount = sp->enc_incount; + outcount = sp->enc_outcount; + checkpoint = sp->enc_checkpoint; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + free_ent = sp->lzw_free_ent; + maxcode = sp->lzw_maxcode; + nbits = sp->lzw_nbits; + op = tif->tif_rawcp; + limit = sp->enc_rawlimit; + ent = sp->enc_oldcode; + + if (ent == (hcode_t) -1 && cc > 0) { + /* + * NB: This is safe because it can only happen + * at the start of a strip where we know there + * is space in the data buffer. + */ + PutNextCode(op, CODE_CLEAR); + ent = *bp++; cc--; incount++; + } + while (cc > 0) { + c = *bp++; cc--; incount++; + fcode = ((long)c << BITS_MAX) + ent; + h = (c << HSHIFT) ^ ent; /* xor hashing */ +#ifdef _WINDOWS /* ?? */ + /* + * Check hash index for an overflow. + */ + if (h >= HSIZE) + h -= HSIZE; +#endif + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + continue; + } + if (hp->hash >= 0) { + /* + * Primary hash failed, check secondary hash. + */ + disp = HSIZE - h; + if (h == 0) + disp = 1; + do { + /* + * Avoid pointer arithmetic 'cuz of + * wraparound problems with segments. + */ + if ((h -= disp) < 0) + h += HSIZE; + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + goto hit; + } + } while (hp->hash >= 0); + } + /* + * New entry, emit code and add to table. + */ + /* + * Verify there is space in the buffer for the code + * and any potential Clear code that might be emitted + * below. The value of limit is setup so that there + * are at least 4 bytes free--room for 2 codes. + */ + if (op > limit) { + tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata); + TIFFFlushData1(tif); + op = tif->tif_rawdata; + } + PutNextCode(op, ent); + ent = c; + hp->code = free_ent++; + hp->hash = fcode; + if (free_ent == CODE_MAX-1) { + /* table is full, emit clear code and reset */ + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else { + /* + * If the next entry is going to be too big for + * the code size, then increase it, if possible. + */ + if (free_ent > maxcode) { + nbits++; + assert(nbits <= BITS_MAX); + maxcode = (int) MAXCODE(nbits); + } else if (incount >= checkpoint) { + long rat; + /* + * Check compression ratio and, if things seem + * to be slipping, clear the hash table and + * reset state. The compression ratio is a + * 24+8-bit fractional number. + */ + checkpoint = incount+CHECK_GAP; + CALCRATIO(sp, rat); + if (rat <= sp->enc_ratio) { + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else + sp->enc_ratio = rat; + } + } + hit: + ; + } + + /* + * Restore global state. + */ + sp->enc_incount = incount; + sp->enc_outcount = outcount; + sp->enc_checkpoint = checkpoint; + sp->enc_oldcode = ent; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->lzw_free_ent = free_ent; + sp->lzw_maxcode = maxcode; + sp->lzw_nbits = nbits; + tif->tif_rawcp = op; + return (1); +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ +static int +LZWPostEncode(TIFF* tif) +{ + register LZWEncodeState *sp = EncoderState(tif); + tidataval_t* op = tif->tif_rawcp; + long nextbits = sp->lzw_nextbits; + long nextdata = sp->lzw_nextdata; + long outcount = sp->enc_outcount; + int nbits = sp->lzw_nbits; + + if (op > sp->enc_rawlimit) { + /* fprintf(stderr, "Yupp!\n"); */ + tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata); + TIFFFlushData1(tif); + op = tif->tif_rawdata; + } + if (sp->enc_oldcode != (hcode_t) -1) { + /* fprintf(stderr, "EIK\n"); */ + PutNextCode(op, sp->enc_oldcode); + sp->enc_oldcode = (hcode_t) -1; + } + PutNextCode(op, CODE_EOI); + if (nextbits > 0) + *op++ = (unsigned char)(nextdata << (8-nextbits)); + tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata); + return (1); +} + +/* + * Reset encoding hash table. + */ +static void +cl_hash(LZWEncodeState* sp) +{ + register hash_t *hp = &sp->enc_hashtab[HSIZE-1]; + register long i = HSIZE-8; + + do { + i -= 8; + hp[-7].hash = -1; + hp[-6].hash = -1; + hp[-5].hash = -1; + hp[-4].hash = -1; + hp[-3].hash = -1; + hp[-2].hash = -1; + hp[-1].hash = -1; + hp[ 0].hash = -1; + hp -= 8; + } while (i >= 0); + for (i += 8; i > 0; i--, hp--) + hp->hash = -1; +} + +static void +LZWCleanup(TIFF* tif) +{ + if (tif->tif_data) { + if (tif->tif_reading_p) { + if (DecoderState(tif)->dec_codetab) + _TIFFfree(DecoderState(tif)->dec_codetab); + } else { + if (EncoderState(tif)->enc_hashtab) + _TIFFfree(EncoderState(tif)->enc_hashtab); + } + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + } +} + +static int +TIFFInitLZW(TIFF* tif) +{ + /* assert(scheme == COMPRESSION_LZW); */ + /* + * Allocate state block so tag methods have storage to record values. + */ + if (tif->tif_reading_p) { + tif->tif_data = (tidataval_t*) _TIFFmalloc(sizeof (LZWDecodeState)); + if (tif->tif_data == NULL) + goto bad; + DecoderState(tif)->dec_codetab = NULL; + DecoderState(tif)->dec_decode = NULL; + } else { + tif->tif_data = (tidataval_t*) _TIFFmalloc(sizeof (LZWEncodeState)); + if (tif->tif_data == NULL) + goto bad; + EncoderState(tif)->enc_hashtab = NULL; + } +#if 0 /**** pts ****/ + /* + * Install codec methods. + */ + tif->tif_setupdecode = LZWSetupDecode; + tif->tif_predecode = LZWPreDecode; + tif->tif_decoderow = LZWDecode; + tif->tif_decodestrip = LZWDecode; + tif->tif_decodetile = LZWDecode; + tif->tif_setupencode = LZWSetupEncode; + tif->tif_preencode = LZWPreEncode; + tif->tif_postencode = LZWPostEncode; + tif->tif_encoderow = LZWEncode; + tif->tif_encodestrip = LZWEncode; + tif->tif_encodetile = LZWEncode; + tif->tif_cleanup = LZWCleanup; +#endif +#if 0 /**** pts ****/ + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); +#endif + return (1); +bad: + TIFFError("TIFFInitLZW", "No space for LZW state block"); + return (0); +} + +/* + * Copyright (c) 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#endif /* LZW_SUPPORT */ + +#if 0 +#ifdef __cplusplus +extern "C" +#else +extern +#endif +FILE *fdopen (int fildes, const char *mode); /* POSIX, but not ANSI */ +#else +#undef _POSIX_SOURCE +#define _POSIX_SOURCE 1 +#undef _POSIX_C_SOURCE /* Sat Jun 1 14:25:53 CEST 2002 */ +#define _POSIX_C_SOURCE 2 +#include <stdio.h> +#endif + +#if 0 /**** pts: never needed, because output FillOrder is always 1 */ +void +TIFFReverseBits(register unsigned char* cp, register unsigned long n) +{ + char *TIFFBitRevTable=...; /**** pts ****/ + for (; n > 8; n -= 8) { + cp[0] = TIFFBitRevTable[cp[0]]; + cp[1] = TIFFBitRevTable[cp[1]]; + cp[2] = TIFFBitRevTable[cp[2]]; + cp[3] = TIFFBitRevTable[cp[3]]; + cp[4] = TIFFBitRevTable[cp[4]]; + cp[5] = TIFFBitRevTable[cp[5]]; + cp[6] = TIFFBitRevTable[cp[6]]; + cp[7] = TIFFBitRevTable[cp[7]]; + cp += 8; + } + while (n-- > 0) + *cp = TIFFBitRevTable[*cp], cp++; +} +#endif + +static void TIFFError(char const*a, char const*b) { + fprintf(stderr, "%s: %s\n", a, b); +} +static int TIFFAppendTo(TIFF*tif, tidataval_t* data, tsize_t cc) { + (void)tif; + (void)data; + (void)cc; + /* fwrite(data, 1, cc, (FILE*)tif->tif_sout); + if (ferror((FILE*)tif->tif_sout)) return 0; */ + if (-1==tif->tif_writer((char*)data, cc, tif->tif_sout)) return 0; +#if 0 /**** pts ****/ /* tif_write.h */ + (void)strip; + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "TIFFAppendToStrip"; + + if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { + /* + * No current offset, set the current strip. + */ + if (td->td_stripoffset[strip] != 0) { + if (!SeekOK(tif, td->td_stripoffset[strip])) { + TIFFError(module, + "%s: Seek error at scanline %lu", + tif->tif_name, (unsigned long) tif->tif_row); + return (0); + } + } else + td->td_stripoffset[strip] = + TIFFSeekFile(tif, (toff_t) 0, SEEK_END); + tif->tif_curoff = td->td_stripoffset[strip]; + } + if (!WriteOK(tif, data, cc)) { + TIFFError(module, "%s: Write error at scanline %lu", + tif->tif_name, (unsigned long) tif->tif_row); + return (0); + } + tif->tif_curoff += cc; + td->td_stripbytecount[strip] += cc; +#endif + return (1); +} + +#if 0 +static tidataval_t readbuf[4096]; +unsigned int readlen; +static char *inname; +typedef int (*filter_t)(FILE *sin, FILE*sout); +/** /LZWEncode filter, STDIN -> STDOUT */ +static int lzw_encode(FILE *sin, FILE *sout) { + TIFF tif; + tif.tif_sout=sout; + tif.tif_reading_p=0; +#if 0 + tif.tif_revbits_p=0; +#endif + tif.tif_name=inname; + tif.tif_rawdata=(tidataval_t*)_TIFFmalloc(tif.tif_rawdatasize=4096); /* Imp: check */ + tif.tif_rawcp=tif.tif_rawdata; + tif.tif_rawcc=0; + if (TIFFInitLZW(&tif) && + LZWSetupEncode(&tif) && + LZWPreEncode(&tif) /* for each strip */) { + while ((readlen=fread(readbuf, 1, sizeof(readbuf), sin))!=0) { + if (!LZWEncode(&tif, readbuf, readlen)) goto err; + /* fprintf(stderr, "readlen=%d\n", readlen); */ + } + if (!LZWPostEncode(&tif)) goto err; /* for each strip */ + LZWCleanup(&tif); + if (!TIFFFlushData1(&tif)) { _TIFFfree(tif.tif_rawdata); fflush(sout); return 0; } + fflush(sout); + } else { err: + fflush(sout); + LZWCleanup(&tif); + _TIFFfree(tif.tif_rawdata); + return 0; + } + return 1; +} +/** /LZWEncode filter, STDIN -> STDOUT */ +static int lzw_decode(FILE *sin, FILE *sout) { + TIFF tif; + /* tidataval_t *rawend0; */ + /* char *xbuf; */ + int got; + unsigned int left; + tif.tif_reading_p=1; +#if 0 + tif.tif_revbits_p=0; +#endif + tif.tif_name=inname; + tif.tif_rawdata=(tidataval_t*)_TIFFmalloc(tif.tif_rawdatasize=4096); /* Imp: check */ + tif.tif_rawcc=0; + left=0; + if (TIFFInitLZW(&tif) && + LZWSetupDecode(&tif) && + LZWPreDecode(&tif) /* for each strip */) { + /* vvv Dat: fread returns >=0 ! */ + while ((readlen=left+fread(tif.tif_rawdata+left, 1, tif.tif_rawdatasize-left, sin))!=0) { + #if DEBUGMSG + fprintf(stderr, "readlen+=%d\n", readlen); + #endif + while (readlen<=3) { + if ((got=fread(tif.tif_rawdata+readlen, 1, tif.tif_rawdatasize-readlen, sin))==0) { + tif.tif_rawend=tif.tif_rawdata+readlen; + goto star; + } + readlen+=got; + } + tif.tif_rawend=tif.tif_rawdata+readlen-3; + star: + tif.tif_rawcp=tif.tif_rawdata; + #if DEBUGMSG + fprintf(stderr, "readlen:=%d\n", readlen); + #endif + while (1) { + if (-1==(got=(DecoderState(&tif)->dec_decode)(&tif, readbuf, sizeof(readbuf)))) goto err; + #if DEBUGMSG + fprintf(stderr, "OK, written: %d %d\n", got, tif.tif_rawend-tif.tif_rawcp); + #endif + if (0==got) break; + fwrite(readbuf, 1, got, sout); + } + left=tif.tif_rawdata+readlen-tif.tif_rawcp; + got=left; + #if DEBUGMSG + fprintf(stderr, "left=%d\n", left); fflush(stderr); + #endif + while (got--!=0) { tif.tif_rawdata[got]=tif.tif_rawcp[got]; } + } +#if 0 + if (!LZWPostDecode(&tif)) { LZWCleanup(&tif); return 0; } /* for each strip */ +#endif + LZWCleanup(&tif); + fflush(sout); + } else { err: + fflush(sout); + LZWCleanup(&tif); + _TIFFfree(tif.tif_rawdata); + return 0; + } + return 1; +} +#endif + +static int feeder(char *readbuf, unsigned readlen, TIFF *tif) { + /*(void)LZWPreDecode;*/ /* Imp: better avoid gcc warning... */ + if (readlen!=0) { + if (!LZWEncode(tif, (tidataval_t*)readbuf, readlen)) { e1: + LZWCleanup(tif); e2: + _TIFFfree(tif->tif_rawdata); + return 0; + } + } else { + if (!LZWPostEncode(tif)) goto e1; + LZWCleanup(tif); + if (!TIFFFlushData1(tif)) goto e2; + } + return 1; +} + +/** /LZWEncode filter, STDIN -> STDOUT */ +int pts_lzw_init(TIFF *tif) { + /* tif_sout and tif_writer are already filled */ + tif->tif_feeder=feeder; + tif->tif_reading_p=0; +#if 0 + tif->tif_revbits_p=0; +#endif + tif->tif_name="//.filter";/*inname;*/ + tif->tif_rawdata=(tidataval_t*)_TIFFmalloc(tif->tif_rawdatasize=4096); /* Imp: check */ + tif->tif_rawcp=tif->tif_rawdata; + tif->tif_rawcc=0; + if (TIFFInitLZW(tif) && + LZWSetupEncode(tif) && + LZWPreEncode(tif) /* for each strip */) { + return 1; + } + LZWCleanup(tif); + _TIFFfree(tif->tif_rawdata); + return 0; +} + + +#if 0 +/**** pts ****/ +int main(int argc, char **argv) { + filter_t filter; + FILE *sin, *sout; + inname="STDIN"; + + if (argc>=2 && argc<=4 && argv[1][0]=='e') { + filter=lzw_encode; + } else if (argc>=2 && argc<=4 && argv[1][0]=='d') { + filter=lzw_decode; + } else { + fprintf(stderr, + "This is PotterSoftware LZW codec v0.1, (C) pts@fazekas.hu in Late Dec 2001\n" + "THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!\n" + "This program is free software, covered by the GNU GPL.\n" + " Derived from code Copyright (c) 1988-1997 Sam Leffler\n" + " Derived from code Copyright (c) 1991-1997 Silicon Graphics, Inc.\n\n" + "Usage: %s encode|decode [INFILE] [OUTFILE]\n\n" + "Unspecified file names mean STDIN or STDOUT.\n" + "Encoding is /LZWEncode compression, decoding is /LZWDecode uncompression.\n\n" + "Note that the LZW compression (but not uncompression) is patented by\n" + "Unisys (patent number #4,558,302), so use this program at your own legal\n" + "risk!\n" + ,argv[0]); + return 2; + } + if (argc>=3) sin= fopen(inname=argv[2],"rb"); + else sin= fdopen(0, "rb"); + if (sin==0) { + fprintf(stderr, "%s: error opening infile\n", argv[0]); + return 3; + } + if (argc>=4) sout=fopen(inname=argv[3],"wb"); + else sout=fdopen(1, "wb"); + if (sout==0) { + fprintf(stderr, "%s: error opening outfile\n", argv[0]); + return 4; + } + return !filter(sin, sout); + /* fclose(sout); fclose(sin); */ +} +#endif diff --git a/Build/source/utils/sam2p/pts_lzw.h b/Build/source/utils/sam2p/pts_lzw.h new file mode 100644 index 00000000000..c9897618178 --- /dev/null +++ b/Build/source/utils/sam2p/pts_lzw.h @@ -0,0 +1,55 @@ +/* + * pts_lzw.h -- a compact LZW compressor (not uncompressor) interface + * compiled by pts@fazekas.hu at Mon Mar 4 00:31:20 CET 2002 + */ + +#ifndef PTS_LZW_H +#define PTS_LZW_H 1 + +#ifdef __GNUC__ +#pragma interface +#endif + +/**** pts ****/ +#ifndef ___ +#if (defined(__STDC__) || defined(__cplusplus)) && !defined(NO_PROTO) +# define _(args) args +# define OF(args) args +# define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */ +#else +# define _(args) () +# define OF(args) () +# define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */ +#endif +#endif +typedef char tbool_t; +typedef unsigned char tidataval_t; /* internal image data value type */ +typedef unsigned int tsize_t; /* i/o size in bytes */ +typedef int (*tiwriter_t) OF((char *block, unsigned len, void *zfile)); +struct pts_lzw_state; +struct pts_lzw_state { + /*FILE*/void* tif_sout; /**** pts ****/ /* for encode */ + tiwriter_t tif_writer; + int (*tif_feeder)(char *readbuf, unsigned readlen, struct pts_lzw_state *tif); +#if 0 + tbool_t tif_revbits_p; /**** pts ****/ +#endif + tbool_t tif_reading_p; /**** pts ****/ + char* tif_name; /* name of open file, used for debugging */ +/* compression scheme hooks */ + tidataval_t* tif_data; /* compression scheme private data */ +/* input/output buffering */ + tidataval_t* tif_rawend; /**** pts ****/ + tidataval_t* tif_rawdata; /* raw data buffer */ + tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */ + tidataval_t* tif_rawcp; /* current spot in raw buffer */ + tsize_t tif_rawcc; /* bytes unread from raw buffer */ +}; + +extern +#ifdef __cplusplus +"C" +#endif +int pts_lzw_init OF((struct pts_lzw_state*)); + +#endif diff --git a/Build/source/utils/sam2p/resource.h b/Build/source/utils/sam2p/resource.h new file mode 100644 index 00000000000..841ed6ce8ea --- /dev/null +++ b/Build/source/utils/sam2p/resource.h @@ -0,0 +1,44 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by vcsam2p.rc +// +#define IDC_MYICON 2 +#define IDOK2 3 +#define IDD_VCSAM2P_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDS_APP_TITLE 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDS_HELLO 106 +#define IDI_VCSAM2P 107 +#define IDI_SMALL 108 +#define IDC_VCSAM2P 109 +#define IDR_MAINFRAME 128 +#define IDI_SAM2P16 131 +#define IDI_SAM2P32 132 +#define IDD_RUN 133 +#define IDC_PRODUCT 1000 +#define IDC_EDIT1 1001 +#define IDC_ELOG 1001 +#define IDC_INFO 1001 +#define IDC_EDIT2 1002 +#define IDM_OPEN 32771 +#define IDM_SAVE 32772 +#define IDM_WEBSITE 32773 +#define IDM_SAVE_AS 32774 +#define IDM_NEW 32775 +#define IDM_PARAMETERS 32776 +#define IDC_STATIC -1 +#define IDC_COPYRIGHT -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 134 +#define _APS_NEXT_COMMAND_VALUE 32777 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/Build/source/utils/sam2p/rule.cpp b/Build/source/utils/sam2p/rule.cpp new file mode 100644 index 00000000000..3c8b84f905f --- /dev/null +++ b/Build/source/utils/sam2p/rule.cpp @@ -0,0 +1,1088 @@ +/* + * rule.cpp -- generic Rule handling + * by pts@fazekas.hu at Fri Mar 15 21:13:47 CET 2002 + */ + +#ifdef __GNUC__ +#pragma implementation +#endif + +#include "rule.hpp" +#include "error.hpp" +#include <string.h> /* strlen() */ + +bool Rule::Cache::isPDF() const { + return 80<=FileFormat && FileFormat<100; +} +bool Rule::Cache::isPDFB() const { + return 90<=FileFormat && FileFormat<100; +} +bool Rule::Cache::isIndexed() const { + return SampleFormat==Image::SF_Indexed1 + || SampleFormat==Image::SF_Indexed2 + || SampleFormat==Image::SF_Indexed4 + || SampleFormat==Image::SF_Indexed8; +} +bool Rule::Cache::isTransparentM() const { + return SampleFormat==Image::SF_Mask + || SampleFormat==Image::SF_Transparent2 + || SampleFormat==Image::SF_Transparent4 + || SampleFormat==Image::SF_Transparent8; +} +bool Rule::Cache::isOneBit() const { + return SampleFormat==Image::SF_Mask + || SampleFormat==Image::SF_Indexed1 + || SampleFormat==Image::SF_Gray1; +} +#if 0 +bool Rule::Cache::is8() const { + return SampleFormat==Image::SF_Indexed1 + || SampleFormat==Image::SF_Indexed2 + || SampleFormat==Image::SF_Indexed4 + || SampleFormat==Image::SF_Indexed8; +} +#endif +bool Rule::Cache::isGray() const { + return SampleFormat==Image::SF_Gray1 + || SampleFormat==Image::SF_Gray2 + || SampleFormat==Image::SF_Gray4 + || SampleFormat==Image::SF_Gray8; +} +bool Rule::Cache::isRGB() const { + return SampleFormat==Image::SF_Rgb1 + || SampleFormat==Image::SF_Rgb2 + || SampleFormat==Image::SF_Rgb4 + || SampleFormat==Image::SF_Rgb8; +} +bool Rule::Cache::isBinSB() const { + return TransferEncoding==TE_Binary + || TransferEncoding==TE_MSBfirst + || TransferEncoding==TE_LSBfirst; +} +bool Rule::Cache::isPS() const { + return FileFormat>=100; +} +bool Rule::Cache::isPSL2() const { + return FileFormat>=120; +} +bool Rule::Cache::isPSL3() const { + return FileFormat>=130; +} +bool Rule::Cache::hasPredictor() const { + return Predictor!=PR_None; +} +bool Rule::Cache::isDCTE() const { + /* Dat: _not_ CO_JAI */ + return Compression==CO_DCT || Compression==CO_IJG; +} +bool Rule::Cache::isZIPOK() const { + return Compression!=CO_ZIP || + ( FileFormat!=FF_PSL1 && FileFormat!=FF_PSLC && FileFormat!=FF_PSL2 + && FileFormat!=FF_PDF10 && FileFormat!=FF_PDFB10 + ); +} + +static MiniPS::Dict *y_FileFormat=(MiniPS::Dict*)NULLP, + *y_SampleFormat, *y_TransferEncoding, + *y_Compression, *y_Scale; +static const slen_t SampleFormat_MAXLEN=32; + +static void init_dicts() { + register MiniPS::Dict*y; + + if (y_FileFormat!=NULLP) return; + + y=y_FileFormat=new MiniPS::Dict(); + y->put("/PSL1", MiniPS::Qinteger(Rule::Cache::FF_PSL1)); + y->put("/PSLC", MiniPS::Qinteger(Rule::Cache::FF_PSLC)); + y->put("/PSL2", MiniPS::Qinteger(Rule::Cache::FF_PSL2)); + y->put("/PSL3", MiniPS::Qinteger(Rule::Cache::FF_PSL3)); + y->put("/PDFB1.0",MiniPS::Qinteger(Rule::Cache::FF_PDFB10)); + y->put("/PDFB1.2",MiniPS::Qinteger(Rule::Cache::FF_PDFB12)); + y->put("/PDF1.0", MiniPS::Qinteger(Rule::Cache::FF_PDF10)); + y->put("/PDF1.2", MiniPS::Qinteger(Rule::Cache::FF_PDF12)); + y->put("/GIF89a", MiniPS::Qinteger(Rule::Cache::FF_GIF89a)); + y->put("/GIF", MiniPS::Qinteger(Rule::Cache::FF_GIF89a)); + y->put("/Empty", MiniPS::Qinteger(Rule::Cache::FF_Empty)); + y->put("/Meta", MiniPS::Qinteger(Rule::Cache::FF_Meta)); + y->put("/PNM", MiniPS::Qinteger(Rule::Cache::FF_PNM)); + y->put("/PAM", MiniPS::Qinteger(Rule::Cache::FF_PAM)); + y->put("/PIP", MiniPS::Qinteger(Rule::Cache::FF_PIP)); + y->put("/JPEG", MiniPS::Qinteger(Rule::Cache::FF_JPEG)); + y->put("/JPG", MiniPS::Qinteger(Rule::Cache::FF_JPEG)); + y->put("/TIFF", MiniPS::Qinteger(Rule::Cache::FF_TIFF)); + y->put("/TIF", MiniPS::Qinteger(Rule::Cache::FF_TIFF)); + y->put("/PNG", MiniPS::Qinteger(Rule::Cache::FF_PNG)); + y->put("/XPM", MiniPS::Qinteger(Rule::Cache::FF_XPM)); + y->put("/BMP", MiniPS::Qinteger(Rule::Cache::FF_BMP)); + y->put("/XWD", MiniPS::Qinteger(Rule::Cache::FF_XWD)); + y->put("/X11", MiniPS::Qinteger(Rule::Cache::FF_X11)); + + /* vvv strlen must be shorter then SampleFormat_MAXLEN */ + y=y_SampleFormat=new MiniPS::Dict(); + y->put("/Opaque", MiniPS::Qinteger(Image::SF_Opaque)); + y->put("/Transparent", MiniPS::Qinteger(Image::SF_Transparent)); + y->put("/Transparent2", MiniPS::Qinteger(Image::SF_Transparent2)); + y->put("/Transparent4", MiniPS::Qinteger(Image::SF_Transparent4)); + y->put("/Transparent8", MiniPS::Qinteger(Image::SF_Transparent8)); + y->put("/Gray1", MiniPS::Qinteger(Image::SF_Gray1)); + y->put("/Gray2", MiniPS::Qinteger(Image::SF_Gray2)); + y->put("/Gray4", MiniPS::Qinteger(Image::SF_Gray4)); + y->put("/Gray8", MiniPS::Qinteger(Image::SF_Gray8)); + y->put("/Indexed1", MiniPS::Qinteger(Image::SF_Indexed1)); + y->put("/Indexed2", MiniPS::Qinteger(Image::SF_Indexed2)); + y->put("/Indexed4", MiniPS::Qinteger(Image::SF_Indexed4)); + y->put("/Indexed8", MiniPS::Qinteger(Image::SF_Indexed8)); + y->put("/Mask", MiniPS::Qinteger(Image::SF_Mask)); + y->put("/Rgb1", MiniPS::Qinteger(Image::SF_Rgb1)); /* recommended */ + y->put("/Rgb2", MiniPS::Qinteger(Image::SF_Rgb2)); + y->put("/Rgb4", MiniPS::Qinteger(Image::SF_Rgb4)); + y->put("/Rgb8", MiniPS::Qinteger(Image::SF_Rgb8)); + y->put("/RGB1", MiniPS::Qinteger(Image::SF_Rgb1)); /* obsolete */ + y->put("/RGB2", MiniPS::Qinteger(Image::SF_Rgb2)); + y->put("/RGB4", MiniPS::Qinteger(Image::SF_Rgb4)); + y->put("/RGB8", MiniPS::Qinteger(Image::SF_Rgb8)); + y->put("/Asis", MiniPS::Qinteger(Image::SF_Asis)); + y->put("/Bbox", MiniPS::Qinteger(Image::SF_Bbox)); + + y=y_TransferEncoding=new MiniPS::Dict(); + y->put("/Binary", MiniPS::Qinteger(Rule::Cache::TE_Binary)); + y->put("/ASCII", MiniPS::Qinteger(Rule::Cache::TE_ASCII)); + y->put("/Hex", MiniPS::Qinteger(Rule::Cache::TE_Hex)); /* recommended */ + y->put("/AHx", MiniPS::Qinteger(Rule::Cache::TE_Hex)); + y->put("/ASCIIHex", MiniPS::Qinteger(Rule::Cache::TE_Hex)); + y->put("/A85", MiniPS::Qinteger(Rule::Cache::TE_A85)); /* recommended */ + y->put("/ASCII85", MiniPS::Qinteger(Rule::Cache::TE_A85)); + y->put("/MSBfirst", MiniPS::Qinteger(Rule::Cache::TE_MSBfirst)); + y->put("/LSBfirst", MiniPS::Qinteger(Rule::Cache::TE_LSBfirst)); + + y=y_Compression=new MiniPS::Dict(); + y->put("/ ", MiniPS::Qinteger(Rule::Cache::CO_None)); /* default */ + y->put("/None", MiniPS::Qinteger(Rule::Cache::CO_None)); /* recommended */ + y->put("/LZW", MiniPS::Qinteger(Rule::Cache::CO_LZW)); /* recommended */ + y->put("/ZIP", MiniPS::Qinteger(Rule::Cache::CO_ZIP)); /* recommended */ + y->put("/Flate", MiniPS::Qinteger(Rule::Cache::CO_ZIP)); + y->put("/Fl", MiniPS::Qinteger(Rule::Cache::CO_ZIP)); + y->put("/RLE", MiniPS::Qinteger(Rule::Cache::CO_RLE)); /* recommended */ + y->put("/RunLength", MiniPS::Qinteger(Rule::Cache::CO_RLE)); + y->put("/RunLengthEncoded", MiniPS::Qinteger(Rule::Cache::CO_RLE)); + y->put("/RL", MiniPS::Qinteger(Rule::Cache::CO_RLE)); + y->put("/PackBits", MiniPS::Qinteger(Rule::Cache::CO_RLE)); + y->put("/Fax", MiniPS::Qinteger(Rule::Cache::CO_Fax)); /* recommended */ + y->put("/CCITTFax", MiniPS::Qinteger(Rule::Cache::CO_Fax)); + y->put("/CCF", MiniPS::Qinteger(Rule::Cache::CO_Fax)); + y->put("/DCT", MiniPS::Qinteger(Rule::Cache::CO_DCT)); /* recommended */ + y->put("/JPEG",MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* changed at Sun Jun 23 17:06:34 CEST 2002 */ + y->put("/JPG", MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* changed at Sun Jun 23 17:06:34 CEST 2002 */ + y->put("/JFIF",MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* changed at Sun Jun 23 17:06:34 CEST 2002 */ + y->put("/IJG", MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* recommended */ + y->put("/JAI", MiniPS::Qinteger(Rule::Cache::CO_JAI)); /* recommended */ + + y=y_Scale=new MiniPS::Dict(); + y->put("/ ", MiniPS::Qinteger(Rule::CacheHints::SC_None)); /* default */ + y->put("/None", MiniPS::Qinteger(Rule::CacheHints::SC_None)); + y->put("/OK", MiniPS::Qinteger(Rule::CacheHints::SC_OK)); + y->put("/RotateOK",MiniPS::Qinteger(Rule::CacheHints::SC_RotateOK)); +} + +Image::sf_t Rule::Cache::parseSampleFormat(char const*s, slen_t slen) { + /* Tue Jul 2 13:48:12 CEST 2002 */ + #if 0 /* BUGFIX for g++-3.4 (needs symbols __cxa_guard_acquire, __cxa_guard_release) */ + static char rule_dummy=(init_dicts(),0); /* call once per process */ + (void)rule_dummy; + #else + if (y_FileFormat==NULLP) init_dicts(); + #endif + while (slen!=0 && s[0]=='/') { s++; slen--; } + if (slen<=0 || slen>=SampleFormat_MAXLEN) return Image::SF_max; + char buf[SampleFormat_MAXLEN]; + GenBuffer::tolower_memcpy(buf, s, slen); + if (buf[0]>='a' && buf[0]<='z') buf[0]+='A'-'a'; /* capitalize 1st letter */ + MiniPS::VALUE v=y_SampleFormat->get(buf, slen); + return (Image::sf_t) (v==MiniPS::Qundef ? Image::SF_max : MiniPS::int2ii(v)); +} + +char const* Rule::Cache::dumpFileFormat(ff_t FileFormat, co_t Compression) { + switch (FileFormat) { + case FF_eps: return Compression==CO_ZIP ? "PSL3" : "PSL2"; + case FF_pdf: return Compression==CO_ZIP ? "PDF1.2" : "PDF1.0"; + case FF_pdfb: return Compression==CO_ZIP ? "PDFB1.2" : "PDFB1.0"; + case FF_PSL1: return "PSL1"; + case FF_PSLC: return "PSLC"; + case FF_PSL2: return "PSL2"; + case FF_PSL3: return "PSL3"; + case FF_PDFB10:return "PDFB1.0"; + case FF_PDFB12:return "PDFB1.2"; + case FF_PDF10: return "PDF1.0"; + case FF_PDF12: return "PDF1.2"; + case FF_GIF89a:return "GIF89a"; + case FF_PNM: return "PNM"; + case FF_PAM: return "PAM"; + case FF_PIP: return "PIP"; + case FF_Empty: return "Empty"; + case FF_Meta: return "Meta"; + case FF_JPEG: return "JPEG"; + case FF_TIFF: return "TIFF"; + case FF_PNG: return "PNG"; + case FF_XPM: return "XPM"; + case FF_BMP: return "BMP"; + case FF_XWD: return "XWD"; + case FF_X11: return "X11"; + } + return (char const*)NULLP; +} +char const* Rule::Cache::dumpTransferEncoding(te_t TransferEncoding) { + switch (TransferEncoding) { + case TE_Binary: return "Binary"; + case TE_ASCII: return "ASCII"; + case TE_Hex: return "Hex"; + case TE_A85: return "A85"; + case TE_MSBfirst:return "MSBfirst"; + case TE_LSBfirst:return "LSBfirst"; + } + return (char const*)NULLP; +} +char const* Rule::Cache::dumpSampleFormat(Image::sf_t SampleFormat) { + switch (SampleFormat) { + case Image::SF_Opaque: return "Opaque"; + case Image::SF_Transparent: return "Transparent"; + case Image::SF_Gray1: return "Gray1"; + case Image::SF_Indexed1: return "Indexed1"; + case Image::SF_Mask: return "Mask"; + case Image::SF_Transparent2: return "Transparent2"; + case Image::SF_Gray2: return "Gray2"; + case Image::SF_Indexed2: return "Indexed2"; + case Image::SF_Transparent4: return "Transparent4"; + case Image::SF_Rgb1: return "Rgb1"; + case Image::SF_Gray4: return "Gray4"; + case Image::SF_Indexed4: return "Indexed4"; + case Image::SF_Transparent8: return "Transparent8"; + case Image::SF_Rgb2: return "Rgb2"; + case Image::SF_Gray8: return "Gray8"; + case Image::SF_Indexed8: return "Indexed8"; + case Image::SF_Rgb4: return "Rgb4"; + case Image::SF_Rgb8: return "Rgb8"; + case Image::SF_Asis: return "Asis"; + case Image::SF_Bbox: return "Bbox"; + } + return (char const*)NULLP; +} +char const* Rule::Cache::dumpCompression(co_t Compression) { + switch (Compression) { + case CO_None:return "None"; + case CO_LZW: return "LZW"; + case CO_ZIP: return "ZIP"; + case CO_RLE: return "RLE"; + case CO_Fax: return "Fax"; + case CO_DCT: return "DCT"; + case CO_IJG: return "IJG"; + case CO_JAI: return "JAI"; + } + return (char const*)NULLP; +} + +char const* Rule::CacheHints::dumpScale(sc_t Scale) { + switch (Scale) { + case SC_None: return "None"; + case SC_OK: return "OK"; + case SC_RotateOK:return "RotateOK"; + } + return (char const*)NULLP; +} + +/* Checks and recovers Predictor. Called by scanf_dict. + * @return Qundef if param invalid + * Qinteger(1) if param==Qundef + * valid Qinteger otherwise + */ +static MiniPS::VALUE better_predictor(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(1) /* PR_None */ + : v==MiniPS::Qinteger(1) || v==MiniPS::Qinteger(2) || v==MiniPS::Qinteger(45) || + ((v&1)!=0 && v>=MiniPS::Qinteger(10) && v<=MiniPS::Qinteger(15)) ? v + : MiniPS::Qundef; +} +static MiniPS::VALUE better_xColors(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(0) + : ((v&1)!=0 && v>=MiniPS::Qinteger(1) && v<=MiniPS::Qinteger(4)) ? v + : MiniPS::Qundef; +} +static MiniPS::VALUE better_predictorBPC(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(0) + : v==MiniPS::Qinteger(1) || v==MiniPS::Qinteger(2) || + v==MiniPS::Qinteger(4) || v==MiniPS::Qinteger(8) ? v + : MiniPS::Qundef; +} +static MiniPS::VALUE better_effort(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(-1) + : ((v&1)!=0 && v>=MiniPS::Qinteger(-1) && v<=MiniPS::Qinteger(9)) ? v + : MiniPS::Qundef; +} +static MiniPS::VALUE better_k(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(0) + : ((v&1)!=0 && v>=MiniPS::Qinteger(-2)) ? v /* -2 means: positive value marking the image height */ + : MiniPS::Qundef; +} +static MiniPS::VALUE better_quality(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(75) + : ((v&1)!=0 && v>=MiniPS::Qinteger(0) && v<=MiniPS::Qinteger(100)) ? v + : MiniPS::Qundef; +} +static MiniPS::VALUE better_colorTransform(MiniPS::VALUE v) { + return v==MiniPS::Qundef ? MiniPS::Qinteger(3) + : ((v&1)!=0 && v>=MiniPS::Qinteger(0) && v<=MiniPS::Qinteger(3)) ? v + : MiniPS::Qundef; +} + +void Rule::OutputRule::fromDict(MiniPS::VALUE dict_) { + #if 0 /* BUGFIX for g++-3.4 (needs symbols __cxa_guard_acquire, __cxa_guard_release) */ + static char rule_dummy=(init_dicts(),0); /* call once per process */ + (void)rule_dummy; + #else + if (y_FileFormat==NULLP) init_dicts(); + #endif + MiniPS::VALUE dummy; (void)dummy; + MiniPS::VALUE FileFormat, SampleFormat, WarningOK, TransferEncoding, + Compression, Predictor, Transparent; + MiniPS::VALUE PredictorColumns, PredictorColors, PredictorBPC, Effort, K, + RecordSize, Quality, ColorTransform, TransferCPL, + EncoderRows, EncoderColumns, EncoderBPL, EncoderColors, DCT, Scale; + + MiniPS::scanf_dict(dict_, /*show_warnings:*/true, + "FileFormat", MiniPS::S_SENUM, y_FileFormat, &FileFormat, + "SampleFormat", MiniPS::S_SENUM, y_SampleFormat, &SampleFormat, + "WarningOK", MiniPS::T_BOOLEAN, MiniPS::Qtrue, &WarningOK, + "TransferEncoding",MiniPS::S_SENUM, y_TransferEncoding, &TransferEncoding, + "Compression", MiniPS::S_SENUM, y_Compression, &Compression, + "Predictor", MiniPS::S_FUNC, better_predictor, &Predictor, + "Transparent", MiniPS::S_RGBSTR, MiniPS::Qnull, &Transparent, /* force an RGB color transparent */ + "Hints", MiniPS::T_DICT, MiniPS::Qnull, &dictHints, + NULLP + ); + dict=(MiniPS::Dict*)dict_; + cache.FileFormat=(Rule::Cache::ff_t)MiniPS::int2ii(FileFormat); + cache.SampleFormat=(Image::sf_t)MiniPS::int2ii(SampleFormat); + cache.WarningOK=(Rule::Cache::ff_t)WarningOK==MiniPS::Qtrue; + cache.TransferEncoding=(Rule::Cache::te_t)MiniPS::int2ii(TransferEncoding); + cache.Compression=(Rule::Cache::co_t)MiniPS::int2ii(Compression); + cache.Predictor=(Rule::Cache::pr_t)MiniPS::int2ii(Predictor); + cache.Transparent=0x1000000UL; /* No extra transparency */ + if (Transparent!=MiniPS::Qnull) { + unsigned char const*p=(unsigned char const*)(MiniPS::RSTRING(Transparent)->begin_()); + cache.Transparent=(p[0]<<16)+(p[1]<<8)+p[2]; + } + //MiniPS::dump(Predictor); + // fprintf(stderr,"cpred=%u\n", cache.Predictor); + + if ((MiniPS::VALUE)dictHints==MiniPS::Qnull) dict->put("/Hints", (MiniPS::VALUE)(dictHints=new MiniPS::Dict())); + MiniPS::scanf_dict((MiniPS::VALUE)dictHints, /*show_warnings:*/true, + "EncoderBPL", MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &EncoderBPL, + "EncoderColumns", MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &EncoderColumns, + "EncoderRows", MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &EncoderRows, + "EncoderColors", MiniPS::S_FUNC, better_xColors, &EncoderColors, + "PredictorColumns",MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &PredictorColumns, + "PredictorColors", MiniPS::S_FUNC, better_xColors, &PredictorColors, + "PredictorBPC", MiniPS::S_FUNC, better_predictorBPC, &PredictorBPC, + "Effort", MiniPS::S_FUNC, better_effort, &Effort, + "RecordSize", MiniPS::S_UINTEGER,MiniPS::Qinteger(0), &RecordSize, + "K", MiniPS::S_FUNC, better_k, &K, + "Quality", MiniPS::S_FUNC, better_quality, &Quality, + "ColorTransform", MiniPS::S_FUNC, better_colorTransform, &ColorTransform, + "TransferCPL", MiniPS::S_PINTEGER,MiniPS::Qinteger(78), &TransferCPL, + "DCT", MiniPS::T_DICT, MiniPS::Qnull, &DCT, + "Scale", MiniPS::S_SENUM, y_Scale, &Scale, + "ImageDPI", MiniPS::S_PNUMBER, MiniPS::Qinteger(72), &cacheHints.ImageDPI, + "TopMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.TopMargin, + "BottomMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.BottomMargin, + "LeftMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.LeftMargin, + "RightMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.RightMargin, + "LowerMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.LowerMargin, + + "Comment", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Comment, + "Title", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Title, + "Subject", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Subject, + "Author", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Author, + "Creator", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Creator, + "Producer", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Producer, + "Created", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Created, + "Produced", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Produced, +#if 0 + /* vvv parameters for /DCTEncode. Currently ignored. Obsoleted by /DCT */ + "Colors", MiniPS::S_ANY, MiniPS::Qnull, &dummy, + "HSamples", MiniPS::S_ANY, MiniPS::Qnull, &dummy, + "VSamples", MiniPS::S_ANY, MiniPS::Qnull, &dummy, + "QuantTables", MiniPS::S_ANY, MiniPS::Qnull, &dummy, + "QFactor", MiniPS::S_ANY, MiniPS::Qnull, &dummy, + "HuffTables", MiniPS::S_ANY, MiniPS::Qnull, &dummy, +#endif + NULLP + ); + if (DCT==MiniPS::Qnull) dict->put("/DCT", DCT=(MiniPS::VALUE)new MiniPS::Dict()); + // cacheHints.DCT=(DCT==MiniPS::Qnull)? new MiniPS::Dict() : MiniPS::RDICT(DCT); + if (cache.isPS()) { + MiniPS::setDumpPS(cacheHints.TopMargin, true); + MiniPS::setDumpPS(cacheHints.BottomMargin, true); + MiniPS::setDumpPS(cacheHints.LeftMargin, true); + MiniPS::setDumpPS(cacheHints.RightMargin, true); + MiniPS::setDumpPS(cacheHints.LowerMargin, true); + } + cacheHints.DCT=MiniPS::RDICT(DCT); + cacheHints.EncoderColumns=MiniPS::int2ii(EncoderColumns); + cacheHints.EncoderBPL=MiniPS::int2ii(EncoderBPL); + cacheHints.EncoderColors=MiniPS::int2ii(EncoderColors); + cacheHints.EncoderRows=MiniPS::int2ii(EncoderRows); + cacheHints.PredictorColumns=MiniPS::int2ii(PredictorColumns); + cacheHints.PredictorColors=MiniPS::int2ii(PredictorColors); + cacheHints.PredictorBPC=MiniPS::int2ii(PredictorBPC); + cacheHints.Effort=MiniPS::int2ii(Effort); + cacheHints.RecordSize=MiniPS::int2ii(RecordSize); + cacheHints.K=MiniPS::int2ii(K); + cacheHints.Quality=MiniPS::int2ii(Quality); + cacheHints.ColorTransform=MiniPS::int2ii(ColorTransform); + cacheHints.TransferCPL=MiniPS::int2ii(TransferCPL); + cacheHints.Scale=(Rule::CacheHints::sc_t)MiniPS::int2ii(Scale); + /* fprintf(stderr, "scaled=%g\n", (char*)MiniPS::scale(ImageDPI,1)); */ +} + +void Rule::OutputRule::doSampleFormat(Image::SampledInfo *info, bool separatep) { + /* Dat: called from appliers.cpp:out_*_work(); the sample format is final */ + bool separatep2= + separatep && + ( cache.SampleFormat==Image::SF_Transparent2 + || cache.SampleFormat==Image::SF_Transparent4 + || cache.SampleFormat==Image::SF_Transparent8); + /* vvv simplifier added at Sat Jun 15 13:59:40 CEST 2002 */ + if (separatep2) cache.SampleFormat=Image::SF_Transparent8; + if (!info->setSampleFormat(cache.SampleFormat, cache.WarningOK, /*TryOnly*/false, cache.Transparent)) + Error::sev(Error::EERROR) << "doSampleFormat: cannot set desired SampleFormat" << (Error*)0; + Image::Sampled *img=info->getImg(); + slen_t n=1; + if (separatep2) { + info->separate(); + img=info->getImgs()[0];/*NULLP OK*/; + n=info->getNncols(); + } + if (img!=NULLP) { + if (0==cacheHints.EncoderBPL) cacheHints.EncoderBPL=(slen_t)img->getWd()*img->getCpp()*img->getBpc(); + if (0==cacheHints.EncoderColumns) cacheHints.EncoderColumns=img->getWd(); + if (0==cacheHints.EncoderColors) cacheHints.EncoderColors=img->getCpp(); + if (0==cacheHints.EncoderRows) cacheHints.EncoderRows=img->getHt()*n; + if (0==cacheHints.PredictorColumns) cacheHints.PredictorColumns=img->getWd(); + if (0==cacheHints.PredictorColors) cacheHints.PredictorColors=img->getCpp(); + if (0==cacheHints.PredictorBPC) cacheHints.PredictorBPC=img->getBpc(); + if (-2==cacheHints.K) cacheHints.K=img->getHt()*n; + } +} + +static char const*getDecode(Rule::Cache::co_t Compression) { + return (Compression==Rule::Cache::CO_LZW ? "/LZWDecode" + :Compression==Rule::Cache::CO_Fax ? "/CCITTFaxDecode" + :Compression==Rule::Cache::CO_ZIP ? "/FlateDecode" + :Compression==Rule::Cache::CO_RLE ? "/RunLengthDecode" + :Compression==Rule::Cache::CO_DCT ? "/DCTDecode" + :Compression==Rule::Cache::CO_IJG ? "/DCTDecode" + :Compression==Rule::Cache::CO_JAI ? "/DCTDecode" + :""); +} + +/** For PDF BI inline images */ +static char const*getBIDecode(Rule::Cache::co_t Compression) { + return (Compression==Rule::Cache::CO_LZW ? "/LZW" + :Compression==Rule::Cache::CO_Fax ? "/CCF" + :Compression==Rule::Cache::CO_ZIP ? "/Fl" + :Compression==Rule::Cache::CO_RLE ? "/RL" + :Compression==Rule::Cache::CO_DCT ? "/DCT" + :Compression==Rule::Cache::CO_IJG ? "/DCT" + :Compression==Rule::Cache::CO_JAI ? "/DCT" + :""); +} + +void Rule::OutputRule::appendDecoderSpec(GenBuffer::Writable &out) const { + assert(cacheHints.PredictorBPC!=0 && "doSampleFormat already called"); + bool hps=hasPredictorSpec(); + if (cache.isPDF()) { + /* Dat: also implies appendTransferSpec() -- this is true only for PDF */ + if (!cache.isPDFB()) { + if (cache.Compression==cache.CO_None) { + if (cache.TransferEncoding==cache.TE_Hex) out << "/Filter/ASCIIHexDecode"; + else if (cache.TransferEncoding==cache.TE_A85) out << "/Filter/ASCII85Decode"; + } else if (cache.TransferEncoding!=cache.TE_Hex && cache.TransferEncoding!=cache.TE_A85) { + out << "/Filter" << getDecode(cache.Compression); + if (hps) { out << "/DecodeParms"; appendPredictorSpec(out); } + } else { /* both TransferEncoding and Compression */ + if (cache.TransferEncoding==cache.TE_Hex) out << "/Filter[/ASCIIHexDecode"; + else if (cache.TransferEncoding==cache.TE_A85) out << "/Filter[/ASCII85Decode"; + else assert(0); + out << getDecode(cache.Compression); + if (hps) { out << "]/DecodeParms[null"; appendPredictorSpec(out); } + /* ^^^ BUGFIX at Tue Jun 4 18:50:13 CEST 2002 */ + out << ']'; + } + } else { + if (cache.Compression==cache.CO_None) { + if (cache.TransferEncoding==cache.TE_Hex) out << "/F/AHx"; + else if (cache.TransferEncoding==cache.TE_A85) out << "/F/A85"; + } else if (cache.TransferEncoding!=cache.TE_Hex && cache.TransferEncoding!=cache.TE_A85) { + out << "/F" << getBIDecode(cache.Compression); + if (hps) { out << "/DP"; appendPredictorSpec(out); } + } else { /* both TransferEncoding and Compression */ + if (cache.TransferEncoding==cache.TE_Hex) out << "/F[/AHx"; + else if (cache.TransferEncoding==cache.TE_A85) out << "/F[/A85"; + else assert(0); + out << getBIDecode(cache.Compression); + if (hps) { out << "]/DP[null"; appendPredictorSpec(out); } + out << ']'; + } + } /* IFELSE PDFB */ + } else { /* NOT PDF */ + if (cache.Compression!=cache.CO_None) { + appendPredictorSpec(out); + out << getDecode(cache.Compression) << " filter"; + } + } /* IFELSE PDF */ +} + +bool Rule::OutputRule::hasPredictorSpec() const { + return cache.Compression==cache.CO_Fax + || (cache.Compression==cache.CO_ZIP || cache.Compression==cache.CO_LZW) && cache.Predictor!=cache.PR_None; +} + +void Rule::OutputRule::appendPredictorSpec(GenBuffer::Writable &out) const { + assert(cacheHints.PredictorBPC!=0 && "doSampleFormat already called"); + if (cache.Compression==cache.CO_Fax) + out << "<</K " << cacheHints.K + << "/Columns " << cacheHints.EncoderBPL + /* ^^^ EncoderColumns -> EncoderBPL BUGFIX at Wed Jul 3 20:05:12 CEST 2002 */ + << ">>"; + else if ((cache.Compression==cache.CO_ZIP || cache.Compression==cache.CO_LZW) && + cache.Predictor!=cache.PR_None) + out<< "<</BitsPerComponent " << (unsigned)cacheHints.PredictorBPC + << "/Columns " << cacheHints.PredictorColumns + << "/Colors " << (unsigned)cacheHints.PredictorColors + << (cache.Predictor==cache.PR_TIFF2 ? "/Predictor 2>>": "/Predictor 10>>"); +} +void Rule::OutputRule::appendTransferSpec(GenBuffer::Writable &out) const { + if (cache.TransferEncoding==cache.TE_Hex) out << "/ASCIIHexDecode filter"; + else if (cache.TransferEncoding==cache.TE_A85) out << "/ASCII85Decode filter"; +} + +/* --- */ + +static Rule::Applier *first=(Rule::Applier*)NULLP; + +void Rule::register0(Rule::Applier *anew) { + param_assert(anew!=NULLP); + anew->next=first; + first=anew; +} + +unsigned Rule::printAppliers(GenBuffer::Writable &out) { + unsigned num=0; + Applier *p=first; + while (p!=(Applier*)NULLP) { + if (p->check_rule!=0/*NULLP*/ && p->work!=0/*NULLP*/) { num++; out << ' ' << p->format; } + p=p->next; + } + return num; +} + +Rule::OutputRule* Rule::buildProfile(MiniPS::VALUE Profile, bool quiet) { + param_assert(MiniPS::getType(Profile)==MiniPS::T_ARRAY); + MiniPS::Array *pary=MiniPS::RARRAY(Profile); + OutputRule *ret=new OutputRule[pary->getLength()+1], *or_=ret; + /* ^^^ just enough place; there may be BAD items which won't be stored */ + MiniPS::VALUE *val; + unsigned c; + #if !USE_BUILTIN_LZW + bool lzw_warning=true; + #endif + if (quiet) Error::pushPolicy((Error::level_t)0, + /*printed_:*/Error::getTopPrinted()+0>Error::WARNING+0 ? Error::getTopPrinted() : Error::WARNING, + Error::WARNING_DEFER, (GenBuffer::Writable*)NULLP); /* Dat: WARNING_DEFER untested */ + for (c=0, pary->getFirst(val); val!=NULLP; pary->getNext(val), c++) { + /* val: each OutputRule of the Profile */ + or_->fromDict(*val); + or_->c=c; + Applier *p=first; + // printf("building: %s...\n", p->format); + #if !USE_BUILTIN_LZW + if (or_->cache.Compression==or_->cache.CO_LZW && lzw_warning) { + lzw_warning=false; + Error::sev(Error::WARNING) << "buildProfile: please `configure --enable-lzw' for /Compression/LZW support in OutputRule #" << c << (Error*)0; + } + #endif + while (p!=NULLP) { + if (p->check_rule!=0/*NULLP*/) switch (p->check_rule(or_)) { + case Applier::BAD: + Error::sev(Error::WARNING_DEFER) << "buildProfile: ^^^ thus ignoring impossible OutputRule #" << c << (Error*)0; + goto end_appliers; + case Applier::MAYBE: case Applier::OK: + if (p->work!=0/*NULLP*/) { or_++; goto end_appliers; } + Error::sev(Error::WARNING_DEFER) << "buildProfile: ^^^ ignoring unimplemented OutputRule #" << c << (Error*)0; + // case p->DONT_KNOW: ; + } + p=p->next; /* continue with other Appliers; hope other than DONT_KNOW */ + } + Error::sev(Error::WARNING_DEFER) << "buildProfile: ignoring, no handlers for OutputRule #" << c << (Error*)0; + end_appliers: + if (quiet) delete Error::getRecorded(); + } + if (quiet) { delete Error::getRecorded(); Error::popPolicy(); } + if (or_==ret) Error::sev(Error::WARNING) << "buildProfile: all OutputRules in the .job file are useless" << (Error*)0; + or_->dict=or_->dictHints=(MiniPS::Dict*)NULLP; /* end-of-list */ + return ret; +} + +void Rule::applyProfile(GenBuffer::Writable& out, OutputRule*rule_list, Image::SampledInfo *sf) { + OutputRule *or_; + // unsigned tryc=0; /* Wed Jul 3 19:30:33 CEST 2002 */ + Error::pushPolicy((Error::level_t)0, + /*printed_:*/Error::getTopPrinted()+0>Error::NOTICE+0 ? Error::getTopPrinted() : Error::NOTICE, + Error::NOTICE_DEFER, (GenBuffer::Writable*)NULLP); + Image::Sampled::rgb_t Transparent=0x1000000UL; + if (rule_list->dict!=NULLP) { + Transparent=rule_list->cache.Transparent; + for (or_=rule_list+1; or_->dict!=NULLP; or_++) { + if (Transparent!=rule_list->cache.Transparent) { + /* Imp: make different copies, based on different or_->cache.Transparent -- or not? */ + Error::sev(Error::EERROR) << "applyProfile: ambiguous /Transparent" << (Error*)0; + } + } + } + /* Dat: -transparent ... makes the specified color transparent, but it cannot + * be used to remove transparenct + */ + // printf("Transparent=0x%lx\n",Transparent); + for (or_=rule_list; or_->dict!=NULLP; or_++) { + /* ^^^ Try each OutputRule (or_) in reverse order of registration */ + Error::sev(Error::NOTICE_DEFER) << "applyProfile: trying OutputRule #" << or_->c << (Error*)0; + if (sf->setSampleFormat(or_->cache.SampleFormat, or_->cache.WarningOK, /*TryOnly*/true, or_->cache.Transparent)) { + /* image supports the SampleFormat of OutputRule */ + Applier *p=first; + while (p!=NULLP) { + /* ^^^ Try each output Applier for the current candidate OutputRule */ + if (p->check_rule!=0/*NULLP*/ && p->work!=0/*NULLP*/) { + // tryc++; + switch (p->work(out, or_, sf)) { + case Applier::BAD: + Error::sev(Error::WARNING) << "applyProfile: ^^^ thus cannot apply OutputRule #" << or_->c << (Error*)0; + goto end_appliers; + case Applier::OK: + // if (or_->c!=0) { + delete Error::getRecorded(); Error::popPolicy(); + Error::sev(Error::NOTICE) << "applyProfile: applied OutputRule #" << or_->c << (Error*)0; + return; + /* case Applier::MAYBE: impossible */ + // case p->DONT_KNOW: ; + } + } + p=p->next; /* continue with other Appliers; hope other than DONT_KNOW */ + end_appliers: ; + } + } /* IF image supports SampleFormat */ + } + Error::sev(Error::EERROR) << "applyProfile: invalid combination, no applicable OutputRule" << (Error*)0; +} + +void Rule::deleteProfile(OutputRule*rule_list) { + /* MiniPS::* objects still remain -- the caller (reader) will delete them. */ + delete [] rule_list; +} + +/* --- */ + +//#include <string.h> +//static char xx[5000]; + +void Rule::writeData(GenBuffer::Writable&, GenBuffer::Writable&outstream, Image::SampledInfo *sf) { + Image::Indexed **imgs=sf->getImgs(); + slen_t rlenht; + if (imgs!=NULLP) { + unsigned i; + if (sf->getNncols()!=0 && 0!=(rlenht=imgs[0]->getRlen()*imgs[0]->getHt())) { + // fprintf(stderr,"rh=%u nc=%u\n", rlenht, sf->getNncols()); + for (i=0;i<sf->getNncols();i++) outstream.vi_write(imgs[i]->getRowbeg(), rlenht); + //for (i=0;i<sf->getNncols();i++) { + // memset(xx, 1<<(i), sizeof(xx)); + // outstream.vi_write(xx, rlenht); + //} + } + } else { + Image::Sampled *img=sf->getImg(); + rlenht=img->getRlen()*img->getHt(); + if (rlenht!=0) outstream.vi_write(img->getRowbeg(), rlenht); + } + outstream.vi_write(0,0); /* Dat: frees cp, bp, (ap) */ +} +void Rule::writePalData(GenBuffer::Writable& outpal, GenBuffer::Writable&outstream, Image::SampledInfo *sf) { + Image::Sampled *img=sf->getImg(); + slen_t wlen=img->getRowbeg()-img->getHeadp(); + if (wlen!=0) outpal.vi_write(img->getHeadp(), wlen); + writeData(outpal, outstream, sf); + /* vvv replaced by the more generic writeData */ + // slen_t rlenht=img->getRlen()*img->getHt(); + // if (rlenht!=0) outstream.vi_write(img->getRowbeg(), rlenht); + // outstream.vi_write(0,0); /* Dat: frees cp, bp, (ap) */ +} + +/** Returns a divisor of v1*v2 near 4096 */ +static slen_t near_div(slen_t v1, slen_t v2) { + static const slen_t LOW=2048, MID=4096, HIGH=8192; + slen_t d, p; + if (v1>v2) { d=v1; v1=v2; v2=d; } + if (LOW<=v2 && v2<=HIGH) return v2; /* larger */ + if (LOW<=v1 && v1<=HIGH) return v1; /* smaller */ + if ((p=v1*v2)<=HIGH) return p; /* smaller */ + for (d=MID;d<=HIGH;d++) if (p%d==0) return d; + for (d=MID-1;d>=LOW;d--) if (p%d==0) return d; + return v1; /* the smaller one */ +} + +/** Basicly out.format("%g", (double)n/255);, but we don't want to depend on + * floating point arithmetic of the underlying architecture. + */ +static void div255(GenBuffer::Writable& out, unsigned n) { + char tmp[7]; + unsigned abc; + param_assert(n<=255); + tmp[0]='0'; tmp[1]='.'; tmp[3]='\0'; + if (n%51!=0) { + /* Divisors of 255: 1, 3, 5, 15, 17, 51, 85, 255. + * 0/255 == "0" 51/255 == "0.2" + * 102/255 == "0.4" 153/255 == "0.6" + * 204/255 == "0.8" 255/255 == "1" + * All other k/255 are infinite as a decimal fraction. + * 1000 > 2*255, so 3 digits after '.' is enough. + */ + assert(n<=254); + #if 0 + abc=(127L+1000*n)/255; + tmp[2]='0'+abc/100; + tmp[3]='0'+(abc/10)%10; + tmp[4]='0'+abc%10; + tmp[5]='\0'; + #else + abc=(127L+10000*n)/255; + tmp[2]='0'+abc/1000; + tmp[3]='0'+(abc/100)%10; + tmp[4]='0'+(abc/10)%10; + tmp[5]='0'+abc%10; + tmp[6]='\0'; + #endif + } else if (n<153) { + if (n<51) tmp[1]='\0'; + else if (n>51) tmp[2]='4'; + else tmp[2]='2'; + } + else if (n<204) tmp[2]='6'; + else if (n>204) { tmp[0]='1'; tmp[1]='\0'; } + else tmp[2]='8'; + out << tmp; +} + +void Rule::writeTTE( + GenBuffer::Writable& out, + GenBuffer::Writable&outpal, + GenBuffer::Writable&outstream, + char const*template_, Rule::OutputRule*or_, Image::SampledInfo *sf, stream_writer_t stream_writer, char const*const*strings) { + unsigned int i, j; + register char const*p; + char *r; + Image::Sampled *img=sf->getImg(); + param_assert(template_!=(const char*)NULLP); + p=template_; + bool nzp, scp; + SimBuffer::B scf; + while (1) { + assert(template_==p); + while (*p!='`' && *p!='\0') p++; /* '`' is the escape character */ + if (p!=template_) out.vi_write(template_, p-template_); + if (*p++=='\0') break; + switch (*p++) { + case '\0': + p--; /* fall through */ + case '`': + out.vi_write("`", 1); break; + case '#': /* number of non-transparent colors of /Indexed*, /Transparent* */ + out << sf->getNncols(); break; + case 'p': /* 3*(number of non-transparent colors of /Indexed*, /Transparent*) */ + out << (3*sf->getNncols()); break; + case 'P': /* number of palette bytes (including the transparent color) */ + out << img->getRowbeg()-img->getHeadp(); break; + case '0': case '1': case '2': /* arbitrary, user-defined string */ + param_assert(strings!=(char const*const*)NULLP); + out << strings[p[-1]-'0']; break; + case 'C': /* PDF /Procset entries */ + if (or_->cache.isIndexed()) out << "/ImageI"; + else if (or_->cache.isGray()) out << "/ImageB"; + else out << "/ImageC"; /* SF_Rgb*, SF_Asis etc. */ + break; + case 'i': /* PS image or colorimage operator */ + out << (or_->cache.isGray() ? "image" + : or_->cache.SampleFormat==Image::SF_Mask || or_->cache.SampleFormat==Image::SF_Indexed1 ? "imagemask" + : "false 3 colorimage"); + break; + case 'I': /* PS warning for usage of colorimage operator */ + // if (!or_->cache.isGray()) out << "% PSLC required\n"; + if (!or_->cache.isGray() && !or_->cache.isTransparentM()) out << "%%Extensions: CMYK\n"; + break; +#if 0 + case "p:invalid": /* optional predictor specification */ + { unsigned char pred=or_->cache.Predictor; + if (pred== 2) out << "/Predictor 2"; /* TIFF predictor */ + else if (pred>=10) out << "/Predictor 10"; /* any PNG predictor */ + } +#endif + case 'w': /* image width, decimal */ + out << img->getWd(); + break; + case 'h': /* image height, decimal */ + out << img->getHt(); + break; + case '?': /* a divisor of rlen*height near 4096 */ + if (sf->getImgs()!=NULLP) { /* /Transparent+ */ + out << near_div(sf->getImgs()[0]->getRlen(), img->getHt()); + /* Dat: `img->getHt()*sf->getNncols()' would be wrong */ + } else { + out << near_div(img->getRlen(), img->getHt()); + } + break; + case 'B': /* Clean7Bits or Binary; Sun Jun 23 18:55:35 CEST 2002 */ + out << (or_->cache.isPDF() ? (or_->cache.isBinSB() ? "%\307\354\217\242\n" : "") + : (or_->cache.isBinSB() ? "Binary" : "Clean7Bit")); + break; + case 'b': /* image bpc, decimal */ + /* added "true"|"false" for sam2p-0.39 at Sun Sep 22 17:49:25 CEST 2002 */ + if (or_->cache.SampleFormat==Image::SF_Mask) out << "false"; + else if (or_->cache.SampleFormat==Image::SF_Indexed1) out << "true"; + else out << (unsigned)img->getBpc(); + break; + case 'c': /* image cpp, decimal */ + out << (unsigned)img->getCpp(); + break; + case 'd': /* device-specific color-space name */ + out << Image::Sampled::cs2devcs(img->getCs()); + break; + case 't': /* closefile specification in PostScript */ + if (or_->cache.Compression!=or_->cache.CO_None) out << " F closefile"; + if (or_->cache.TransferEncoding!=or_->cache.TE_Binary) out << " T closefile"; + break; + case 'T': /* TransferEncoding specification in PostScript */ + or_->appendTransferSpec(out); + break; + case 'F': /* decoding filter specification in PostScript */ + or_->appendDecoderSpec(out); + break; + case 'O': /* 0..1 /Decode values */ + i=1; + emit_Decode: + j=img->getCpp(); + out << "0 " << i; + while (j--!=1) out << " 0 " << i; + break; + case 'D': /* 0..1 /Decode values for indexed, 0..max-1 for others */ + i=(or_->cache.isIndexed())?(1<<img->getBpc())-1:1; + goto emit_Decode; + case 'S': /* image data stream */ + stream_writer(outpal, outstream, sf); + break; + case 'g': /* PDF 0..1 RGB triplet of the 0th palette color */ + assert(img->getTy()==img->TY_INDEXED); + r=img->getHeadp(); + goto appG; + case 'G': /* PDF 0..1 RGB triplet of the 1st palette color */ + assert(img->getTy()==img->TY_INDEXED); + r=img->getHeadp()+3; + appG: + div255(out, (unsigned char)r[0]); out << ' '; + div255(out, (unsigned char)r[1]); out << ' '; + div255(out, (unsigned char)r[2]); + break; + case 'r': /* PS 0..1 RGB triplet of the 0th palette color */ + assert(img->getTy()==img->TY_INDEXED); + r=img->getHeadp(); + out << (unsigned)(unsigned char)r[0] << " 255 div " + << (unsigned)(unsigned char)r[1] << " 255 div " + << (unsigned)(unsigned char)r[2] << " 255 div"; + break; + case 'R': /* PS code for setting up bg and fg colors for an imagemask */ + /* formerly: PS 0..1 RGB triplet of the 1st palette color */ + /* changed at Sun Sep 22 18:02:41 CEST 2002 */ + if (or_->cache.SampleFormat==Image::SF_Mask || or_->cache.SampleFormat==Image::SF_Indexed1) { + assert(img->getTy()==img->TY_INDEXED); + r=img->getHeadp(); + out << (unsigned)(unsigned char)r[0] << " 255 div " /* 0th palette color */ + << (unsigned)(unsigned char)r[1] << " 255 div " + << (unsigned)(unsigned char)r[2] << " 255 div setrgbcolor\n"; + if (or_->cache.SampleFormat==Image::SF_Indexed1) { + out << "0 0 moveto\n" + << img->getWd() << " 0 lineto\n0 " + << img->getHt() << " rlineto\n-" + << img->getWd() << " 0 rlineto\nclosepath fill\n" + << (unsigned)(unsigned char)r[3] << " 255 div " /* 1st palette color */ + << (unsigned)(unsigned char)r[4] << " 255 div " + << (unsigned)(unsigned char)r[5] << " 255 div\nsetrgbcolor\n"; + } + } + break; + case 'E': /* EPS header for unscaled PS files */ + if (or_->cacheHints.Scale==or_->cacheHints.SC_None) out << " EPSF-3.0"; + break; + case 'X': /* BoundingBox for EPS, MediaBox for PDF */ + if (or_->cache.isPDF()) { + // out << "0 0 "; + out << "0 "; + goto do_bbox; + } else if (or_->cacheHints.Scale==or_->cacheHints.SC_None) { + /* It is no point to start the BoundingBox of EPS files at + * (LeftMargin,BottomMargin). The effect would be the same as + * specifying no margins at all. Our choice is better: the + * BoundingBox contains the image and the margins too. + */ + // out << "%%BoundingBox: 0 0 "; + out << "%%BoundingBox: 0 "; + do_bbox: + // out << MiniPS::RVALUE(or_->cacheHints.LowerMargin) << ';'; /* SUXX: this would put `1 72 mul' */ + // out << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << ';'; /* SUXX: this would put `1 72 mul' */ + MiniPS::dumpAdd3(out, MiniPS::Qinteger(0), MiniPS::Qinteger(0), MiniPS::Qinteger(0), or_->cacheHints.LowerMargin, or_->cacheHints.BottomMargin, 1); + out << ' '; + MiniPS::dumpAdd3(out, or_->cacheHints.ImageDPI, MiniPS::Qinteger(img->getWd()), + or_->cacheHints.LeftMargin, or_->cacheHints.RightMargin, MiniPS::Qinteger(0), 2); + out << ' '; + MiniPS::dumpAdd3(out, or_->cacheHints.ImageDPI, MiniPS::Qinteger(img->getHt()), + or_->cacheHints.TopMargin, or_->cacheHints.LowerMargin, MiniPS::Qinteger(0), 2); + if (!or_->cache.isPDF()) out << '\n'; + } + break; + case 's': /* scaling to a full PostScript page or translation for PDF and EPS */ + nzp=!(MiniPS::isZero(or_->cacheHints.LowerMargin) + && MiniPS::isZero(or_->cacheHints.TopMargin)); + scp=!MiniPS::isEq(or_->cacheHints.ImageDPI, 72); + + if (or_->cache.isPDF()) { + SimBuffer::B scf; + if (scp) MiniPS::dumpScale(scf, or_->cacheHints.ImageDPI); + else scf << 'x'; + if (nzp || scp) out << " " << scf << " 0 0 " << scf << " " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) + << ' ' << MiniPS::RVALUE(or_->cacheHints.LowerMargin) + << " cm"; /* translate */ + } else switch (or_->cacheHints.Scale) { + case Rule::CacheHints::SC_None: + if (nzp) out << '\n' << MiniPS::RVALUE(or_->cacheHints.LeftMargin) + << ' ' << MiniPS::RVALUE(or_->cacheHints.LowerMargin) + << " translate"; + if (scp) { + MiniPS::dumpScale(scf, or_->cacheHints.ImageDPI); + out << '\n' << scf << " dup scale"; + } + break; + case Rule::CacheHints::SC_OK: + /* from pshack/big.ps */ + out <<"\n6 dict begin currentpagedevice/PageSize get dup 0 get\n " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.RightMargin) << " sub/w exch\n" + " def 1 get " << MiniPS::RVALUE(or_->cacheHints.TopMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << " sub/h exch\n" + " def/x " << img->getWd() << " def/y " << img->getHt() << " def " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << ' ' << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << " translate x h\n" + " mul y w mul gt{w x 0 h y w mul x div sub 2 div}{h y w x h mul y div sub 2 div\n" + " 0}ifelse translate div dup scale\nend"; + break; + case Rule::CacheHints::SC_RotateOK: + /* from pshack/big.ps */ + out <<"\n6 dict begin currentpagedevice/PageSize get dup 0 get\n " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.RightMargin) << " sub/w exch\n" + " def 1 get " << MiniPS::RVALUE(or_->cacheHints.TopMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << " sub/h exch\n" + " def/x " << img->getWd() << " def/y " << img->getHt() << " def " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << ' ' << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << "/b y h mul x\n" + " w mul gt def b{w y}{h x}ifelse div/c x h mul y w mul gt def c{w x}{h y}ifelse\n" + " div gt{h add translate -90 rotate b{w y h x w mul y div sub 2 div 0}{h\n" + " x 0 w y h mul x div sub 2 div}}{translate c{w x 0 h y w mul x div sub 2 div}{h\n" + " y w x h mul y div sub 2 div 0}}ifelse ifelse translate div dup scale\nend"; + break; + } + break; + default: + Error::sev(Error::EERROR) << "writeTTE: unknown escape: " << (char)p[-1] << (Error*)0; + } + template_=p; + } +} + +/** by pts@fazekas.hu at Mon Apr 15 22:31:03 CEST 2002 */ +void Rule::writeTTM( + Filter::VerbatimE &outve, + GenBuffer::Writable&outpal, + GenBuffer::Writable&outstream, + MiniPS::Array *chunkArray, + Rule::OutputRule*or_, + Image::SampledInfo *sf, + stream_writer_t stream_writer, + char const*const*strings) { + static const unsigned MAXLEN=64; + /* Imp: use heap instead of stack space */ + slen_t offsets[MAXLEN+1]; /* 260 bytes stack */ + SimBuffer::B chunks[MAXLEN]; /* <=1024 bytes stack; default constructor */ + MiniPS::VALUE *chunk; + param_assert(chunkArray!=NULLP); + // param_assert(chunkArray->getLength()<=MAXLEN); + if (chunkArray->getLength()>(int)MAXLEN) Error::sev(Error::EERROR) << "writeTTM: TTM too long" << (Error*)0; + GenBuffer::Writable& out=outve.getOut(); + MiniPS::ii_t i, ii; + for (chunkArray->getFirst(chunk), i=0; chunk!=NULLP; chunkArray->getNext(chunk), i++) { + if (MiniPS::getType(*chunk)==MiniPS::T_ARRAY) { + outve.setOut(chunks[i]); + writeTTM(outve, outpal, outstream, MiniPS::RARRAY(*chunk), or_, sf, stream_writer, strings); + } + } + for (chunkArray->getFirst(chunk), offsets[i=0]=0; chunk!=NULLP; chunkArray->getNext(chunk), i++) { + switch (MiniPS::getType(*chunk)) { + case MiniPS::T_ARRAY: + break; + case MiniPS::T_STRING: /* always null-terminated */ + outve.setOut(chunks[i]); + writeTTE(outve, outpal, outstream, MiniPS::RSTRING(*chunk)->begin_(), or_, sf, stream_writer, strings); + break; + case MiniPS::T_INTEGER: + if (0==(ii=MiniPS::int2ii(*chunk))) Error::sev(Error::EERROR) << "writeTTM: zero is an invalid chunk" << (Error*)0; + if (ii>0) { /* an offset */ + if (ii>i) Error::sev(Error::EERROR) << "writeTTM: cannot predict chunk offset" << (Error*)0; + if (MiniPS::T_ARRAY==MiniPS::getType(chunkArray->get(ii))) + chunks[i].write_num(offsets[ii], 10); /* Dat: 10: 10 digits (for PDF xref table), not base 10 */ + else chunks[i] << offsets[ii]; + } else { /* a length */ + chunks[i] << chunks[-ii].getLength(); + } + break; + default: + Error::sev(Error::EERROR) << "writeTTM: invalid chunk type: " << MiniPS::getTypeStr(MiniPS::getType(*chunk)) << (Error*)0; + } + offsets[i+1]=offsets[i]+chunks[i].getLength(); + } /* NEXT */ + outve.setOut(out); + for (i=0; i<chunkArray->getLength(); i++) out << chunks[i]; + /* Imp: organize that chunks[.] gets freed earlier than this */ +} /* Rule::writeTTM() */ + +MiniPS::Dict *Rule::Templates=(MiniPS::Dict*)NULLP; + +void Rule::writeTTT( + GenBuffer::Writable&out, + GenBuffer::Writable&outpal, + GenBuffer::Writable&outstream, + char const *template_key, + Rule::OutputRule*or_, + Image::SampledInfo *sf, + stream_writer_t stream_writer, + char const*const*strings) { + assert(Templates!=NULLP); + Error::sev(Error::NOTICE) << "writeTTT: using template: " << template_key << (Error*)0; + MiniPS::VALUE val=Templates->get(template_key, strlen(template_key)); + assert(val!=MiniPS::Qundef); + switch (MiniPS::getType(val)) { + case MiniPS::T_STRING: + writeTTE(out, outpal, outstream, MiniPS::RSTRING(val)->begin_(), or_, sf, stream_writer, strings); + break; + case MiniPS::T_ARRAY: + /* Imp: vvv This up-cast is unsafe! */ + writeTTM(*(Filter::VerbatimE*)&out, outpal, outstream, MiniPS::RARRAY(val), or_, sf, stream_writer, strings); + break; + default: + Error::sev(Error::EERROR) << "writeTTT: invalid template type: " << MiniPS::getTypeStr(MiniPS::getType(val)) << (Error*)0; + } +} + +/* __END__ */ diff --git a/Build/source/utils/sam2p/rule.hpp b/Build/source/utils/sam2p/rule.hpp new file mode 100644 index 00000000000..31dcc0590bb --- /dev/null +++ b/Build/source/utils/sam2p/rule.hpp @@ -0,0 +1,315 @@ +/* rule.hpp -- Output rules + * by pts@fazekas.hu Fri Mar 15 15:11:38 CET 2002 + */ + +#ifdef __GNUC__ +#pragma interface +#endif + +#ifndef RULE_HPP +#define RULE_HPP 1 + +#include "config2.h" +#include "gensio.hpp" +#include "image.hpp" +#include "minips.hpp" + +/** a namespace */ +class Rule { public: + struct Cache { + bool WarningOK; + BEGIN_STATIC_ENUM(unsigned char,ff_t) + FF_default=0, /* only for one-liner */ + FF_eps=71, /* only for one-liner, temporary */ + FF_pdf=72, /* only for one-liner, temporary */ + FF_pdfb=73, /* only for one-liner, temporary */ + FF_PSL1=110, + FF_PSLC=115, + FF_PSL2=120, + FF_PSL3=130, + FF_PDFB10=90, + FF_PDFB12=92, + FF_PDF10=80, + FF_PDF12=82, + FF_GIF89a=1, + FF_PNM=2, + FF_PAM=3, + FF_PIP=4, /* Portable Indexed file format by pts */ + FF_Empty=5, + FF_Meta=6, + FF_JPEG=7, + FF_TIFF=8, + FF_PNG=9, + FF_XPM=10, + FF_BMP=11, + FF_XWD=12, + FF_X11=13 + END_STATIC_ENUM() + ff_t FileFormat; + Image::sf_t SampleFormat; + /** Used only in appliers.cpp when _check_rule() changes SampleFormat so + * setSampleFormat() called before _work() would set that dummy + * SampleFormat. + */ + Image::sf_t origSampleFormat; + BEGIN_STATIC_ENUM(unsigned char,te_t) + TE_default=0, /* only for one-liner */ + TE_Binary=1, + TE_ASCII=2, + TE_Hex=3, + TE_A85=4, + TE_MSBfirst=5, + TE_LSBfirst=6 + END_STATIC_ENUM() + te_t TransferEncoding; + + BEGIN_STATIC_ENUM(unsigned char,co_t) + CO_default=0, /* only for one-liner */ + CO_None=1, + CO_LZW=2, + CO_ZIP=3, + CO_RLE=4, + CO_Fax=5, + CO_DCT=6, + CO_IJG=7, + CO_JAI=8, + CO_max=8 + END_STATIC_ENUM() + co_t Compression; + + BEGIN_STATIC_ENUM(unsigned char,pr_t) + PR_None=1, + PR_TIFF2=2, + PR_PNGNone=10, PR_PNG=10, + PR_PNGSub=11, + PR_PNGUP=12, + PR_PNGAverage=13, + PR_PNGPaeth=14, + PR_PNGAuto=15, + PR_PNGAutoUnsigned=45 + END_STATIC_ENUM() + pr_t Predictor; + + Image::Sampled::rgb_t Transparent; + + bool isOneBit() const; + bool isPDF() const; + bool isPDFB() const; + bool isPS() const; + bool isPSL2() const; + bool isPSL3() const; + bool hasPredictor() const; + bool isIndexed() const; + bool isTransparentM() const; + bool isGray() const; + bool isRGB() const; + bool isDCTE() const; + bool isBinSB() const; + /** /Compression/ZIP not OK with /PSL1, /PSLC, /PSL2, /PDF10, /PDFB10 */ + bool isZIPOK() const; + // bool is8() const; + + /** @param s is case insensitive, leading `/' is optional. + * @return SF_max if not found, or a valid SF_... constant + */ + static Image::sf_t parseSampleFormat(char const*s, slen_t slen); + static char const* dumpFileFormat(ff_t FileFormat, co_t Compression=CO_default); + static char const* dumpTransferEncoding(te_t TransferEncoding); + static char const* dumpSampleFormat(Image::sf_t SampleFormat); + static char const* dumpCompression(co_t Compression); + }; + + struct CacheHints { + BEGIN_STATIC_ENUM(unsigned char,sc_t) /* Fri Aug 16 16:33:47 CEST 2002 */ + SC_default=0, + SC_None=1, + SC_OK=2, + SC_RotateOK=3 + END_STATIC_ENUM() + sc_t Scale; + + /* Image dimensions for encoding filters (may be different from real + * image dimensions, but _really_ disrecommended). + * slen_t important becasuse of separate(). + */ + slen_t EncoderColumns, EncoderBPL, EncoderRows; + /** Number of color components (channels) per pixel. */ + unsigned char EncoderColors; + slen_t PredictorColumns; + unsigned char PredictorBPC, PredictorColors; + unsigned ColorTransform; + signed Effort; + slen_t RecordSize; + slendiff_t K; + /* JPEG quality for the IJG encoding filter */ + unsigned char Quality; + unsigned TransferCPL; + MiniPS::String *Comment, *Title, *Subject, *Author, *Creator, *Producer; + MiniPS::String *Created, *Produced; + MiniPS::Dict *DCT; + /** MiniPS::Real* or integer */ + MiniPS::VALUE TopMargin, BottomMargin, LeftMargin, RightMargin; + /** MiniPS::Real* or integer. Specifies the dimension the image should + * be lowered below the baseline for (PostScript or PDF) output with + * /Scale/None. Default to 0. + */ + MiniPS::VALUE LowerMargin; + /** 72 by default. */ + MiniPS::VALUE ImageDPI; + static char const* dumpScale(sc_t Scale); + }; + + struct OutputRule { + Cache cache; + CacheHints cacheHints; + MiniPS::Dict* dict; + /* /Hints entry in dict */ + MiniPS::Dict* dictHints; + /* Number of this output rule, as appeared in .job. Imp: name */ + unsigned c; + inline bool isEOL() const { return dictHints==NULLP; } + /** In: dict, dictHints, cache and cacheHints is uninitialized. Out: they + * get inititalized from param. Errors might occur and error messages + * might get printed. + */ + void fromDict(MiniPS::VALUE); + /** Calls info->setSampleFormat(), and sets cacheHints.PredictorColumns + * and some other fields if they are zero (unspecified in the .job file) + */ + void doSampleFormat(Image::SampledInfo *info, bool separate=false); + /** Appends "" when CO_None, + * "<</K ... /Columns ...>>/CCITTFaxDecode filter" when CO_Fax + * "/...Decode filter" otherwise + * Calls appendPredictorSpec() if necessary. + * For PDF (not PS!), implies appendTransferSpec(). + */ + void appendDecoderSpec(GenBuffer::Writable &out) const; + /** Appends "" when PR_None or + * appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 2>>" or + * appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 10>>" + * appends "<</K ...>>" + */ + void appendPredictorSpec(GenBuffer::Writable &out) const; + /** Appends "" or "/ASCII85Decode filter" or "/ASCIIHexDecode filter" + */ + void appendTransferSpec(GenBuffer::Writable &out) const; + bool hasPredictorSpec() const; + }; + + struct Applier { + BEGIN_STATIC_ENUM(unsigned,cons_t) + DONT_KNOW=0, BAD=1, MAYBE=2, OK=3 + END_STATIC_ENUM() + /** Checks the specified OutputRule for internal consistency, updates + * the `or->cache', emits warnings, and returns consistency status + * information. + * + * -- If (this) Applier doesn't know how to handle the OutputRule, returns + * DONT_KNOW immediately. + * -- If (this) Applier knows that the OutputRule is internally + * inconsistent or proved to be unsupported (i.e printing JPEG images + * on PostScript Level1 printers), regardless of the image itself, it + * returns BAD immediately and emits a warning about the reason. + * -- If (this) Applier knows that the OutputRule may or may not be + * processed, depending on the actual image, then MAYBE is returned. + * -- If (this) Applier knows that the OutputRule can be processed on + * any image, then OK is returned. + */ + typedef cons_t(*check_rule_t)(OutputRule* or_); + + /** Outputs (writes) the PostScript or PDF presentation of the image + * specified in param `sf' to the output stream in param `out', using + * the Output Rule specified in param `or'. + * @return DONT_KNOW if doesn't know how to handle the OutputRule; + * BAD if it is sure that the image cannot be written with the + * specified OutputRule; + * OK if writing was successful + */ + typedef cons_t(*work_t)(GenBuffer::Writable& out, OutputRule*or_, Image::SampledInfo *sf); + + /** A short, informal description of this Applier. */ + char const*format; + check_rule_t check_rule; + /** May be NULLP if `check_rule' never returns OK or MAYBE */ + work_t work; + /** Null or next Applier to probe. Filled by register0(); */ + Applier *next; + }; + + /* Registers a new type of output Applier, i.e a new output file + * format/method. The new output format will be put in front of all others, + * and will be checked first by apply_best(). + */ + static void register0(Applier*); + /* Loads the image contained in te file `filename'. */ + + /** Builds the list of available profiles from the Profile element read + * from a .job file. To do the task, calls check_rule() of all registered (!) + * Appliers. Also calls OutputRule::fromDict for each profile element. + * All returned OutputRules have an Applier which returned OK or MAYBE. + * @return a dict==NULLP-terminated list of OutputRules + */ + static OutputRule* buildProfile(MiniPS::VALUE Profile, bool quiet=false); + + /** Applies the Profile specified in param `rule_list' to the image + * specified in param `sf', and writes the output to param `out'. + */ + static void applyProfile(GenBuffer::Writable& out, OutputRule*rule_list, Image::SampledInfo *sf); + + /** Frees memory associated with a profile returned by buildProfile() */ + static void deleteProfile(OutputRule*); + + static unsigned printAppliers(GenBuffer::Writable &out); + + + typedef void (*stream_writer_t)(GenBuffer::Writable&out, GenBuffer::Writable&outstream, Image::SampledInfo *sf); + + /** Writes a PS/PDF file to `out' according to `template_': substitutes + * actual image (pixel) data from `sf->getImg()', and substitutes image + * metadata from `sf'. `outstream' should be a prepared stream (top of chain + * of Encode filters). + * See a .tte file for an example template. + */ + static void writeTTE( + GenBuffer::Writable& out, + GenBuffer::Writable& outpal, + GenBuffer::Writable& outstream, + char const*template_, + Rule::OutputRule*or_, + Image::SampledInfo *sf, + stream_writer_t stream_writer, + char const*const*strings=(char**)NULLP); + + /** Doesn't invoke MiniPS::delete0(chunkArray); */ + static void writeTTM( + Filter::VerbatimE &outve, + GenBuffer::Writable&outpal, + GenBuffer::Writable&outstream, + MiniPS::Array *chunkArray, + Rule::OutputRule*or_, + Image::SampledInfo *sf, + stream_writer_t stream_writer, + char const*const*strings=(char**)NULLP); + + /** Used by writeTTT() to find template specification by name */ + static MiniPS::Dict* Templates; + /** @param out must be of type Filter::VerbatimE if the template is a TTM + * array. + * @param template_key a key in file bts.ttt + */ + static void writeTTT( + GenBuffer::Writable&out, + GenBuffer::Writable&outpal, + GenBuffer::Writable&outstream, + char const *template_key, + Rule::OutputRule*or_, + Image::SampledInfo *sf, + stream_writer_t stream_writer, + char const*const*strings=(char**)NULLP); + + static void writeData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf); + static void writePalData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf); + +}; + +#endif diff --git a/Build/source/utils/sam2p/sam2p16.ico b/Build/source/utils/sam2p/sam2p16.ico Binary files differnew file mode 100644 index 00000000000..b712b321667 --- /dev/null +++ b/Build/source/utils/sam2p/sam2p16.ico diff --git a/Build/source/utils/sam2p/sam2p32.ico b/Build/source/utils/sam2p/sam2p32.ico Binary files differnew file mode 100644 index 00000000000..c5b26e26598 --- /dev/null +++ b/Build/source/utils/sam2p/sam2p32.ico diff --git a/Build/source/utils/sam2p/sam2p_main.cpp b/Build/source/utils/sam2p/sam2p_main.cpp new file mode 100644 index 00000000000..d42bcae4651 --- /dev/null +++ b/Build/source/utils/sam2p/sam2p_main.cpp @@ -0,0 +1,1063 @@ +/* sam2p_main.cpp + * by pts@fazekas.hu at Fri Mar 15 16:11:03 CET 2002 + */ + +#include "gensi.hpp" +#include "gensio.hpp" +#include "image.hpp" +#include "error.hpp" +#include "encoder.hpp" +#include "minips.hpp" +#include "rule.hpp" +#include "main.hpp" +#include "in_jai.hpp" + +/* Sat Jul 6 16:39:19 CEST 2002 + * empirical checkerg++ helper routines for gcc version 2.95.2 20000220 (Debian GNU/Linux) + * see c_lgcc.cpp for more + */ +#if !defined(OBJDEP) && defined(__CHECKER__) && !HAVE_PTS_C_LGCC_CPP_REQUIRED +# include "c_lgcc.cpp" +#endif + +#if 0 /*#ifdef __CHECKER__*/ +#include <stdlib.h> +void* __builtin_vec_new(unsigned len){ return malloc(len); } +void __builtin_vec_delete(void *p) { free(p); } +void* __builtin_new(unsigned len){ return malloc(len); } +void __builtin_delete(void *p) { free(p); } +void __rtti_user() { abort(); } +void __rtti_si() { abort(); } +void terminate() { abort(); } +extern "C" void __pure_virtual(); +void __pure_virtual() { abort(); } +#endif + +#if OBJDEP +# warning PROVIDES: sam2p_main +# warning REQUIRES: gensi.o +# warning REQUIRES: gensio.o +# warning REQUIRES: image.o +# warning REQUIRES: error.o +# warning REQUIRES: encoder.o +# warning REQUIRES: minips.o +# warning REQUIRES: rule.o +#endif + +#include <stdio.h> +#include <string.h> /* memset() */ + +#if OBJDEP +# warning REQUIRES: in_tiff.o +# warning REQUIRES: in_jpeg.o +# warning REQUIRES: in_png.o +# warning REQUIRES: in_jai.o +# warning REQUIRES: in_pcx.o +# warning REQUIRES: in_xpm.o +# warning REQUIRES: in_lbm.o +# warning REQUIRES: in_gif.o +# warning REQUIRES: in_bmp.o +# warning REQUIRES: in_pnm.o +# warning REQUIRES: in_tga.o +/*# warning REQUIRES: in_pdf.o Dat: no more, integrated to in_ps.o */ +# warning REQUIRES: in_ps.o +#endif +extern Image::Loader in_tiff_loader; +extern Image::Loader in_jpeg_loader; +extern Image::Loader in_png_loader; +extern Image::Loader in_jai_loader; +extern Image::Loader in_pcx_loader; +extern Image::Loader in_xpm_loader; +extern Image::Loader in_lbm_loader; +extern Image::Loader in_gif_loader; +extern Image::Loader in_bmp_loader; +extern Image::Loader in_pnm_loader; +extern Image::Loader in_tga_loader; +extern Image::Loader in_pdf_loader; +extern Image::Loader in_ps_loader; +void init_loader() { + static bool had_init_loader=false; + if (had_init_loader) return; + Image::register0(&in_tga_loader); /* checker not sure; install early */ + Image::register0(&in_pcx_loader); + Image::register0(&in_xpm_loader); + Image::register0(&in_lbm_loader); + Image::register0(&in_gif_loader); + Image::register0(&in_bmp_loader); + Image::register0(&in_pnm_loader); + Image::register0(&in_tiff_loader); + Image::register0(&in_jpeg_loader); + Image::register0(&in_png_loader); + Image::register0(&in_jai_loader); + Image::register0(&in_pdf_loader); + Image::register0(&in_ps_loader); + had_init_loader=true; +} + +#if OBJDEP +# warning REQUIRES: appliers.o +#endif +extern Rule::Applier out_pnm_applier; +extern Rule::Applier out_jpeg_applier; +extern Rule::Applier out_jpegjai_applier; +extern Rule::Applier out_tiffjai_applier; +extern Rule::Applier out_tiff_applier; +extern Rule::Applier out_png_applier; +extern Rule::Applier out_bmp_applier; +extern Rule::Applier out_gif89a_applier; +extern Rule::Applier out_xpm_applier; +extern Rule::Applier out_l1c_applier; +// extern Rule::Applier out_l1op_applier; +extern Rule::Applier out_l1tr_applier; +extern Rule::Applier out_l23_applier; +// extern Rule::Applier out_l1fa85g_applier; +extern Rule::Applier out_l2jbin_applier; +// extern Rule::Applier out_p0jbin_applier; +extern Rule::Applier out_empty_applier; +extern Rule::Applier out_meta_applier; +extern Rule::Applier out_xwd_applier; +extern Rule::Applier out_x11_applier; +void init_applier() { + static bool had_init_applier=false; + if (had_init_applier) return; + // Rule::register0(&out_l1op_applier); + Rule::register0(&out_l1tr_applier); + // Rule::register0(&out_l1fa85g_applier); + Rule::register0(&out_l2jbin_applier); + // Rule::register0(&out_p0jbin_applier); + Rule::register0(&out_l23_applier); + Rule::register0(&out_l1c_applier); + Rule::register0(&out_xpm_applier); + Rule::register0(&out_gif89a_applier); + Rule::register0(&out_pnm_applier); + Rule::register0(&out_jpeg_applier); + Rule::register0(&out_jpegjai_applier); + Rule::register0(&out_tiffjai_applier); + Rule::register0(&out_tiff_applier); + Rule::register0(&out_png_applier); + Rule::register0(&out_bmp_applier); + Rule::register0(&out_empty_applier); + Rule::register0(&out_meta_applier); + Rule::register0(&out_xwd_applier); + Rule::register0(&out_x11_applier); + had_init_applier=true; +} + +static char *bts_ttt= +#include "bts2.tth" +; + +/* --- One-liner mode */ + +/** Dat: mod 16 does matter: expected # args etc. */ +static const unsigned + OPT_unknown=0, + OPT_SampleFormat=0x02, + OPT_LoadHints=0x12, + OPT_Compression=0x22, + OPT_TransferEncoding=0x32, + OPT_TransferEncodingF=0x42, + OPT_Asis=0x50, + OPT_PSL1=0x60, + OPT_PSLC=0x70, + OPT_PSL2=0x80, + OPT_PSL3=0x90, + OPT_PS=0xA1, + OPT_PDF=0xB1, + OPT_DisplayJobFile=0xC1, + OPT_Hints=0xD2, + OPT_InputFile=0xE2, + OPT_OutputFile=0xF2, + OPT_Scale=0x101, + OPT_Margins=0x112, + OPT_Transparent=0x122; + +/** @param s an option (lower/upper case intact), without leading `-'s + * @param slen length of option + * @return 0 if invalid/unsupported/unknown option + * | 16*(k+1)+0 if the option never accepts parameters + * | 16*(k+2)+1 if the option may or may not have a parameter + * | 16*(k+3)+2 if the option must have a parameter + */ +static unsigned sam2p_optval(char const* s, slen_t slen) { + if (slen==1) { + switch (s[0]) { + case 's': return OPT_SampleFormat; + case 'l': return OPT_LoadHints; + case 'h': return OPT_Hints; + case 't': return OPT_TransferEncoding; + case 'f': return OPT_TransferEncodingF; + case 'c': return OPT_Compression; + // case 'a': return OPT_Asis; /* disabled, automatic! */ + case '1': return OPT_PSL1; + case '2': return OPT_PSL2; + case '3': return OPT_PSL3; + case 'j': return OPT_DisplayJobFile; + case 'o': case 'O': return OPT_OutputFile; + case 'e': return OPT_Scale; + case 'm': return OPT_Margins; + } + } else { + slen_t len=slen; /* strlen(s); */ + if (len>=32) return OPT_unknown; + char buf[32]; + GenBuffer::tolower_memcpy(buf, s, len); + buf[len]='\0'; + /* printf("buf=(%s)\n", buf); */ + if (0==strcmp(buf, "sampleformat")) return OPT_SampleFormat; + if (0==strcmp(buf, "loadhints")) return OPT_LoadHints; + if (0==strcmp(buf, "transparent")) return OPT_Transparent; + if (0==strcmp(buf, "hints")) return OPT_Hints; + if (0==strcmp(buf, "ps") + || 0==strcmp(buf, "eps")) return OPT_PS; + if (0==strcmp(buf, "pdf")) return OPT_PDF; + if (0==strcmp(buf, "1c")) return OPT_PSLC; + if (0==strcmp(buf, "scale")) return OPT_Scale; + if (0==strcmp(buf, "hints")) return OPT_Margins; + } + return OPT_unknown; +} + +static void displayJob(GenBuffer::Writable &sout, SimBuffer::Flat const& jobss) { + fflush(stdout); fflush(stderr); + #if 0 + puts("\n\n% begin sam2p job dump"); + fwrite(stdout, 1, jobss.getLength(), jobss); + puts("% end sam2p job dump\n"); + #else + /* vvv Dat: sout conflicts /OutputFile(-), but it is OK here */ + sout << "\n% begin sam2p job dump\n" + << jobss + << "%)%)%)% end sam2p job dump\n\n"; + #endif + fflush(stdout); fflush(stderr); +} + +static inline char const *protect_null(char const *s) { + return s==(char const*)NULLP ? "//" : s; +} + +/** @return the value for the parameter if matches key or the first letter of + * key; or NULLP if no match. + * @param key lower case + */ +static char const*one_pabbr(char const*param, char const *key) { + return GenBuffer::nocase_strbegins(param, key) ? param+strlen(key) + : (param[0]==key[0] || param[0]==key[0]+'A'-'a') && param[1]==':' ? param+2 + : (char const*)NULLP; +} + +#if 0 /* cannot set badp... */ +static inline void one_setdimen2(char const*&Dimen1, char const*&Dimen2, char const*p2) { + if (MiniPS::Real::isDimen(p2)) Dimen1=Dimen2=p2; + else Error::sev(Error::ERROR_CONT) << "one_liner: dimen expected" /*<< (SimBuffer::B().appendDumpC(p2, true))*/ << (Error*)0; +} +#endif +#if 0 +#define one_setdimen2(Dimen1,Dimen2,p2) do { \ + if (MiniPS::Real::isDimen(p2)) Dimen1=Dimen2=p2; \ + else { badmsg="one_liner: dimen expected: "; goto bad_label; } \ +} while(0) +#endif + +static Filter::UngetFILED *ufd; +static bool do_DisplayJobFile; +static bool buildProfile_quiet=false; +/** Creates an in-memory job file according to the command-line options. + * @param a argv+1 + * @param job initially an empty string. On error, this function leaves it + * as-is, but on success, a valid job file is appened. + * @return true on syntax error + */ +static bool one_liner(SimBuffer::B &jobss, char const *const* a) { + /* Tue Jul 2 21:27:15 CEST 2002 */ + char const *p, *pend; + bool no_option_term=true; + bool badp=false; + bool no_selector=true; + char const *badmsg; + // SimBuffer::B Profile /* MiniPS code */ + SimBuffer::B Hints; /* MiniPS code */ + /* ^^^ Imp: separate hint for each -c arg?? */ + SimBuffer::B LoadHints; + Rule::Cache::pr_t Predictor=Rule::Cache::PR_None; /* Imp: separate for each Compression */ + Rule::Cache::ff_t FileFormat=Rule::Cache::FF_default; + Rule::Cache::te_t TransferEncoding=Rule::Cache::TE_default; + do_DisplayJobFile=false; + bool do_stop_SampleFormat=false; + char const *Transparent=(char const*)NULLP; /* change 1 color to transparent unless NULL */ + char const *OutputFile=(char const*)NULLP, *InputFile=(char const*)NULLP; + // SimBuffer::B tmp; + char const *TopMargin=(char const*)NULLP, *BottomMargin=(char const*)NULLP, + *LeftMargin=(char const*)NULLP, *RightMargin=(char const*)NULLP, + *LowerMargin=(char const*)NULLP, *ImageDPI=(char const*)NULLP; + bool negLowerMargin=false; + Rule::CacheHints::sc_t Scale=Rule::CacheHints::SC_default; + #define APPEND_sf(val) do { if (sfx[val]==0) { sfx[val]=1; sft[sflen++]=val; } } while (0) + Image::sf_t sft[Image::SF_max+1]; char sfx[Image::SF_max+1]; memset(sfx, 0, sizeof(sfx)); unsigned sflen=0; + #define APPEND_co(val) do { if (cox[val]==0) { cox[val]=1; cot[colen++]=val; } } while (0) + Rule::Cache::co_t cot[Rule::Cache::CO_max+1]; char cox[Image::SF_max+1]; memset(cox, 0, sizeof(cox)); unsigned colen=0; + /* ^^^ BUGFIX at 2002.12.02 */ + + /** OPT_* value of current option */ + unsigned opt; + /** Parameter for current option. May be NULL. */ + char const *param=""; /* pacify VC6.0 */ + char const *p2; + slen_t paramlen; + SimBuffer::B tmpnam; /* any dir -- keep on stack frame */ + + buildProfile_quiet=true; + + for (; (p=*a)!=(char const*)NULLP; a++) { + if (p[0]=='-' && p[1]=='\0') { /* `-': Filename: STDIN or STDOUT */ + #if 1 + goto normal_label; + #else + Error::sev(Error::ERROR_CONT) << "one_liner: `-' (stdin|stdout) not allowed as filename" << (Error*)0; + badp=true; + continue; + #endif + } else if (p[0]=='-' && p[1]=='-' && p[2]=='\0') { /* `--': No more options */ + if (a[1]==(char const*)NULLP && InputFile!=(char const*)NULLP) { /* `--' is last argument */ + p=InputFile; /* OutputFile:=InputFile */ + goto normal_label; + } + no_option_term=false; + } else if (p[0]=='-' && no_option_term) { /* an option */ + while (*p=='-') p++; /* short options (-p) and long options (--pdf) are equivalent */ + pend=p; while (*pend!='\0' && *pend!=':' && *pend!='=') pend++; + SimBuffer::Static optss(p, pend-p); + if (0==(opt=sam2p_optval(p, pend-p))) { + badmsg="one_liner: unknown option: "; + bad_label: + Error::sev(Error::ERROR_CONT) << badmsg << (SimBuffer::B().appendDumpC(optss, true)) << (Error*)0; + badp=true; + continue; + } + if ((opt&15)==0) { /* no parameters */ + if (*pend!='\0') { badmsg="one_liner: don't give param to option: "; goto bad_label; } + param=(char const*)NULLP; + } else if ((opt&15)==1) { /* an optional parameter */ + if (*pend!='\0') { + param=pend+1; while (*pend==*param) param++; + } else param=(char const*)NULLP; + } else if ((opt&15)==2) { /* a mandatory parameter */ + if (*pend!='\0') { + param=pend+1; while (*pend==*param) param++; + } else if ((param=*++a)==(char const*)NULLP) { badmsg="one_liner: missing param for option: "; goto bad_label; } + } else assert(0); + paramlen=param==(char const*)NULLP ? 0 : strlen(param); + + /* Dat: now opt, paramlen and param are correct */ + switch (opt) { + case OPT_LoadHints: LoadHints << ',' << param; break; + case OPT_Transparent: Transparent=param; break; /* Imp: is this good memory management */ + case OPT_Hints: Hints << '\n' << param; break; + case OPT_PSL1: FileFormat=Rule::Cache::FF_PSL1; break; + case OPT_PSLC: FileFormat=Rule::Cache::FF_PSLC; break; + case OPT_PSL2: FileFormat=Rule::Cache::FF_PSL2; break; + case OPT_PSL3: FileFormat=Rule::Cache::FF_PSL3; break; + case OPT_DisplayJobFile: + // fprintf(stderr, "param=(%s)\n", param); + if (paramlen==0 || 0==GenBuffer::nocase_strcmp(param, "job")) do_DisplayJobFile=true; + else if (0==GenBuffer::nocase_strcmp(param, "warn")) buildProfile_quiet=false; + else if (GenBuffer::nocase_strbegins(param, "warn:")) buildProfile_quiet=!GenBuffer::parseBool(param+5, paramlen-5); + else if (0==GenBuffer::nocase_strcmp(param, "quiet")) { buildProfile_quiet=true; Error::setTopPrinted(Error::ERROR_CONT); } /* Dat: hide warnings, info etc. */ /* at Fri Aug 26 07:54:00 CEST 2005 */ + else if (GenBuffer::nocase_strbegins(param, "job:")) do_DisplayJobFile=GenBuffer::parseBool(param+4, paramlen-4); + else do_DisplayJobFile=GenBuffer::parseBool(param, paramlen); /* Imp: better error report */ + break; + case OPT_Margins: + /* Dat:abbreviation letters are distinct: [ahxvylrtubd] */ + if (0!=(p2=one_pabbr(param,"all:"))) { all5: + if (MiniPS::Real::isDimen(p2)) LeftMargin=RightMargin=TopMargin=BottomMargin=LowerMargin=p2; + else { err_dimexp: badmsg="one_liner: dimen expected: "; goto bad_label; } + } + else if (0!=(p2=one_pabbr(param,"horiz:")) + || 0!=(p2=one_pabbr(param,"x:"))) { if (MiniPS::Real::isDimen(p2)) LeftMargin=RightMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"vert:")) + || 0!=(p2=one_pabbr(param,"y:"))) { if (MiniPS::Real::isDimen(p2)) TopMargin=BottomMargin=LowerMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"left:"))) { if (MiniPS::Real::isDimen(p2)) LeftMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"right:"))) { if (MiniPS::Real::isDimen(p2)) RightMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"dpi:"))) { if (MiniPS::Real::isDimen(p2)) ImageDPI=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"top:")) + || 0!=(p2=one_pabbr(param,"up:"))) { if (MiniPS::Real::isDimen(p2)) TopMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"bottom:")) + || 0!=(p2=one_pabbr(param,"down:"))) { if (MiniPS::Real::isDimen(p2)) BottomMargin=LowerMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"raise:"))) { if (MiniPS::Real::isDimen(p2)) LowerMargin=p2; else goto err_dimexp; } + else if (0!=(p2=one_pabbr(param,"lower:"))) { negLowerMargin=true; if (MiniPS::Real::isDimen(p2)) LowerMargin=p2; else goto err_dimexp; } + else { p2=param; goto all5; } + break; + case OPT_Scale: + if (paramlen==0 || 0==GenBuffer::nocase_strcmp(param, "scale")) Scale=Rule::CacheHints::SC_OK; + else if (0==GenBuffer::nocase_strcmp(param, "none")) Scale=Rule::CacheHints::SC_None; + else if (0==GenBuffer::nocase_strcmp(param, "rot")) Scale=Rule::CacheHints::SC_RotateOK; + else if (0==GenBuffer::nocase_strcmp(param, "rotate")) Scale=Rule::CacheHints::SC_RotateOK; + else Scale=(Rule::CacheHints::sc_t)(GenBuffer::parseBool(param, paramlen) ? 0+Rule::CacheHints::SC_OK : 0+Rule::CacheHints::SC_None); + /* ^^^ Imp: better error report */ + /* ^^^ +0: pacify g++-3.1 */ + break; + case OPT_TransferEncoding: + if (0==GenBuffer::nocase_strcmp(param, "bin")) TransferEncoding=Rule::Cache::TE_Binary; + else if (0==GenBuffer::nocase_strcmp(param, "hex")) TransferEncoding=Rule::Cache::TE_Hex; + else if (0==GenBuffer::nocase_strcmp(param, "a85")) TransferEncoding=Rule::Cache::TE_A85; + else if (0==GenBuffer::nocase_strcmp(param, "ascii"))TransferEncoding=Rule::Cache::TE_ASCII; + else if (0==GenBuffer::nocase_strcmp(param, "lsb1")) TransferEncoding=Rule::Cache::TE_LSBfirst; + else if (0==GenBuffer::nocase_strcmp(param, "msb1")) TransferEncoding=Rule::Cache::TE_MSBfirst; + else { inv_par: badmsg="one_liner: invalid param for option: "; goto bad_label; } + break; + case OPT_TransferEncodingF: + if (0==GenBuffer::nocase_strcmp(param, "lsb2msb")) TransferEncoding=Rule::Cache::TE_LSBfirst; + else if (0==GenBuffer::nocase_strcmp(param, "msb2lsb")) TransferEncoding=Rule::Cache::TE_MSBfirst; + else goto inv_par; + break; + case OPT_PS: + if (param==(char const*)NULLP || param[0]=='\0') FileFormat=Rule::Cache::FF_eps; + else if (0==GenBuffer::nocase_strcmp(param, "1")) FileFormat=Rule::Cache::FF_PSL1; + else if (0==GenBuffer::nocase_strcmp(param, "1c") + || 0==GenBuffer::nocase_strcmp(param, "c")) FileFormat=Rule::Cache::FF_PSLC; + else if (0==GenBuffer::nocase_strcmp(param, "2")) FileFormat=Rule::Cache::FF_PSL2; + else if (0==GenBuffer::nocase_strcmp(param, "3")) FileFormat=Rule::Cache::FF_PSL3; + else goto inv_par; + break; + case OPT_PDF: + if (param==(char const*)NULLP || param[0]=='\0') FileFormat=Rule::Cache::FF_pdfb; + else if (0==GenBuffer::nocase_strcmp(param, "b")) FileFormat=Rule::Cache::FF_pdfb; /* BI */ + else if (0==GenBuffer::nocase_strcmp(param, "x")) FileFormat=Rule::Cache::FF_pdf; /* XObject */ + else if (0==GenBuffer::nocase_strcmp(param, "b0")) FileFormat=Rule::Cache::FF_PDFB10; + else if (0==GenBuffer::nocase_strcmp(param, "b2")) FileFormat=Rule::Cache::FF_PDFB12; + else if (0==GenBuffer::nocase_strcmp(param, "0")) FileFormat=Rule::Cache::FF_PDF10; + else if (0==GenBuffer::nocase_strcmp(param, "2")) FileFormat=Rule::Cache::FF_PDF12; + else goto inv_par; + break; + case OPT_SampleFormat: + pend=param; + while (*pend!='\0') { + while (*pend==':') pend++; + if (do_stop_SampleFormat) goto inv_par; /* already stopped */ + p=pend; while (*pend!='\0' && *pend!=':') pend++; + paramlen=pend-p; + if (4==paramlen && 0==memcmp(p,"stop",4)) { do_stop_SampleFormat=true; buildProfile_quiet=false; break; } + if (5==paramlen && 0==memcmp(p,"stopq",5)) { do_stop_SampleFormat=true; break; } + if (2==paramlen && 0==memcmp(p,"tr",2)) { + APPEND_sf(Image::SF_Transparent); + APPEND_sf(Image::SF_Opaque); + APPEND_sf(Image::SF_Mask); + APPEND_sf(Image::SF_Transparent2); + APPEND_sf(Image::SF_Transparent4); + APPEND_sf(Image::SF_Transparent8); + } else { + Image::sf_t sf=Rule::Cache::parseSampleFormat(p, paramlen); + if (sf==Image::SF_max) goto inv_par; + APPEND_sf(sf); + } + } + break; + case OPT_Compression: + assert(param!=(char const*)NULLP); + if (0==GenBuffer::nocase_strcmp(param, "none")) APPEND_co(Rule::Cache::CO_None); + else if (0==GenBuffer::nocase_strcmp(param, "lzw")) APPEND_co(Rule::Cache::CO_LZW); + else if (0==GenBuffer::nocase_strcmp(param, "zip")) APPEND_co(Rule::Cache::CO_ZIP); + else if (0==GenBuffer::nocase_strcmp(param, "rle") + || 0==GenBuffer::nocase_strcmp(param, "packbits")) APPEND_co(Rule::Cache::CO_RLE); + else if (0==GenBuffer::nocase_strcmp(param, "dct")) { APPEND_co(Rule::Cache::CO_DCT); Hints << "\n/DCT<<>>"; } + else if (0==GenBuffer::nocase_strcmp(param, "jpg") + || 0==GenBuffer::nocase_strcmp(param, "jpeg")) { APPEND_co(Rule::Cache::CO_JAI); APPEND_co(Rule::Cache::CO_IJG); } + else if (0==GenBuffer::nocase_strcmp(param, "ijg")) APPEND_co(Rule::Cache::CO_IJG); + else if (0==GenBuffer::nocase_strcmp(param, "g4")) { APPEND_co(Rule::Cache::CO_Fax); Hints << "\n/K -1"; } + else if (0==GenBuffer::nocase_strcmp(param, "g3") + || 0==GenBuffer::nocase_strcmp(param, "fax") + || 0==GenBuffer::nocase_strcmp(param, "g3:1d"))APPEND_co(Rule::Cache::CO_Fax); + else if (0==GenBuffer::nocase_strcmp(param, "g3:2d")){ APPEND_co(Rule::Cache::CO_Fax); Hints << "\n/K -2"; } + else if (0==GenBuffer::nocase_strcmp(param, "jai")) APPEND_co(Rule::Cache::CO_JAI); + else if (GenBuffer::nocase_strbegins(param, "lzw:")) { + SimBuffer::Static s(param+4); + unsigned long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_LZW); Predictor=(Rule::Cache::pr_t)i; + } else if (GenBuffer::nocase_strbegins(param, "rle:")) { + SimBuffer::Static s(param+4); + unsigned long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_RLE); Hints << "\n/RecordSize " << i; + } else if (GenBuffer::nocase_strbegins(param, "packbits:")) { + SimBuffer::Static s(param+9); + unsigned long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_RLE); Hints << "\n/RecordSize " << i; + } else if (GenBuffer::nocase_strbegins(param, "fax:")) { + SimBuffer::Static s(param+4); + long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_Fax); Hints << "\n/K " << i; + } else if (GenBuffer::nocase_strbegins(param, "dct:")) { + APPEND_co(Rule::Cache::CO_DCT); Hints << "\n/DCT<< " << (param+4) << " >>"; + } else if (GenBuffer::nocase_strbegins(param, "ijg:")) { + SimBuffer::Static s(param+4); + unsigned long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_IJG); Hints << "\n/Quality " << i; + } else if (GenBuffer::nocase_strbegins(param, "jpeg:")) { + SimBuffer::Static s(param+5); + unsigned long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_JAI); + APPEND_co(Rule::Cache::CO_IJG); Hints << "\n/Quality " << i; + } else if (GenBuffer::nocase_strbegins(param, "zip:")) { + pend=param+4; while (*pend!='\0' && *pend!=':') pend++; + SimBuffer::Static s(param+4, pend-param-4); + unsigned long i; /* toInteger() is quickest on long */ + if (s.toInteger(i)) goto inv_par; + APPEND_co(Rule::Cache::CO_ZIP); Predictor=(Rule::Cache::pr_t)i; + if (*pend==':') { + pend++; while (*pend==':') pend++; + SimBuffer::Static s(pend); + if (s.toInteger(i)) goto inv_par; + // Error::sev(Error::FATAL) << "SUXX)" << s << ',' << i << '.' << (Error*)0; + APPEND_co(Rule::Cache::CO_ZIP); Hints << "\n/Effort " << i; + // Error::sev(Error::FATAL) << "SUXX(" << s << ',' << Hints << '.' << (Error*)0; + } + } else goto inv_par; + break; + default: assert(0); + } + } else { /* a selector or a normal argument */ + if (!(no_selector && no_option_term)) goto normal_label; + pend=p; while (*pend!='\0' && *pend!=':') pend++; + if (pend-p>=2 && *pend==':') { /* an ImageMagick-style FileFormat selector */ + if (GenBuffer::nocase_strbegins(p, "PSL2:") + || GenBuffer::nocase_strbegins(p, "EPS2:")) FileFormat=Rule::Cache::FF_PSL2; + else if (GenBuffer::nocase_strbegins(p, "EPS:")) FileFormat=Rule::Cache::FF_eps; + else if (GenBuffer::nocase_strbegins(p, "PS2:")) { FileFormat=Rule::Cache::FF_PSL2; if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_RotateOK; } + else if (GenBuffer::nocase_strbegins(p, "PS:")) { FileFormat=Rule::Cache::FF_eps; if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_RotateOK; } + else if (GenBuffer::nocase_strbegins(p, "PSL1:")) FileFormat=Rule::Cache::FF_PSL1; + else if (GenBuffer::nocase_strbegins(p, "PSLC:")) FileFormat=Rule::Cache::FF_PSLC; + else if (GenBuffer::nocase_strbegins(p, "PSL3:")) FileFormat=Rule::Cache::FF_PSL3; + else if (GenBuffer::nocase_strbegins(p, "PDF:") + || GenBuffer::nocase_strbegins(p, "PDF:")) FileFormat=Rule::Cache::FF_pdfb; + else if (GenBuffer::nocase_strbegins(p, "PDFX:")) FileFormat=Rule::Cache::FF_pdf; + else if (GenBuffer::nocase_strbegins(p, "PDFB1.0:")) FileFormat=Rule::Cache::FF_PDFB10; + else if (GenBuffer::nocase_strbegins(p, "PDFB1.2:")) FileFormat=Rule::Cache::FF_PDFB12; + else if (GenBuffer::nocase_strbegins(p, "PDF1.0:")) FileFormat=Rule::Cache::FF_PDF10; + else if (GenBuffer::nocase_strbegins(p, "PDF1.2:")) FileFormat=Rule::Cache::FF_PDF12; + else if (GenBuffer::nocase_strbegins(p, "GIF89a:") + || GenBuffer::nocase_strbegins(p, "GIF:")) FileFormat=Rule::Cache::FF_GIF89a; + /* vvv do_stop_SampleFormat BUGFIX at Thu Nov 21 23:44:20 CET 2002 */ + else if (GenBuffer::nocase_strbegins(p, "PNM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); APPEND_sf(Image::SF_Gray8); APPEND_sf(Image::SF_Rgb8); APPEND_sf(Image::SF_Transparent8); do_stop_SampleFormat=true; } + else if (GenBuffer::nocase_strbegins(p, "PBM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); do_stop_SampleFormat=true; } + else if (GenBuffer::nocase_strbegins(p, "PGM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray8); do_stop_SampleFormat=true; } + else if (GenBuffer::nocase_strbegins(p, "PPM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Rgb8); do_stop_SampleFormat=true; } + else if (GenBuffer::nocase_strbegins(p, "PAM:")) FileFormat=Rule::Cache::FF_PAM; + else if (GenBuffer::nocase_strbegins(p, "PIP:")) FileFormat=Rule::Cache::FF_PIP; + else if (GenBuffer::nocase_strbegins(p, "Empty:"))FileFormat=Rule::Cache::FF_Empty; + else if (GenBuffer::nocase_strbegins(p, "Meta:")) FileFormat=Rule::Cache::FF_Meta; + else if (GenBuffer::nocase_strbegins(p, "JPEG:") + || GenBuffer::nocase_strbegins(p, "JPG:")) FileFormat=Rule::Cache::FF_JPEG; + else if (GenBuffer::nocase_strbegins(p, "TIFF:") + || GenBuffer::nocase_strbegins(p, "TIF:")) FileFormat=Rule::Cache::FF_TIFF; + else if (GenBuffer::nocase_strbegins(p, "PNG:")) FileFormat=Rule::Cache::FF_PNG; + else if (GenBuffer::nocase_strbegins(p, "XPM:")) FileFormat=Rule::Cache::FF_XPM; + else if (GenBuffer::nocase_strbegins(p, "BMP:") + || GenBuffer::nocase_strbegins(p, "RLE:")) { FileFormat=Rule::Cache::FF_BMP; /*APPEND_co(Rule::Cache::CO_RLE);*/ } + else if (GenBuffer::nocase_strbegins(p, "XWD:")) FileFormat=Rule::Cache::FF_XWD; + else if (GenBuffer::nocase_strbegins(p, "X11:")) FileFormat=Rule::Cache::FF_X11; + else { + Error::sev(Error::ERROR_CONT) << "one_liner: invalid FileFormat selector: " << (SimBuffer::B().appendDumpC(SimBuffer::Static(p, pend-p), true)) << (Error*)0; + badp=true; + continue; + } + no_selector=false; + while (*pend==':') pend++; + if (*pend=='\0') continue; /* this arg is just a selector */ + /* normal argument is coming */ + p=pend; + } + normal_label: + if (InputFile==(char const*)NULLP) { + InputFile=p; /* set it even on error */ + /* vvv since Sat Apr 19 13:37:57 CEST 2003: + * Possibly unseekable STDIN is handled by Filter::UngetFILED + */ + #if 0 + if (p[0]=='-' && p[1]=='\0') { /* Filename: STDIN */ + Files::set_binary_mode(0, true); + if (0!=fseek(stdin, 0L, 0)) { unseekable: + #if 0 + Error::sev(Error::ERROR_CONT) << "one_liner: `-' (stdin) not allowed as InputFile (stdin unseekable)" << (Error*)0; + badp=true; continue; + #endif + FILE *f=Files::open_tmpnam(tmpnam); + if (!f) { Error::sev(Error::ERROR_CONT) << "one_liner: cannot open" << " temporary file for `-' (stdin)" << (Error*)0; badp=true; continue; } + tmpnam.term0(); + Files::tmpRemoveCleanup(InputFile=tmpnam()); + char *buf=new char[4096]; + unsigned got; + while ( + (0<(got=fread(buf, 1, sizeof(buf), stdin))) + && got==fwrite(buf, 1, sizeof(buf), f)) {} + delete [] buf; + if (ferror(f) || 0!=fclose(f) || ferror(stdin)) + { Error::sev(Error::ERROR_CONT) << "one_liner: cannot write" << " temporary file for `-' (stdin)" << (Error*)0; badp=true; continue; } + // fprintf(stderr, "if=(%s)\n", InputFile); + continue; + /* Imp: report `-' as filename on errors etc. */ + } + int c=MACRO_GETC(stdin); + if (0!=fseek(stdin, 0L, 0)) { if (c>=0) ungetc(c, stdin); goto unseekable; } /* active test */ + /* ungetc() is not necessary because of fseek() */ + } + #endif + } else if (OutputFile==(char const*)NULLP) { /* Filename: STDOUT */ + Files::set_binary_mode(1, true); + OutputFile=p; + if (FileFormat==Rule::Cache::FF_default) { /* OutputFile; determine FileFormat from extension */ + pend=p+strlen(p); + while (pend!=p && *pend!='.') pend--; + /* ^^^ Dat: extra care later for /a/b.c/d */ + if (pend!=p) { /* have extension */ + assert(*pend=='.'); pend++; + if (0==GenBuffer::nocase_strcmp(pend, "eps") + || 0==GenBuffer::nocase_strcmp(pend, "epsi") + || 0==GenBuffer::nocase_strcmp(pend, "epsf")) FileFormat=Rule::Cache::FF_eps; + else if (0==GenBuffer::nocase_strcmp(pend, "ps")) { FileFormat=Rule::Cache::FF_eps; if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_RotateOK; } + else if (0==GenBuffer::nocase_strcmp(pend, "pdf")) FileFormat=Rule::Cache::FF_pdfb; + else if (0==GenBuffer::nocase_strcmp(pend, "gif")) FileFormat=Rule::Cache::FF_GIF89a; + else if (0==GenBuffer::nocase_strcmp(pend, "pnm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); APPEND_sf(Image::SF_Gray8); APPEND_sf(Image::SF_Rgb8); APPEND_sf(Image::SF_Transparent8); do_stop_SampleFormat=true; } + else if (0==GenBuffer::nocase_strcmp(pend, "pbm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); do_stop_SampleFormat=true; } + else if (0==GenBuffer::nocase_strcmp(pend, "pgm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray8); do_stop_SampleFormat=true; } + else if (0==GenBuffer::nocase_strcmp(pend, "ppm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Rgb8); do_stop_SampleFormat=true; } + else if (0==GenBuffer::nocase_strcmp(pend, "pam")) FileFormat=Rule::Cache::FF_PAM; + else if (0==GenBuffer::nocase_strcmp(pend, "pip")) FileFormat=Rule::Cache::FF_PIP; + else if (0==GenBuffer::nocase_strcmp(pend, "empty"))FileFormat=Rule::Cache::FF_Empty; + else if (0==GenBuffer::nocase_strcmp(pend, "meta")) FileFormat=Rule::Cache::FF_Meta; + else if (0==GenBuffer::nocase_strcmp(pend, "jpeg") + || 0==GenBuffer::nocase_strcmp(pend, "jpg")) FileFormat=Rule::Cache::FF_JPEG; + else if (0==GenBuffer::nocase_strcmp(pend, "tiff") + || 0==GenBuffer::nocase_strcmp(pend, "tif")) FileFormat=Rule::Cache::FF_TIFF; + else if (0==GenBuffer::nocase_strcmp(pend, "png")) FileFormat=Rule::Cache::FF_PNG; + else if (0==GenBuffer::nocase_strcmp(pend, "xpm")) FileFormat=Rule::Cache::FF_XPM; + else if (0==GenBuffer::nocase_strcmp(pend, "bmp") + || 0==GenBuffer::nocase_strcmp(pend, "rle")) { FileFormat=Rule::Cache::FF_BMP; /*APPEND_co(Rule::Cache::CO_RLE);*/ } + else if (0==GenBuffer::nocase_strcmp(pend, "xwd")) FileFormat=Rule::Cache::FF_XWD; + // else if (0==GenBuffer::nocase_strcmp(pend, "x11")) FileFormat=Rule::Cache::FF_X11; + /* ^^^ .x11 extension is useless */ + } + } + } else { + Error::sev(Error::ERROR_CONT) << "one_liner: got too many (>2) filenames" << (Error*)0; + badp=true; + continue; + } + } /* IF */ + } /* NEXT */ + + if (InputFile==(char const*)NULLP) { + Error::sev(Error::ERROR_CONT) << "one_liner: InputFile unspecified" << (Error*)0; + badp=true; + } + if (OutputFile==(char const*)NULLP) { + Error::sev(Error::ERROR_CONT) << "one_liner: OutputFile unspecified" << (Error*)0; + badp=true; + } + if (FileFormat==Rule::Cache::FF_default) { + Error::sev(Error::ERROR_CONT) << "one_liner: FileFormat unspecified" << (Error*)0; + badp=true; + } + if (badp) return true; + + if (colen==0) { /* apply default if Compression is unspecified */ + // Error::sev(Error::FATAL) << "FileFormat=" << (unsigned)FileFormat << (Error*)0; + switch (FileFormat) { + case Rule::Cache::FF_TIFF: + case Rule::Cache::FF_eps: case Rule::Cache::FF_PSL2: + case Rule::Cache::FF_PDFB10: case Rule::Cache::FF_PDF10: + APPEND_co(Rule::Cache::CO_JAI); + #if HAVE_LZW + APPEND_co(Rule::Cache::CO_LZW); + #endif + APPEND_co(Rule::Cache::CO_RLE); + APPEND_co(Rule::Cache::CO_None); break; + case Rule::Cache::FF_BMP: + case Rule::Cache::FF_PSL1: case Rule::Cache::FF_PSLC: + /* assert(0); */ + APPEND_co(Rule::Cache::CO_RLE); + APPEND_co(Rule::Cache::CO_None); break; + case Rule::Cache::FF_PSL3: + case Rule::Cache::FF_pdfb: /* BUGFIX at Sun Sep 22 14:57:03 CEST 2002 */ + case Rule::Cache::FF_pdf: + case Rule::Cache::FF_PDFB12: case Rule::Cache::FF_PDF12: + APPEND_co(Rule::Cache::CO_JAI); + APPEND_co(Rule::Cache::CO_ZIP); + APPEND_co(Rule::Cache::CO_None); break; + case Rule::Cache::FF_GIF89a: + APPEND_co(Rule::Cache::CO_LZW); /* _not_ /LZWEncode filter */ + APPEND_co(Rule::Cache::CO_None); break; + case Rule::Cache::FF_JPEG: + APPEND_co(Rule::Cache::CO_JAI); + APPEND_co(Rule::Cache::CO_IJG); break; + case Rule::Cache::FF_PNG: + APPEND_co(Rule::Cache::CO_ZIP); break; + default: + APPEND_co(Rule::Cache::CO_None); break; + /* for others FileFormats: CO_None, but that is _not_ appended anyway */ + } + } + /* Dat: don't append /Compression/None if the user has specified `-c'. The + * user can append `-c none' manually. + */ + + if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_None; + if (TransferEncoding==Rule::Cache::TE_default) { /* apply default if TransferEncoding is unspecified */ + switch (FileFormat) { + case Rule::Cache::FF_PSL1: case Rule::Cache::FF_PSLC: + TransferEncoding=(Rule::Cache::te_t)(cox[Rule::Cache::CO_ZIP]!=0 || + cox[Rule::Cache::CO_LZW]!=0 ? 0+Rule::Cache::TE_A85 : 0+Rule::Cache::TE_Hex); break; + /* ^^^ Dat: /Hex is default for /RLE */ + case Rule::Cache::FF_eps: case Rule::Cache::FF_PSL2: + case Rule::Cache::FF_PSL3: + TransferEncoding=Rule::Cache::TE_A85; break; + #if 0 /* useless bugfix */ + case Rule::Cache::FF_XPM: /* BUGFIX at Thu Jul 11 21:53:56 CEST 2002 */ + // assert(0); + TransferEncoding=Rule::Cache::TE_ASCII; break; + #endif + default: + TransferEncoding=Rule::Cache::TE_Binary; break; + } + } + + unsigned coc=colen; + + /* Smart verify whether /Compression/JAI is requested. If so, and the input + * file is JPEG, then load it as-is. Our heuristic is that if the user + * allowed /Compression/JAI among others, and the input file is a baseline + * JPEG, then /Compression/JAI will be the best (and only) compression + * method. + */ + bool jaip=cox[Rule::Cache::CO_JAI]!=0; + if (jaip) { + if (ufd==NULLP) ufd=new Filter::UngetFILED(InputFile, stdin, + Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp); + /* vvv Imp: no error handling */ + if (1!=jai_is_baseline_jpeg(ufd)) { jaip=false; coc--; cox[Rule::Cache::CO_JAI]=0; } + ufd->seek(0); +#if 0 + assert(ufd->vi_getcc()==255); + assert(ufd->vi_getcc()==0xd8); + assert(ufd->vi_getcc()==255+0); + assert(0); +#endif + } + + if (jaip) { /* Dat: might have changed to false */ + APPEND_sf(Image::SF_Asis); + LoadHints << ",jpeg-asis,"; + cot[0]=Rule::Cache::CO_JAI; colen=1; /* disable all other compression */ + } else if (coc==1 && cox[Rule::Cache::CO_Fax]!=0) { + APPEND_sf(Image::SF_Opaque); + APPEND_sf(Image::SF_Transparent); + APPEND_sf(Image::SF_Gray1); + APPEND_sf(Image::SF_Indexed1); + APPEND_sf(Image::SF_Mask); + } else if (coc==1 && (cox[Rule::Cache::CO_DCT]!=0 || cox[Rule::Cache::CO_IJG]!=0)) { + APPEND_sf(Image::SF_Opaque); + APPEND_sf(Image::SF_Transparent); + APPEND_sf(Image::SF_Gray8); + APPEND_sf(Image::SF_Rgb8); + } else if (!do_stop_SampleFormat) { + /* JAI compression is automatically disabled since jaip==false */ + /* Guess SampleFormat automatically. The order is significant, so most + * warnings emitted by Image::SampledInfo::setSampleFormat() are avoided. + */ + APPEND_sf(Image::SF_Opaque); + APPEND_sf(Image::SF_Transparent); + APPEND_sf(Image::SF_Gray1); + APPEND_sf(Image::SF_Indexed1); + APPEND_sf(Image::SF_Mask); + APPEND_sf(Image::SF_Gray2); + APPEND_sf(Image::SF_Indexed2); + APPEND_sf(Image::SF_Rgb1); + APPEND_sf(Image::SF_Gray4); + APPEND_sf(Image::SF_Indexed4); + APPEND_sf(Image::SF_Rgb2); + APPEND_sf(Image::SF_Gray8); + APPEND_sf(Image::SF_Indexed8); + APPEND_sf(Image::SF_Rgb4); + APPEND_sf(Image::SF_Rgb8); + APPEND_sf(Image::SF_Transparent2); /* transparents are put last because of expensive color separation */ + APPEND_sf(Image::SF_Transparent4); + APPEND_sf(Image::SF_Transparent8); + } + + /* Append more Hints */ + if (Scale!=Rule::CacheHints::SC_None) Hints << "\n/Scale /" << protect_null(Rule::CacheHints::dumpScale(Scale)); + if ((char const*)NULLP!=ImageDPI) Hints << "\n/ImageDPI " << ImageDPI; + if ((char const*)NULLP!=LeftMargin) Hints << "\n/LeftMargin " << LeftMargin; + if ((char const*)NULLP!=RightMargin) Hints << "\n/RightMargin " << RightMargin; + if ((char const*)NULLP!=TopMargin) Hints << "\n/TopMargin " << TopMargin; + if ((char const*)NULLP!=BottomMargin) Hints << "\n/BottomMargin " << BottomMargin; + if ((char const*)NULLP!=LowerMargin) { + Hints << "\n/LowerMargin "; + if (negLowerMargin) { + if (LowerMargin[0]=='-') Hints << (LowerMargin+1); + else Hints << '-' << LowerMargin; + } else Hints << LowerMargin; + } + + /* Emit job file */ + jobss << "<<%sam2p in-memory job file, autogenerated by " << Error::banner0 + << "\n/InputFile "; + jobss.appendDumpPS(SimBuffer::Static(InputFile), true); + jobss << "\n/OutputFile "; + jobss.appendDumpPS(SimBuffer::Static(OutputFile), true); + jobss << "\n/LoadHints "; + jobss.appendDumpPS(LoadHints, true); + jobss << "\n/Profile[\n"; + + unsigned coi, sfi; + slen_t orc=0; + for (sfi=0;sfi<sflen;sfi++) { for (coi=0;coi<colen;coi++) { + // for (coi=0;coi<colen;coi++) for (sfi=0;sfi<sflen;sfi++) + if (cot[coi]==Rule::Cache::CO_JAI) { + if (!jaip || sft[sfi]!=Image::SF_Asis) continue; + } + jobss << "<<% OutputRule #" << orc++ + << "\n /FileFormat /" << protect_null(Rule::Cache::dumpFileFormat(FileFormat, cot[coi])) + << "\n /TransferEncoding /" << protect_null(Rule::Cache::dumpTransferEncoding(TransferEncoding)) + << "\n /SampleFormat /" << protect_null(Rule::Cache::dumpSampleFormat(sft[sfi])) + << "\n /Compression /" << protect_null(Rule::Cache::dumpCompression (cot[coi])) + << "\n /Predictor " << (cot[coi]==Rule::Cache::CO_LZW || cot[coi]==Rule::Cache::CO_ZIP ? Predictor : 1) + << "\n /Hints << " << Hints << " >>"; + // jobss << " /Transparent (\377\377\377)\n"; + if (Transparent!=NULL) { + jobss << "\n /Transparent "; + jobss.appendDumpPS(SimBuffer::Static(Transparent), true); + } + jobss << "\n>>\n"; + } + } + jobss << "]>>% __EOF__\n"; + + /* Common keys not emited here: + * /TmpRemove true /Templates pop + * /ColorTransform pop + * /EncoderColumns 0 /EncoderBPL 0 /EncoderRows 0 /EncoderColors 0 + * /PredictorColumns 0 /PredictorBPC 0 /PredictorColors 0 + * /Transparent null + * /WarningOK true + * /Comment pop + * /Title pop + * /Subject pop + * /Author pop + * /Creator pop + * /Producer pop + * /Created pop + * /Produced pop + */ + return false; + #undef APPEND_sf + #undef APPEND_co +} /* one_liner() */ + +static bool option_eq(char const *arg, char const*option) { + if (option[0]=='-') { option++; while (arg[0]=='-') arg++; } + return 0==GenBuffer::nocase_strcmp(arg, option); +} + +void init_sam2p_engine(char const*argv0) { + Error::long_argv0=argv0==(char const*)NULLP ? "sam2p" : argv0; + Error::argv0=Files::only_fext(Error::long_argv0); + Error::tmpargv0="_sam2p_"; + Error::banner0="sam2p v0.44"; +} + +/* --- */ + +void run_sam2p_engine(Files::FILEW &sout, Files::FILEW &serr, char const*const*argv1, bool helpp) { + Error::serr=&serr; + + /* --- Parse arguments, generate/read .job file */ + + MiniPS::VALUE job=MiniPS::Qundef; + Filter::FlatD bts(bts_ttt); + ufd=(Filter::UngetFILED*)NULLP; + if (!helpp && argv1[0]!=(char const*)NULLP && argv1[1]==(char const*)NULLP) { + /* A single argument: must be the name of the .job file */ + MiniPS::Parser p(argv1[0]); + p.addSpecRun("%bts", &bts); /* bts: Built-in TemplateS, the bts.ttt file in the sources */ + job=p.parse1(); + if (p.parse1(p.EOF_ALLOWED)!=MiniPS::Qundef) + Error::sev(Error::EERROR) << "job: the .job file should contain a single job" << (Error*)0; + /* ^^^ Dat: the result of the second p.parse1() doesn't get delete0(...)d */ + } else if (helpp || argv1[0]==(char const*)NULLP) { help: /* help message */ + sout << "Usage: " << Error::long_argv0 << " <filename.job>\n" << + " " << Error::long_argv0 << " [options] <in.img> [OutputFormat:] <out.img>\n" << + "Example: " << Error::long_argv0 << " test.gif EPS: test.eps\n"; + if (helpp) Error::cexit(0); + Error::sev(Error::EERROR) << "Incorrect command line" << (Error*)0; + } else { /* one_liner */ + SimBuffer::B jobss; + if (one_liner(jobss, argv1)) goto help; + if (do_DisplayJobFile) displayJob(sout, jobss); + Filter::FlatD jobr(jobss(), jobss.getLength()); + MiniPS::Parser p(&jobr); + p.addSpecRun("%bts", &bts); /* bts: Built-in TemplateS, the bts.ttt file in the sources */ + if (MiniPS::Qerror==(job=p.parse1(p.EOF_ILLEGAL, Error::ERROR_CONT)) + || p.parse1(p.EOF_ALLOWED)!=MiniPS::Qundef + ) { + displayJob(sout, jobss); + Error::sev(Error::EERROR) << "job: in-memory .job file corrupt (bug?" "?)" << (Error*)0; + /* ^^^ Dat: the result of the second p.parse1() doesn't get delete0(...)d */ + } + } + Files::doSignalCleanup(); + + /* --- Pre-parse .job file */ + + /* Dat: memory storage for the MiniPS objects in the .job file are + * allocated by p.parse1() and freed by MiniPS::delete0(job). Other + * structures throughout this program hold pointers to inside `job', + * but storage is not copied. + */ + + MiniPS::String *InputFile, *OutputFile, *LoadHints; + MiniPS::Array *Profile; + MiniPS::VALUE TmpRemove; + MiniPS::scanf_dict(job, /*show_warnings:*/true, + "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile, + "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile, + "LoadHints", MiniPS::T_STRING, MiniPS::Qnull, &LoadHints, + "Templates", MiniPS::T_DICT, MiniPS::Qnull, &Rule::Templates, + "Profile", MiniPS::T_ARRAY, MiniPS::Qundef, &Profile, + "TmpRemove", MiniPS::T_BOOLEAN,MiniPS::Qtrue, &TmpRemove, /* remove temporary files upon exit? */ + NULLP + ); + // MiniPS::dump(sout, job, 1); + Files::tmpRemove=TmpRemove==MiniPS::Qtrue; + if (MiniPS::Qnull==(MiniPS::VALUE)Rule::Templates) { + Filter::FlatD flatd("<< (%bts) run >>"); + MiniPS::Parser p(&flatd); + p.addSpecRun("%bts", &bts); + Rule::Templates=(MiniPS::Dict*)p.parse1(); + MiniPS::RDICT(job)->put("/Templates", (MiniPS::VALUE)Rule::Templates); /* avoid memory leak (job gets freed recursively) */ + } + + /* --- Preprocess Appliers */ + + Rule::OutputRule *rule_list=Rule::buildProfile((MiniPS::VALUE)Profile, buildProfile_quiet); + + /* --- Read/open other files */ + + if ((MiniPS::VALUE)LoadHints==MiniPS::Qnull) { /* smart default */ + if (!rule_list[0].isEOL() && rule_list[0].cache.Compression==Rule::Cache::CO_JAI) { + LoadHints=new MiniPS::String("jpeg-asis",4); /* used by in_jai.cpp and in_jpeg.cpp; even TIFF/JPEG */ + } else { + LoadHints=new MiniPS::String("",0); + } + MiniPS::RDICT(job)->put("/LoadHints", (MiniPS::VALUE)LoadHints); /* avoid memory leak (job gets freed recursively) */ + } + + /* Imp: eliminate memory leak from default LoadHints */ + /* vvv may raise tons of error messages */ + // InputFile->term0(); /* always term0() for MiniPS::String */ + if (ufd==NULLP) ufd=new Filter::UngetFILED(InputFile->begin_(), stdin, + Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp); + // fprintf(stderr, "ufd=%p\n", ufd); + Image::SampledInfo info(Image::load( + #if 0 + InputFile->begin_(), /* knows about stdin `-' */ + SimBuffer::B(",",1, LoadHints->begin_(),LoadHints->getLength(), ",",1 ).term0() /* three-way concatentation */ + #else + (Image::Loader::UFD*)ufd, + SimBuffer::B(",",1, LoadHints->begin_(),LoadHints->getLength(), ",",1 ).term0(), /* three-way concatentation */ + /*format:*/(char const*)NULLP + #endif + )); + Error::sev(Error::NOTICE) << "job: read InputFile: " << + FNQ2STDOK(InputFile->begin_(),InputFile->getLength()) << (Error*)0; + delete ufd; + // assert(0); + + bool overwrite=false; + if (0==strcmp(InputFile->begin_(), OutputFile->begin_()) && 0!=strcmp("-", InputFile->begin_())) { + // Error::sev(Error::WARNING) << "job: InputFile == OutputFile" << (Error*)0; + OutputFile->replace(OutputFile->begin_(), OutputFile->getLength(), ".s2new", 6); + overwrite=true; + } + FILE *of=stdout; + if (OutputFile->getLength()!=1 || OutputFile->begin_()[0]!='-') { + if ((of=fopen(OutputFile->begin_(), "wb"))==(FILE*)NULLP) { + Error::sev(Error::EERROR) << "job: cannot rewrite OutputFile: " << FNQ2STDOK(OutputFile->begin_(),OutputFile->getLength()) << (Error*)0; + } + /*if (!overwrite)*/ + Files::tmpRemoveCleanup(OutputFile->begin_(), &of); + } else Files::set_binary_mode(1, true); + + /* --- Find and apply best applier */ + + Files::FILEW wf(of); + Rule::applyProfile(wf, rule_list, &info); + + /* --- Done, flush files and clean up. */ + + fflush(of); + if (ferror(of)) { + /* FILE *backup=of; of=(FILE*)NULLP; fclose(backup); */ + Error::sev(Error::EERROR) << "job: error writing OutputFile: " << FNQ2STDOK(OutputFile->begin_(),OutputFile->getLength()) << (Error*)0; + } + if (of!=stdout) { /* Don't interfere with tmpRemoveCleanup() */ + FILE *backup=of; of=(FILE*)NULLP; fclose(backup); + } + if (overwrite) { + if (0!=rename(OutputFile->begin_(), InputFile->begin_())) { + // remove(OutputFile->begin_()); /* tmpRemoveCleanup() does it */ + Error::sev(Error::EERROR) << "job: error renaming, InputFile left intact" << (Error*)0; + } + } + Error::sev(Error::NOTICE) << "job: written OutputFile: " << FNQ2STDOK(OutputFile->begin_(),OutputFile->getLength()) << (Error*)0; + + /* Freeing memory may cause segfaults because of possibly + * bad code design :-(. Luckily we have already saved the output file. + */ + Rule::deleteProfile(rule_list); + MiniPS::delete0(job); /* frees OutputFile etc. */ + + if (Error::getTopPrinted()+0<=Error::NOTICE+0) fputs("Success.\n", stderr); + fflush(stdout); fflush(stderr); + Error::cexit(0); +} + +/** main: process entry point for the sam2p utility. */ +int main(int, char const*const* argv) { + Files::FILEW sout(stdout); + Files::FILEW serr(stderr); + /* --- Initialize */ + + bool helpp=argv[0]==(char const*)NULLP || argv[0]!=(char const*)NULLP && argv[1]!=(char const*)NULLP && argv[2]==(char const*)NULLP && ( + option_eq(argv[1], "-help") || + option_eq(argv[1], "-h") || + option_eq(argv[1], "-?") || + option_eq(argv[1], "/h") || + option_eq(argv[1], "/?")); + bool versionp=argv[0]!=(char const*)NULLP && argv[1]!=(char const*)NULLP && argv[2]==(char const*)NULLP && ( + option_eq(argv[1], "-version") || + option_eq(argv[1], "-v")); + bool quietp=argv[0]!=(char const*)NULLP && argv[1]!=(char const*)NULLP && + option_eq(argv[1], "-j:quiet"); + init_sam2p_engine(argv[0]); + + if (versionp) { + sout << "This is " << Error::banner0 << ".\n"; + return 0; + } + + /* Don't print diagnostics to stdout, becuse it might be the OutputFile */ + if (!quietp) { serr << "This is " << Error::banner0 << ".\n"; } + init_loader(); + if (!quietp) { serr << "Available Loaders:"; Image::printLoaders(serr); serr << ".\n"; } + init_applier(); + if (!quietp) { serr << "Available Appliers:"; Rule::printAppliers(serr); serr << ".\n"; } + + run_sam2p_engine(sout, serr, argv+(argv[0]!=(char const*)NULLP), helpp); + return 0; /*notreached*/ +} diff --git a/Build/source/utils/sam2p/snprintf.c b/Build/source/utils/sam2p/snprintf.c new file mode 100644 index 00000000000..d73b32bc0e0 --- /dev/null +++ b/Build/source/utils/sam2p/snprintf.c @@ -0,0 +1,993 @@ +/* + * snprintf.c + * ripped from rsync sources by pts@inf.bme.hu at Thu Mar 7 18:16:00 CET 2002 + * ripped from reTCP sources by pts@fazekas.hu at Tue Jun 11 14:47:01 CEST 2002 + * + * Why does this .c file rock? + * + * -- minimal dependencies: only <stdarg.h> is included + * -- minimal dependencies: not even -lm is required + * -- can print floating point numbers + * -- can print `long long' and `long double' + * -- C99 semantics (NULL arg for vsnprintf OK, always returns the length + * that would have been printed) + * -- provides all vsnprintf(), snprintf(), vasprintf(), asprintf() + */ + +/**** pts: sam2p-specific defines ****/ +#include "snprintf.h" +/* #include <stdarg.h> -- from snprintf.h */ +#define P_CONST PTS_const +#define NULL ((void*)0) +#ifdef __cplusplus +# define malloc ::operator new +#else +# include <stdlib.h> /* malloc() */ +#endif +#define size_t slen_t /* normally defined in <sys/types.h> */ +#define sizeret_t slen_t /* normally: int, unsigned */ +#undef HAVE_LONG_DOUBLE +#undef HAVE_LONG_LONG +#undef HAVE_C99_VSNPRINTF /* force local implementation */ +#undef HAVE_ASPRINTF +#undef HAVE_VASPRINTF +#undef TEST_SNPRINTF +#undef DEBUG_SNPRINTF +#define NEED_SPRINTF 1 +#define vsnprintf fixup_vsnprintf +#define snprintf fixup_snprintf +#define vasprintf fixup_vasprintf +#define asprintf fixup_asprintf +#define sprintf fixup_sprintf +typedef slen_t ret_t; + +/* vvv repeat prototypes in snprintf.h */ +EXTERN_C sizeret_t fixup_vsnprintf(char *str, size_t count, P_CONST char *fmt, va_list args); +EXTERN_C sizeret_t fixup_snprintf(char *str,size_t count,P_CONST char *fmt,...); +EXTERN_C sizeret_t fixup_vasprintf(char **ptr, P_CONST char *format, va_list ap); +EXTERN_C sizeret_t fixup_asprintf(char **ptr, P_CONST char *format, ...); +EXTERN_C sizeret_t fixup_sprintf(char *ptr, P_CONST char *format, ...); + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell (papowell@astart.com) + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions + */ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + **************************************************************/ + + +#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) +/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ +#include <stdio.h> + /* make the compiler happy with an empty file */ + void dummy_snprintf(void) {} +#else + +#if HAVE_LONG_DOUBLE && NEED_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#if HAVE_LONG_LONG && NEED_LONG_LONG +#define LLONG long long +#else +#define LLONG long +#endif + +static size_t dopr(char *buffer, size_t maxlen, P_CONST char *format, + va_list args); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 +#define DP_C_LLONG 4 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +/**** pts ****/ +#undef isdigit +#define isdigit(c) ((unsigned char)((c)-'0')<=(unsigned char)('9'-'0')) + +static size_t dopr(char *buffer, size_t maxlen, P_CONST char *format, va_list args) +{ + char ch; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + min = 10*min + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } else { + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } else if (ch == '*') { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, LLONG); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (long)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = (long)va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = (LLONG)va_arg (args, unsigned LLONG); + else + value = (long)va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, (char)va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (max == -1) { + /**** pts ****/ + for (max = 0; strvalue[max]; ++max); /* strlen */ + } + if (min > 0 && max >= 0 && min > max) max = min; + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = (char*)(va_arg (args, void *)); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } else if (cflags == DP_C_LONG) { + long int *num; + num = va_arg (args, long int *); + *num = (long int)currlen; + } else if (cflags == DP_C_LLONG) { + LLONG *num; + num = va_arg (args, LLONG *); + *num = (LLONG)currlen; + } else { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + + return currlen; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = "<NULL>"; + } + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, (char)signvalue); /* pacify VC6.0 */ + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + long l=0; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int index; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 16 digits past the decimal because of our + * conversion method + */ + if (max > 16) + max = 16; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + + /* Convert integer part */ + do { + temp = intpart; + my_modf(intpart*0.1, &intpart); + temp = temp*0.1; + index = (int) ((temp -intpart +0.05)* 10.0); + /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, index); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart; + my_modf(fracpart*0.1, &fracpart); + temp = temp*0.1; + index = (int) ((temp -fracpart +0.05)* 10.0); + /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, (char)signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, (char)signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} + +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + sizeret_t vsnprintf (char *str, size_t count, P_CONST char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + sizeret_t snprintf(char *str,size_t count,P_CONST char *fmt,...) +{ + size_t ret; + va_list ap; + + PTS_va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#endif + +#endif + +#ifndef HAVE_VASPRINTF + sizeret_t vasprintf(char **ptr, P_CONST char *format, va_list ap) +{ + size_t ret; + + ret = vsnprintf((char*)NULL, 0, format, ap); + if (ret+1 <= 1) return ret; /* pts: bit of old unsigned trick... */ + + if (NULLP==(*ptr = (char *)malloc(ret+1))) return (sizeret_t)-1; + ret = vsnprintf(*ptr, ret+1, format, ap); + + return ret; +} +#endif + + +#ifndef HAVE_ASPRINTF + sizeret_t asprintf(char **ptr, P_CONST char *format, ...) +{ + va_list ap; + sizeret_t ret; + + PTS_va_start(ap, format); + ret = vasprintf(ptr, format, ap); + va_end(ap); + + return ret; +} +#endif + +/**** pts ****/ +#ifdef NEED_SPRINTF + sizeret_t sprintf(char *ptr, P_CONST char *format, ...) +{ + va_list ap; + sizeret_t ret; + + PTS_va_start(ap, format); +#if 0 + ret = vsnprintf(NULL, 0, format, ap); + if (ret+1 <= 1) return ret; + ret = vsnprintf(ptr, ret, format, ap); +#else + ret = vsnprintf(ptr, (slen_t)-1, format, ap); +#endif + va_end(ap); + + return ret; +} +#endif + +#ifdef TEST_SNPRINTF + + sizeret_t sprintf(char *str,P_CONST char *fmt,...); + + int main (void) +{ + char buf1[1024]; + char buf2[1024]; + char *fp_fmt[] = { + "%1.1f", + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + "%.0f", + "%f", + "-16.16f", + NULL + }; + double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; + char *str_fmt[] = { + "10.5s", + "5.10s", + "10.1s", + "0.10s", + "10.0s", + "1.10s", + "%s", + "%.1s", + "%.10s", + "%10s", + NULL + }; + char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; + int x, y; + int fail = 0; + int num = 0; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); + int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + fp_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); + fail++; + } + num++; + } + } + + for (x = 0; int_fmt[x] ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); + int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + int_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); + fail++; + } + num++; + } + } + + for (x = 0; str_fmt[x] ; x++) { + for (y = 0; str_vals[y] != 0 ; y++) { + int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); + int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + sprintf (buf2, str_fmt[x], str_vals[y]); + if (strcmp (buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", + str_fmt[x], buf1, buf2); + fail++; + } + if (l1 != l2) { + printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); + fail++; + } + num++; + } + } + + printf ("%d tests failed out of %d.\n", fail, num); + + printf("seeing how many digits we support\n"); + { + double v0 = 0.12345678901234567890123456789012345678901; + for (x=0; x<100; x++) { + snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x)); + sprintf(buf2, "%1.1f", v0*pow(10, x)); + if (strcmp(buf1, buf2)) { + printf("we seem to support %d digits\n", x-1); + break; + } + } + } + + return 0; +} +#endif /* SNPRINTF_TEST */ diff --git a/Build/source/utils/sam2p/snprintf.h b/Build/source/utils/sam2p/snprintf.h new file mode 100644 index 00000000000..9e3e12a05b3 --- /dev/null +++ b/Build/source/utils/sam2p/snprintf.h @@ -0,0 +1,26 @@ +/* + * snprintf.h -- interface for our fixup vsnprintf() etc. functions + */ + +#ifndef SNPRINTF_H +#define SNPRINTF_H 1 + +#ifdef __GNUC__ +#pragma interface +#endif + +#include "config2.h" +#include <stdarg.h> /* ... */ +#ifndef __cplusplus +# define EXTERN_C extern +#else +# define EXTERN_C extern "C" +#endif + +EXTERN_C slen_t fixup_vsnprintf(char *str, slen_t count, PTS_const char *fmt, va_list args); +EXTERN_C slen_t fixup_snprintf(char *str,slen_t count,PTS_const char *fmt,...); +EXTERN_C slen_t fixup_vasprintf(char **ptr, PTS_const char *format, va_list ap); +EXTERN_C slen_t fixup_asprintf(char **ptr, PTS_const char *format, ...); +EXTERN_C slen_t fixup_sprintf(char *ptr, PTS_const char *format, ...); + +#endif /* snprintf.h */ diff --git a/Build/source/utils/sam2p/test_main.cpp b/Build/source/utils/sam2p/test_main.cpp new file mode 100644 index 00000000000..11dbc8ca276 --- /dev/null +++ b/Build/source/utils/sam2p/test_main.cpp @@ -0,0 +1,328 @@ +/* test_main.cpp + * by pts@fazekas.hu at Sun Feb 24 16:24:38 CET 2002 + */ + +#include "gensi.hpp" +#include "gensio.hpp" +#include "image.hpp" +#include "error.hpp" +#include "encoder.hpp" +#include "minips.hpp" +#include "mapping.hpp" + +#if OBJDEP +# warning PROVIDES: test_main +# warning REQUIRES: gensi.o +# warning REQUIRES: gensio.o +# warning REQUIRES: image.o +# warning REQUIRES: error.o +# warning REQUIRES: encoder.o +# warning REQUIRES: minips.o +# warning REQUIRES: mapping.o +#endif + +#include <stdio.h> +#include <stdlib.h> + +Files::FILEW sout(stdout); + +#if OBJDEP +# warning REQUIRES: in_xpm.o +# warning REQUIRES: in_lbm.o +# warning REQUIRES: in_gif.o +# warning REQUIRES: in_bmp.o +# warning REQUIRES: in_pnm.o +# warning REQUIRES: in_tga.o +#endif +extern Image::Loader in_xpm_loader; +extern Image::Loader in_lbm_loader; +extern Image::Loader in_gif_loader; +extern Image::Loader in_bmp_loader; +extern Image::Loader in_pnm_loader; +extern Image::Loader in_tga_loader; +static void init_loader() { + Image::register0(&in_tga_loader); /* checker not sure; install early */ + Image::register0(&in_xpm_loader); + Image::register0(&in_lbm_loader); + Image::register0(&in_gif_loader); + Image::register0(&in_bmp_loader); + Image::register0(&in_pnm_loader); + sout << "Available Loaders:"; + Image::printLoaders(sout); + sout << ".\n"; +} + +static void test_data() { + int i; + SimBuffer::Static world("World!"); + SimBuffer::Static("-1984").toInteger(i); + sout << "Hello," << ' ' << world << '\n' + << i << " luftballons.\n" + << -99U << " negatives.\n"; + sout << (world >= "FooBar") << '\n'; /// true + + { bool b=true; + SimBuffer::Linked sli; sli << (world>"Zorba"); + sli.toBool(b); + sout << b << '\n'; /// false + } + + SimBuffer::Linked li, lj("LJ"); + li << "answer is: " << 42L << '\n'; + li.prepend("The X", 4); + lj << "uff."; + lj=li; + lj.prepend("D.A said: ",10); + sout << li; /// The answer is 42 + sout << lj; /// D.A said: The answer is 42 + + { Buffer b="Hello!\n"; /* <= 8 chars */ + sout << b; + } + { Buffer b="Hello, World!\n"; /* > 8 chars */ + sout << b; + } + { sout << "Hello,"+Buffer(" World2!\n"); } + { Buffer b; sout << b.format("Hello,%cWorld %d%s", ' ', -42, "!\n"); } + { Buffer b; sout << b.format("123456789012\n"); } + { Buffer b; sout << b.format("1234567890123\n"); } + { Buffer b; sout << b.format("12345678901234\n"); } + { Buffer b; sout << b.format("123456789012345\n"); } + { Buffer b; sout << b.format("1234567890123456\n"); } + { Buffer b; sout << b.format("1234567890%u\n",123456789L); } + { Buffer b("Hello, World!\n"); memcpy(b.substr_grow(7,5,3), "Bar", 3); sout << b; } + { Buffer b("Hello, World!\n"); memcpy(b.substr_grow(7,5,6), "FooBar", 6); sout << b; } + { Buffer b("Hello, World!\n"); memcpy(b.substr_grow(7,15,8), "FooBar!\n", 8); sout << b; } + { Buffer b("Hello, World!"); memcpy(b.substr_grow(17,15,8), "HowDYD?\n", 8); sout << b; } + { Buffer b="bena"; Buffer c; c=(SimBuffer::Flat)b; } + sout << "Done.\n"; +} + +static void test_image() { + // Image::Sampled *img=Image::load("at-logo.xpm"); + // Image::Sampled *img=Image::load("pts.xpm"); + // Image::Sampled *img=Image::load("tex5.xpm"); + // Image::Sampled *img=Image::load("at-logo.lbm"); + // Image::Sampled *img=Image::load("ptest.lbm"); + // Image::Sampled *img=Image::load("chessbrd.lbm"); + // Image::Sampled *img=Image::load("at-logo.gif"); + // Image::Sampled *img=Image::load("ptsbanner.gif"); + // Image::Sampled *img=Image::load("ptsbanner.bmp"); + // Image::Sampled *img=Image::load("pts.bmp"); + // Image::Sampled *img=Image::load("t.cpp"); + // Image::Sampled *img=Image::load("ptsbanner.tga"); + // Image::Sampled *img=Image::load("mixing.xpm"); + Image::Sampled *img=Image::load("mixing0.xpm", SimBuffer::B()); + Files::FILEW f(fopen("t.ppm","wb")); /* Imp: autoclose... */ + + Image::Sampled *bak=img; + img=img->toIndexed(); if (bak!=img) delete bak; + assert(img->getTy()==img->TY_INDEXED); + sout << "ncol0=" << PTS_dynamic_cast(Image::Indexed*,img)->getNcols() << '\n'; + PTS_dynamic_cast(Image::Indexed*,img)->packPal(); + sout << "ncols=" << PTS_dynamic_cast(Image::Indexed*,img)->getNcols() << '\n'; + PTS_dynamic_cast(Image::Indexed*,img)->setBpc(0); + sout << "bpc=" << (int)img->getBpc() << '\n'; + // Files::tmpRemoveCleanup("t.dump"); + // Files::tmpRemoveCleanup("t.dump"); /* twice: OK */ + /* Files::tmpRemoveCleanup("/bin"); */ + Files::FILEW f2(fopen("t.dump","wb")); + PTS_dynamic_cast(Image::Indexed*,img)->dumpDebug(f2); + f2.close(); + + f << *img; + f.close(); + // delete img; +} + +static void test_encoder() { + // Files::tmpRemove=false; /* Imp: make this a command-line option */ + + { Filter::FILEE a("t.a85"); + PSEncoder *bp=PSEncoder::newASCII85Encode(a,78); + // FlateEncode c(b,5); + // LZWEncode c(b); + // PipeEncode c(b,"gs -dNODISPLAY -q -c '/i(%stdin)(r)file def/o(%stdout)(w)file/LZWEncode filter def/s 4096 string def{i s readstring exch o exch writestring not{exit}if}loop o closefile quit'"); + // GSEncode c(b,"xFlateEncode"); + // PSEncoder *cp=PSEncoder::newLZWEncode(*bp); + #if 1 + PSEncoder *cp=PSEncoder::newRunLengthEncode(*bp); + // delete [] cp; exit(0); /* Cannot free a GSEncode with multiple inheritance :-(( -> SegFault. virtual inheritance SUXX */ + // PSEncoder *cp=PSEncoder::newRunLengthEncode(a); + + // FILE *fin=fopen("t55","rb"); + FILE *fin=fopen("t.dump","rb"); + // FILE *fin=fopen("t.xin","rb"); + + static char mybuf[2033]; + unsigned long sum=0; + while (1) { + unsigned size=fread(mybuf, 1, sizeof(mybuf), fin); + if (size<1) { fprintf(stderr,"nosiz=%u\n",size); cp->vi_write(0,0); break; } + fprintf(stderr, "sending size=%u ofs=%lu\n", size, sum); + sum+=size; + cp->vi_write(mybuf, size); + } + assert(feof(fin)); + assert(!ferror(fin)); + fprintf(stderr, "ftell=%lu\n", ftell(fin)); + fclose(fin); + #else + img->to8(); + //img->setBpc(0); + //sout << "bpc2=" << (int)img->getBpc() << '\n'; + //Files::FILEW f2(fopen("t.dump2","wb")); + //PTS_dynamic_cast(Image::Indexed*,img)->dumpDebug(f2); + //f2.close(); + PSEncoder *cp=PSEncoder::newDCTEncode(*bp, img->getWd(), img->getHt(), 1); + cp->vi_write(img->getRowbeg(), img->getWd()*img->getHt()); + cp->vi_write(0,0); + #endif + + delete cp; + delete bp; + } +} + +static void test_predictor() { + /* by pts@fazekas.hu at Tue Mar 12 10:51:27 CET 2002 */ + Image::SampledInfo info(Image::load("mixing1.xpm", SimBuffer::B())); + info.setSampleFormat(Image::SF_Indexed2, false, false, 0x1000000L); + Image::Sampled *img=info.getImg(); + + /* Imp: test predictors with rgb-4 */ + unsigned char pred=11; + Files::FILEW f2(fopen("predictor_gen.eps","wb")); + f2 << "%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 " << img->getWd() << ' ' << img->getHt() << "\n%%EndComments\n" + << "% `*image' forces grayscale :-(\nsave 99 dict begin\n" + "{[ /Indexed /DeviceRGB " << ((img->getRowbeg()-img->getHeadp())/3-1) << " currentfile " << (img->getRowbeg()-img->getHeadp()) << " string readstring pop ] setcolorspace\n" + "/f currentfile <</Predictor " << (((unsigned)pred)%30) << " /Columns " << img->getWd() << " /Colors " << (unsigned)img->getCpp() << " /BitsPerComponent " << (unsigned)img->getBpc() << ">> /FlateDecode filter def\n" +// "/f currentfile /FlateDecode filter def\n" + << img->getWd() << ' ' << img->getHt() << ' ' << (unsigned)img->getBpc() + << "[1 0 0 -1 0 " << img->getHt() << "]f image\nf closefile}\n" + "%%BeginData:\nexec\n"; + f2.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); /* Write palette */ + PSEncoder *bp=PSEncoder::newFlateEncode(f2); + // Encoder *cp=Encoder::newTIFFPredictor2(*bp, img->getBpc(), img->getWd(), img->getCpp()); + // Encoder *cp=Encoder::newPNGPredictor11(*bp, img->getBpc(), img->getWd(), img->getCpp()); + Encoder *cp=PSEncoder::newPredictor(*bp, pred, img->getBpc(), img->getWd(), img->getCpp()); + cp->vi_write(img->getRowbeg(), img->getRlen()*img->getHt()); + cp->vi_write(0,0); + f2 << "\n%%EndData\nend\nrestore showpage\n%%Trailer\n%%EOF\n"; + f2.close(); + + /* destructor of info frees all memory */ +} + +static void test_dump() { + MiniPS::VALUE e=(MiniPS::VALUE)new MiniPS::Dict(); + MiniPS::VALUE d=(MiniPS::VALUE)new MiniPS::Dict(); + MiniPS::VALUE a=(MiniPS::VALUE)new MiniPS::Array(); + MiniPS::RARRAY(a)->push(MiniPS::Qinteger(3)); + MiniPS::VALUE b=(MiniPS::VALUE)new MiniPS::Array(); + MiniPS::RARRAY(b)->push(MiniPS::Qinteger(4)); + MiniPS::RARRAY(b)->push(MiniPS::Qinteger(5)); + MiniPS::RARRAY(b)->push(MiniPS::Qinteger(6)); + MiniPS::RARRAY(b)->push((MiniPS::VALUE)new MiniPS::String("Hel\téna \n\n\n\n\n\n\n",15)); +#if 0 + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/alma",5), MiniPS::Qinteger(42)); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/korte",6), MiniPS::Qnull); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/szilva",7), MiniPS::Qtrue); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/narancs",8), MiniPS::Qfalse); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc2",8), (MiniPS::VALUE)new MiniPS::Array()); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc3",8), a); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc4",8), b); + MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc5",8), e); +#else + MiniPS::RDICT(d)->push("/alma",5, MiniPS::Qinteger(42)); + MiniPS::RDICT(d)->push("/korte",6, MiniPS::Qnull); + MiniPS::RDICT(d)->push("/szilva",7, MiniPS::Qtrue); + MiniPS::RDICT(d)->push("/narancs",8, MiniPS::Qfalse); + MiniPS::RDICT(d)->push("/naranc2",8, (MiniPS::VALUE)new MiniPS::Array()); + MiniPS::RDICT(d)->push("/naranc3",8, a); + MiniPS::RDICT(d)->push("/naranc4",8, b); + MiniPS::RDICT(d)->push("/naranc5",8, e); +#endif + MiniPS::dump(sout, d); + MiniPS::delete0(d); +} + +static void test_tokenizer() { + Files::FILER sin(stdin); + MiniPS::Tokenizer pst(sin); + int i; + while ((i=pst.yylex())!=pst.EOFF) { + putchar(i); + putchar('\n'); + } +} + +static void test_parser() { + { MiniPS::Parser p("-"); /* STDIN */ + MiniPS::VALUE d=p.parse1(); + MiniPS::dump(sout, d); + MiniPS::delete0(d); + } +} + + +static void test_hash() { + {Mapping::H h(6); + h.set("alma",4,"apple"); + printf("alma=%s.\n", h.get("alma",4)); + printf("korte=%s.\n", h.get("korte",5)); + h.set("korte",5,"bear_"); + printf("alma=%s.\n", h.get("alma",4)); + printf("kort=%s.\n", h.get("korte",4)); + printf("korte=%s.\n", h.get("korte",5)); + } + + /* Dat: this might take a long time to run */ + /* Imp: srand, but that would make the test less predictable */ + char tmp[2]; + unsigned i, j; + Mapping::H h(sizeof(tmp)); + for (i=0; i<10000000; i++) { + // printf("%u\n", i); + for (j=0; j<sizeof(tmp); ) tmp[j++]=rand(); + if ((rand()&3)!=0) h.set(tmp, sizeof(tmp), tmp); + else h.deletee(tmp, sizeof(tmp)); + // putchar('.'); + // h.rehash(); + } + printf("OK!\n"); +} + +static void test_decoder() { + SimBuffer::B sb("Hello, World!\n"); + char const*p=sb(); + Filter::BufD bd(sb); + Filter::PipeD pd(bd, "tr A-Z a-z <%S"); + int i; + while ((i=pd.vi_getcc())>=0) { + putchar(':'); + putchar(i); + if (i!=(*p>='A' && *p<='Z'?*p+'a'-'A':*p)) abort(); + p++; + } + pd.vi_read(0,0); + /* Dat: the destructors do their jobs; freeing is not necessary */ +} + +int main(int argc, char **argv) { + (void)argc; + (void)argv; + + Error::argv0=argc>=1 ? argv[0] : "test_main"; /* Imp: update this */ + Error::tmpargv0="test_main"; + Files::tmpRemove=0; + init_loader(); + + test_data(); + + sout << "Success (test_main).\n"; + fflush(stdout); + Error::cexit(0); + assert(0); + return 0; /*notreached*/ +} diff --git a/Build/source/utils/sam2p/testfax_main.c b/Build/source/utils/sam2p/testfax_main.c new file mode 100644 index 00000000000..cb1adcec225 --- /dev/null +++ b/Build/source/utils/sam2p/testfax_main.c @@ -0,0 +1,176 @@ +/* + * testfax_main.c -- CCITTFax(En|De)code usage sample + * by pts@fazekas.hu at Sat Jul 6 20:03:35 CEST 2002 + * Sun Jul 7 22:25:55 CEST 2002 + * + * Note that this sample is incomplete since the parameters (such as /K) + * cannot be set from the command line. + */ + +#include "pts_fax.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> + +#ifdef __GNUC__ +#pragma implementation +#endif + +#if OBJDEP +# warning PROVIDES: testfax_main +#endif + +static void* gsfax_xalloc(unsigned n) { + void *ret; + if ((ret=malloc(n))==0) abort(); + return ret; +} +static void gsfax_free(void *ptr) { + free(ptr); +} +static void gsfax_memset(void *s, int c, unsigned n) { + /*return*/ memset(s,c,n); +} +static void gsfax_memcpy(void *dest, const void *src, unsigned n) { + /*return*/ memcpy(dest, src, n); +} + + + +#if 0 +CCITTFaxEncode: + +bool Uncompressed=false; +int K=0; +bool EndOfLine=false; +bool EncodedByteAlign=false; +int Columns=1728; +int Rows=0; // Decode only +bool EndOfBlock=true; +bool BlackIs1=false; +int DamagedRowsBeforeError=0; // Decode only +bool FirstBitLowOrder=false; // GS only +int DecodedByteAlign=1; // GS only +bool CloseSource; +bool CloseTarget; +#endif + +/* GS expected + * min_left=0 + * bits_left=32 + * + */ + +static void work(FILE *f, stream_template const*template_, stream_state *state) { + unsigned got, pog; + stream_cursor_read r; + stream_cursor_write w; + unsigned char rbuf[4096], wbuf[1000], *hard, *rlimit; + bool last; + + #if __CHECKER__ + memset(&r, 0, sizeof(r)); + memset(&w, 0, sizeof(w)); + #endif + + template_->init(state); + + r.ptr=rlimit=rbuf-1; + hard=rbuf+sizeof(rbuf)-1; + assert(hard-r.ptr>=(int)template_->min_in_size); + last=false; + + + while (1) { + assert(r.ptr==rbuf-1); + if (last==false) { + if (0==(got=fread(rlimit+1, 1, hard-rlimit, f))) last=true; + rlimit+=got; + } + /* if (r.ptr==rlimit) break; */ + w.ptr=wbuf-1; + w.limit=wbuf+sizeof(wbuf)-1; + assert(w.limit-w.ptr>=(int)template_->min_out_size); + r.limit=rlimit; + pog=template_->process(state, &r, &w, last); + fprintf(stderr, "pog=%d write=%d last=%d\n", pog, w.ptr-(wbuf-1), last); + if ((int)pog==PTSFAX_ERRC) { + fprintf(stderr, "syntax error!\n"); + abort(); + } + /* assert(last || r.ptr>=rbuf); */ + fwrite(wbuf, 1, w.ptr-(wbuf-1), stdout); + if (last && (pog==0 || (int)pog==PTSFAX_EOFC)) break; + if (r.ptr!=rbuf-1) { + fprintf(stderr, "limit=%d\n", rlimit-r.ptr); + memmove(rbuf, r.ptr+1, rlimit-r.ptr); + rlimit=rbuf-1+(rlimit-r.ptr); + r.ptr=rbuf-1; + } + } + + template_->release(state); +} + +int main(int argc, char **argv) { + FILE *f; + + (void)argc; + (void)argv; +/* +-* Define a limit on the Rows parameter, close to max_int. *- +#define cf_max_height 32000 + if (code >= 0 && + (state.K < -cf_max_height || state.K > cf_max_height || + state.Columns < 0 || state.Columns > cfe_max_width || + state.Rows < 0 || state.Rows > cf_max_height || + state.DamagedRowsBeforeError < 0 || + state.DamagedRowsBeforeError > cf_max_height || + state.DecodedByteAlign < 1 || state.DecodedByteAlign > 16 || + (state.DecodedByteAlign & (state.DecodedByteAlign - 1)) != 0) + ) +*/ + + f=stdin; + /* f=fopen("stdpre.x","rb"); */ + /* f=fopen("216","rb"); */ + assert(f!=0); + + if (0) { + #if USE_BUILTIN_FAXE + #if OBJDEP + # warning REQUIRES: pts_faxe + #endif + } else if (argc==2 && 0==strcmp(argv[1], "encode")) { + stream_CFE_state sCFEs; + sCFEs.memset_=gsfax_memset; + sCFEs.xalloc_=gsfax_xalloc; + sCFEs.free_=gsfax_free; + sCFEs.memcpy_=gsfax_memcpy; + s_CFE_template.set_defaults((stream_state*)&sCFEs); + /* sCFEs.K=-1; ... */ + work(f, (stream_template const*)&s_CFE_template, (stream_state*)&sCFEs); + #endif + #if USE_BUILTIN_FAXD + #if OBJDEP + # warning REQUIRES: pts_faxd + #endif + } else if (argc==2 && 0==strcmp(argv[1], "decode")) { + stream_CFD_state sCFDs; + sCFDs.memset_=gsfax_memset; + sCFDs.xalloc_=gsfax_xalloc; + sCFDs.free_=gsfax_free; + sCFDs.memcpy_=gsfax_memcpy; + s_CFD_template.set_defaults((stream_state*)&sCFDs); + /* sCFEs.K=-1; ... */ + work(f, (stream_template const*)&s_CFD_template, (stream_state*)&sCFDs); + #endif + } else { + fprintf(stderr, "Usage: %s encode|decode <INFILE >OUTFILE\n", argv[0]); + return 2; + } + fclose(f); + + return 0; +} diff --git a/Build/source/utils/sam2p/vcsam2p.cpp b/Build/source/utils/sam2p/vcsam2p.cpp new file mode 100644 index 00000000000..0e91cb21637 --- /dev/null +++ b/Build/source/utils/sam2p/vcsam2p.cpp @@ -0,0 +1,919 @@ +// vcsam2p.cpp : Defines the entry point for the application. +// + +#include "config2.h" +#include "image.hpp" +#include "error.hpp" +#include "main.hpp" /* init_loader(), init_applier() */ +#include "stdafx.h" +#include "resource.h" + +#define MAX_LOADSTRING 100 + +extern "C" int main(int argc, char**argv); + +#if 0 +extern "C" int getpid(void); + +//#include <windows.h> /* OSVERSIONINFO etc. */ +//#include <process.h> /* _getpid() */ +static unsigned long win32_os_id(void) { + static OSVERSIONINFO osver; + static DWORD w32_platform = (DWORD)-1; + if (w32_platform==-1 || osver.dwPlatformId != w32_platform) { + memset(&osver, 0, sizeof(OSVERSIONINFO)); + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osver); + w32_platform = osver.dwPlatformId; + } + return (unsigned long)w32_platform; +} +static inline bool IsWin95(void) { + return (win32_os_id() == VER_PLATFORM_WIN32_WINDOWS); +} + +// static int win32_getpid(void) { +int getpid(void) { + int pid; + pid = _getpid(); + /* Windows 9x appears to always reports a pid for threads and processes + * that has the high bit set. So we treat the lower 31 bits as the + * "real" PID for Perl's purposes. */ + if (IsWin95() && pid < 0) pid = -pid; + return pid; +} +#endif + + +// Global Variables: +HINSTANCE hInst; // current instance +// TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text + +// Foward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK dialogRun(HWND, UINT, WPARAM, LPARAM); + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE /*hPrevInstance*/, + LPSTR /*lpCmdLine*/, // !! + int nCmdShow) { + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + + // Initialize global strings + // LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_VCSAM2P, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_VCSAM2P); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return msg.wParam; +} + + + +// +// FUNCTION: MyRegisterClass() +// +// PURPOSE: Registers the window class. +// +// COMMENTS: +// +// This function and its usage is only necessary if you want this code +// to be compatible with Win32 systems prior to the 'RegisterClassEx' +// function that was added to Windows 95. It is important to call this function +// so that the application will get 'well formed' small icons associated +// with it. +// +ATOM MyRegisterClass(HINSTANCE hInstance) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = 0; /*CS_HREDRAW | CS_VREDRAW;*/ + wcex.lpfnWndProc = (WNDPROC)WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SAM2P32); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = (LPCSTR)IDC_VCSAM2P; + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SAM2P16); + return RegisterClassEx(&wcex); +} + +/* --- */ + +/** An image that can be rendered onto a window really quickly */ +class WinFastImage { + HDC hmemdc; + HBITMAP hbitmap; + slen_t wd, ht; + public: + // WinFastImage::WinFastImage(slen_t wd_, slen_t ht_); + WinFastImage(); + ~WinFastImage(); + /** Constructs a WinFastImage that can be drawn fast onto hdc. */ + WinFastImage(HDC hdc, HBITMAP hsrc); + /** Constructs a WinFastImage that can be drawn fast onto hwnd and all compatible HDCs. */ + WinFastImage(HWND hwnd, HBITMAP hsrc); + slen_t getWd() const { return wd; } + slen_t getHt() const { return ht; } + /* @param hdc dc on which fast rendering is desired + * @param hsrc source bitmap containing the data + */ + void set(HDC hdc, HBITMAP hsrc); + inline void drawTo(HDC hdc, slen_t dstX, slen_t dstY) const { + drawTo(hdc, dstX, dstY, wd, ht, 0, 0); + } + inline void drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY) const { + BitBlt(hdc,dstX,dstY,dstWd,dstHt,hmemdc,srcX,srcY,SRCCOPY); + } + // void drawTo(HDC hdc, slen_t dstX, slen_t dstY); + // void drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY); + /** MSDN says hbitmap must be a DDB, but it worked fine for me with a DIB */ + static void getSize(HBITMAP hbitmap, slen_t &wd, slen_t &ht); +}; + +void WinFastImage::getSize(HBITMAP hbitmap, slen_t &wd, slen_t &ht) { + /* It took me 1 hour to figure this out. Not documented anywhere! */ + BITMAPINFOHEADER h2; + h2.biSize=sizeof(h2); + h2.biBitCount=0; + // h2.biWidth=11; h2.biHeight=22; h2.biPlanes=1; + HDC hxdc=CreateDC("DISPLAY",NULL,NULL,NULL); + GetDIBits(hxdc, hbitmap, 0, 0, NULL, (BITMAPINFO*)&h2, DIB_RGB_COLORS); + wd=h2.biWidth; ht=h2.biHeight; + DeleteDC(hxdc); +} + +WinFastImage::WinFastImage(): hmemdc(NULL), hbitmap(NULL), wd(0), ht(0) {} +WinFastImage::WinFastImage(HDC hdc, HBITMAP hsrc): hmemdc(NULL), hbitmap(NULL) { set(hdc, hsrc); } +WinFastImage::WinFastImage(HWND hwnd, HBITMAP hsrc): hmemdc(NULL), hbitmap(NULL) { + HDC hdc=GetDC(hwnd); + set(hdc, hsrc); + ReleaseDC(hwnd, hdc); +} + +WinFastImage::~WinFastImage() { + if (hmemdc!=NULL) DeleteDC(hmemdc); + if (hbitmap!=NULL) DeleteObject(hbitmap); +} +void WinFastImage::set(HDC hdc, HBITMAP hsrc) { + if (hmemdc!=NULL) DeleteDC(hmemdc); + if (hbitmap!=NULL) DeleteObject(hbitmap); + /* Imp: error handling */ + getSize(hsrc, wd, ht); + hmemdc=CreateCompatibleDC(hdc); + hbitmap=CreateCompatibleBitmap(hdc, wd, ht); /* BUGFIX at 22:07 */ + DeleteObject(SelectObject(hmemdc, hbitmap)); + HDC hsrcdc=CreateCompatibleDC(hmemdc); + SelectObject(hsrcdc, hsrc); + BitBlt(hmemdc,0,0,wd,ht,hsrcdc,0,0,SRCCOPY); + DeleteDC(hsrcdc); +} + +/* --- */ + +class CopyableImage { public: + virtual slen_t vi_getWd() const =0; + virtual slen_t vi_getHt() const =0; + /** Copies an row in RGB PPM8 format from (this) to `to' */ + virtual void copyRGBRow(char *to, slen_t whichRow) const =0; +}; + +/** A rectangular RGB image, suitable for displaying in Win32 API */ +class WinImageRGB { + /** Number of bytes per scanline */ + slen_t rlen; + HBITMAP hbitmap; + /** data[0] is blue of upper left pixel, data[1] is green, data[2] is red. Rows + * are aligned to 4-byte boundary + */ + char *data; + BITMAPINFOHEADER header; + void init(slen_t wd_, slen_t ht_); + public: + inline WinImageRGB(slen_t wd_, slen_t ht_) { init(wd_, ht_); } + WinImageRGB(CopyableImage const&); + ~WinImageRGB(); + inline slen_t getWd() const { return header.biWidth; } + inline slen_t getHt() const { return -header.biHeight; } + virtual inline slen_t vi_getWd() const { return header.biWidth; } + virtual inline slen_t vi_getHt() const { return -header.biHeight; } + virtual void copyRGBRow(char *to, slen_t whichRow) const; + inline slen_t getRlen() const { return rlen; } + inline char* getData() const { return data; } + inline HBITMAP getHbitmap() const { return hbitmap; } + void drawTo(HDC hdc, slen_t dstX, slen_t dstY) const; + void drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY) const; + /** Copies image data from an other image in the PPM8 format: ppm8_data[0] + * is red, ppm8_data[1] is green, pp8_data[2] is blue. Rows are aligned to + * byte boundary. + */ + void fromPPM8(char const*ppm8_data); + void fill(char r, char g, char b); + void putPixel(slen_t x, slen_t y, char r, char g, char b); +}; + +void WinImageRGB::init(slen_t wd_, slen_t ht_) { + rlen=(wd_*3+3)&~3; + header.biSize=sizeof(header); + header.biWidth=wd_; + header.biHeight=0-ht_; + header.biPlanes=1; + header.biBitCount=24; + header.biCompression=BI_RGB; + header.biSizeImage=0; + header.biXPelsPerMeter=1000; /* returned by GetBitmapDimensionEx */ + header.biXPelsPerMeter=1000; + header.biClrUsed=0; + header.biClrImportant=0; + hbitmap=CreateDIBSection(NULL, (CONST BITMAPINFO*)&header, DIB_RGB_COLORS, (void**)&data, NULL, 0); +// slen_t xx=GetDeviceCaps(hbitmap, HORZRES); +} + +WinImageRGB::WinImageRGB(CopyableImage const& other) { + init(other.vi_getWd(), other.vi_getHt()); + char *buf=new char[rlen]; + slen_t pad=(header.biWidth)&3, x, y=0, ym=header.biHeight; + char *p=data; + char const *ppm8_data; + while (ym++!=0) { + other.copyRGBRow(buf, y++); ppm8_data=buf; + x=header.biWidth; + while (x--!=0) { p[2]=*ppm8_data++; p[1]=*ppm8_data++; p[0]=*ppm8_data++; p+=3; } + p+=pad; + } + delete buf; +} + +WinImageRGB::~WinImageRGB() { + DeleteObject(hbitmap); +} + +void WinImageRGB::copyRGBRow(char *to, slen_t whichRow) const { + if (whichRow<0U-header.biHeight) { + char *p=data+rlen*whichRow, *pend=p+rlen; + while (p!=pend) { to[0]=p[2]; to[1]=p[1]; to[2]=p[0]; p+=3; to+=3; } + } +} + +void WinImageRGB::drawTo(HDC hdc, slen_t dstX, slen_t dstY) const { + drawTo(hdc, dstX, dstY, header.biWidth, -header.biHeight, 0, 0); +} + +void WinImageRGB::drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY) const { + HDC hmemdc=CreateCompatibleDC(hdc); + DeleteObject(SelectObject(hmemdc, hbitmap)); + /* ^^^ set the bitmap for hmemdc that Rectangle (hmemdc etc.) will draw to, to (this) */ + + // slen_t xx=GetDeviceCaps(hdc, HORZRES); + // HPEN hpen=CreatePen(PS_SOLID, 0, RGB(255,0,0)); + // HANDLE hold=SelectObject(hmemdc, hpen); + // Rectangle(hmemdc,10,10,200,100); + // SelectObject(hmemdc, hold); + // DeleteObject(hpen); + + BitBlt(hdc,dstX,dstY,dstWd,dstHt,hmemdc,srcX,srcY,SRCCOPY); + DeleteDC(hmemdc); +} + +void WinImageRGB::fromPPM8(char const* ppm8_data) { + /* Dat: biWidth*3 is considered when calculating pad */ + slen_t pad=(header.biWidth)&3, x, y=header.biHeight; + char *p=data; + while (y++!=0) { + x=header.biWidth; + while (x--!=0) { p[2]=*ppm8_data++; p[1]=*ppm8_data++; p[0]=*ppm8_data++; p+=3; } + p+=pad; + } +} + +void WinImageRGB::fill(char r, char g, char b) { + /* Dat: biWidth*3 is considered when calculating pad */ + slen_t pad=(header.biWidth)&3, x, y=header.biHeight; + char *p=data; + while (y++!=0) { + x=header.biWidth; + while (x--!=0) { *p++=b; *p++=g; *p++=r; } + p+=pad; + } +} + +void WinImageRGB::putPixel(slen_t x, slen_t y, char r, char g, char b) { + if (x<(slen_t)header.biWidth && y<(slen_t)-header.biHeight) { + char *p=data+rlen*y+x; + p[0]=b; p[1]=g; p[2]=r; + } +} + +/* --- */ + + +/** Implements the CopyableImage interface for the sam2p Image::Sampled class. */ +class CopyableAdapter: public CopyableImage { + Image::Sampled const& img; + public: + inline CopyableAdapter(Image::Sampled const& img_): img(img_) {} + inline virtual slen_t vi_getHt() const { return img.getHt(); } + inline virtual slen_t vi_getWd() const { return img.getWd(); } + inline virtual void copyRGBRow(char *to, slen_t whichRow) const { img.copyRGBRow(to, whichRow); } +}; + +/* --- */ + +/** Size of previous open image */ +static slen_t wd_last=0, ht_last=0; +/** Size of window including decorations !! exclude decorations */ +static const unsigned wd_def=150, ht_def=90; +static WinImageRGB *imgr=NULL; +static WinFastImage *imgf=NULL; +static HWND hwnd_main; +/** Changed since last save? */ +static bool dirty=false; +/** File loaded. NULL if no/new; begins with "* " for a dirty file, ": " for a normal file */ +static char *filename2=NULL; +static bool first_paint_p=true; +// static char szHello[MAX_LOADSTRING]; +/* OK: not resizable: WM_... */ +/* Imp: clipboard copy-paste image */ +/* !! about editbox non-grey disabled */ +/* !! open rxvt_bug.bmp wrong window size */ +/* !! test larger image than screen */ +/* !! SetWindowText() LineScroll() */ +/* !! bongeszo ne irjon felul ablakot */ +/* !! transparent images */ +/* void CHistoryEdit::AppendString(CString str) + { SendMessage(EM_SETSEL,0xFFFFFFFF,-1); + SendMessage(EM_REPLACESEL,FALSE,(LPARAM)(LPCTSTR)str); + } +*/ + +// PURPOSE: Saves instance handle and creates main window +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { + init_sam2p_engine("vcsam2p"); + hInst = hInstance; // Store instance handle in our global variable + hwnd_main = CreateWindow(szWindowClass, Error::banner0, + WS_OVERLAPPED| WS_CAPTION| WS_SYSMENU| WS_MINIMIZEBOX| WS_BORDER| WS_THICKFRAME, + // WS_THICKFRAME: resizable (has sizing border) + // WS_MAXIMIZEBOX, WS_OVERLAPPEDWINDOW + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + if (!hwnd_main) return FALSE; + SetWindowPos(hwnd_main, NULL, 0, 0, wd_def, ht_def, SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + #if 0 + imgr=new WinImageRGB(226, 33); + if (imgr==NULL) return FALSE; + imgr->fill(0,0,(char)255); + HDC hdc_main=GetDC(hwnd_main); + imgf=new WinFastImage(hdc_main, imgr->getHbitmap()); + #endif + ShowWindow(hwnd_main, nCmdShow); + // ReleaseDC(hwnd_main, hdc_main); + UpdateWindow(hwnd_main); + // imgr->fill((char)255,0,0); + return TRUE; +} + +static void do_ask_save_as() { + // !! implement this +} + +/** @return true iff save successful */ +static bool do_save(bool ask_save_as) { + /* !! implement this */ + if (!dirty) return true; + if (filename2==NULL && ask_save_as) do_ask_save_as(); + if (filename2==NULL) return false; + if (IDYES==MessageBox(hwnd_main, "Saving... Success?", NULL, MB_YESNO)) { + dirty=false; + return true; + } + return false; +} + +static void do_save_as(void) { + char *old_filename2=filename2; + filename2=NULL; + do_ask_save_as(); + if (filename2!=NULL) { + if (do_save(false)) { delete [] old_filename2; return; } + delete [] filename2; + } + filename2=old_filename2; +} + +/** no@@return true iff should exit */ +static void do_exit(void) { + if (dirty) { + int i=MessageBox(hwnd_main, "Save changes before exit?", "Confirm exit", + MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_DEFBUTTON1); + if (i==IDCANCEL || (i==IDYES && !do_save(true))) return; + } + DestroyWindow(hwnd_main); +} + +static void getFrameSize(HWND hwnd, LONG &wd_ret, LONG &ht_ret) { + RECT wr; GetWindowRect(hwnd, &wr); + RECT cr; GetClientRect(hwnd, &cr); + wd_ret=(wr.right-wr.left)-(cr.right-cr.left); + ht_ret=(wr.bottom-wr.top)-(cr.bottom-cr.top); +} + +extern Image::Loader in_bmp_loader; + +struct SamArgs { + typedef void* (WINAPI*samfun_t)(SamArgs const*); +}; + +struct SamImageLoad: public SamArgs { + char const *filename; + SimBuffer::Flat *loadHints; +}; + +void* WINAPI do_image_load(SamImageLoad const* args) { + // Error::sev((Error::level_t) 2) << "a lma" << (Error*)0; + return Image::load(args->filename, *(args->loadHints)); +} + +void* do_samfun(SamArgs::samfun_t samfun, SamArgs const* args) { + SimBuffer::B log; + GenBuffer::Writable *old_serr=Error::serr; + Error::pushPolicy((Error::level_t)0, (Error::level_t)-99, (Error::level_t)-199, &log); // Error::serr=&log; + HANDLE hthread; + DWORD res=0, tid; + /* printf("Creating thread.\n"); */ + if (NULL==(hthread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)samfun, (void*)args, CREATE_SUSPENDED, &tid))) { + log << "CreateThread() failed\n"; + on_error: + Error::serr=old_serr; + log.term0(); + MessageBox(hwnd_main, log(), Error::banner0, 0); + return NULL; + } + /* printf("Resuming thread (h=0x%x tid=0x%x).\n", hthread, tid); */ + if (0==1+ResumeThread(hthread)) { + log << "ResumeThread() failed\n"; + on_thread_error: + TerminateThread(hthread, 0); + CloseHandle(hthread); + goto on_error; + } + /* printf("Waiting for thread.\n"); */ + if (WAIT_FAILED==WaitForSingleObject(hthread, INFINITE)) { log << "WaitForSingleObject() failed\n"; goto on_thread_error; } + if (0==GetExitCodeThread(hthread, &res)) { log << "GetExitCodeThread() failed\n"; goto on_thread_error; } + Error::popPolicy(); + CloseHandle(hthread); + Error::serr=old_serr; + // !! vvv 0 == NULL, exit(1), exit(2) is + if (res+0U<10U) { /* log << "return(NULL);\n1\n"; */ goto on_error; } + /* printf("Done, thread has returned=%u\n", res); */ + return (void*)res; +} + + +/** Load image from disk, update imgr and imgf + * @return true on success + */ +static bool do_open_image(char const* filename) { + // MessageBox(NULL, filename, "opening image", 0); + if (imgf!=NULL) { + if (imgr!=NULL) { delete imgr; imgr=NULL; } + delete imgf; imgf=NULL; + if (filename2!=NULL) filename2[0]='-'; /* mark file closed */ + } + + // !! free + // !! check for errors + // !! generalize + + SimBuffer::B loadHints; + #if 0 + Image::Loader::reader_t reader=in_bmp_loader.checker( + "BM\0\0\0\0" "\0\0\0\0" + "\0\0\0\0" "\0\0\0\0", "", opt); + FILE *f=fopen(filename, "rb"); + if (f==NULL) return false; + Image::Sampled *img=reader((Image::filep_t)f, loadHints); + fclose(f); + #endif + + init_loader(); + SamImageLoad args; + args.filename=filename; + args.loadHints=&loadHints; + Image::Sampled *img=(Image::Sampled*)do_samfun((SamArgs::samfun_t)do_image_load, &args); + if (img==NULL) return false; + // Image::load(filename, loadHints); + + imgr=new WinImageRGB(CopyableAdapter(*img)); + // Image::Sampled *imgrgb=img->toRGB(8); + // imgr=new WinImageRGB(img->getWd(), img->getHt()); + // imgr->fill(0,0,(char)255); + // imgr->fromPPM8(imgrgb->getRowbeg()); + assert(imgr!=NULL); /* `operator new' never returns NULL */ + // HDC hdc_main=GetDC(hwnd_main); + imgf=new WinFastImage(hwnd_main, imgr->getHbitmap()); + wd_last=imgf->getWd(); ht_last=imgf->getHt(); + // ReleaseDC(hwnd_main, hdc_main); + + slen_t len=strlen(filename); + if (filename2!=NULL) delete [] filename2; + strcpy(filename2=new char[len+3], ": "); + strcpy(filename2+2, filename); + SetWindowText(hwnd_main, filename2); + SetWindowLong(hwnd_main, GWL_STYLE, GetWindowLong(hwnd_main, GWL_STYLE)&~WS_THICKFRAME); + /* ^^^ The Win32 API way to say hwnd_main.setResizable(false); :-) */ + InvalidateRect(hwnd_main, NULL, TRUE); +#if 0 + LONG fr_wd, fr_ht; + getFrameSize(hwnd_main, fr_wd, fr_ht); + // !! handle minimum window size + SetWindowPos(hwnd_main, NULL, 0, 0, fr_wd+imgf->getWd(), fr_ht+imgf->getHt(), SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + GdiFlush(); + { /* Dat: strange, two iterations of getFrameSize + SetWindowPos is needed !! still bad */ + getFrameSize(hwnd_main, fr_wd, fr_ht); + SetWindowPos(hwnd_main, NULL, 0, 0, fr_wd+imgf->getWd(), fr_ht+imgf->getHt(), SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + } +BOOL CYourWndOrDialog::ResizeClient (int nWidth, int nHeight, BOOL bRedraw) { + RECT rcWnd; + GetClientRect (&rcWnd); + if(nWidth != -1) + rcWnd.right = nWidth; + if(nHeight != -1) + rcWnd.bottom = nHeight; + if(!::AdjustWindowRectEx(&rcWnd, + GetStyle(), + (!(GetStyle() & WS_CHILD) + && GetMenu() != NULL)), GetExStyle())) + return FALSE; + UINT uFlags = SWP_NOZORDER | SWP_NOMOVE; + if(!bRedraw) + uFlags |= SWP_NOREDRAW; + return SetWindowPos(NULL, + 0, 0, + rcWnd.right - rcWnd.left, + rcWnd.bottom - rcWnd.top, + uFlags); + } // CYourWndOrDialog::ResizeClient +#endif + RECT rt; + rt.left=0; rt.right=imgf->getWd(); + rt.top=0; rt.bottom=imgf->getHt(); + AdjustWindowRect(&rt, GetWindowLong(hwnd_main, GWL_STYLE), TRUE); // !! true + SetWindowPos(hwnd_main, NULL, 0,0, rt.right-rt.left, rt.bottom-rt.top, + SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + return true; +} + +static char const* loadImageFilter= + "all loadable images\0*.tiff;*.tif;*.jpeg;*.jpg;*.gif;*.png;*.pnm;*.pgm;*.ppm;*.xpm;*.lbm;*.tga;*.pcx;*.bmp\0" + "TIFF images\0*.tiff;*.tif\0" + "JPEG images\0*.jpeg;*.jpg\0" + "GIF images\0*.gif\0" + "PNG images\0*.png\0" + "PNM images\0*.pnm;*.pbm;*.pgm;*.ppm\0" + "PBM images\0*.pbm\0" + "PGM images\0*.pgm\0" + "PPM images\0*.ppm\0" + "XPM images\0*.xpm\0" + "IFF ILBM images\0*.lbm\0" + // "EPS figures\0*.eps\0" + // "PostScript documents\0*.ps\0" + // "PDF figures\0*.pdf\0" + // "XWD screen shots\0*.xwd\0" + // "PAM images\0*.pam\0" + // "Image meta information\0*.meta\0" + "Targa TGA images\0*.tga\0" + "PCX images\0*.pcx\0" + "Windows BMP bitmaps\0*.bmp\0" + "All files (*)\0*\0"; + +static char const* saveImageFilter= + "all saveable images\0*.tiff;*.tif;*.jpeg;*.jpg;*.gif;*.png" + ";*.pnm;*.pgm;*.ppm;*.xpm;*.lbm;*.tga;*.pcx;*.bmp;*.eps;*.ps;*.pdf;*.xwd;*.pam;*.meta\0" + "TIFF images\0*.tiff;*.tif\0" + "JPEG images\0*.jpeg;*.jpg\0" + "GIF images\0*.gif\0" + "PNG images\0*.png\0" + "PNM images\0*.pnm;*.pbm;*.pgm;*.ppm\0" + "PBM images\0*.pbm\0" + "PGM images\0*.pgm\0" + "PPM images\0*.ppm\0" + "XPM images\0*.xpm\0" + "IFF ILBM images\0*.lbm\0" + "EPS figures\0*.eps\0" + "PostScript documents\0*.ps\0" + "PDF figures\0*.pdf\0" + "XWD screen shots\0*.xwd\0" + // "PAM images\0*.pam\0" + "Image meta information\0*.meta\0" + "Targa TGA images\0*.tga\0" + "PCX images\0*.pcx\0" + "Windows BMP bitmaps\0*.bmp\0" + "All files (*)\0*\0"; + +static void do_open(void) { + OPENFILENAME ofn; + // ZeroMemory(&ofn, sizeof(ofn)); + char szFileName[MAX_PATH]; + szFileName[0]='\0'; + ofn.lpstrTitle="Open image with sam2p"; + ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW + ofn.hwndOwner = NULL; // hwnd; + ofn.lpstrFilter=loadImageFilter; + ofn.lpstrDefExt=NULL; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST /*|OFN_HIDEREADONLY*/ + |OFN_EXTENSIONDIFFERENT /*|OFN_NODEREFERENCELINKS*/ |OFN_READONLY; + ofn.lpstrDefExt = "txt"; + ofn.hInstance=NULL; + ofn.lpstrCustomFilter=NULL; // !! + ofn.nMaxCustFilter=0; // !! + ofn.nFilterIndex=0; // use Custom Filter + ofn.lpstrFileTitle=NULL; + ofn.nMaxFileTitle=0; + ofn.lpstrInitialDir=NULL; // use current directory + ofn.nFileOffset=0; + ofn.nFileExtension=0; + ofn.lCustData=NULL; + ofn.lpfnHook=NULL; + ofn.lpTemplateName=NULL; + // MessageBox(NULL, "hello", "world", 0); + if (GetOpenFileName(&ofn)) { + do_open_image(szFileName); + } +} + +static void do_new(void) { + if (imgf!=NULL) { + if (filename2!=NULL) filename2[0]='-'; + if (imgr!=NULL) { delete imgr; imgr=NULL; } + delete imgf; imgf=NULL; + #if 0 + if (filename2!=NULL) { delete [] filename2; filename2=NULL; } + SetWindowText(hwnd_main, Error::banner0); + #endif + SetWindowLong(hwnd_main, GWL_STYLE, GetWindowLong(hwnd_main, GWL_STYLE)|WS_THICKFRAME); + /* ^^^ The Win32 API way to say hwnd_main.setResizable(true); :-) */ + InvalidateRect(hwnd_main, NULL, TRUE); + // SetWindowPos(hwnd_main, NULL, 0, 0, wd_def, ht_def, SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER); + /* ^^^ Do _not_ revert to default window size */ + SendMessage(hwnd_main, WM_SIZE, 0, 0); /* calls updateBgText() */ + } else if (wd_last!=0 || ht_last!=0) { + if (filename2!=NULL) { delete [] filename2; filename2=NULL; } + SetWindowText(hwnd_main, Error::banner0); + wd_last=0; ht_last=0; + SendMessage(hwnd_main, WM_SIZE, 0, 0); /* calls updateBgText() */ + } +} + +/** Rectangle to draw the background text into */ +static RECT bgRect={0,0,0,0}; +static char bgText[128]; + +/** @param hwnd hwnd_main */ +static void updateBgText(HWND hwnd, slen_t x, slen_t y) { + RECT rt; + HDC hdc=GetDC(hwnd); + GetClientRect(hwnd, &rt); bgRect=rt; + sprintf(bgText, "%s\n%lu\327%lu", Error::banner0, x+0UL, y+0UL); + // DrawText(hdc, msg, strlen(msg), &rt, DT_CENTER|DT_VCENTER|DT_SINGLELINE); + int textht=DrawText(hdc, bgText, -1, &rt, DT_CENTER|DT_CALCRECT); + bgRect.top+=(bgRect.bottom-bgRect.top-textht)/2; + ReleaseDC(hwnd, hdc); +} + +//void CDECL AfxTrace(LPCTSTR lpszFormat, ...); + +/** Processes messages for the main window. */ +LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { + PAINTSTRUCT ps; + HDC hdc; + RECT *rp, rt; + int i; + switch (message) { + case WM_PAINT: + if (first_paint_p) { + first_paint_p=false; + // LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); + } + hdc = BeginPaint(hwnd, &ps); + if (imgf==NULL) { /* no image is loaded yet */ + DrawText(hdc, bgText, -1, &bgRect, DT_CENTER); + } else { + GetClientRect(hwnd, &rt); + bool xbad=0U+rt.right-rt.left>imgf->getWd(), ybad=0U+rt.bottom-rt.top>imgf->getHt(); + if (ps.fErase && (xbad || ybad)) { + /* Erase only region not part of the image; to avoid flicker */ + // HDC hdc=GetDC(hwnd); + // HBRUSH hbrush=(HBRUSH)GetClassLong(hwnd, GCL_HBRBACKGROUND); + HBRUSH hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH); + HGDIOBJ holdbrush=SelectObject(hdc, hbrush); + HPEN hpen=(HPEN)GetStockObject(WHITE_PEN); /* always used */ + HGDIOBJ holdpen=SelectObject(hdc, hpen); + Rectangle(hdc, imgf->getWd(), rt.top, rt.right, rt.bottom); + Rectangle(hdc, rt.left, imgf->getHt(), imgf->getWd(), rt.bottom); + SelectObject(hdc, holdpen); + SelectObject(hdc, holdbrush); + // ReleaseDC(hwnd, hdc); + } + // if (imgf==NULL) imgf=new WinFastImage(hdc, imgr->getHbitmap()); + // rt.right-=rt.left; rt.bottom-=rt.top; + imgf->drawTo(hdc, rt.left, rt.top); + if (xbad) { /* show the borders of the image inside the window */ + MoveToEx(hdc, rt.left+imgf->getWd(), rt.top, NULL); + LineTo(hdc, rt.left+imgf->getWd(), rt.bottom-1); + LineTo(hdc, rt.right-1, rt.top); + } + if (ybad) { /* show the borders of the image inside the window */ + MoveToEx(hdc, rt.left, imgf->getHt()+rt.top, NULL); + LineTo(hdc, rt.left+imgf->getWd(), rt.bottom-1); + LineTo(hdc, rt.left, imgf->getHt()+rt.top); + } + } + EndPaint(hwnd, &ps); + return 0; + case WM_COMMAND: + /* int wmId=LOWORD(wParam), wmEvent=HIWORD(wParam); */ + switch (LOWORD(wParam)) { + case IDM_SAVE: + do_save(true); return 0; + case IDM_SAVE_AS: + { + char *argv[]={"(progname)","pts.ppm","pts.ps",NULL}; + int argc=3; + char result[30]; + int ret=main(argc, argv); + // int ret=getpid(); + sprintf(result, "main run: %d", ret); + MessageBox(hwnd, result, NULL, 0); /* unreached !! */ + } + do_save_as(); return 0; + case IDM_WEBSITE: + /* Dat: it seems to be impossible to force the browser to open the URL + * in a new window (instead of overwriting the current window). There + * are OLE/DDE solutions for Netscape4 and Internet Explorer, but no + * generic solution. + */ + ShellExecute(hwnd, "open", "http://www.inf.bme.hu/~pts/sam2p/", 0, 0, SW_SHOWDEFAULT); + return 0; + case IDM_ABOUT: + DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hwnd, (DLGPROC)About); + return 0; + case IDM_OPEN: + do_open(); return 0; + case IDM_NEW: + do_new(); return 0; + case IDM_PARAMETERS: + DialogBox(hInst, (LPCTSTR)IDD_RUN, hwnd, (DLGPROC)dialogRun); + return 0; + case IDM_EXIT: + do_exit(); return 0; + default: + MessageBox(hwnd,"Unimplemented.", Error::banner0, 0); + return 0; + } + case WM_SIZING: /* possibly override resize requests */ + if (imgf!=NULL) { /* resize the window to perfectly fit the image */ + rp=(RECT*)lParam; + // RECT wr; GetWindowRect(hwnd, &wr); + // RECT cr; GetClientRect(hwnd, &cr); + // rp->right=rp->left+imgf->getWd()+(wr.right-wr.left)-(cr.right-cr.left); + // rp->bottom=rp->top+imgf->getHt()+(wr.bottom-wr.top)-(cr.bottom-cr.top); + getFrameSize(hwnd, rp->right, rp->bottom); + rp->right+=rp->left+imgf->getWd(); + rp->bottom+=rp->top+imgf->getHt(); + return TRUE; + } else return FALSE; + case WM_ERASEBKGND: + if (imgf!=NULL) return FALSE; + break; + /* Dat: upon window resize, WM_SIZING, WM_SIZE, WM_ERASEBKGND and WM_PAINT is sent in this order */ + case WM_SIZE: /* we have been resized; let's invalidate the window contents */ + GetClientRect(hwnd, &rt); + if (wd_last==0 && ht_last==0) updateBgText(hwnd, rt.right-rt.left, rt.bottom-rt.top); + else updateBgText(hwnd, wd_last, ht_last); + InvalidateRect(hwnd, NULL, TRUE); + return 0; + case WM_CLOSE: /* user has clicked button X on the title bar; confirm exit first */ + do_exit(); return 0; + case WM_DESTROY: /* exit already confirmed */ + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + +#if 0 +char *s="1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"; +#endif + +// Mesage handler for about box. +LRESULT CALLBACK About(HWND hdlg, UINT message, WPARAM wParam, LPARAM /*lParam*/) { + switch (message) { + case WM_INITDIALOG: + { HFONT hfont=CreateFont(10, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0, /*"System"*/ "MS Sans Serif"); + SendMessage(GetDlgItem(hdlg, IDC_PRODUCT), WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); + // !! DeleteObject + SetDlgItemText(hdlg, IDC_PRODUCT, Error::banner0); + SetDlgItemText(hdlg, IDC_INFO, +"This is the Win32 GUI of sam2p.\r\n" +" sam2p is a UNIX command line utility written in ANSI C++ that converts many " +"raster (bitmap) image formats into Adobe PostScript or PDF files and several " +"other formats. The images " +"are not vectorized. sam2p gives full control to the user to specify " +"standards-compliance, compression, and bit depths. In some cases sam2p can " +"compress an image 100 times smaller than the PostScript output of many other " +"common image converters. sam2p provides ZIP, RLE and LZW (de)compression " +"filters even on Level1 devices.\r\n"); + } + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + { CHOOSEFONT cf; + ZeroMemory(&cf, sizeof(cf)); + cf.lStructSize=sizeof(cf); + cf.rgbColors=0; /* black */ + cf.Flags=CF_EFFECTS|CF_FORCEFONTEXIST|CF_NOSIMULATIONS|CF_NOVERTFONTS|CF_SCREENFONTS; + cf.hwndOwner=NULL; + cf.hDC=NULL; + ChooseFont(&cf); + } + EndDialog(hdlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} + +LRESULT CALLBACK dialogRun(HWND hdlg, UINT message, WPARAM wParam, LPARAM /*lParam*/) { + switch (message) { + case WM_INITDIALOG: + { HWND hwnd=GetDlgItem(hdlg, IDC_ELOG); + HFONT hfont=CreateFont(10, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0,"Fixedsys"); + SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0)); + // DeleteObject(hfont); /* Imp: where to do DeleteObject()? */ + /* PostMessage doesn't work, either */ + unsigned i; + char buf[222]; + for (i=0;i<100;i++) { + SendMessage(hwnd,EM_SETSEL,0U-1,0U-1); + sprintf(buf, "%d Hello, World! 0123456789 1111111111 222222222 333333333\r\n", i); + SendMessage(hwnd,EM_REPLACESEL,FALSE,(LPARAM)(LPCTSTR)buf); + } + SendMessage(hwnd,EM_SCROLLCARET,0,0); + InvalidateRect(hwnd,NULL,FALSE); /* no effect */ + // !! EM_REPLACESEL doesn't make the end of the edit box text + } + return TRUE; + #if 0 + case WM_ACTIVATE: + { // HWND hwnd=GetDlgItem(hdlg, IDC_ELOG); + // MessageBox(NULL,"Hello","",0); + //SendMessage(hwnd,EM_SETSEL,-1,2000); + //SendMessage(hwnd,EM_SCROLLCARET,0,0); + //InvalidateRect(hwnd,NULL,FALSE); /* no effect */ + } + return TRUE; + #endif + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) { + HWND hwnd=GetDlgItem(hdlg, IDC_ELOG); + SendMessage(hwnd,EM_SETSEL,0xFFFFFFFF,-1); + SendMessage(hwnd,EM_REPLACESEL,FALSE,(LPARAM)(LPCTSTR)"Append."); + break; + } + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hdlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/Build/source/utils/sam2p/vcsam2p.dsp b/Build/source/utils/sam2p/vcsam2p.dsp new file mode 100644 index 00000000000..98e409d1256 --- /dev/null +++ b/Build/source/utils/sam2p/vcsam2p.dsp @@ -0,0 +1,300 @@ +# Microsoft Developer Studio Project File - Name="vcsam2p" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=vcsam2p - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "vcsam2p.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "vcsam2p.mak" CFG="vcsam2p - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "vcsam2p - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "vcsam2p - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "vcsam2p - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "vcsam2p - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W4 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "vcsam2p - Win32 Release" +# Name "vcsam2p - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\appliers.cpp +# End Source File +# Begin Source File + +SOURCE=.\crc32.c +# End Source File +# Begin Source File + +SOURCE=.\encoder.cpp + +!IF "$(CFG)" == "vcsam2p - Win32 Release" + +!ELSEIF "$(CFG)" == "vcsam2p - Win32 Debug" + +# ADD CPP /W4 /GX- /Od /YX"config2.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\error.cpp +# End Source File +# Begin Source File + +SOURCE=.\gensi.cpp +# End Source File +# Begin Source File + +SOURCE=.\gensio.cpp +# End Source File +# Begin Source File + +SOURCE=.\image.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_gif.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_jai.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_jpeg.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_lbm.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_pcx.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_png.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_pnm.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_tga.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_tiff.cpp +# End Source File +# Begin Source File + +SOURCE=.\in_xpm.cpp +# End Source File +# Begin Source File + +SOURCE=.\mapping.cpp +# End Source File +# Begin Source File + +SOURCE=.\minips.cpp +# End Source File +# Begin Source File + +SOURCE=.\out_gif.cpp +# End Source File +# Begin Source File + +SOURCE=.\pts_defl.c +# End Source File +# Begin Source File + +SOURCE=.\pts_fax.c +# End Source File +# Begin Source File + +SOURCE=.\pts_lzw.c +# End Source File +# Begin Source File + +SOURCE=.\rule.cpp +# End Source File +# Begin Source File + +SOURCE=.\sam2p_main.cpp +# End Source File +# Begin Source File + +SOURCE=.\snprintf.c +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\vcsam2p.cpp +# End Source File +# Begin Source File + +SOURCE=.\vcsam2p.rc +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\at_bitmap.h +# End Source File +# Begin Source File + +SOURCE=.\cgif.h +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\config2.h +# End Source File +# Begin Source File + +SOURCE=.\crc32.h +# End Source File +# Begin Source File + +SOURCE=.\pts_defl.h +# End Source File +# Begin Source File + +SOURCE=.\pts_fax.h +# End Source File +# Begin Source File + +SOURCE=.\pts_lzw.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\snprintf.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\tmp.h +# End Source File +# Begin Source File + +SOURCE=.\vcsam2p.h +# End Source File +# Begin Source File + +SOURCE=.\xpmc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\small.ico +# End Source File +# Begin Source File + +SOURCE=.\vcsam2p.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/Build/source/utils/sam2p/vcsam2p.h b/Build/source/utils/sam2p/vcsam2p.h new file mode 100644 index 00000000000..e1c29032e6e --- /dev/null +++ b/Build/source/utils/sam2p/vcsam2p.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_VCSAM2P_H__26C24785_06B6_11D7_846E_0004E2009304__INCLUDED_) +#define AFX_VCSAM2P_H__26C24785_06B6_11D7_846E_0004E2009304__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_VCSAM2P_H__26C24785_06B6_11D7_846E_0004E2009304__INCLUDED_) diff --git a/Build/source/utils/sam2p/vcsam2p.ico b/Build/source/utils/sam2p/vcsam2p.ico Binary files differnew file mode 100644 index 00000000000..386883523bc --- /dev/null +++ b/Build/source/utils/sam2p/vcsam2p.ico diff --git a/Build/source/utils/sam2p/vcsam2p.rc b/Build/source/utils/sam2p/vcsam2p.rc new file mode 100644 index 00000000000..2cfcca387ad --- /dev/null +++ b/Build/source/utils/sam2p/vcsam2p.rc @@ -0,0 +1,162 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SAM2P16 ICON DISCARDABLE "sam2p16.ico" +IDI_SAM2P32 ICON DISCARDABLE "sam2p32.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_VCSAM2P MENU DISCARDABLE +BEGIN + POPUP "&Image" + BEGIN + MENUITEM "&New/Close", IDM_NEW + MENUITEM "&Open...", IDM_OPEN + MENUITEM "&Save", IDM_SAVE + MENUITEM "Save &as...", IDM_SAVE_AS + MENUITEM "&Parameters...", IDM_PARAMETERS + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About sam2p...", IDM_ABOUT + MENUITEM "&Web site", IDM_WEBSITE + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_VCSAM2P ACCELERATORS MOVEABLE PURE +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 142, 76 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_SAM2P32,IDC_MYICON,2,3,16,16 + LTEXT "vcsam2p Version 1.0",IDC_PRODUCT,19,5,90,8,SS_NOPREFIX + LTEXT "Copyright (C) 2002 pts",IDC_STATIC,1,20,139,52 + DEFPUSHBUTTON "OK",IDOK,110,4,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE "vcsam2p" + IDS_HELLO "Hello World!" + IDC_VCSAM2P "VCSAM2P" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Build/source/utils/sam2p/xpmc.h b/Build/source/utils/sam2p/xpmc.h new file mode 100644 index 00000000000..1960e489459 --- /dev/null +++ b/Build/source/utils/sam2p/xpmc.h @@ -0,0 +1,4 @@ +#define xpmColors_mul 95 +#define xpmColors_mod 1109 +unsigned short xpmColors_ofs[]={0,0,0,1,0,0,0,0,0,0,0,0,15,0,43,0,0,0,0,0,0,0,65,0,0,0,84,0,0,0,0,0,96,0,0,0,0,0,0,0,113,0,0,0,0,0,0,0,0,0,0,129,140,151,162,173,199,210,221,232,243,0,254,0,0,0,0,268,0,0,0,0,282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,296,0,310,0,0,0,0,0,0,0,0,0,0,0,0,0,329,0,0,0,0,0,0,0,0,343,352,0,0,0,0,0,0,368,0,0,0,0,0,0,0,0,0,0,0,0,0,382,0,0,0,0,0,0,0,0,0,0,0,391,402,413,424,435,446,457,468,479,490,0,0,0,0,0,0,0,0,0,501,0,516,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,525,0,0,0,0,0,0,540,0,557,0,0,0,568,0,0,576,0,0,0,0,0,0,0,0,0,0,594,0,0,0,0,0,607,0,0,0,0,0,0,0,0,0,0,0,0,0,0,623,634,645,656,667,678,689,700,711,722,0,0,733,0,0,0,743,0,0,0,0,0,0,0,0,0,0,0,0,763,0,0,0,0,771,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,785,0,0,0,794,0,0,0,0,0,0,0,0,806,816,0,0,0,0,833,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,842,853,864,875,886,897,908,919,930,941,0,952,0,0,0,0,0,966,0,0,0,0,0,0,0,0,0,980,0,0,0,0,0,0,989,0,0,1011,0,1026,0,0,0,0,0,0,0,0,0,1041,1056,0,0,1066,0,0,0,0,0,1075,1090,0,1106,0,1120,0,0,0,1134,0,0,0,0,0,1148,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1167,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,1180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1199,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1214,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1228,0,0,0,0,0,0,1241,1255,0,0,0,0,1265,1279,0,0,0,0,0,0,0,0,0,1293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1312,0,0,0,0,0,0,0,0,0,0,0,0,0,1324,0,1333,0,1345,0,0,0,0,0,0,0,0,0,0,1359,0,0,0,1370,0,0,0,0,1387,1405,0,0,1418,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,1436,0,0,0,1450,0,0,0,1461,0,0,0,0,1482,0,1497,0,0,0,0,0,0,0,1511,0,0,0,0,0,0,0,0,0,1527,0,0,0,0,0,0,0,0,0,1541,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1560,1571,1582,1593,1604,1615,1626,1637,1648,1659,0,0,0,0,0,0,0,0,0,0,0,1670,0,0,1685,0,0,0,0,0,1699,0,0,0,0,0,0,0,1710,0,0,0,0,0,0,1721,0,0,0,0,0,0,0,0,0,0,0,1739,1748,0,0,0,0,0,0,1758,0,1776,0,1788,0,0,0,0,0,0,0,0,0,1806,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1831,1857,1868,1879,1890,1901,1912,1923,1934,1945,0,0,0,0,0,0,0,1956,0,0,0,0,0,0,0,0,0,0,0,0,0,1969,0,0,0,0,0,0,0,1979,0,0,0,0,0,0,1994,0,2004,0,0,0,0,0,2015,0,0,0,0,0,0,0,0,0,0,0,0,2033,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2049,0,0,0,0,2067,2078,2089,2100,2111,2122,2133,2144,2155,2166,0,0,0,0,2177,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2190,2209,2225,0,0,0,0,0,0,0,2241,0,2256,0,0,0,0,2267,0,2286,0,2297,0,0,0,0,0,0,0,0,0,0,0,2312,0,0,0,0,0,0,0,0,0,0,0,0,2328,0,0,0,0,0,0,0,0,0,0,2340,0,0,0,2358,0,0,0,2372,2383,2394,2405,2432,2443,2464,2488,2499,2510,2521,2538,0,0,0,0,0,0,0,2558,2568,0,0,0,0,0,0,0,0,0,0,2583,0,0,0,2603,0,0,0,0,0,0,2623,0,0,0,2635,0,2649,0,0,0,2663,2673,2683,2693,2703,2713,2723,2733,2743,2753,0,0,0,0,0,0,2763,2777,0,0,0,0,2790,2809,0,0,0,0,2826,0,2841,2851,0,0,0,0,0,0,0,0,0,0,0,2862,2873,2884,2895,2906,2917,2928,2939,2950,2961,0,2972,0,0,2981,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2994,}; +char xpmColors_dat[]="\000LawnGreen\000|\374\000\000SlateGray\000p\200\220WhiteSmoke\000\365\365\365\000MediumForestGreen\000""2\201K\000LightSlateGray\000w\210\231\000Magenta\000\377\000\377\000DarkSeaGreen\000\217\274\217\000ForestGreen\000P\237i\000Gray60\000\231\231\231\000Gray61\000\234\234\234\000Gray62\000\236\236\236\000Gray63\000\241\241\241\000GreenYellow\000\255\377/Gray64\000\243\243\243\000Gray65\000\246\246\246\000Gray66\000\250\250\250\000Gray67\000\253\253\253\000Gray68\000\255\255\255\000Gray69\000\260\260\260\000PaleGreen\000s\336x\000chocolate\000\322i\036\000DarkKhaki\000\275\267k\000PeachPuff\000\377\332\271\000DarkOliveGreen\000UV/\000LightCyan\000\340\377\377\000Blue\000\000\000\377\000NavajoWhite\000\377\336\255\000AliceBlue\000\360\370\377\000Gold\000\332\252\000\000Gray70\000\263\263\263\000Gray71\000\265\265\265\000Gray72\000\270\270\270\000Gray73\000\272\272\272\000Gray74\000\275\275\275\000Gray75\000\277\277\277\000Gray76\000\302\302\302\000Gray77\000\304\304\304\000Gray78\000\307\307\307\000Gray79\000\311\311\311\000GhostWhite\000\370\370\377\000peru\000\315\205?\000DarkSalmon\000\351\226z\000MidnightBlue\000//d\000Salmon\000\351\226z\000Tan\000\336\270\207\000DarkSlateGray\000/OO\000moccasin\000\377\344\265\000LightYellow\000\377\377\340\000Gray80\000\314\314\314\000Gray81\000\317\317\317\000Gray82\000\321\321\321\000Gray83\000\324\324\324\000Gray84\000\326\326\326\000Gray85\000\331\331\331\000Gray86\000\333\333\333\000Gray87\000\336\336\336\000Gray88\000\340\340\340\000Gray89\000\343\343\343\000Azure\000\360\377\377\000MediumSlateBlue\000jj\215\000Red\000\377\000\000\000VioletRed\000\363>\226\000Plum\000\305H\233\000SkyBlue\000r\237\377\000linen\000\372\360\346\000AntiqueWhite\000\372\353\327\000Navy\000##u\000Gray90\000\345\345\345\000Gray91\000\350\350\350\000Gray92\000\353\353\353\000Gray93\000\355\355\355\000Gray94\000\360\360\360\000Gray95\000\362\362\362\000Gray96\000\365\365\365\000Gray97\000\367\367\367\000Gray98\000\372\372\372\000Gray99\000\374\374\374\000OliveDrab\000k\216#\000LightBlue\000\260\342\377\000None\000\003\002\001\000MediumSpringGreen\000#\216#\000BlueViolet\000\212+\342\000MediumBlue\000""22\314\000PapayaWhip\000\377\357\325\000Brown\000\245**\000Pink\000\377\265\305\000chartreuse\000\177\377\000\000SpringGreen\000A\254A\000RoyalBlue\000Ai\341\000Goldenrod\000\357\337\204\000Turquoise\000\031\314\337\000LightGoldenrod\000\356\335\202\000NavyBlue\000##u\000MediumSeaGreen\000""4wf\000PowderBlue\000\260\340\346\000LimeGreen\000\000\257\024\000honeydew\000\360\377\360\000LightPink\000\377\266\301\000ivory\000\377\377\360\000OrangeRed\000\377E\000\000SteelBlue\000Tp\252\000LightSteelBlue\000|\230\323\000Gray100\000\377\377\377\000Gray\000~~~\000DimGray\000TTT\000gainsboro\000\334\334\334\000tomato\000\377cG\000LemonChiffon\000\377\372\315\000DarkGoldenrod\000\270\206\013\000SeaGreen\000R\225\204\000DarkTurquoise\000\000\246\246\000Firebrick\000\216##\000Yellow\000\377\377\000\000MediumAquamarine\000\000\223\217\000DodgerBlue\000\036\220\377\000CadetBlue\000_\222\236\000YellowGreen\000""2\330""8\000SlateBlue\000~\210\253\000LightSlateBlue\000\204p\377\000Gray10\000\032\032\032\000Gray11\000\034\034\034\000Gray12\000\037\037\037\000Gray13\000!!!\000Gray14\000$$$\000Gray15\000&&&\000Gray16\000)))\000Gray17\000+++\000Gray18\000...\000Gray19\000""000\000DarkOrange\000\377\214\000\000LightGray\000\250\250\250\000Orange\000\377\207\000\000Sienna\000\226R-\000PaleVioletRed\000\333p\223\000snow\000\377\372\372\000Coral\000\377rV\000PaleGoldenrod\000\356\350\252\000OldLace\000\375\365\346\000PaleTurquoise\000\257\356\356\000LightGoldenrodYellow\000\372\372\322\000DeepSkyBlue\000\000\277\377Gray20\000""333\000Gray21\000""666\000Gray22\000""888\000Gray23\000;;;\000Gray24\000===\000Gray25\000@@@\000Gray26\000BBB\000Gray27\000EEE\000Gray28\000GGG\000Gray29\000JJJ\000seashell\000\377\365\356\000Black\000\000\000\000\000DarkViolet\000\224\000\323\000Wheat\000\365\336\263\000Violet\000\234>\316\000LightSeaGreen\000\040\262\252\000FloralWhite\000\377\372\360\000LavenderBlush\000\377\360\365\000Gray30\000MMM\000Gray31\000OOO\000Gray32\000RRR\000Gray33\000TTT\000Gray34\000WWW\000Gray35\000YYY\000Gray36\000\\\\\\\000Gray37\000^^^\000Gray38\000aaa\000Gray39\000ccc\000DeepPink\000\377\024\223\000Green\000\000\377\000White\000\377\377\377\000LightSalmon\000\377\240z\000Transparent\000\000\000\001\000DarkOrchid\000\213\040\213\000purple\000\240\040\360\000BlanchedAlmond\000\377\353\315\000Orchid\000\357\204\357\000LightCoral\000\360\200\200\000SaddleBrown\000\213E\023\000Thistle\000\330\277\330\000DarkSlateBlue\000""8Kf\000burlywood\000\336\270\207\000Gray40\000fff\000Gray41\000iii\000Gray42\000kkk\000MediumPurple\000\223p\333Gray43\000nnn\000Gray44\000ppp\000Maroon\000\217\000RGray45\000sss\000IndianRed\000k99Gray46\000uuu\000Gray47\000xxx\000Gray48\000zzz\000Gray49\000}}}\000MediumOrchid\000\275R\275\000MediumVioletRed\000\325\040y\000Khaki\000\263\263~\000SandyBrown\000\364\244`\000MediumGoldenrod\000\321\301f\000MediumTurquoise\000\000\322\322\000HotPink\000\377i\264\000MistyRose\000\377\344\341\000MintCream\000\365\377\372\000Gray0\000\000\000\000\000Gray1\000\003\003\003\000Gray2\000\005\005\005\000Gray3\000\010\010\010\000Gray4\000\012\012\012\000Gray5\000\015\015\015\000Gray6\000\017\017\017\000Gray7\000\022\022\022\000Gray8\000\024\024\024\000Gray9\000\027\027\027\000RosyBrown\000\274\217\217\000cornsilk\000\377\370\334\000CornflowerBlue\000\"\"\230\000LightSkyBlue\000\207\316\372\000Aquamarine\000""2\277\301\000Beige\000\365\365\334\000Bisque\000\377\344\304\000Gray50\000\177\177\177\000Gray51\000\202\202\202\000Gray52\000\205\205\205\000Gray53\000\207\207\207\000Gray54\000\212\212\212\000Gray55\000\214\214\214\000Gray56\000\217\217\217\000Gray57\000\221\221\221\000Gray58\000\224\224\224\000Gray59\000\226\226\226\000Cyan\000\000\377\377\000lavender\000\346\346\372\000DarkGreen\000\000V-"; |