diff options
Diffstat (limited to 'buildtools')
-rw-r--r-- | buildtools/Makefile | 46 | ||||
-rw-r--r-- | buildtools/Makefile.manpage | 366 | ||||
-rw-r--r-- | buildtools/README.pkg | 144 | ||||
-rw-r--r-- | buildtools/config_template | 52 | ||||
-rwxr-xr-x | buildtools/configure.pl | 2111 | ||||
-rwxr-xr-x | buildtools/empty_depend | 19 | ||||
-rwxr-xr-x | buildtools/endiangen | bin | 0 -> 14005 bytes | |||
-rw-r--r-- | buildtools/endiangen.c | 97 | ||||
-rwxr-xr-x | buildtools/install.sh | 255 | ||||
-rwxr-xr-x | buildtools/installnetpbm.pl | 919 | ||||
-rwxr-xr-x | buildtools/installosf | 31 | ||||
-rwxr-xr-x | buildtools/libopt | bin | 0 -> 18008 bytes | |||
-rw-r--r-- | buildtools/libopt.c | 541 | ||||
-rwxr-xr-x | buildtools/make_merge.sh | 12 | ||||
-rwxr-xr-x | buildtools/makecat | 18 | ||||
-rwxr-xr-x | buildtools/makeman | 333 | ||||
-rwxr-xr-x | buildtools/makepointerman | 91 | ||||
-rwxr-xr-x | buildtools/mkinstalldirs | 41 | ||||
-rwxr-xr-x | buildtools/stamp-date | 23 | ||||
-rwxr-xr-x | buildtools/typegen | bin | 0 -> 14159 bytes | |||
-rw-r--r-- | buildtools/typegen.c | 113 |
21 files changed, 5212 insertions, 0 deletions
diff --git a/buildtools/Makefile b/buildtools/Makefile new file mode 100644 index 00000000..63da1adf --- /dev/null +++ b/buildtools/Makefile @@ -0,0 +1,46 @@ +ifeq ($(SRCDIR)x,x) + SRCDIR = $(CURDIR)/.. + BUILDDIR = $(SRCDIR) +endif +SUBDIR = buildtools +VPATH = .:$(SRCDIR)/$(SUBDIR) +include $(BUILDDIR)/Makefile.config + +MERGE_OBJECTS = + +# These are programs that are used by the make files: +PROGS = libopt typegen endiangen + +all: $(PROGS) + +BINARIES = +SCRIPTS = + +OMIT_BUILDTOOL_RULE = 1 +include $(SRCDIR)/Makefile.common + +ifdef DLLVER +STRIP_DLL_VERSION=-DDLLVERSTR="\"$(DLLVER)\"" +endif + +ifeq ($(LINKER_CAN_DO_EXPLICIT_LIBRARY),Y) +EXPLICIT=-DEXPLICIT +endif + +libopt.o: libopt.c + $(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) \ + -DSHLIBPREFIXLIST="\"$(SHLIBPREFIXLIST)\"" \ + $(STRIP_DLL_VERSION) $(EXPLICIT) $(CFLAGS_PERSONAL) $(CADD) \ + -o $@ $< + +typegen.o endiangen.o:%.o:%.c + $(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) -o $@ $< + +$(PROGS):%:%.o + $(LD_FOR_BUILD) -o $@ $< + +clean: cleanlocal +.PHONY: cleanlocal +cleanlocal: + rm -f $(PROGS) + diff --git a/buildtools/Makefile.manpage b/buildtools/Makefile.manpage new file mode 100644 index 00000000..e8c17972 --- /dev/null +++ b/buildtools/Makefile.manpage @@ -0,0 +1,366 @@ +# -*-makefile-*- <-- an Emacs control + +# Make Unix man pages from Netpbm HTML user manual + +MAKEMAN = makeman + +MANDIR = /usr/share/man/man1 + +# These can convert to man pages cleanly +MAN1 = \ + 411toppm.1 \ + anytopnm.1 \ + asciitopgm.1 \ + atktopbm.1 \ + bioradtopgm.1 \ + bmptopnm.1 \ + bmptoppm.1 \ + brushtopbm.1 \ + cmuwmtopbm.1 \ + ddbugtopbm.1 \ + escp2topbm.1 \ + eyuvtoppm.1 \ + fiascotopnm.1 \ + fitstopnm.1 \ + fstopgm.1 \ + g3topbm.1 \ + gemtopbm.1 \ + gemtopnm.1 \ + giftopnm.1 \ + gouldtoppm.1 \ + hdifftopam.1 \ + hipstopgm.1 \ + hpcdtoppm.1 \ + icontopbm.1 \ + ilbmtoppm.1 \ + imgtoppm.1 \ + infotopam.1 \ + jbigtopnm.1 \ + jpeg2ktopam.1 \ + jpegtopnm.1 \ + leaftoppm.1 \ + lispmtopgm.1 \ + macptopbm.1 \ + mdatopbm.1 \ + mgrtopbm.1 \ + mrf.1 \ + mrftopbm.1 \ + mtvtoppm.1 \ + neotoppm.1 \ + palmtopnm.1 \ + pamarith.1 \ + pamchannel.1 \ + pamcomp.1 \ + pamcut.1 \ + pamdeinterlace.1 \ + pamdice.1 \ + pamditherbw.1 \ + pamedge.1 \ + pamendian.1 \ + pamfile.1 \ + pamflip.1 \ + pamfunc.1 \ + pamgauss.1 \ + pamlookup.1 \ + pamoil.1 \ + pamperspective.1 \ + pampop9.1 \ + pamscale.1 \ + pamseq.1 \ + pamsharpmap.1 \ + pamsharpness.1 \ + pamslice.1 \ + pamstack.1 \ + pamstereogram.1 \ + pamstretch-gen.1 \ + pamstretch.1 \ + pamsummcol.1 \ + pamsumm.1 \ + pamtodjvurle.1 \ + pamtohdiff.1 \ + pamtohtmltbl.1 \ + pamtojpeg2k.1 \ + pamtopfm.1 \ + pamtopnm.1 \ + pamtotga.1 \ + pamtouil.1 \ + pbmclean.1 \ + pbmlife.1 \ + pbmmake.1 \ + pbmmask.1 \ + pbmpage.1 \ + pbmpscale.1 \ + pbmreduce.1 \ + pbmtext.1 \ + pbmtextps.1 \ + pbmto10x.1 \ + pbmto4425.1 \ + pbmtoascii.1 \ + pbmtoatk.1 \ + pbmtobbnbg.1 \ + pbmtocmuwm.1 \ + pbmtodjvurle.1 \ + pbmtoepsi.1 \ + pbmtoepson.1 \ + pbmtoescp2.1 \ + pbmtog3.1 \ + pbmtogem.1 \ + pbmtogo.1 \ + pbmtoicon.1 \ + pbmtolj.1 \ + pbmtoln03.1 \ + pbmtolps.1 \ + pbmtomacp.1 \ + pbmtomda.1 \ + pbmtomgr.1 \ + pbmtomrf.1 \ + pbmtonokia.1 \ + pbmtopgm.1 \ + pbmtopi3.1 \ + pbmtopk.1 \ + pbmtoplot.1 \ + pbmtoppa.1 \ + pbmtopsg3.1 \ + pbmtoptx.1 \ + pbmtowbmp.1 \ + pbmtox10bm.1 \ + pbmtoxbm.1 \ + pbmtoybm.1 \ + pbmtozinc.1 \ + pbmupc.1 \ + pc1toppm.1 \ + pcdovtoppm.1 \ + pcxtoppm.1 \ + pfmtopam.1 \ + pgmabel.1 \ + pgmbentley.1 \ + pgmcrater.1 \ + pgmedge.1 \ + pgmenhance.1 \ + pgmhist.1 \ + pgmkernel.1 \ + pgmminkowski.1 \ + pgmmorphconv.1 \ + pgmnoise.1 \ + pgmnorm.1 \ + pgmoil.1 \ + pgmramp.1 \ + pgmslice.1 \ + pgmtexture.1 \ + pgmtofs.1 \ + pgmtolispm.1 \ + pgmtopbm.1 \ + pgmtopgm.1 \ + pgmtoppm.1 \ + pi1toppm.1 \ + pi3topbm.1 \ + picttoppm.1 \ + pjtoppm.1 \ + pktopbm.1 \ + pngtopnm.1 \ + pnmalias.1 \ + pnmarith.1 \ + pnmcat.1 \ + pnmcolormap.1 \ + pnmcomp.1 \ + pnmconvol.1 \ + pnmcrop.1 \ + pnmcut.1 \ + pnmdepth.1 \ + pnmenlarge.1 \ + pnmfile.1 \ + pnmgamma.1 \ + pnmhisteq.1 \ + pnmhistmap.1 \ + pnmindex.1 \ + pnminterp.1 \ + pnminvert.1 \ + pnmmargin.1 \ + pnmmontage.1 \ + pnmnlfilt.1 \ + pnmnoraw.1 \ + pnmnorm.1 \ + pnmpad.1 \ + pnmpaste.1 \ + pnmpsnr.1 \ + pnmquant.1 \ + pnmremap.1 \ + pnmrotate.1 \ + pnmscalefixed.1 \ + pnmscale.1 \ + pnmshear.1 \ + pnmsmooth.1 \ + pnmsplit.1 \ + pnmstitch.1 \ + pnmtile.1 \ + pnmtoddif.1 \ + pnmtofiasco.1 \ + pnmtofits.1 \ + pnmtojbig.1 \ + pnmtojpeg.1 \ + pnmtopalm.1 \ + pnmtopclxl.1 \ + pnmtoplainpnm.1 \ + pnmtopng.1 \ + pnmtopnm.1 \ + pnmtops.1 \ + pnmtorast.1 \ + pnmtorle.1 \ + pnmtosgi.1 \ + pnmtosir.1 \ + pnmtotiffcmyk.1 \ + pnmtotiff.1 \ + pnmtoxwd.1 \ + ppm3d.1 \ + ppmbrighten.1 \ + ppmchange.1 \ + ppmcie.1 \ + ppmcolormask.1 \ + ppmdim.1 \ + ppmdist.1 \ + ppmdither.1 \ + ppmfade.1 \ + ppmflash.1 \ + ppmforge.1 \ + ppmglobe.1 \ + ppmhist.1 \ + ppmlabel.1 \ + ppmmake.1 \ + ppmmix.1 \ + ppmnorm.1 \ + ppmntsc.1 \ + ppmpat.1 \ + ppmquantall.1 \ + ppmquant.1 \ + ppmrainbow.1 \ + ppmrelief.1 \ + ppmrough.1 \ + ppmshadow.1 \ + ppmshift.1 \ + ppmspread.1 \ + ppmsvgalib.1 \ + ppmtoacad.1 \ + ppmtoarbtxt.1 \ + ppmtobmp.1 \ + ppmtoeyuv.1 \ + ppmtogif.1 \ + ppmtoicr.1 \ + ppmtoilbm.1 \ + ppmtojpeg.1 \ + ppmtoleaf.1 \ + ppmtolj.1 \ + ppmtomitsu.1 \ + ppmtompeg.1 \ + ppmtoneo.1 \ + ppmtopcx.1 \ + ppmtopgm.1 \ + ppmtopi1.1 \ + ppmtopict.1 \ + ppmtopj.1 \ + ppmtopjxl.1 \ + ppmtoppm.1 \ + ppmtopuzz.1 \ + ppmtorgb3.1 \ + ppmtosixel.1 \ + ppmtoterm.1 \ + ppmtotga.1 \ + ppmtouil.1 \ + ppmtowinicon.1 \ + ppmtoxpm.1 \ + ppmtoyuv.1 \ + ppmtoyuvsplit.1 \ + ppmtv.1 \ + ppmwheel.1 \ + psidtopgm.1 \ + pstopnm.1 \ + qrttoppm.1 \ + rasttopnm.1 \ + rawtopgm.1 \ + rawtoppm.1 \ + rgb3toppm.1 \ + rletopnm.1 \ + sbigtopgm.1 \ + sgitopnm.1 \ + sirtopnm.1 \ + sldtoppm.1 \ + spctoppm.1 \ + spottopgm.1 \ + sputoppm.1 \ + tgatoppm.1 \ + thinkjettopbm.1 \ + tifftopnm.1 \ + vidtoppm.1 \ + wbmptopbm.1 \ + winicontoppm.1 \ + xbmtopbm.1 \ + ximtoppm.1 \ + xpmtoppm.1 \ + xvminitoppm.1 \ + xwdtopnm.1 \ + ybmtopbm.1 \ + yuvsplittoppm.1 \ + yuvtoppm.1 \ + zeisstopnm.1 \ + +MAN3 = \ + libnetpbm.3 \ + libnetpbm_image.3 \ + libnetpbm_ug.3 \ + libpbm.3 \ + libpgm.3 \ + libpm.3 \ + libpnm.3 \ + libppm.3 \ + libsystem.3 \ + libtmpfile.3 \ + +MAN5 = \ + extendedopacity.5 \ + pam.5 \ + pbm.5 \ + pgm.5 \ + pnm.5 \ + ppm.5 \ + +MANPAGES = $(MAN1) netpbm.1 $(MAN3) $(MAN5) +HTMLMANUALS = $(MAN1:.1=.html) $(MAN3:.3=.html) $(MAN5:.5=.html) +XML = $(HTMLMANUALS:.html=.xml) netpbm.xml + +# These things don't get converted to manual pages +# They're basically link lists, not useful in the man hierarchy. +EXCEPTIONS = directory.html libnetpbm_dir.html + +# Make man pages -- reports bad lines to standard error +manpages: + @python $(MAKEMAN) index.html $(HTMLMANUALS) + mv index.1 netpbm.1 + +# Make XML pages, and validate them. +xmlpages: + @for x in $(MANPAGES); do doclifter $$x; done + @for x in $(XML); do xmllint -xinclude --postvalid $$x >/dev/null; done + +# This will install the generated man pages +installman: manpages + for f in $(MAN1); do \ + if [ -f $$f ]; then gzip <$$f >$(MANDIR)/man1/$$f.gz; fi; \ + done + for f in $(MAN3); do \ + if [ -f $$f ]; then gzip <$$f >$(MANDIR)/man3/$$f.gz; fi; \ + done + for f in $(MAN5); do \ + if [ -f $$f ]; then gzip <$$f >$(MANDIR)/man5/$$f.gz; fi; \ + done + # Clean up old locations on Fedora Core 2 + rm -f $(MANDIR)/man1/extendedopacity.1.gz + rm -f $(MANDIR)/man3/directory.3.gz + rm -f $(MANDIR)/man3/libnetpbm_dir.3.gz + # remove pointer man pages (that say, "The man page isn't here") + # which might have been installed previously + for f in $(MAN1); do rm -f $(MANDIR)/man1/$$f; done + for f in $(MAN3); do rm -f $(MANDIR)/man3/$$f; done + for f in $(MAN5); do rm -f $(MANDIR)/man5/$$f; done + +clean: + @rm -f *.[135] $(XML) + diff --git a/buildtools/README.pkg b/buildtools/README.pkg new file mode 100644 index 00000000..b2a6b0ef --- /dev/null +++ b/buildtools/README.pkg @@ -0,0 +1,144 @@ +THESE ARE THE MANUAL INSTALLATION INSTRUCTIONS FOR NETPBM + +Most people install using the interactive install program 'installnetpbm' +that is in the top level directory of the Netpbm source tree. But it +isn't right for everyone. If it doesn't do what you need, you can use +these instructions instead. + + +Once you have built and packaged Netpbm, installing is pretty +straightforward. If you browse the package directory, you can +probably figure it out without reading any further. + + +The parts to be installed are: + + Executables + + These are the basic Netpbm programs, such as 'jpegtopnm'. + You will find these in the 'bin' subdirectory of the package directory. + + You normally want to copy all of these into a directory that is in your + default program search path (which is controlled by your PATH + environment variable). Typical directories for this are /bin, /usr/bin, + and /usr/local/bin. + + Shared Library + + This is the library that all Netpbm programs need to load and link + to at run time. It is in the 'lib' subdirectory of the package + directory. Building a shared library is optional; if you didn't + do it (which means you built executables that don't require it), + you don't have a 'lib' subdirectory. Shared libraries are also + known as dynamic libraries and DLLs. + + You normally want to copy the shared library to a directory that + is in your system's default shared library search path. On + systems that have an 'ldconfig' program, that program controls the + shared library search path, and you must run it after copying the + Netpbm shared library to its directory. Often, simply rebooting + will cause it to run cleanly. + + Typical directories for this are /lib, /usr/lib, and /usr/local/lib. + + On Windows, the DLLs are treated like executables, so you should + find the 'lib' directory empty and you should find the Netpbm DLL + in the 'bin' directory. You'll probably want to install the DLL + and the executables in the same directory, because the shared + library and executable search paths are the same. + + Link Library + + This is a static link library. You don't need it to run Netpbm. You + need it only if you want to build your own programs that use the Netpbm + library. It is in the 'link' subdirectory of the package directory. + + You normally want to copy the link library into a directory that is + in the default search path of your linker. Typical directories for + this are /usr/lib and /usr/local/lib. + + Interface Headers + + These are the files that declare the interface to the Netpbm + programming library. You don't need them to run Netpbm. You need + them only if you want to build your own programs that use the + Netpbm library. They are in the 'include' subdirectory of the + package directory. + + You normally want to copy the interface header files into a directory + that is in the default search path of your compiler. Typical + directories for this are /usr/include and /usr/local/include. + + Data Files + + These are files that you can use for various purposes as input to + Netpbm programs. People rarely have uses for them, actually. They + are in the 'data' subdirectory of the package directory. + + Put these somewhere that users will be able to find them. + /usr/lib/netpbm and /usr/share/netpbm are typical choices. + + Man Pages + + Netpbm does not have the typical Unix form of documentation. The + documentation is not in files that you can read with the common + 'man' program. Instead, it is in HTML form, and it is not in the + package directory at all. You must install it separately. + + But so that a user who is not familiar with Netpbm documentation + doesn't find himself out in the cold with no access to + documentation, the package directory contains traditional man + pages that do nothing but tell you where to get the real + documentation. (Exactly where that is depends on the options with + which you built and packaged Netpbm). We call these "pointer man + pages." You will find these man pages in the 'man' subdirectory + of the package directory. + + You should copy the contents of this directory wherever your 'man' + program looks for man pages. Typically, this is /usr/man, which + has subdirectories equivalent to those in the package directory's + 'man' subdirectory. + + + One of the Netpbm programs is Manweb, which is designed to be a + replacement for the classic Man program that can access both + traditional man pages and worldwide web documentation in the + Netpbm style with the familiar 'man jpegtopnm' kind of command. + To set up your system for this, you will have to be sure to create + the /usr/man/web directory, with 'netpbm.url' in it. Also, If you + install Manweb as 'man', there is no point to installing the + pointer man pages -- they will never be used. + + + +The instructions above suggest putting the Netpbm parts in common +directories such as /usr/bin, mingled with other packages. This is +usually the easiest way to get Netpbm working. But also consider +putting all Netpbm parts in separate Netpbm directories, such as +/usr/bin/netpbm/ and /usr/link/netpbm. In fact, you can just copy the +entire package directory in one piece to some place such as +/usr/local/netpbm. You'll have to take care to set up search paths +and such to make this kind of configuration work. The advantage of +keeping Netpbm separate is that it makes it easy to wipe out the +entire installation when you don't want it anymore, and to keep +multiple versions around. + + +netpbm.config +------------- + +You should create a shell script named 'netpbm.config' out of the +template file 'config_template' in the package directory, and install +netpbm.config in your executable search path. Programs that want to +find out where you installed some part of Netpbm can invoke +netpbm.config and it will tell them. For example, a make file for a +program that uses the Netpbm programming library might use +netpbm.config to generate the necessary compiler and linker options to +access that library. + +Using netpbm.config, it's possible to have a viable Netpbm +installation where netpbm.config is the only file in any default +search path. + +The xxx.config file concept is a relatively new but growing convention, +seen mostly in software related to the X Window System. diff --git a/buildtools/config_template b/buildtools/config_template new file mode 100644 index 00000000..04a32079 --- /dev/null +++ b/buildtools/config_template @@ -0,0 +1,52 @@ +@ This is a template to be processed into a Bourne shell program. +@ +#!/bin/sh + +# This program was generated by the Netpbm installer. Its purpose is to +# allow other programs to find out about how Netpbm is installed on this +# system. This program is supposed to be invoked via the PATH. + +@ The following @xxx@ strings get replaced by Installnetpbm when it turns +@ this template into an actual Bourne shell program. +version='@VERSION@' +datadir='@DATADIR@' +linkdir='@LINKDIR@' +includedir='@INCLUDEDIR@' +bindir='@BINDIR@' + + +if test $# -eq 0; then + echo >&2 "You need to specify one of these options:" + echo >&2 " --version" + echo >&2 " --datadir" + echo >&2 " --linkdir" + echo >&2 " --includedir" + echo >&2 " --bindir" + exit 100 + fi + +case "$1" in + --version) + echo $version + exit 0 + ;; + --datadir) + echo $datadir + exit 0 + ;; + --linkdir) + echo $linkdir + exit 0 + ;; + --includedir) + echo $includedir + exit 0 + ;; + --bindir) + echo $bindir + exit 0 + ;; + *) + echo >&2 "Unrecognized option to $0: $1" + exit 100 + esac diff --git a/buildtools/configure.pl b/buildtools/configure.pl new file mode 100755 index 00000000..3a44a0da --- /dev/null +++ b/buildtools/configure.pl @@ -0,0 +1,2111 @@ +#!/usr/bin/perl -w + +require 5.000; + +use strict; +use English; +use File::Basename; +use Cwd 'abs_path'; +use Fcntl; +use Config; +#use File::Temp "tempfile"; Not available before Perl 5.6.1 + + +my ($TRUE, $FALSE) = (1,0); + +# This program generates Makefile.config, which is included by all of the +# Netpbm makefiles. You run this program as the first step in building +# Netpbm. (The second step is 'make'). + +# This program is only a convenience. It is supported to create +# Makefile.config any way you want. In fact, an easy way is to copy +# Makefile.config.in and follow the instructions in the comments therein +# to uncomment certain lines and make other changes. + +# Note that if you invoke 'make' without having first run 'configure', +# the make will call 'configure' itself when it finds +# 'Makefile.config' missing. That might look a little messy to the +# user, but it isn't the normal build process. + +# The argument to this program is the filepath of the Makefile.config.in +# file. If unspecified, the default is 'Makefile.config.in' in the +# Netpbm source directory. + +# For explanations of the stuff we put in the make files, see the comments +# in Makefile.config.in. + + +# $testCc is the command we use to do test compiles. Note that test +# compiles are never more than heuristics, because we may be configuring +# a build that will happen on a whole different system, which will build +# programs to run on a third system. + +my $testCc; + +#****************************************************************************** +# +# SUBROUTINES +# +#***************************************************************************** + +sub autoFlushStdout() { + my $oldFh = select(STDOUT); + $OUTPUT_AUTOFLUSH = $TRUE; + select($oldFh); +} + + + +sub prompt($$) { + + my ($prompt, $default) = @_; + + my $defaultPrompt = defined($default) ? $default : "?"; + + print("$prompt [$defaultPrompt] ==> "); + + my $response = <STDIN>; + + if (defined($response)) { + chomp($response); + if ($response eq "" && defined($default)) { + $response = $default; + } + } else { + print("\n"); + die("End of file on Standard Input when expecting response to prompt"); + } + + return $response; +} + + + +sub tmpdir() { +# This is our approximation of File::Spec->tmpdir(), which became part of +# basic Perl some time after Perl 5.005_03. + + my $retval; + + if ($ENV{"TMPDIR"}) { + $retval = $ENV{"TMPDIR"}; + } else { + if ($Config{'osvers'} eq "djgpp") { + $retval = "/dev/env/DJDIR/tmp"; + } else { + $retval = "/tmp"; + } + } + return $retval; +} + + + +sub tempFile($) { + +# Here's what we'd do if we could expect Perl 5.6.1 or later, instead +# of calling this subroutine: +# my ($cFile, $cFileName) = tempfile("netpbmXXXX", +# SUFFIX=>".c", +# DIR=>File::Spec->tmpdir(), +# UNLINK=>0); + my ($suffix) = @_; + my $fileName; + local *file; # For some inexplicable reason, must be local, not my + my $i; + $i = 0; + do { + $fileName = tmpdir() . "/netpbm" . $i++ . $suffix; + } until sysopen(*file, $fileName, O_RDWR|O_CREAT|O_EXCL); + + return(*file, $fileName); +} + + + +sub commandExists($) { + my ($command) = @_; +#----------------------------------------------------------------------------- +# Return TRUE iff a shell command $command exists. +#----------------------------------------------------------------------------- + +# Note that it's significant that the redirection on the following +# causes it to be executed in a shell. That makes the return code +# from system() a lot different than if system() were to try to +# execute the program directly. + + return(system("$command 1</dev/null 1>/dev/null 2>/dev/null")/256 != 127); +} + + + +sub chooseTestCompiler($$) { + + my ($compiler, $testCcR) = @_; + + my $cc; + + if (!defined($compiler)) { + if ($ENV{'CC'}) { + $cc = $ENV{'CC'}; + } else { + if (commandExists('cc')) { + $cc = 'cc'; + } elsif (commandExists("gcc")) { + $cc = 'gcc'; + } + } + } elsif ($compiler eq 'cc') { + $cc = "cc"; + } elsif ($compiler eq 'gcc') { + $cc = 'gcc'; + } else { + die("Internal error: invalid value \"$compiler\" for \$compiler"); + } + $$testCcR = $cc; +} + + + +sub testCflags($) { + my ($needLocal) = @_; + + my $cflags; + + $cflags = ""; # initial value + + if ($ENV{"CPPFLAGS"}) { + $cflags = $ENV{"CPPFLAGS"}; + } else { + $cflags = ""; + } + + if ($ENV{"CFLAGS"}) { + $cflags .= " " . $ENV{"CFLAGS"}; + } + + if ($needLocal) { + $cflags .= " -I/usr/local/include"; + } + return $cflags; +} + + + +sub testCompile($$$) { + my ($cflags, $cSourceCodeR, $successR) = @_; +#----------------------------------------------------------------------------- +# Do a test compile of the program in @{$cSourceCodeR}. +# +# Return $$successR == $TRUE iff the compile succeeds (exit code 0). +#----------------------------------------------------------------------------- + my ($cFile, $cFileName) = tempFile(".c"); + + print $cFile @{$cSourceCodeR}; + + my ($oFile, $oFileName) = tempFile(".o"); + # Note: we tried using /dev/null for the output file and got complaints + # from the Sun compiler that it has the wrong suffix. 2002.08.09. + + my $compileCommand = "$testCc -c -o $oFileName $cflags $cFileName"; + print ("Doing test compile: $compileCommand\n"); + my $rc = system($compileCommand); + + unlink($oFileName); + close($oFile); + unlink($cFileName); + close($cFile); + + $$successR = ($rc == 0); +} + + + +sub displayIntroduction() { + print("This is the Netpbm configurator. It is an interactive dialog " . + "that\n"); + print("helps you build the file 'Makefile.config' and prepare to build "); + print("Netpbm.\n"); + print("\n"); + + print("Do not be put off by all the questions. Configure gives you " . + "the \n"); + print("opportunity to make a lot of choices, but you don't have to. " . + "If \n"); + print("you don't have reason to believe you're smarter than Configure,\n"); + print("just take the defaults (hit ENTER) and don't sweat it.\n"); + print("\n"); + + print("If you are considering having a program feed answers to the " . + "questions\n"); + print("below, please read doc/INSTALL, because that's probably the " . + "wrong thing to do.\n"); + print("\n"); + + print("Hit ENTER to begin.\n"); + my $response = <STDIN>; +} + + +sub askAboutCygwin() { + + print("Are you building in/for the Cygwin environment?\n"); + print("\n"); + + my $default; + if ($OSNAME eq "cygwin") { + $default = "y"; + } else { + $default = "n"; + } + + my $retval; + + while (!defined($retval)) { + my $response = prompt("(y)es or (n)o", $default); + + if (uc($response) =~ /^(Y|YES)$/) { + $retval = $TRUE; + } elsif (uc($response) =~ /^(N|NO)$/) { + $retval = $FALSE; + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'yes' or 'no' (or 'y' or 'n').\n"); + } + } + return $retval; +} + + + +sub askAboutDjgpp() { + + print("Are you building in/for the DJGPP environment?\n"); + print("\n"); + + my $default; + if ($OSNAME eq "dos") { + $default = "y"; + } else { + $default = "n"; + } + + my $retval; + + while (!defined($retval)) { + my $response = prompt("(y)es or (n)o", $default); + + if (uc($response) =~ /^(Y|YES)$/) { + $retval = $TRUE; + } elsif (uc($response) =~ /^(N|NO)$/) { + $retval = $FALSE; + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'yes' or 'no' (or 'y' or 'n').\n"); + } + } +} + + + +sub computePlatformDefault($) { + + my ($defaultP) = @_; + + if ($OSNAME eq "linux") { + $$defaultP = "gnu"; + } elsif ($OSNAME eq "cygwin") { + $$defaultP = "win"; + } elsif ($OSNAME eq "dos") { + # DJGPP says "dos" + $$defaultP = "win"; + } elsif ($OSNAME eq "aix" || $OSNAME eq "freebsd" || $OSNAME eq "darwin" || + $OSNAME eq "amigaos") { + $$defaultP = $OSNAME; + } elsif ($OSNAME eq "solaris") { + $$defaultP = "sun"; + } elsif ($OSNAME eq "dec_osf") { + $$defaultP = "tru64"; + } else { + print("Unrecognized OSNAME='$OSNAME'. No default possible\n"); + } + # OK - if you know what $OSNAME is on any other platform, send me a patch! +} + + + +sub getPlatform() { + + my $platform; + my $default; + + computePlatformDefault(\$default); + + print("Which of the following best describes your platform?\n"); + + print("gnu GNU/Linux\n"); + print("sun Solaris or SunOS\n"); + print("hp HP-UX\n"); + print("aix AIX\n"); + print("win Windows/DOS (Cygwin, DJGPP, Mingw32)\n"); + print("tru64 Tru64\n"); + print("irix Irix\n"); + print("bsd NetBSD, BSD/OS\n"); + print("openbsd OpenBSD\n"); + print("freebsd FreeBSD\n"); + print("darwin Darwin or Mac OS X\n"); + print("amigaos Amiga\n"); + print("unixware Unixware\n"); + print("sco SCO OpenServer\n"); + print("beos BeOS\n"); + print("none none of these are even close\n"); + print("\n"); + + my $response = prompt("Platform", $default); + + my %platform = ("gnu" => "GNU", + "sun" => "SOLARIS", + "hp" => "HP-UX", + "aix" => "AIX", + "tru64" => "TRU64", + "irix" => "IRIX", + "win" => "WINDOWS", + "beos" => "BEOS", + "bsd" => "NETBSD", + "openbsd" => "OPENBSD", + "freebsd" => "FREEBSD", + "unixware" => "UNIXWARE", + "sco" => "SCO", + "darwin" => "DARWIN", + "amigaos" => "AMIGA", + "none" => "NONE" + ); + + $platform = $platform{$response}; + if (!defined($platform)) { + print("'$response' isn't one of the choices.\n"); + exit 8; + } + + my $subplatform; + + if ($platform eq "WINDOWS") { + my ($djgpp, $cygwin); + + if ($OSNAME eq "dos") { + $djgpp = askAboutDjgpp(); + if ($djgpp) { + $cygwin = $FALSE; + } else { + $cygwin = askAboutCygwin(); + } + } else { + $cygwin = askAboutCygwin(); + if ($cygwin) { + $djgpp = $FALSE; + } else { + $djgpp = askAboutDjgpp(); + } + } + + if ($cygwin) { + $subplatform = "cygwin"; + } elsif ($djgpp) { + $subplatform = "djgpp"; + } else { + $subplatform = "other"; + } + } + + return($platform, $subplatform); +} + + + +sub getCompiler($$) { + my ($platform, $compilerR) = @_; +#----------------------------------------------------------------------------- +# Here are some of the issues surrounding choosing a compiler: +# +# - It's not just the name of the program we need -- different compilers +# need different options. +# +# - There are basically two choices on any system: native compiler or +# GNU compiler. That's all this program recognizes, anyway. +# +# - A user may well have various compilers. Different releases, using +# different standard libraries, for different target machines, etc. +# +# - The CC environment variable tells the default compiler. +# +# - In the absence of a CC environment variable, 'cc' is the default +# compiler. +# +# - The user must be able to specify the compiler by overriding the CC +# make variable (e.g. make CC=gcc2). +# +# - Configure needs to do test compiles. The test is best if it uses +# the same compiler that the build eventually will use, but it's +# useful even if not. +# +# The value this subroutine returns is NOT the command name to invoke the +# compiler. It is simply "cc" to mean native compiler or "gcc" to mean +# GNU compiler or undefined to express no preference. +#----------------------------------------------------------------------------- + my %gccCapablePlatform = ("SOLARIS" => 1, + "TRU64" => 1, + "SCO" => 1, + "AIX" => 1, + "HP" => 1); + + if ($gccCapablePlatform{$platform}) { + print("GNU compiler or native operating system compiler (cc)?\n"); + print("\n"); + + my $default; + + if ($platform eq "SOLARIS" || $platform eq "SCO" ) { + $default = "gcc"; + } else { + $default = "cc"; + } + + my $response = prompt("gcc or cc", $default); + + if ($response eq "gcc") { + $$compilerR = "gcc"; + } elsif ($response eq "cc") { + $$compilerR = "cc"; + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'gcc' or 'cc'.\n"); + exit 12; + } + + if ($$compilerR eq 'gcc' && !commandExists('gcc')) { + print("WARNING: You selected the GNU compiler, " . + "but do not appear to have a program " . + "named 'gcc' in your PATH. This may " . + "cause trouble later. You may need to " . + "set the CC environment variable or CC " . + "makefile variable or install 'gcc'\n"); + } + print("\n"); + } +} + + + +sub gccLinker() { +#----------------------------------------------------------------------------- +# Determine what linker Gcc on this system appears to use. +# +# Return either "gnu" or "sun" +# +# For now, we assume it must be either a GNU linker or Sun linker and +# that all Sun linkers are fungible. +# +# If we can't tell, we assume it is the GNU linker. +#----------------------------------------------------------------------------- + # First, we assume that the compiler calls 'collect2' as the linker + # front end. The specs file might specify some other program, but + # it usually says 'collect2'. + + my $retval; + + my $collect2 = qx{gcc --print-prog-name=collect2}; + + if (defined($collect2)) { + chomp($collect2); + my $linker = qx{$collect2 -v 2>&1}; + if (defined($linker) && $linker =~ m{GNU ld}) { + $retval = "gnu"; + } else { + $retval = "sun"; + } + } else { + $retval = "gnu"; + } + return $retval; +} + + + +sub getLinker($$$$) { + + my ($platform, $compiler, $baseLinkerR, $viaCompilerR) = @_; + + my $baseLinker; + + if ($platform eq "SOLARIS") { + $$viaCompilerR = $TRUE; + + while (!defined($$baseLinkerR)) { + print("GNU linker or SUN linker?\n"); + print("\n"); + + my $default; + + if ($compiler eq "gcc") { + $default = gccLinker(); + } else { + $default = "sun"; + } + my $response = prompt("sun or gnu", $default); + + if ($response eq "gnu") { + $$baseLinkerR = "GNU"; + } elsif ($response eq "sun") { + $$baseLinkerR = "SUN"; + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'sun' or 'gnu'.\n"); + } + print("\n"); + } + } else { + $$viaCompilerR = $TRUE; + $$baseLinkerR = "?"; + } +} + + + +sub libSuffix($) { + my ($platform) = @_; +#----------------------------------------------------------------------------- +# Return the traditional suffix for the link-time library on platform +# type $platform. +# +# Note that this information is used mainly for cosmetic purposes in this +# this program and the Netpbm build, because the build typically removes +# any suffix and uses link options such as "-ltiff" to link the library. +# This leaves it up to the linker to supply the actual suffix. +#----------------------------------------------------------------------------- + my $suffix; + + if ($platform eq "windows") { + $suffix = ".a"; + } else { + $suffix = ".so"; + } +} + + + +sub getLibTypes($$$$$$$$) { + my ($platform, $subplatform, $default_target, + $netpbmlibtypeR, $netpbmlibsuffixR, $shlibprefixlistR, + $willBuildSharedR, $staticlib_tooR) = @_; + + print("Do you want libnetpbm to be statically linked or shared?\n"); + print("\n"); + + my $default = ($default_target eq "merge") ? "static" : "shared"; + + my ($netpbmlibtype, $netpbmlibsuffix, $shlibprefixlist, + $willBuildShared, $staticlib_too); + + my $response = prompt("static or shared", $default); + + if ($response eq "shared") { + $willBuildShared = $TRUE; + if ($platform eq "WINDOWS") { + $netpbmlibtype = "dll"; + $netpbmlibsuffix = "dll"; + if ($subplatform eq "cygwin") { + $shlibprefixlist = "cyg lib"; + } + } elsif ($platform eq "DARWIN") { + $netpbmlibtype = "dylib"; + $netpbmlibsuffix = "dylib"; + } else { + if ($platform eq "IRIX") { + $netpbmlibtype = "irixshared"; + } else { + $netpbmlibtype = "unixshared"; + } + if ($platform eq "AIX") { + $netpbmlibsuffix = "a"; + } elsif ($platform eq "HP-UX") { + $netpbmlibsuffix = "sl"; + } else { + $netpbmlibsuffix = "so"; + } + } + } elsif ($response eq "static") { + $willBuildShared = $FALSE; + $netpbmlibtype = "unixstatic"; + $netpbmlibsuffix = "a"; + # targets, but needed for building + # libopt + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'static' or 'shared'.\n"); + exit 12; + } + + print("\n"); + + # Note that we can't do both a static and shared library for AIX, because + # they both have the same name: libnetpbm.a. + + if (($netpbmlibtype eq "unixshared" or + $netpbmlibtype eq "irixshared" or + $netpbmlibtype eq "dll") and $netpbmlibsuffix ne "a") { + print("Do you want to build static libraries too (for linking to \n"); + print("programs not in the Netpbm package?\n"); + print("\n"); + + my $default = "y"; + + my $response = prompt("(y)es or (n)o", $default); + + if (uc($response) =~ /^(Y|YES)$/) { + $staticlib_too = "y"; + } elsif (uc($response) =~ /^(N|NO)$/) { + $staticlib_too = "n"; + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'yes' or 'no' (or 'y' or 'n').\n"); + exit 12; + } + } else { + $staticlib_too = "n"; + } + print("\n"); + + $$netpbmlibtypeR = $netpbmlibtype; + $$netpbmlibsuffixR = $netpbmlibsuffix; + $$shlibprefixlistR = $shlibprefixlist; + $$willBuildSharedR = $willBuildShared; + $$staticlib_tooR = $staticlib_too; +} + + + +sub inttypesDefault() { + + my $retval; + + if (defined($testCc)) { + + print("(Doing test compiles to choose a default for you -- " . + "ignore errors)\n"); + + my $cflags = testCflags($FALSE); + + my $works; + + # We saw a system (Irix 5.3 with native IDO, December 2005) on + # which sys/types.h defines uint32_t, but not int32_t and other + # similar types. We saw a Mac OS X system (January 2006) on which + # sys/types sometimes defines uint32_t, but sometimes doesn't. + # So we make those last resorts. + + # int_fastXXX_t are the least likely of all the types to be + # defined, so we look for that. + + # Solaris 8, for example, has a <sys/inttypes.h> that defines + # int32_t and uint32_t, but nothing the defines int_fast32_t. + + my @candidateList = ("<inttypes.h>", "<sys/inttypes.h>", + "<types.h>", "<sys/types.h>"); + + for (my $i = 0; $i < @candidateList && !$works; ++$i) { + my $candidate = $candidateList[$i]; + my @cSourceCode = ( + "#include $candidate\n", + "int_fast32_t testvar;\n" + ); + + testCompile($cflags, \@cSourceCode, \my $success); + + if ($success) { + $works = $candidate; + } + } + if ($works) { + $retval = $works; + } else { + testCompile($cflags, ["int_fast32_t testvar;"], \my $success); + if ($success) { + $retval = "NONE"; + } else { + $retval = '"inttypes_netpbm.h"'; + } + } + print("\n"); + } else { + $retval = '<inttypes.h>'; + } + return $retval; +} + + + +sub getInttypes($) { + my ($inttypesHeaderFileR) = @_; + + my $gotit; + + print("What header file defines uint32_t, etc.?\n"); + print("\n"); + + my $default = inttypesDefault(); + + while (!$gotit) { + my $response = prompt("'#include' argument or NONE", $default); + + if ($response eq "NONE") { + $$inttypesHeaderFileR = ''; + $gotit = $TRUE; + } else { + if ($response !~ m{<.+>} && + $response !~ m{".+"}) { + print("'$response' is not a legal argument of a C #include " . + "statement. It must be something in <> or \"\".\n"); + } else { + $gotit = $TRUE; + $$inttypesHeaderFileR = $response; + } + } + } +} + + +sub getInt64($$) { + + my ($inttypes_h, $haveInt64R) = @_; + + if (defined($testCc)) { + + print("(Doing test compiles to determine if you have int64 type -- " . + "ignore errors)\n"); + + my $cflags = testCflags($FALSE); + + my $works; + + my @cSourceCode = ( + "#include $inttypes_h\n", + "int64_t testvar;\n" + ); + + testCompile($cflags, \@cSourceCode, \my $success); + + if ($success) { + print("You do.\n"); + $$haveInt64R = 'Y'; + } else { + print("You do not. 64-bit code won't be built.\n"); + $$haveInt64R = 'N'; + } + print("\n"); + } else { + $$haveInt64R = "N"; + } +} + + + +# TODO: These should do test compiles to see if the headers are in the +# default search path, both to create a default to offer and to issue a +# warning after user has chosen. Also test links to test the link library. + +# It looks like these should all be in the default search paths and were there +# just to override defaults in Makefile.config.in. Since Configure now +# creates a default of "standard search path," I'm guessing we don't need +# to set these anymore. + +sub getTiffLibrary($@) { + + my ($platform, @suggestedHdrDir) = @_; + + my $tifflib; + { + my $default = "libtiff" . libSuffix($platform); + + print("What is your TIFF (graphics format) library?\n"); + + my $response = prompt("library filename or 'none'", $default); + + if ($response ne "none") { + $tifflib = $response; + } + if (defined($tifflib) and $tifflib =~ m{/} and !-f($tifflib)) { + printf("WARNING: No regular file named '$tifflib' exists.\n"); + } + } + my $tiffhdr_dir; + if (defined($tifflib)) { + my $default; + + if (-d("/usr/include/tiff")) { + $default = "/usr/include/tiff"; + } elsif (-d("/usr/include/libtiff")) { + $default = "/usr/include/libtiff"; + } else { + $default = "default"; + } + print("Where are the interface headers for it?\n"); + + my $response = prompt("TIFF header directory", $default); + + if ($response ne "default") { + $tiffhdr_dir = $response; + } + if (defined($tiffhdr_dir) and !-d($tiffhdr_dir)) { + printf("WARNING: No directory named '$tiffhdr_dir' exists.\n"); + } + } + return($tifflib, $tiffhdr_dir); +} + + + +sub getJpegLibrary($@) { + + my ($platform, @suggestedHdrDir) = @_; + + my $jpeglib; + { + my $default = "libjpeg" . libSuffix($platform); + + print("What is your JPEG (graphics format) library?\n"); + + my $response = prompt("library filename or 'none'", $default); + + if ($response ne "none") { + $jpeglib = $response; + } + } + my $jpeghdr_dir; + if (defined($jpeglib)) { + my $default; + + if (-d("/usr/include/jpeg")) { + $default = "/usr/include/jpeg"; + } else { + $default = "default"; + } + print("Where are the interface headers for it?\n"); + + my $response = prompt("JPEG header directory", $default); + + if ($response ne "default") { + $jpeghdr_dir = $response; + } + if (defined($jpeghdr_dir) and !-d($jpeghdr_dir)) { + printf("WARNING: No directory named '$jpeghdr_dir' exists.\n"); + } + } + return($jpeglib, $jpeghdr_dir); +} + + + +sub getPngLibrary($@) { + + my ($platform, @suggestedHdrDir) = @_; + + my ($pnglib, $pnghdr_dir); + + if (commandExists('libpng-config')) { + # We don't need to ask where Libpng is; there's a 'libpng-config' + # That tells exactly how to access it, and the make files will use + # that. + } else { + { + my $default = "libpng" . libSuffix($platform); + + print("What is your PNG (graphics format) library?\n"); + + my $response = prompt("library filename or 'none'", $default); + + if ($response ne "none") { + $pnglib = $response; + } + } + if (defined($pnglib)) { + my $default; + + if (-d("/usr/include/png")) { + $default = "/usr/include/libpng"; + } else { + $default = "default"; + } + + print("Where are the interface headers for it?\n"); + + my $response = prompt("PNG header directory", $default); + + if ($response ne "default") { + $pnghdr_dir = $response; + } + } + } + return($pnglib, $pnghdr_dir); +} + + + +sub getZLibrary($@) { + + my ($platform, @suggestedHdrDir) = @_; + + my ($zlib, $zhdr_dir); + + { + my $default = "libz" . libSuffix($platform); + + print("What is your Z (compression) library?\n"); + + my $response = prompt("library filename or 'none'", $default); + + if ($response ne "none") { + $zlib = $response; + } + } + if (defined($zlib)) { + my $default; + + if (-d("/usr/include/zlib")) { + $default = "/usr/include/zlib"; + } else { + $default = "default"; + } + + print("Where are the interface headers for it?\n"); + + my $response = prompt("Z header directory", $default); + + if ($response ne "default") { + $zhdr_dir = $response; + } + } + return($zlib, $zhdr_dir); +} + + + +sub getX11Library($@) { + + my ($platform, @suggestedHdrDir) = @_; + + my $x11lib; + { + my $default; + + if (-d('/usr/link/X11')) { + $default = '/usr/link/X11/libX11' . libSuffix($platform); + } elsif (-d('/usr/lib/X11')) { + $default = '/usr/lib/libX11' . libSuffix($platform); + } else { + $default = "libX11" . libSuffix($platform); + } + print("What is your X11 (X client) library?\n"); + + my $response = prompt("library filename or 'none'", $default); + + if ($response ne "none") { + $x11lib = $response; + } + } + my $x11hdr_dir; + if (defined($x11lib)) { + my $default; + + $default = "default"; + + print("Where are the interface headers for it?\n"); + + my $response = prompt("X11 header directory", $default); + + if ($response ne "default") { + $x11hdr_dir = $response; + } + if (defined($x11hdr_dir)) { + if (!-d($x11hdr_dir)) { + printf("WARNING: No directory named '$x11hdr_dir' exists.\n"); + } elsif (!-d("$x11hdr_dir/X11")) { + printf("WARNING: Directory '$x11hdr_dir' does not contain " . + "the requisite 'X11' subdirectory\n"); + } + } + } + return($x11lib, $x11hdr_dir); +} + + + +sub getLinuxsvgaLibrary($@) { + + my ($platform, @suggestedHdrDir) = @_; + + my ($svgalib, $svgalibhdr_dir); + + if ($platform eq "GNU") { + { + my $default; + + if (-d('/usr/link/svgalib')) { + $default = '/usr/link/svgalib/libvga.so'; + } elsif (-d('/usr/lib/svgalib')) { + $default = '/usr/lib/svgalib/libvga.so'; + } else { + $default = 'libvga.so'; + } + + print("What is your Svgalib library?\n"); + + my $response = prompt("library filename or 'none'", $default); + + if ($response ne "none") { + $svgalib = $response; + } + } + } + if (defined($svgalib)) { + my $default; + + if (-d('/usr/include/svgalib')) { + $default = '/usr/include/svgalib'; + } else { + $default = "default"; + } + print("Where are the interface headers for it?\n"); + + my $response = prompt("Svgalib header directory", $default); + + if ($response ne "default") { + $svgalibhdr_dir = $response; + } + if (defined($svgalibhdr_dir)) { + if (!-d($svgalibhdr_dir)) { + printf("WARNING: No directory named " . + "'$svgalibhdr_dir' exists.\n"); + } + } + } + return($svgalib, $svgalibhdr_dir); +} + + + +sub symlink_command() { + + my $retval; + + # Some Windows environments don't have symbolic links (or even a + # simulation via a "ln" command, but have a "cp" command which works + # in a pinch. Some Windows environments have "ln", but it won't do + # symbolic links. + + if (commandExists("ln")) { + # We assume if Perl can do symbolic links, so can Ln, and vice + # versa. + + my $symlink_exists = eval { symlink("",""); 1 }; + + if ($symlink_exists) { + $retval = "ln -s"; + } else { + $retval = "ln"; + } + } elsif (commandExists("cp")) { + $retval = "cp"; + } else { + # Well, maybe we just made a mistake. + $retval = "ln -s"; + } + return $retval; +} + + + +sub help() { + + print("This is the Netpbm custom configuration program. \n"); + print("It is not GNU Configure.\n"); + print("\n"); + print("There is one optional argument to this program: The " . + "name of the file to use as the basis for the Makefile.config " . + "file. Default is 'Makefile.config.in'\n"); + print("\n"); + print("Otherwise, the program is interactive.\n"); +} + + + +sub gnuOptimizeOpt($) { + my ($gccCommandName) = @_; +#----------------------------------------------------------------------------- +# Compute the -O compiler flag appropriate for a GNU system. Ordinarily, +# this is just -O3. But many popular GNU systems have a broken compiler +# that causes -O3 to generate incorrect code (symptom: pnmtojpeg --quality=95 +# generates a syntax error message from shhopt). +#----------------------------------------------------------------------------- +# I don't know what are exactly the cases that Gcc is broken. I know +# Red Hat 7.1 and 7.2 and Mandrake 8.2, running gcc 2.96.1, commonly have +# the problem. But it may be limited to a certain subrelease level or +# CPU type or other environment. People who have reported the problem have +# reported that Gcc 3.0 doesn't have it. Gcc 2.95.3 doesn't have it. + +# Note that automatic inlining happens at -O3 level, but there are some +# subroutines in Netpbm marked for explicit inlining, and we need to disable +# that inlining too, so we must go all the way down to -O0. + + my @gccVerboseResp = `$gccCommandName --verbose 2>&1`; + + my $brokenCompiler; + + if (@gccVerboseResp ==2) { + if ($gccVerboseResp[1] =~ m{gcc version 2.96}) { + $brokenCompiler = $TRUE; + } else { + $brokenCompiler = $FALSE; + } + } else { + $brokenCompiler = $FALSE; + } + + my $oOpt; + + if ($brokenCompiler) { + print("You appear to have a broken compiler which would produce \n"); + print("incorrect code if requested to do inline optimization.\n"); + print("Therefore, I am configuring the build to not do inline \n"); + print("optimization. This will make some Netpbm programs \n"); + print("noticeably slower. If I am wrong about your compiler, just\n"); + print("edit Makefile.config and change -O0 to -O3 near the bottom.\n"); + print("\n"); + print("The problem is known to exist in the GNU Compiler \n"); + print("release 2.96. If you upgrade, you will not have this \n"); + print("problem.\n"); + print("---------------------------------------------\n"); + print("\n"); + $oOpt = "-O0"; + } else { + $oOpt = "-O3"; + } + return $oOpt; +} + + + +sub needLocal($) { +#----------------------------------------------------------------------------- +# Return wether or not /usr/local paths must be added to compiles and +# links. In a properly configured system, those paths should be in +# the compiler and linker default search paths, e.g. the compiler +# should search /usr/local/include and then /usr/include without any +# -I options needed. But we've seen some systems where it isn't. +# +# Actually, I have doubts now as to whether these misconfigured systems +# really exist. This subroutine was apparently always broken, because +# before 04.03.15, it had "netbsd", etc. in lower case. So it always +# returned false. I never had a complaint. Plus, we had a bug in +# Makefile.config.in wherein it wiped out the user's setting of the LDFLAGS +# environment variable. This could explain /usr/local/lib not being in +# the path when it should have been. +# +# So I've disabled this function; we'll see if we encounter any truly +# misconfigured systems. 04.03.15. +#----------------------------------------------------------------------------- + my ($platform) = @_; + + return $FALSE; # See comments above. + + my $needLocal; + + if ($platform eq "NETBSD" || $platform eq "OPENBSD" || + $platform eq "FREEBSD") { + $needLocal = $TRUE; + } else { + $needLocal = $FALSE; + } + return $needLocal; +} + + + +sub findProcessManagement($) { + my ($dontHaveProcessMgmtR) = @_; +#----------------------------------------------------------------------------- +# Return $TRUE iff the system does not have <sys/wait.h> in its default +# search path. +#----------------------------------------------------------------------------- + my $cflags = testCflags($FALSE); + + my @cSourceCode = ( + "#include <sys/wait.h>\n", + ); + + testCompile($cflags, \@cSourceCode, \my $success); + + if (!$success) { + print("Your system does not appear to have <sys/wait.h> in its " . + "standard compiler include path. Therefore, we will build " . + "Netpbm with some function missing (e.g. the pm_system() " . + "function in libnetpbm and most of 'pamlookup'\n"); + $$dontHaveProcessMgmtR = $TRUE; + } else { + $$dontHaveProcessMgmtR = $FALSE; + } +} + + + +sub validateLibraries(@) { + my @libList = @_; +#----------------------------------------------------------------------------- +# Check each library name in the list @libList for viability. +#----------------------------------------------------------------------------- + foreach my $libname (@libList) { + if (defined($libname)) { + if ($libname =~ m{/} and !-f($libname)) { + print("WARNING: No regular file named '$libname' exists.\n"); + } elsif (!($libname =~ m{ .* \. (so|a|sa|sl|dll|dylib) $ }x)) { + print("WARNING: The library name '$libname' does not have " . + "a conventional suffix (.so, .a, .dll, etc.)\n"); + } + } + } +} + + + +sub warnJpegTiffDependency($$) { + my ($jpeglib, $tifflib) = @_; + + if (defined($tifflib) && !defined($jpeglib)) { + print("WARNING: You say you have a Tiff library, " . + "but no Jpeg library.\n"); + print("Sometimes the Tiff library prerequires the " . + "Jpeg library. If \n"); + print("that is the case on your system, you will " . + "have some links fail with\n"); + print("missing 'jpeg...' symbols. If so, rerun " . + "Configure and say you\n"); + print("have no Tiff library either.\n"); + print("\n"); + } +} + + + +sub testCompileJpeglibH($$) { + my ($cflags, $successR) = @_; +#----------------------------------------------------------------------------- +# Do a test compile to see if we can see jpeglib.h. +#----------------------------------------------------------------------------- + my @cSourceCode = ( + "#include <ctype.h>\n", + "#include <stdio.h>\n", + "#include <jpeglib.h>\n", + ); + + testCompile($cflags, \@cSourceCode, $successR); +} + + + +sub testCompileJpegMarkerStruct($$) { + my ($cflags, $successR) = @_; +#----------------------------------------------------------------------------- +# Do a test compile to see if struct jpeg_marker_struct is defined in +# jpeglib.h. Assume it is already established that the compiler works +# and can find jpeglib.h. +#----------------------------------------------------------------------------- + my @cSourceCode = ( + "#include <ctype.h>\n", + "#include <stdio.h>\n", + "#include <jpeglib.h>\n", + "struct jpeg_marker_struct test;\n", + ); + + testCompile($cflags, \@cSourceCode, $successR); +} + + + +sub printMissingHdrWarning($$) { + + my ($name, $hdr_dir) = @_; + + print("WARNING: You said the compile-time part of the $name library " . + "(the header\n"); + print("files) is in "); + + if (defined($hdr_dir)) { + print("directory '$hdr_dir', "); + } else { + print("the compiler's default search path, "); + } + print("but a test compile failed\n"); + print("to confirm that. If your configuration is exotic, the test " . + "compile might\n"); + print("just be wrong, but otherwise the Netpbm build will fail.\n"); + print("\n"); + print("To fix this, either install the $name library there \n"); + print("or re-run Configure and answer the question about the $name " . + "library\n"); + print("differently.\n"); + print("\n"); +} + + + +sub printOldJpegWarning() { + print("WARNING: Your JPEG library appears to be too old for Netpbm.\n"); + print("We base this conclusion on the fact that jpeglib.h apparently\n"); + print("does not define struct jpeg_marker_struct.\n"); + print("If the JPEG library is not Independent Jpeg Group's Version 6b\n"); + print("or better, the Netpbm build will fail when it attempts to build\n"); + print("the parts that use the JPEG library.\n"); + print("\n"); + print("If your configuration is exotic, this test may just be wrong.\n"); + print("Otherwise, either upgrade your JPEG library or re-run Configure\n"); + print("and say you don't have a JPEG library.\n"); + print("\n"); +} + + + +sub testJpegHdr($$) { + + my ($needLocal, $jpeghdr_dir) = @_; + + if (defined($testCc)) { + + my $generalCflags = testCflags($needLocal); + + my $jpegIOpt = $jpeghdr_dir ? "-I$jpeghdr_dir" : ""; + + testCompileJpeglibH("$generalCflags $jpegIOpt", \my $success); + + if (!$success) { + print("\n"); + printMissingHdrWarning("JPEG", $jpeghdr_dir); + } else { + # We can get to something named jpeglib.h, but maybe it's an old + # version we can't use. Check it out. + testCompileJpegMarkerStruct("$generalCflags $jpegIOpt", + \my $success); + if (!$success) { + print("\n"); + printOldJpegWarning(); + } + } + } +} + + + +sub testCompileZlibH($$) { + my ($cflags, $successR) = @_; +#----------------------------------------------------------------------------- +# Do a test compile to see if we can see zlib.h. +#----------------------------------------------------------------------------- + my @cSourceCode = ( + "#include <zlib.h>\n", + ); + + testCompile($cflags, \@cSourceCode, $successR); +} + + + +sub testCompilePngH($$) { + my ($cflags, $successR) = @_; +#----------------------------------------------------------------------------- +# Do a test compile to see if we can see png.h, assuming we can see +# zlib.h, which png.h #includes. +#----------------------------------------------------------------------------- + my @cSourceCode = ( + "#include <png.h>\n", + ); + + testCompile($cflags, \@cSourceCode, $successR); +} + + + +sub testPngHdr($$$) { +#----------------------------------------------------------------------------- +# Issue a warning if the compiler can't find png.h. +#----------------------------------------------------------------------------- + my ($needLocal, $pnghdr_dir, $zhdr_dir) = @_; + + if (defined($testCc)) { + + my $generalCflags = testCflags($needLocal); + + my $zlibIOpt = $zhdr_dir ? "-I$zhdr_dir" : ""; + + testCompileZlibH("$generalCflags $zlibIOpt", \my $success); + if (!$success) { + print("\n"); + printMissingHdrWarning("Zlib", $zhdr_dir); + } else { + my $pngIOpt = $pnghdr_dir ? "-I$pnghdr_dir" : ""; + + testCompilePngH("$generalCflags $zlibIOpt $pngIOpt", + \my $success); + + if (!$success) { + print("\n"); + printMissingHdrWarning("PNG", $pnghdr_dir); + } + } + } +} + + + +sub testLibpngConfig($) { + my ($needLocal) = @_; +#----------------------------------------------------------------------------- +# Issue a warning if the instructions 'libpng-config' give for compiling +# with Libpng don't work. +#----------------------------------------------------------------------------- + my $generalCflags = testCflags($needLocal); + + my $pngCflags = qx{libpng-config --cflags}; + chomp($pngCflags); + + testCompilePngH("$generalCflags $pngCflags", \my $success); + + if (!$success) { + print("\n"); + print("Unable to compile a test PNG program using the compiler " . + "flags that libpng-config says to use: '$pngCflags'.\n"); + print("This indicates that you have Libpng installed incorrectly.\n"); + print("libpng-config gets installed as part of the Libpng package.\n"); + } else { + + + + } +} + + + +sub testConfiguration($$$$$$$) { + + my ($needLocal, $jpeglib, $jpeghdr_dir, + $pnglib, $pnghdr_dir, $zlib, $zhdr_dir) = @_; + + if (defined($jpeglib)) { + testJpegHdr($needLocal, $jpeghdr_dir); + } + if (defined($pnglib) && defined($zlib)) { + testPngHdr($needLocal, $pnghdr_dir, $zhdr_dir); + } elsif (commandExists('libpng-config')) { + testLibpngConfig($needLocal); + } + + # TODO: We ought to validate other libraries too. But it's not + # that important, because in the vast majority of cases where the + # user incorrectly identifies any library, it affects all the + # libraries and if the user can get a handle on the JPEG library + # problem, he will also solve problems with any other library. +} + + + +#****************************************************************************** +# +# MAINLINE +# +#***************************************************************************** + +autoFlushStdout(); + +my $configInPathArg; +if (@ARGV > 0) { + if ($ARGV[0] =~ "^-") { + if ($ARGV[0] eq "--help") { + help(); + exit(0); + } else { + die("Unrecognized option: $ARGV[0]"); + } + } + $configInPathArg = $ARGV[0]; +} + +if (stat("Makefile.config")) { + print("Discard existing Makefile.config?\n"); + print("Y or N (N) ==> "); + + my $answer = <STDIN>; + if (!defined($answer)) { + die("\nEnd of file on Standard Input"); + } + chomp($answer); + if (uc($answer) ne "Y") { + print("Aborting at user request.\n"); + exit(1); + } +} + +print("\n"); + +displayIntroduction(); + +my ($platform, $subplatform) = getPlatform(); + +print("\n"); + +if ($platform eq "NONE") { + print("You will have to construct Makefile.config manually. To do \n"); + print("this, copy Makefile.config.in as Makefile.config, and then \n"); + print("edit it. Follow the instructions and examples in the file. \n"); + print("Please report your results to the Netpbm maintainer so he \n"); + print("can improve the configure program. \n"); + exit; +} + +getCompiler($platform, \my $compiler); +getLinker($platform, $compiler, \my $baseLinker, \my $linkViaCompiler); + +chooseTestCompiler($compiler, \$testCc); + +my $netpbmlib_runtime_path; + # Undefined if the default from Makefile.config.in is acceptable. + +if ($platform eq "SOLARIS" or $platform eq "IRIX" or + $platform eq "DARWIN" or $platform eq "NETBSD" or + $platform eq "AMIGA") { + print("Where will the Netpbm shared library reside once installed?\n"); + print("Enter 'default' if it will reside somewhere that the shared\n"); + print("library loader will find it automatically. Otherwise, \n"); + print("this directory will get built into the Netpbm programs.\n"); + print("\n"); + + my $default = "default"; + my $response = prompt("Netpbm shared library directory", $default); + + if ($response eq "default") { + $netpbmlib_runtime_path = ""; + } else { + $netpbmlib_runtime_path = $response; + } +} + +my $default_target; + +print("Do you want a regular build or a merge build?\n"); +print("If you don't know what this means, " . + "take the default or see doc/INSTALL\n"); +print("\n"); + +{ + my $default = "regular"; + my $response = prompt("regular or merge", $default); + + if ($response eq "regular") { + $default_target = "nonmerge"; + } elsif ($response eq "merge") { + $default_target = "merge"; + } else { + print("'$response' isn't one of the choices. \n" . + "You must choose 'regular' or 'merge'.\n"); + exit 12; + } +} + +print("\n"); + +getLibTypes($platform, $subplatform, $default_target, + \my $netpbmlibtype, \my $netpbmlibsuffix, \my $shlibprefixlist, + \my $willBuildShared, \my $staticlib_too); + + +getInttypes(\my $inttypesHeaderFile); + +getInt64($inttypesHeaderFile, \my $haveInt64); + +findProcessManagement(\my $dontHaveProcessMgmt); + +#****************************************************************************** +# +# FIND THE PREREQUISITE LIBRARIES +# +#***************************************************************************** + +print("\n\n"); +print("The following questions concern the subroutine libraries that are " . + "Netpbm\n"); +print("prerequisites. Every library has a compile-time part (header " . + "files)\n"); +print("and a link-time part. In the case of a shared library, these are " . + "both\n"); +print("part of the \"development\" component of the library, which may be " . + "separately\n"); +print("installable from the runtime shared library. For each library, you " . + "must\n"); +print("give the filename of the link library. If it is not in your " . + "linker's\n"); +print("default search path, give the absolute pathname of the file. In " . + "addition,\n"); +print("you will be asked for the directory in which the library's interface " . + "headers\n"); +print("reside, and you can respond 'default' if they are in your compiler's " . + "default\n"); +print("search path.\n"); +print("\n"); +print("If you don't have the library on your system, you can enter 'none' " . + "as the\n"); +print("library filename and the builder will skip any part that requires " . + "that "); +print("library.\n"); +print("\n"); + +my ($jpeglib, $jpeghdr_dir) = getJpegLibrary($platform); +print("\n"); +my ($tifflib, $tiffhdr_dir) = getTiffLibrary($platform, $jpeghdr_dir); +print("\n"); +my ($pnglib, $pnghdr_dir) = getPngLibrary($platform, + $tiffhdr_dir, $jpeghdr_dir); +print("\n"); +my ($zlib, $zhdr_dir) = getZLibrary($platform, + $pnghdr_dir, + $tiffhdr_dir, + $jpeghdr_dir); +print("\n"); +my ($x11lib, $x11hdr_dir) = getX11Library($platform); + +print("\n"); +my ($linuxsvgalib, $linuxsvgahdr_dir) = getLinuxsvgaLibrary($platform); + +print("\n"); + +# We should add the JBIG and URT libraries here too. They're a little +# more complicated because there are versions shipped with Netpbm. + + +#****************************************************************************** +# +# CONFIGURE DOCUMENTATION +# +#***************************************************************************** + +print("What URL will you use for the main Netpbm documentation page?\n"); +print("This information does not get built into any programs or libraries.\n"); +print("It does not make anything actually install that web page.\n"); +print("It is just for including in legacy man pages.\n"); +print("\n"); + +my $default = "http://netpbm.sourceforge.net/doc/"; + +my $netpbm_docurl = prompt("Documentation URL", $default); + +print("\n"); + + + + +#****************************************************************************** +# +# VALIDATE THE CONFIGURATION USER HAS SELECTED +# +#***************************************************************************** + +validateLibraries($jpeglib, $tifflib, $pnglib, $zlib); + +warnJpegTiffDependency($jpeglib, $tifflib); + +testConfiguration(needLocal($platform), + $jpeglib, $jpeghdr_dir, + $pnglib, $pnghdr_dir, + $zlib, $zhdr_dir, + ); + +#****************************************************************************** +# +# FIND THE NETPBM SOURCE TREE AND INITIALIZE BUILD TREE +# +#***************************************************************************** + +my $defaultConfigInPath; + +if (-f("GNUmakefile")) { + # He's apparently running us in the source tree or an already set up + # build directory. + $defaultConfigInPath = "Makefile.config.in"; +} else { + my $srcdir; + my $done; + + $done = $FALSE; + while (!$done) { + print("Where is the Netpbm source code?\n"); + + $srcdir = prompt("Netpbm source directory", + abs_path(dirname($0) . "/..")); + + if (-f("$srcdir/GNUmakefile")) { + $done = $TRUE; + } else { + print("That doesn't appear to contain Netpbm source code.\n"); + print("There is no file named 'GNUmakefile' in it.\n"); + print("\n"); + } + } + unlink("GNUmakefile"); + symlink("$srcdir/GNUmakefile", "GNUmakefile"); + unlink("Makefile"); + symlink("$srcdir/Makefile", "Makefile"); + + open(SRCDIR, ">Makefile.srcdir"); + print(SRCDIR "SRCDIR = $srcdir\n"); + close(SRCDIR); + + $defaultConfigInPath = "$srcdir/Makefile.config.in"; +} + +sub makeCompilerGcc($) { + my ($Makefile_configR) = @_; + my $compileCommand = 'gcc'; + push(@{$Makefile_configR}, "CC = $compileCommand\n"); + push(@{$Makefile_configR}, gnuCflags($compileCommand)); +} + + +#****************************************************************************** +# +# BUILD Makefile.config +# +#***************************************************************************** + +sub gnuCflags($) { + my ($gccCommandName) = @_; + + return("CFLAGS = " . gnuOptimizeOpt($gccCommandName) . " -ffast-math " . + " -pedantic -fno-common " . + "-Wall -Wno-uninitialized -Wmissing-declarations -Wimplicit " . + "-Wwrite-strings -Wmissing-prototypes -Wundef\n"); +} + +my @Makefile_config; + # This is the complete Makefile.config contents. We construct it here + # and ultimately write the whole thing out as Makefile.config. + +# First, we just read the 'Makefile.config.in' in + +my $configInPath; +if (defined($configInPathArg)) { + $configInPath = $configInPathArg; +} else { + $configInPath = $defaultConfigInPath; +} +open (CONFIG_IN,"<$configInPath") or + die("Unable to open file '$configInPath' for input."); + +@Makefile_config = <CONFIG_IN>; + +unshift(@Makefile_config, + "####This file was automatically created by 'configure.'\n", + "####Many variables are set twice -- a generic setting, then \n", + "####a system-specific override at the bottom of the file.\n", + "####\n"); + +close(CONFIG_IN); + +# Now, add the variable settings that override the default settings that are +# done by the Makefile.config.in contents. + +push(@Makefile_config, "\n\n\n\n"); +push(@Makefile_config, "####Lines above were copied from Makefile.config.in " . + "by 'configure'.\n"); +push(@Makefile_config, "####Lines below were added by 'configure' based on " . + "the $platform platform.\n"); +if (defined($subplatform)) { + push(@Makefile_config, "####subplatform '$subplatform'\n"); +} + +push(@Makefile_config, "DEFAULT_TARGET = $default_target\n"); + +push(@Makefile_config, "NETPBMLIBTYPE=$netpbmlibtype\n"); +push(@Makefile_config, "NETPBMLIBSUFFIX=$netpbmlibsuffix\n"); +if (defined($shlibprefixlist)) { + push(@Makefile_config, "SHLIBPREFIXLIST=$shlibprefixlist\n"); +} +push(@Makefile_config, "STATICLIB_TOO=$staticlib_too\n"); + +if (defined($netpbmlib_runtime_path)) { + push(@Makefile_config, "NETPBMLIB_RUNTIME_PATH=$netpbmlib_runtime_path\n"); +} + +if ($platform eq "GNU") { + my $compileCommand; + if (!commandExists("cc") && commandExists("gcc")) { + $compileCommand = "gcc"; + push(@Makefile_config, "CC = $compileCommand\n"); + } else { + $compileCommand = "cc"; + } + push(@Makefile_config, gnuCflags($compileCommand)); +# The merged programs have a main_XXX subroutine instead of main(), +# which would cause a warning with -Wmissing-declarations or +# -Wmissing-prototypes. + push(@Makefile_config, "CFLAGS_MERGE = " . + "-Wno-missing-declarations -Wno-missing-prototypes\n"); + push(@Makefile_config, "LDRELOC = ld --reloc\n"); + push(@Makefile_config, "LINKER_CAN_DO_EXPLICIT_LIBRARY=Y\n"); +} elsif ($platform eq "SOLARIS") { + push(@Makefile_config, 'LDSHLIB = -Wl,-Bdynamic,-G,-h,$(SONAME)', "\n"); + + push(@Makefile_config, 'NEED_RUNTIME_PATH = Y', "\n"); + if ($compiler eq "cc") { + push(@Makefile_config, "CFLAGS = -O\n"); + push(@Makefile_config, "CFLAGS_SHLIB = -Kpic\n"); + } else { + makeCompilerGcc(\@Makefile_config); + } + # Before Netpbm 10.20 (January 2004), we set this to -R for + # $compiler == cc and -rpath otherwise. But now we know that the GNU + # compiler can also invoke a linker that needs -R, so we're more flexible. + if ($baseLinker eq "GNU") { + push(@Makefile_config, "RPATHOPTNAME = -rpath\n"); + } else { + push(@Makefile_config, "RPATHOPTNAME = -R\n"); + } + push(@Makefile_config, "NETWORKLD = -lsocket -lnsl\n"); +} elsif ($platform eq "HP-UX") { + if ($compiler eq "gcc") { + makeCompilerGcc(\@Makefile_config); + push(@Makefile_config, "CFLAGS += -fPIC\n"); + push(@Makefile_config, "LDSHLIB = -shared -fPIC\n"); + push(@Makefile_config, 'LDFLAGS += -Wl,+b,/usr/pubsw/lib', "\n"); + } else { + # We don't know what to do here. We used to (before 10.20) just + # just assume the compiler was gcc. We know that the gcc stuff + # above does NOT work for HP native compiler. + } +} elsif ($platform eq "AIX") { + push(@Makefile_config, 'LDFLAGS = -L /usr/pubsw/lib', "\n"); + if ($compiler eq "cc") { + # Yes, the -L option implies the runtime as well as linktime library + # search path. There's no way to specify runtime path independently. + push(@Makefile_config, "RPATHOPTNAME = -L\n"); + push(@Makefile_config, "LDSHLIB = -qmkshrobj\n"); + } else { + makeCompilerGcc(\@Makefile_config); + push(@Makefile_config, "LDSHLIB = -shared\n"); + } +} elsif ($platform eq "TRU64") { +# push(@Makefile_config, "INSTALL = installbsd\n"); + if ($compiler eq "cc") { + push(@Makefile_config, 'CFLAGS = -O2 -std1', "\n"); + push(@Makefile_config, "LDFLAGS = -call_shared -oldstyle_liblookup " . + "-L/usr/local/lib\n"); + push(@Makefile_config, "LDSHLIB = -shared -expect_unresolved \"*\"\n"); + } else { + # We've never tested this. This is just here to give a user a + # headstart on submitting to us the necessary information. 2002.07.04. + push(@Makefile_config, "CC = gcc\n"); + push(@Makefile_config, 'CFLAGS = -O3', "\n"); + push(@Makefile_config, "LDSHLIB = -shared\n"); + } + # Between May 2000 and July 2003, we had -DLONG_32 in these options. + # We took it out because it generated bad code for a TRU64 user in + # July 2003 whose system has 64 bit long and 32 bit int. It affects + # only Ppmtompeg and it isn't clear that using long instead of int is + # ever right anyway. + + push(@Makefile_config, "OMIT_NETWORK = y\n"); + push(@Makefile_config, "LINKER_CAN_DO_EXPLICIT_LIBRARY=Y\n"); +} elsif ($platform eq "IRIX") { +# push(@Makefile_config, "INSTALL = install\n"); + push(@Makefile_config, "MANPAGE_FORMAT = cat\n"); + push(@Makefile_config, "RANLIB = true\n"); + push(@Makefile_config, "CFLAGS = -n32 -O3 -fullwarn\n"); + push(@Makefile_config, "LDFLAGS = -n32\n"); + push(@Makefile_config, "LDSHLIB = -shared -n32\n"); +} elsif ($platform eq "WINDOWS") { + if ($subplatform eq "cygwin") { + makeCompilerGcc(\@Makefile_config); + } + push(@Makefile_config, "EXE = .exe\n"); + push(@Makefile_config, "OMIT_NETWORK = y\n"); +# # Though it may not have the link as "ginstall", "install" in a Windows +# # Unix environment is usually GNU install. +# my $ginstall_result = `ginstall --version 2>/dev/null`; +# if (!$ginstall_result) { +# # System doesn't have 'ginstall', so use 'install' instead. +# push(@Makefile_config, "INSTALL = install\n"); +# } + push(@Makefile_config, 'SYMLINK = ', symlink_command(), "\n"); + push(@Makefile_config, 'DLLVER=$(NETPBM_MAJOR_RELEASE)', "\n"); + push(@Makefile_config, "LDSHLIB = " . + '-shared -Wl,--image-base=0x10000000 -Wl,--enable-auto-import', "\n"); +} elsif ($platform eq "BEOS") { + push(@Makefile_config, "LDSHLIB = -nostart\n"); +} elsif ($platform eq "NETBSD") { + push(@Makefile_config, 'CFLAGS_SHLIB = -fpic', "\n"); +} elsif ($platform eq "OPENBSD") { + # vedge@vedge.com.ar says on 2001.04.29 that there are a ton of + # undefined symbols in the Fiasco stuff on OpenBSD. So we'll just + # cut it out of the build until someone feels like fixing it. + push(@Makefile_config, "BUILD_FIASCO = N\n"); +} elsif ($platform eq "FREEBSD") { +} elsif ($platform eq "AMIGA") { + push(@Makefile_config, "CFLAGS = -m68020-60 -ffast-math -mstackextend\n"); +} elsif ($platform eq "UNIXWARE") { + # Nothing to do. +} elsif ($platform eq "SCO") { + # Got this from "John H. DuBois III" <spcecdt@armory.com> 2002.09.27: + push(@Makefile_config, "RANLIB = true\n"); + if ($compiler eq "cc") { + push(@Makefile_config, "CFLAGS = -O\n"); + push(@Makefile_config, "CFLAGS_SHLIB = -O -K pic\n"); + push(@Makefile_config, "LD_SHLIB = -G\n"); + push(@Makefile_config, "SHLIB_CLIB =\n"); + } else { + makeCompilerGcc(\@Makefile_config); + } + push(@Makefile_config, "CFLAGS_SHLIB = -fPIC\n"); + push(@Makefile_config, "LDSHLIB = -shared\n"); + push(@Makefile_config, "NETWORKLD = -lsocket -lresolve\n"); +} elsif ($platform eq "DARWIN") { + push(@Makefile_config, "CC = cc -no-cpp-precomp\n"); + push(@Makefile_config, 'CFLAGS_SHLIB = -fno-common', "\n"); + push(@Makefile_config, "LDSHLIB = ", + "-dynamiclib ", + '-install_name $(NETPBM_RUNTIME_PATH)/libnetpbm.$(MAJ).dylib', + "\n"); +# push(@Makefile_config, "INSTALL = install\n"); +} else { + die ("Internal error: invalid value for \$platform: '$platform'\n"); +} + +if (needLocal($platform)) { + push(@Makefile_config, "CFLAGS += -I/usr/local/include\n"); + push(@Makefile_config, "LDFLAGS += -L/usr/local/lib\n"); +} + +if ($linkViaCompiler) { + push(@Makefile_config, "LINKERISCOMPILER = Y\n"); +} + +my $flex_result = `flex --version`; +if (!$flex_result) { + # System doesn't have 'flex'. Maybe 'lex' will work. See the + # make rules for Thinkjettopbm for information on our experiences + # with Lexes besides Flex. + + my $systemRc = system('lex </dev/null &>/dev/null'); + + if ($systemRc >> 8 == 127) { + print("\n"); + print("You do not appear to have the 'flex' or 'lex' pattern \n"); + print("matcher generator on your system, so we will not build \n"); + print("programs that need it (Thinkjettopbm)\n"); + + print("\n"); + print("Press ENTER to continue.\n"); + my $key = <STDIN>; + print("\n"); + + push(@Makefile_config, "LEX=\n"); + } else { + print("\n"); + print("Using 'lex' as the pattern matcher generator, " . + "since we cannot\n"); + print("find 'flex' on your system.\n"); + print("\n"); + + push(@Makefile_config, "LEX = lex\n"); + } +} + +if (defined($tiffhdr_dir)) { + push(@Makefile_config, "TIFFHDR_DIR = $tiffhdr_dir\n"); +} +if (defined($tifflib)) { + push(@Makefile_config, "TIFFLIB = $tifflib\n"); +} + +if (defined($jpeghdr_dir)) { + push(@Makefile_config, "JPEGHDR_DIR = $jpeghdr_dir\n"); +} +if (defined($jpeglib)) { + push(@Makefile_config, "JPEGLIB = $jpeglib\n"); +} + +if (defined($pnghdr_dir)) { + push(@Makefile_config, "PNGHDR_DIR = $pnghdr_dir\n"); +} +if (defined($pnglib)) { + push(@Makefile_config, "PNGLIB = $pnglib\n"); +} + +if (defined($zhdr_dir)) { + push(@Makefile_config, "ZHDR_DIR = $zhdr_dir\n"); +} +if (defined($zlib)) { + push(@Makefile_config, "ZLIB = $zlib\n"); +} + +if (defined($x11hdr_dir)) { + push(@Makefile_config, "X11HDR_DIR = $x11hdr_dir\n"); +} +if (defined($x11lib)) { + push(@Makefile_config, "X11LIB = $x11lib\n"); +} + +if (defined($linuxsvgahdr_dir)) { + push(@Makefile_config, "LINUXSVGAHDR_DIR = $linuxsvgahdr_dir\n"); +} +if (defined($linuxsvgalib)) { + push(@Makefile_config, "LINUXSVGALIB = $linuxsvgalib\n"); +} + +if (defined($netpbm_docurl)) { + push(@Makefile_config, "NETPBM_DOCURL = $netpbm_docurl\n"); +} + +if ($inttypesHeaderFile ne '<inttypes.h>') { + push(@Makefile_config, "INTTYPES_H = $inttypesHeaderFile\n"); +} + +if ($haveInt64 ne 'Y') { + push(@Makefile_config, "HAVE_INT64 = $haveInt64\n"); +} + +if ($dontHaveProcessMgmt) { + push(@Makefile_config, "DONT_HAVE_PROCESS_MGMT = Y\n"); +} + +#****************************************************************************** +# +# WRITE OUT THE FILE +# +#***************************************************************************** + +open(MAKEFILE_CONFIG, ">Makefile.config") or + die("Unable to open Makefile.config for writing in the current " . + "directory."); + +print MAKEFILE_CONFIG @Makefile_config; + +close(MAKEFILE_CONFIG) or + die("Error: Close of Makefile.config failed.\n"); + +print("\n"); +print("We have created the file 'Makefile.config'. Note, however, that \n"); +print("we guessed a lot at your configuration and you may want to look \n"); +print("at Makefile.config and edit it to your requirements and taste \n"); +print("before doing the make.\n"); +print("\n"); + + +print("Now you may proceed with 'make'\n"); +print("\n"); + + +exit 0; diff --git a/buildtools/empty_depend b/buildtools/empty_depend new file mode 100755 index 00000000..a4ba372c --- /dev/null +++ b/buildtools/empty_depend @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +use strict; + +# This program turns every Makefile.depend file into an empty file, +# so that dependencies in there can't make trouble for users trying to +# build Netpbm. They don't need dependencies anyway, since they're +# building everything and not modifying anything. + +# Developers should do 'make dep' to create real Makefile.depend files +# before building + +my $mf_list = `find . -name Makefile.depend`; +my @mf_list = split(/\s/, $mf_list); +foreach (@mf_list) { + print "Emptying $_\n"; + open(MF, ">$_"); + close(MF); +} diff --git a/buildtools/endiangen b/buildtools/endiangen new file mode 100755 index 00000000..8783096e --- /dev/null +++ b/buildtools/endiangen Binary files differdiff --git a/buildtools/endiangen.c b/buildtools/endiangen.c new file mode 100644 index 00000000..07560c10 --- /dev/null +++ b/buildtools/endiangen.c @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------------- + endiangen +------------------------------------------------------------------------------ + This is a program to create C code that declares the endianness of the + machine on which it is run. + + It generates something like this: + + #ifndef LITTLE_ENDIAN + #define LITTLE_ENDIAN 1234 + #endif + + #ifndef BIG_ENDIAN + #define BIG_ENDIAN 4321 + #endif + + #ifndef BYTE_ORDER + #define BYTE_ORDER LITTLE_ENDIAN + #endif + + #define BITS_PER_WORD 32 + #endif + + + Really good code usually is not sensitive to endianness. But fast, + not-so-good code often is. The best way for code to determine + endianness is for it to do a runtime cast of an integer to an array + of characters and see where the bytes land. But if speed requires + even sleazier code than that, use these macros. + +-----------------------------------------------------------------------------*/ +#include <stdio.h> +#include <unistd.h> + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +enum endianness {ENDIAN_LITTLE, ENDIAN_BIG}; + +static enum endianness +byteOrder(void) { + + enum endianness retval; + + union { + unsigned char arrayval[2]; + unsigned short numval; + } testunion; + + testunion.numval = 3; + + if (testunion.arrayval[0] == 3) + retval = ENDIAN_LITTLE; + else + retval = ENDIAN_BIG; + + return retval; +} + + + +static unsigned int +bitsPerWord(void) { + + return MAX(sizeof(long), sizeof(int)) * 8; +} + + + +int +main(int argc, char **argv) { + + printf("/* This was generated by the program 'endiangen' */\n"); + printf("\n"); + printf("/* LITTLE_ENDIAN, BIG_ENDIAN, and BYTE_ORDER " + "may come from the C library\n"); + printf("via ctype.h. */\n"); + printf("#include <ctype.h>\n"); + printf("#ifndef LITTLE_ENDIAN\n"); + printf("#define LITTLE_ENDIAN 1234\n"); + printf("#endif\n"); + printf("#ifndef BIG_ENDIAN\n"); + printf("#define BIG_ENDIAN 4321\n"); + printf("#endif\n"); + printf("\n"); + printf("#ifndef BYTE_ORDER\n"); + printf("#define BYTE_ORDER %s\n", + byteOrder() == ENDIAN_LITTLE ? "LITTLE_ENDIAN" : "BIG_ENDIAN"); + printf("#endif\n"); + printf("\n"); + printf("#define BITS_PER_WORD %u\n", bitsPerWord()); + + return 0; +} + + + + diff --git a/buildtools/install.sh b/buildtools/install.sh new file mode 100755 index 00000000..cd324f3d --- /dev/null +++ b/buildtools/install.sh @@ -0,0 +1,255 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + if [ -f "$1.exe" ] + then + src=$1.exe + else + src=$1 + fi + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/buildtools/installnetpbm.pl b/buildtools/installnetpbm.pl new file mode 100755 index 00000000..db3f6200 --- /dev/null +++ b/buildtools/installnetpbm.pl @@ -0,0 +1,919 @@ +#!/usr/bin/perl -w + +require 5.000; + +#Note: mkdir() must have 2 arguments as late as 5.005. + +use strict; +use English; +use Fcntl; +use File::Basename; + +my ($TRUE, $FALSE) = (1,0); + +my $cpCommand; +#use vars qw($cpCommand); + +#****************************************************************************** +# +# SUBROUTINES +# +#***************************************************************************** + +sub autoFlushStdout() { + my $oldFh = select(STDOUT); + $OUTPUT_AUTOFLUSH = $TRUE; + select($oldFh); +} + + + +sub prompt($$) { + + my ($prompt, $default) = @_; + + print("$prompt ($default) ==> "); + + my $response = <STDIN>; + + chomp($response); + if ($response eq "") { + $response = $default; + } + + return $response; +} + + + +sub getPkgdir() { + + my $pkgdir; + + while (!$pkgdir) { + + print("Where is the install package you created with " . + "'make package'?\n"); + my $default = "/tmp/netpbm"; + + my $response = prompt("package directory", $default); + + if (!-f("$response/pkginfo")) { + print("This does not appear to be a Netpbm install package. \n"); + print("A file named $response/pkginfo does not exist.\n"); + print("\n"); + } else { + $pkgdir = $response; + } + } + print("\n"); + return $pkgdir; +} + + + +sub makePrefixDirectory($) { + + my ($prefixDir) = @_; + + if ($prefixDir ne "" and !-d($prefixDir)) { + print("No directory named '$prefixDir' exists. Do you want " . + "to create it?\n"); + + my $done; + while (!$done) { + my $response = prompt("Y(es) or N(o)", "Y"); + if (uc($response) eq "Y") { + my $success = mkdir($prefixDir, 0777); + if (!$success) { + print("Unable to create directory '$prefixDir'. " . + "Error is $ERRNO\n"); + } + $done = $TRUE; + } elsif (uc($response) eq "N") { + $done = $TRUE; + } + } + } +} + + + + + +sub getPrefix() { + + print("Enter the default prefix for installation locations. " . + "I will use \n"); + print("this in generating defaults for the following prompts to " . + "save you \n"); + print("typing. If you plan to spread Netpbm across your system, \n" . + "enter '/'.\n"); + print("\n"); + + my $default; + if ($OSNAME eq "cygwin") { + $default = "/usr/local"; + } elsif ($ENV{OSTYPE} && $ENV{OSTYPE} eq "msdosdjgpp") { + $default = "/dev/env/DJDIR"; + } else { + $default = "/usr/local/netpbm"; + } + + my $response = prompt("install prefix", $default); + + my $prefix; + + # Remove possible trailing / + if (substr($response,-1,1) eq "/") { + $prefix = substr($response, 0, -1); + } else { + $prefix = $response; + } + print("\n"); + + makePrefixDirectory($prefix); + + return $prefix; +} + + + +sub getCpCommand() { +#----------------------------------------------------------------------------- +# compute the command + options need to do a recursive copy, preserving +# symbolic links and file attributes. +#----------------------------------------------------------------------------- + my $cpCommand; + + # We definitely need more intelligence here, but we'll need input from + # users to do it. Maybe we should just bundle GNU Cp with Netpbm as an + # install tool. Maybe we should write a small recursive copy program + # that uses more invariant tools, like buildtools/install.sh does for + # single files. + + if (`cp --version 2>/dev/null` =~ m/GNU/) { + # It's GNU Cp -- we have options galore, and they're readable. + $cpCommand = "cp --recursive --preserve --no-dereference"; + } else { + # This works on Cp from "4th Berkeley Distribution", July 1994. + # Mac OSX has this. + # -R means recursive with no dereferencing of symlinks + # -p means preserve attributes + $cpCommand = "cp -R -p"; + } + return($cpCommand); +} + + + +sub getBinDir($) { + + my ($prefix) = @_; + + print("Where do you want the programs installed?\n"); + print("\n"); + + my $binDir; + + while (!$binDir) { + my $default = "$prefix/bin"; + + my $response = prompt("program directory", $default); + + if (-d($response)) { + $binDir = $response; + } else { + my $succeeded = mkdir($response, 0777); + + if (!$succeeded) { + print("Unable to create directory '$response'. " . + "Error=$ERRNO\n"); + } else { + $binDir = $response; + } + } + } + print("\n"); + + return $binDir; +} + + + +sub installProgram($$$) { + + my ($pkgdir, $prefix, $bindirR) = @_; + + my $binDir = getBinDir($prefix); + + print("Installing programs...\n"); + + my $rc = system("$cpCommand $pkgdir/bin/* $binDir/"); + + if ($rc != 0) { + print("Copy of programs from $pkgdir/bin to $binDir failed.\n"); + print("cp return code is $rc\n"); + } else { + print("Done.\n"); + } + $$bindirR = $binDir; +} + + + +sub getLibDir($) { + + my ($prefix) = @_; + + print("Where do you want the shared library installed?\n"); + print("\n"); + + my $libDir; + + while (!$libDir) { + my $default = "$prefix/lib"; + + my $response = prompt("shared library directory", $default); + + if (-d($response)) { + $libDir = $response; + } else { + my $succeeded = mkdir($response, 0777); + + if (!$succeeded) { + print("Unable to create directory '$response'. " . + "Error=$ERRNO\n"); + } else { + $libDir = $response; + } + } + } + print("\n"); + + return $libDir; +} + + + +sub +execLdconfig() { +#----------------------------------------------------------------------------- +# Run Ldconfig. Try with the -X option first, and if that is an invalid +# option (which we have seen on an openBSD system), try it without -X. +# +# -X means "don't create any symlinks." Any symlinks required should be +# created as part of installing the library, so we don't need that function +# from Ldconfig. And we want to tread as lightly as possible on the +# system -- we don't want creating symlinks that have nothing to do with +# Netpbm to be a hidden side effect of installing Netpbm. +# +# Note that this Ldconfig works only if the user installed the Netpbm +# library in a standard directory that Ldconfig searches. Note that on +# OpenBSD, Ldconfig is hardcoded to search only /usr/lib ever. We could +# also do 'ldconfig DIR' to scan the particular directory in which we +# installed the Netpbm library. But 1) the effects of this would disappear +# the next time the user rebuilds the cache file; and 2) on OpenBSD, this +# causes the cache file to be rebuilt from ONLY that directory. On OpenBSD, +# you can add the -m option to cause it to ADD the contents of DIR to the +# existing cache file. +# +#----------------------------------------------------------------------------- +# Implementation note: We've seen varying completion codes and varying +# error messages from different versions of Ldconfig when it fails. + + my $ldconfigSucceeded; + + my $ldconfigXResp = `ldconfig -X 2>&1`; + + if (!defined($ldconfigXResp)) { + print("Unable to run Ldconfig.\n"); + $ldconfigSucceeded = $FALSE; + } elsif ($ldconfigXResp eq "") { + $ldconfigSucceeded = $TRUE; + } elsif ($ldconfigXResp =~ m{usage}i) { + print("Trying Ldconfig again without the -X option...\n"); + + my $rc = system("ldconfig"); + + $ldconfigSucceeded = ($rc == 0); + } else { + print($ldconfigXResp); + $ldconfigSucceeded = $FALSE; + } + + if ($ldconfigSucceeded) { + print("Ldconfig completed successfully.\n"); + } else { + print("Ldconfig failed. You will have to fix this later.\n"); + } +} + + + +sub +doLdconfig() { +#----------------------------------------------------------------------------- +# Run Ldconfig where appropriate. +#----------------------------------------------------------------------------- + if ($OSNAME eq "linux" || system("ldconfig -? 2>/dev/null") != 127) { + # This is a system where Ldconfig makes sense + + print("In order for the Netpbm shared library to be found when " . + "you invoke \n"); + print("A Netpbm program, you must either set an environment " . + "variable to \n"); + print("tell where to look for it, or you must put its location " . + "in the shared \n"); + print("library location cache. Do you want to run Ldconfig now " . + "to put the \n"); + print("Netpbm shared library in the cache? This works only if " . + "you have\n"); + print("installed the library in a standard location.\n"); + print("\n"); + + my $done; + + $done = $FALSE; + + while (!$done) { + my $response = prompt("Y(es) or N(o)", "Y"); + + if (uc($response) eq "Y") { + execLdconfig(); + $done = $TRUE; + } elsif (uc($response) eq "N") { + $done = $TRUE; + } else { + print("Invalid response. Enter 'Y' or 'N'\n"); + } + } + } +} + + + +sub installSharedLib($$$) { + + my ($pkgdir, $prefix, $libdirR) = @_; + + if (-d("$pkgdir/lib")) { + my $libDir = getLibDir($prefix); + + print("Installing shared libraries...\n"); + + my $rc = system("$cpCommand $pkgdir/lib/* $libDir/"); + + if ($rc != 0) { + print("Copy of libraries from $pkgdir/lib to $libDir failed.\n"); + print("cp return code is $rc\n"); + } else { + print("done.\n"); + print("\n"); + doLdconfig(); + } + $$libdirR = $libDir; + } else { + print("You did not build a shared library, so I will not " . + "install one.\n"); + } + print("\n"); +} + + + +sub getLinkDir($) { + + my ($prefix) = @_; + + print("Where do you want the static link library installed?\n"); + print("\n"); + + my $linkDir; + + while (!$linkDir) { + my $default = "$prefix/lib"; + + my $response = prompt("static library directory", $default); + + if (-d($response)) { + $linkDir = $response; + } else { + my $succeeded = mkdir($response, 0777); + + if (!$succeeded) { + print("Unable to create directory '$response'. " . + "Error=$ERRNO\n"); + } else { + $linkDir = $response; + } + } + } + print("\n"); + + return $linkDir; +} + + + +sub installStaticLib($$$) { + + my ($pkgdir, $prefix, $linkdirR) = @_; + + if (-d("$pkgdir/link")) { + my $linkDir = getLinkDir($prefix); + + print("Installing link libraries.\n"); + + my $rc = system("$cpCommand $pkgdir/link/* $linkDir/"); + + if ($rc != 0) { + print("Copy of files from $pkgdir/link to $linkDir failed.\n"); + print("cp return code is $rc\n"); + } else { + print("done.\n"); + } + $$linkdirR = $linkDir; + } else { + print("You did not build a static library, so I will not " . + "install one \n"); + } +} + + + +sub getDataDir($) { + + my ($prefix) = @_; + + print("Where do you want the data files installed?\n"); + print("\n"); + + my $dataDir; + + while (!$dataDir) { + my $default = "$prefix/lib"; + + my $response = prompt("data file directory", $default); + + if (-d($response)) { + $dataDir = $response; + } else { + my $succeeded = mkdir($response, 0777); + + if (!$succeeded) { + print("Unable to create directory '$response'. " . + "Error=$ERRNO\n"); + } else { + $dataDir = $response; + } + } + } + print("\n"); + + return $dataDir; +} + + + +sub getHdrDir($) { + + my ($prefix) = @_; + + print("Where do you want the library interface header files installed?\n"); + print("\n"); + + my $hdrDir; + + while (!$hdrDir) { + my $default = "$prefix/include"; + + my $response = prompt("header directory", $default); + + if (-d($response)) { + $hdrDir = $response; + } else { + my $succeeded = mkdir($response, 0777); + + if (!$succeeded) { + print("Unable to create directory '$response'. " . + "Error=$ERRNO\n"); + } else { + $hdrDir = $response; + } + } + } + print("\n"); + + return $hdrDir; +} + + + +sub installDataFile($$$) { + + my ($pkgdir, $prefix, $datadirR) = @_; + + my $dataDir = getDataDir($prefix); + + print("Installing data files...\n"); + + my $rc = system("$cpCommand $pkgdir/misc/* $dataDir/"); + + if ($rc != 0) { + print("copy of data files from $pkgdir/misc to $dataDir " . + "failed.\n"); + print("cp exit code is $rc\n"); + } else { + $$datadirR = $dataDir; + print("done.\n"); + } +} + + + +sub installHeader($$$) { + + my ($pkgdir, $prefix, $includedirR) = @_; + + my $hdrDir = getHdrDir($prefix); + + print("Installing interface header files...\n"); + + my $rc = system("$cpCommand $pkgdir/include/* $hdrDir/"); + + if ($rc != 0) { + print("copy of header files from $pkgdir/include to $hdrDir " . + "failed.\n"); + print("cp exit code is $rc\n"); + } else { + print("done.\n"); + } + $$includedirR = $hdrDir; +} + + + +sub getManDir($) { + + my ($prefix) = @_; + + print("Where do you want the man pages installed?\n"); + + print("\n"); + + my $manDir; + + while (!$manDir) { + my $default = "$prefix/man"; + + my $response = prompt("man page directory", $default); + + if (-d($response)) { + $manDir = $response; + } else { + my $succeeded = mkdir($response, 0777); + + if (!$succeeded) { + print("Unable to create directory '$response'. " . + "Error=$ERRNO\n"); + } else { + $manDir = $response; + } + } + } + print("\n"); + + return $manDir; +} + + + +sub removeObsoleteManPage($) { + + my ($mandir) = @_; + + unlink("$mandir/man1/pgmoil"); + unlink("$mandir/man1/pgmnorm"); + unlink("$mandir/man1/ppmtojpeg"); + unlink("$mandir/man1/bmptoppm"); + unlink("$mandir/man1/ppmtonorm"); + unlink("$mandir/man1/ppmtouil"); + unlink("$mandir/man1/pnmnoraw"); + unlink("$mandir/man1/gemtopbm"); + unlink("$mandir/man1/pnminterp"); +} + + + +sub tryToCreateManwebConf($) { + + my ($manweb_conf_filename) = $@; + + print("You don't have a /etc/manweb.conf, which is the " . + "configuration\n"); + print("file for the 'manweb' program, which is a quick way to " . + "get to Netpbm\n"); + print("documentation. Would you like to create one now?\n"); + + my $done; + + while (!$done) { + my $response = prompt("create /etc/manweb.conf", "Y"); + + if (uc($response) eq "Y") { + my $successful = open(MANWEB_CONF, ">/etc/manweb.conf"); + if (!$successful) { + print("Unable to create file /etc/manweb.conf. " . + "error = $ERRNO\n"); + } else { + print(MANWEB_CONF "#Configuration file for Manweb\n"); + print(MANWEB_CONF "webdir=/usr/man/web\n"); + close(MANWEB_CONF); + $done = $TRUE; + } + } else { + $done = $TRUE; + } + } +} + + + +sub getWebdir($) { + my ($manweb_conf_filename) = @_; +#----------------------------------------------------------------------------- +# Return the value of the Manweb "web directory," as indicated by the +# Manweb configuration file $manweb_conf_filename. +# +# If that file doesn't exist, or doesn't have a 'webdir' value, or +# the 'webdir' value is a chain of directories instead of just one, +# we return an undefined value. +#----------------------------------------------------------------------------- + my $webdir; + + my $success = open(MANWEB_CONF, "<$manweb_conf_filename"); + if (!$success) { + print("Unable to open file '$manweb_conf_filename' for reading. " . + "error is $ERRNO\n"); + } else { + while (<MANWEB_CONF>) { + chomp(); + if (/^\s*#/) { + #It's comment - ignore + } elsif (/^\s*$/) { + #It's a blank line - ignore + } elsif (/\s*(\S+)\s*=\s*(\S+)/) { + #It looks like "keyword=value" + my ($keyword, $value) = ($1, $2); + if ($keyword eq "webdir") { + # We can't handle a multi-directory path; we're looking + # only for a webdir statement naming a sole directory. + if ($value !~ m{:}) { + $webdir = $value; + } + } + } + } + close(MANWEB_CONF); + } + + return $webdir +} + + + +sub userWantsManwebSymlink($$) { + + my ($webdir, $netpbmWebdir) = @_; + + print("Your manweb.conf file says top level documentation " . + "is in $webdir, \n"); + print("but you installed netpbm.url in $netpbmWebdir.\n"); + print("Do you want to create a symlink in $webdir now?\n"); + + my $wants; + my $done; + + while (!$done) { + my $response = prompt("create symlink (Y/N)", "Y"); + + if (uc($response) eq "Y") { + $wants = $TRUE; + $done = $TRUE; + } elsif (uc($response) eq "N") { + $wants = $FALSE; + $done = $TRUE; + } + } + return $wants; +} + + + +sub makeInManwebPath($) { + + my ($netpbmWebdir) = @_; + + # Now we need /etc/manweb.conf to point to the directory in which we + # just installed netpbm.url. + + if (!-f("/etc/manweb.conf")) { + tryToCreateManwebConf("/etc/manweb.conf"); + } + if (-f("/etc/manweb.conf")) { + my $webdir = getWebdir("/etc/manweb.conf"); + if (defined($webdir)) { + if ($webdir ne $netpbmWebdir) { + if (userWantsManwebSymlink($webdir, $netpbmWebdir)) { + my $old = "$netpbmWebdir/netpbm.url"; + my $new = "$webdir/netpbm.url"; + mkdir($webdir, 0777); + my $success = symlink($old, $new); + if (!$success) { + print("Failed to create symbolic link from $new to " . + "$old. Error is $ERRNO\n"); + } + } + } + } + } +} + + + +sub installManPage($$$) { + + +# Note: This installs the pointer man pages and the netpbm.url file for Manweb. + + my ($pkgdir, $prefix, $mandirR) = @_; + + my $manDir = getManDir($prefix); + + print("Installing man pages...\n"); + + my $rc = system("$cpCommand $pkgdir/man/* $manDir/"); + + if ($rc != 0) { + print("copy of man pages from $pkgdir/man to $manDir failed.\n"); + print("cp exit code is $rc\n"); + } else { + print("done.\n"); + } + + print("\n"); + + removeObsoleteManPage($manDir); + + makeInManwebPath("$manDir/web"); + + $$mandirR = $manDir; +} + + + +sub +processTemplate($$$$$$$$$) { + my ($templateR, $version, $bindir, $libdir, $linkdir, $datadir, + $includedir, $mandir, $outputR) = @_; + + my @output; + + foreach (@{$templateR}) { + if (m{^@}) { + # Comment -- ignore it. + } else { + if (defined($version)) { + s/\@VERSION\@/$version/; + } + if (defined($bindir)) { + s/\@BINDIR@/$bindir/; + } + if (defined($libdir)) { + s/\@LIBDIR@/$libdir/; + } + if (defined($linkdir)) { + s/\@LINKDIR@/$linkdir/; + } + if (defined($datadir)) { + s/\@DATADIR@/$datadir/; + } + if (defined($includedir)) { + s/\@INCLUDEDIR@/$includedir/; + } + if (defined($mandir)) { + s/\@MANDIR@/$mandir/; + } + push(@output, $_); + } + } + $$outputR = \@output; +} + + + +sub +installConfig($$$$$$$) { + my ($pkgdir, + $bindir, $libdir, $linkdir, $datadir, $includedir, $mandir) = @_; + + my $error; + + my $configTemplateFilename = dirname($0) . "/config_template"; + + my $templateOpened = open(TEMPLATE, "<", $configTemplateFilename); + if (!$templateOpened) { + $error = "Can't open template file '$configTemplateFilename'.\n"; + } else { + my @template = <TEMPLATE>; + + close(TEMPLATE); + + my $versionOpened = open(VERSION, "<", "$pkgdir/VERSION"); + + my $version; + if (!$versionOpened) { + $error = "Unable to open $pkgdir/VERSION for reading. " . + "Errno=$ERRNO\n"; + } else { + $version = <VERSION>; + chomp($version); + close(VERSION); + + processTemplate(\@template, $version, $bindir, $libdir, + $linkdir, $datadir, $includedir, $mandir, + \my $fileContentsR); + + # TODO: Really, this ought to go in an independent directory, + # because you might want to have the Netpbm executables in + # some place not in the PATH and use this program, via the + # PATH, to find them. + + my $filename = "$bindir/netpbm-config"; + + my $success = open(NETPBM_CONFIG, ">", $filename); + if ($success) { + chmod(0755, $filename); + foreach (@{$fileContentsR}) { print NETPBM_CONFIG; } + close(NETPBM_CONFIG); + } else { + $error = "Unable to open the file " . + "'$filename' for writing. Errno=$ERRNO\n"; + } + } + } + if ($error) { + print(STDERR "Failed to create the Netpbm configuration program. " . + "$error\n"); + } +} + + + +#****************************************************************************** +# +# MAINLINE +# +#***************************************************************************** + +autoFlushStdout(); + +print("Welcome to the Netpbm install dialogue. We will now proceed \n"); +print("to interactively install Netpbm on this system.\n"); +print("\n"); +print("You must have already built Netpbm and then packaged it for \n"); +print("installation by running 'make package'. See the INSTALL file.\n"); +print("\n"); + +my $pkgdir = getPkgdir(); + +my $prefix = getPrefix(); + +$cpCommand = getCpCommand(); + +installProgram($pkgdir, $prefix, \my $bindir); +print("\n"); + +installSharedLib($pkgdir, $prefix, \my $libdir); +print("\n"); + +installStaticLib($pkgdir, $prefix, \my $linkdir); +print("\n"); + +installDataFile($pkgdir, $prefix, \my $datadir); +print("\n"); + +installHeader($pkgdir, $prefix, \my $includedir); +print("\n"); + +installManPage($pkgdir, $prefix, \my $mandir); +print("\n"); + +installConfig($pkgdir, + $bindir, $libdir, $linkdir, $datadir, $includedir, $mandir); + +print("Installation is complete (except where previous error messages have\n"); +print("indicated otherwise).\n"); + +exit(0); diff --git a/buildtools/installosf b/buildtools/installosf new file mode 100755 index 00000000..a4e5c262 --- /dev/null +++ b/buildtools/installosf @@ -0,0 +1,31 @@ +#!/bin/sh + +# This program takes parameters as a Netpbm make file might pass to +# its $(INSTALL) program and invokes OSF1 Install with the proper +# parameters to effect what the make file wants. If your system has +# OSF1 Install on it, you can just set the INSTALL variable in +# Makefile.config to "installosf" and 'make install' will work for +# you. + +# Of course, you could also just install Ginstall and forget about this +# program. + +PERMISSIONS=444 +while [ $# -gt 0 ]; do + if [ "$1" = "-c" ]; then x=x; + elif [ "$1" = "-s" ]; then x=x; + elif [ "$1" = "-m" ]; then + shift + PERMISSIONS=$1 + elif [ ${SOURCE_FILE}x == x ]; then + SOURCE_FILE=$1 + else + TARGET_DIR=$1 + fi + shift; +done + +install -f $TARGET_DIR -m $PERMISSIONS $SOURCE_FILE + + + diff --git a/buildtools/libopt b/buildtools/libopt new file mode 100755 index 00000000..6d84ce67 --- /dev/null +++ b/buildtools/libopt Binary files differdiff --git a/buildtools/libopt.c b/buildtools/libopt.c new file mode 100644 index 00000000..132f05f2 --- /dev/null +++ b/buildtools/libopt.c @@ -0,0 +1,541 @@ +/*---------------------------------------------------------------------------- + libopt +------------------------------------------------------------------------------ + This is a program to convert link library filepaths to linker options + that select them. E.g. ../lib/libnetpbm.so becomes -L../lib -lnetpbm . + + Each argument is a library filepath. The option string to identify + all of those library filepaths goes to Standard Output. + + If there is no slash in the library filepath, we assume it is just a + filename to be searched for in the linker's default search path, and + generate a -l option, but no -L. + + If an argument doesn't make sense as a library filespec, it is + copied verbatim, blank delimited, to the output string. + + The "lib" part of the library name, which we call the prefix, may be + other than "lib". The list of recognized values is compiled in as + the macro SHLIBPREFIXLIST (see below). + + There is no newline or null character or anything after the output. + + If you specify the option "-runtime", the output includes a -R + option in addition, for every library after "-runtime" in the + arguments. -R tells the buildtime linker to include the specified + library's directory in the search path that the runtime linker uses + to find dynamically linked libraries. + + But if you compile this program with the EXPLICIT macro defined, and + a library filepath contains a slash, then it skips all that -L/-l + nonsense and just outputs the input library filepath verbatim (plus + any -R option). +------------------------------------------------------------------------------ + Why would you want to use this? + + On some systems, the -L/-l output of this program has exactly the + same effect as the filepath input when used in the arguments to a + link command. A GNU/Linux system, for example. On others (Solaris, + for example), if you include /tmp/lib/libnetpbm.so in the link as a + link object, the executable gets built in such a way that the system + accesses the shared library /tmp/lib/libnetpbm.so at run time. On the + other hand, if you instead put the options -L/tmp/lib -lnetpbm on the + link command, the executable gets built so that the system accesses + libnetpbm.so in its actual installed directory at runtime (that + location might be determined by a --rpath linker option or a + LD_LIBRARY_PATH environment variable at run time). + + In a make file, it is nice to use the same variable as the + dependency of a rule that builds an executable and as the thing that + the rule's command uses to identify its input. Here is an example + of using libopt for that: + + NETPBMLIB=../lib/libnetpbm.so + ... + pbmmake: pbmmake.o $(PBMLIB) + ld -o pbmmake pbmmake.o `libopt $(PBMLIB)` --rpath=/lib/netpbm + + Caveat: "-L../lib -lnetpbm" is NOT exactly the same as + "../pbm/libnetpbm.so" on any system. All of the -l libraries are + searched for in all of the -L directories. So you just might get a + different library with the -L/-l version than if you specify the + library file explicitly. + + That's why you should compile with -DEXPLICIT if your linker can + handle explicit file names. + +-----------------------------------------------------------------------------*/ +#define _BSD_SOURCE 1 /* Make sure strdup() is in stdio.h */ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ + +#define MAX_PREFIXES 10 + +/* Here's how to use SHLIBPREFIXLIST: Use a -D compile option to pass in + a value appropriate for the platform on which you are linking libraries. + + It's a blank-delimited list of prefixes that library names might + have. "lib" is traditionally the only prefix, as in libc or + libnetpbm. However, on Windows there is a convention of using + different prefixes to distinguish different co-existent versions of + the same library (kind of like a major number in some unices). + E.g. the value "cyg lib" is appropriate for a Cygwin system. +*/ +#ifndef SHLIBPREFIXLIST +# define SHLIBPREFIXLIST "lib" +#endif + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +typedef unsigned char bool; +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +#ifdef DLLVERSTR +static const char * dllverstr = DLLVERSTR; +#else +static const char * dllverstr = ""; +#endif + +bool const explicit = +#ifdef EXPLICIT +TRUE +#else +FALSE +#endif +; + +static void +strfree(const char * const arg) { + free((void*) arg); +} + + +static void +parse_prefixlist(const char * const prefixlist, + char * parsed_prefixes[MAX_PREFIXES+1], + bool * const errorP) { +/*---------------------------------------------------------------------------- + Given a space-separated list of tokens (suffixes), return an + argv-style array of pointers, each to a newly malloc'ed storage + area the prefix as a null-terminated string. Return a null string + for the unused entries at the end of the array + + We never return more than MAX_PREFIXES prefixes from the input, so + there is guaranteed always to be one null string at the end of the + array. + + In case of error, return *errorP == TRUE and don't allocate any + storage. Otherwise, return *errorP = FALSE. +-----------------------------------------------------------------------------*/ + char * prlist; + + prlist = strdup(prefixlist); + if (prlist == NULL) + *errorP = TRUE; + else { + if (strlen(prlist) <= 0) + *errorP = TRUE; + else { + /* NOTE: Mac OS X, at least, does not have strtok_r(). + 2001.09.24 + */ + char * token; + int num_tokens; + int i; + + for (i=0; i < MAX_PREFIXES + 1; i++) { + parsed_prefixes[i] = NULL; + } + num_tokens = 0; + token = strtok(prlist, " "); + *errorP = FALSE; /* initial value */ + while (token != NULL && num_tokens < MAX_PREFIXES && !*errorP) { + parsed_prefixes[num_tokens] = strdup (token); + if (parsed_prefixes[num_tokens] == NULL) + *errorP = TRUE; + num_tokens++; + token = strtok(NULL, " "); + } + for (i = num_tokens; i < MAX_PREFIXES + 1 && !*errorP; i++) { + parsed_prefixes[i] = strdup(""); + if (parsed_prefixes[i] == NULL) + *errorP = TRUE; + } + } + if (*errorP) { + /* Deallocate any array entries we successfully did */ + int i; + for (i = 0; i < MAX_PREFIXES + 1; i++) + if (parsed_prefixes[i]) + free(parsed_prefixes[i]); + } + free(prlist); + } +} + + + +static void +parse_prefix(const char * const filename, + bool * const prefix_good_p, unsigned int * const prefix_length_p, + bool * const error_p) { +/*---------------------------------------------------------------------------- + Find the library name prefix (e.g. "lib") in the library filename + 'filename'. + + Return the length of the prefix, in characters, as *prefix_length_p. + (The prefix always starts at the beginning of the filename). + + Iff we don't find a valid library name prefix, return *prefix_good_p + == FALSE. + + The list of valid prefixes is compiled in as the blank-delimited + string which is the value of the SHLIBPREFIXLIST macro. +-----------------------------------------------------------------------------*/ + char * shlibprefixlist[MAX_PREFIXES+1]; + /* An argv-style array of prefix strings in the first entries, + null strings in the later entries. At most MAX_PREFIXES prefixes, + so at least one null string. + */ + char * prefix; + /* The prefix that the filename actually + uses. e.g. if shlibprefixlist = { "lib", "cyg", "", ... } and the + filename is "path/to/cyg<something>.<extension>", then + prefix = "cyg". String is in the same storage as pointed to by + shlibprefixlist (shlibprefixlist[1] in this example). + */ + bool prefix_good; + /* The first part of the filename matched one of the prefixes + in shlibprefixlist[]. + */ + int prefix_length; + int i; + + parse_prefixlist(SHLIBPREFIXLIST , shlibprefixlist, error_p); + if (!*error_p) { + if (strcmp(shlibprefixlist[0], "") == 0) { + fprintf(stderr, "libopt was compiled with an invalid value " + "of the SHLIBPREFIX macro. It seems to have no " + "tokens. SHLIBPREFIX = '%s'", + SHLIBPREFIXLIST); + exit(100); + } + + i = 0; /* start with the first entry in shlibprefixlist[] */ + prefix_length = 0; /* initial value */ + prefix = shlibprefixlist[i]; + prefix_good = FALSE; /* initial value */ + while ( (*prefix != '\0' ) && !prefix_good ) { + /* stop condition: shlibprefixlist has MAX_PREFIXES+1 entries. + * we only ever put tokens in the 0..MAX_PREFIXES-1 positions. + * Then, we fill DOWN from the MAX_PREFIXES position with '\0' + * so we insure that the shlibprefixlist array contains at + * least one final '\0' string, but probably many '\0' + * strings (depending on how many tokens there were). + */ + prefix_length = strlen(prefix); + if (strncmp(filename, prefix, prefix_length) == 0) { + prefix_good = TRUE; + /* at this point, prefix is pointing to the correct + * entry, and prefix_length has the correct value. + * When we bail out of the while loop because of the + * !prefix_good clause, we can then use these + * vars (prefix, prefix_length) + */ + } else { + prefix = shlibprefixlist[++i]; + } + } + *prefix_length_p = prefix_length; + *prefix_good_p = prefix_good; + { + int i; + for (i=0; i < MAX_PREFIXES + 1; i++) + free (shlibprefixlist[i]); + } + } +} + + + +static void +parse_filename(const char * const filename, + const char ** const libname_p, + bool * const valid_library_p, + bool * const static_p, + bool * const error_p) { +/*---------------------------------------------------------------------------- + Extract the library name root component of the filename 'filename'. This + is just a filename, not a whole pathname. + + Return it in newly malloc'ed storage pointed to by '*libname_p'. + + E.g. for "libxyz.so", return "xyz". + + return *valid_library_p == TRUE iff 'filename' validly names a library + that can be expressed in a -l linker option. + + return *static_p == TRUE iff 'filename' indicates a static library. + (but undefined if *valid_library_p != TRUE). + + return *error_p == TRUE iff some error such as out of memory prevents + parsing. + + Do not allocate any memory if *error_p == TRUE or *valid_library_p == FALSE. +-----------------------------------------------------------------------------*/ + char *lastdot; + /* Pointer to last period in 'filename'. Null if none */ + + /* We accept any period-delimited suffix as a library type suffix. + It's probably .so or .a, but is could be .kalamazoo for all we + care. (HOWEVER, the double-suffixed import lib used on + cygwin (.dll.a) is NOT understood). + */ + char *p; + + lastdot = strrchr(filename, '.'); + if (lastdot == NULL) { + /* This filename doesn't have any suffix, so we don't understand + it as a library filename. + */ + *valid_library_p = FALSE; + *error_p = FALSE; + } else { + unsigned int prefix_length; + bool prefix_good; + + if (strcmp(lastdot, "a") == 0) + *static_p = TRUE; + else + *static_p = FALSE; + + parse_prefix(filename, &prefix_good, &prefix_length, error_p); + if (!*error_p) { + if (!prefix_good) { + *valid_library_p = FALSE; + } else { + /* Extract everything between <prefix> and "." as + the library name root. + */ + char * libname; + + libname = strdup(filename + prefix_length); + if (libname == NULL) + *error_p = TRUE; + else { + libname[lastdot - filename - prefix_length] = '\0'; + if (strlen(dllverstr) > 0) { + p = strstr(libname, dllverstr); + if (p) { + if (libname + strlen(libname) + - strlen(dllverstr) == p) { + *p = '\0'; + } + } + } + if (strlen(libname) == 0) { + *valid_library_p = FALSE; + strfree(libname); + } else + *valid_library_p = TRUE; + } + *libname_p = libname; + } + } + } +} + +static void +parse_filepath(const char * const filepath, + const char ** const directory_p, + const char ** const filename_p, + bool * const error_p) { +/*---------------------------------------------------------------------------- + Extract the directory and filename components of the filepath + 'filepath' and return them in newly malloc'ed storage pointed to by + '*directory_p' and '*filename_p'. + + If there is no directory component, return a null string for it. +-----------------------------------------------------------------------------*/ + char *directory; + char *lastslash; /* Pointer to last slash in 'filepath', or null if none */ + + lastslash = strrchr(filepath, '/'); + + if (lastslash == NULL) { + /* There's no directory component; the filename starts at the + beginning of the filepath + */ + *filename_p = strdup(filepath); + if (*filename_p == NULL) + *error_p = TRUE; + else { + directory = strdup(""); + if (directory == NULL) { + *error_p = TRUE; + strfree(*filename_p); + } else + *error_p = FALSE; + } + } else { + /* Split the string at the slash we just found, into filename and + directory + */ + *filename_p = strdup(lastslash+1); + if (*filename_p == NULL) + *error_p = TRUE; + else { + directory = strdup(filepath); + if (directory == NULL) { + *error_p = TRUE; + strfree(*filename_p); + } else { + *error_p = FALSE; + directory[lastslash - filepath] = '\0'; + } + } + } + *directory_p = directory; +} + + + +static void +doOptions(const char * const filepath, + const char * const directory, + const char * const libname, + bool const runtime, + bool const explicit, + bool const staticlib, + const char ** const optionsP) { + + char * options; + char * linkopt; + + if (strlen(directory) == 0) { + linkopt = malloc(strlen(libname) + 10); + sprintf(linkopt, "-l%s", libname); + } else { + if (explicit) + linkopt = strdup(filepath); + else { + linkopt = malloc(strlen(directory) + strlen(libname) + 10); + sprintf(linkopt, "-L%s -l%s", directory, libname); + } + } + if (runtime && !staticlib && strlen(directory) > 0) { + options = malloc(strlen(linkopt) + strlen(directory) + 10); + sprintf(options, "%s -R%s", linkopt, directory); + } else + options = strdup(linkopt); + + strfree(linkopt); + + *optionsP = options; +} + + + +static void +processOneLibrary(const char * const filepath, + bool const runtime, + bool const explicit, + const char ** const optionsP, + bool * const errorP) { +/*---------------------------------------------------------------------------- + Process the library with filepath 'filepath'. Return the resulting + linker option string as a newly malloced null-terminated string at + *optionsP. +-----------------------------------------------------------------------------*/ + const char *directory; + /* Directory component of 'filepath' */ + const char *filename; + /* Filename component of 'filepath' */ + + parse_filepath(filepath, &directory, &filename, errorP); + if (!*errorP) { + const char *libname; + /* Library name component of 'filename'. e.g. xyz in + libxyz.so + */ + bool valid_library; + /* Our argument is a valid library filepath that can be + converted to -l/-L notation. + */ + bool staticlib; + /* Our argument appears to name a static library. */ + + parse_filename(filename, + &libname, &valid_library, &staticlib, errorP); + + if (!*errorP) { + if (valid_library) { + doOptions(filepath, directory, libname, + runtime, explicit, staticlib, optionsP); + + strfree(libname); + } else + *optionsP = strdup(filepath); + } + strfree(directory); + strfree(filename); + } +} + + + +int +main(int argc, char **argv) { + + bool error; + bool runtime; /* -runtime option has been seen */ + bool quiet; /* -quiet option has been seen */ + int retval; + unsigned int arg; /* Index into argv[] of argument we're processing */ + char outputLine[1024]; + + strcpy(outputLine, ""); /* initial value */ + runtime = FALSE; /* initial value */ + quiet = FALSE; /* initial value */ + error = FALSE; /* no error yet */ + for (arg = 1; arg < argc && !error; arg++) { + if (strcmp(argv[arg], "-runtime") == 0) + runtime = TRUE; + else if (strcmp(argv[arg], "-quiet") == 0) + quiet = TRUE; + else { + if (strlen(argv[arg]) > 200) + error = TRUE; + else { + const char * options; + processOneLibrary(argv[arg], runtime, explicit, + &options, &error); + if (!error) { + if (strlen(outputLine) + strlen(options) + 1 + 1 > + sizeof(outputLine)) + error = TRUE; + else { + strcat(outputLine, " "); + strcat(outputLine, options); + } + strfree(options); + } + } + } + } + if (error) { + fprintf(stderr, "serious libopt error prevented parsing library " + "names. Invalid input to libopt is NOT the problem.\n"); + retval = 10; + } else { + fputs(outputLine, stdout); + retval = 0; + } + return retval; +} diff --git a/buildtools/make_merge.sh b/buildtools/make_merge.sh new file mode 100755 index 00000000..9043ad05 --- /dev/null +++ b/buildtools/make_merge.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# This program is called by the make files. It creates the merge.h +# file which is included by netpbm.c. + +echo "/* File generated by make_merge.sh */" +echo "/* in directory" `pwd` "*/" +echo + +for MERGE_BINARY in $*; do + echo "TRY(\"${MERGE_BINARY}\", main_${MERGE_BINARY});" + done diff --git a/buildtools/makecat b/buildtools/makecat new file mode 100755 index 00000000..3a77a2a6 --- /dev/null +++ b/buildtools/makecat @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +use strict; + +my $TRUE=1; my $FALSE = 0; + +foreach my $htmlfilename (@ARGV) { + if ($htmlfilename =~ m{ (.*) \.html $ }x) { + my $basename = $1; + + my $catfilename = "$basename.1"; + + print ("Converting $htmlfilename to $catfilename...\n"); + system("lynx -dump $htmlfilename >$catfilename"); + } else { + print ("Filename '$htmlfilename' doesn't end in 'html'. Skipping.\n"); + } +} diff --git a/buildtools/makeman b/buildtools/makeman new file mode 100755 index 00000000..634a2c79 --- /dev/null +++ b/buildtools/makeman @@ -0,0 +1,333 @@ +#!/bin/env python +# +# makeman -- compile netpbm's stereotyped HTML to troff markup +# +# This approach works because we control the entire document universe +# this is going to convert and can reinforce useful stereotypes. +# +# The output of this tool uses cliches parseable by doclifter, +# which should thus be able to recover all the semantic information +# it looks like this thing is losing. +# +# Known bugs: +# * Ordered lists are smashed into unordered lists +# +# Limitations: +# * IMG tags are issued as .IMG preceded by a bolded caption containing +# the alt content. This will only work if the page is formatted with +# mwww macros. +# * Loses summary information from tables. +# * Only permits one <HR> in the HTML, right before the index. +# +# Use the makeman: passthrough to insert format lines for tables. +# +# By Eric S. Raymond <esr@thyrsus.com> +# Version 1.0, July 26 2004 + +import os, sys, exceptions, re + +source = "netpbm documentation" +section = 1 + +warning = '''\ +.\" This man page was generated by the Netpbm tool 'makeman' from HTML source. +.\" Do not hand-hack it! If you have bug fixes or improvements, please find +.\" the corresponding HTML page on the Netpbm website, generate a patch +.\" against that, and send it to the Netpbm maintainer. +''' + +class LiftException(exceptions.Exception): + def __init__(self, message, retval=1): + self.message = message + self.retval = retval + +def makeman(name, file, indoc): + "Transform a string representing an HTML document into man markup." + global section, sectmap + # Dot at left margin confuses troff. + # This program generates these, + indoc = indoc.replace("\n.", "\n@%@%@") + # Header-bashing + indoc = indoc.replace('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">\n',"") + indoc = indoc.replace('<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">', "") + indoc = indoc.replace('<?xml version="1.1" encoding="iso-8859-1" ?>\n',"") + indoc = indoc.replace('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "DTD/xhtml11.dtd">', "") + indoc = indoc.replace('<html xmlns="http://www.w3.org/1999/xhtml">', "") + indoc = indoc.replace("<HEAD>", "").replace("</HEAD>", "") + indoc = indoc.replace("<head>", "").replace("</head>", "") + indoc = re.sub('(?i)<A HREF="#index">Table Of Contents</A>', "", indoc) + datematch = re.compile("Updated: (.*)\n") + match = datematch.search(indoc) + if match: + date = match.group(1) + else: + date = "" + indoc = datematch.sub("", indoc) + namematch = re.compile("<H1>(.*)</H1>", re.I) + match = namematch.search(indoc) + if match: + name = match.group(1) + else: + name = None + section = 1 + meta = re.compile('(?i)<META NAME="manual_section" CONTENT="([0-9])">') + match = meta.search(indoc) + if match: + section = int(match.group(1)) + indoc = meta.sub("", indoc) + else: + section = sectmap.get(name, 0) + indoc = namematch.sub("", indoc) + indoc = re.sub("(?i)<BODY[^>]*>", "", indoc) + indoc = re.sub("(?i)<HTML>", "", indoc) + # Remove more superfluous headers + titlematch = re.compile("<TITLE>(.*)</TITLE>\n+", re.I) + match = titlematch.search(indoc) + if match: + title = match.group(1) + else: + title = None + indoc = titlematch.sub("", indoc) + indoc = re.sub("(?i)\n*<BR>\n+", "\n", indoc) + indoc = ('.TH "%s" %d "%s" "%s"\n' % (title,section,date,source)) + indoc + # Literal layout + indoc = re.sub("(?i)\n *<PRE>", "\n.nf", indoc) + indoc = re.sub("(?i)\n *</PRE>", "\n.fi", indoc) + indoc = re.sub("(?i)\n *<BLOCKQUOTE>", "\n.nf", indoc) + indoc = re.sub("(?i)\n *</BLOCKQUOTE>", "\n.fi", indoc) + # Highlight processing + indoc = re.sub("(?i)<B>", r"\\fB", indoc) + indoc = re.sub("(?i)</B>", r"\\fP", indoc) + indoc = re.sub("(?i)<EM>", r"\\fI", indoc) + indoc = re.sub("(?i)</EM>", r"\\fP", indoc) + indoc = re.sub("(?i)<CITE>", r"\\fI", indoc) + indoc = re.sub("(?i)</CITE>", r"\\fP", indoc) + indoc = re.sub("(?i)<I>", r"\\fI", indoc) + indoc = re.sub("(?i)</I>", r"\\fP", indoc) + indoc = re.sub("(?i)<TT>", r"\\f(CW", indoc) + indoc = re.sub("(?i)</TT>", r"\\fP", indoc) + indoc = re.sub("(?i)<KBD>", r"\\f(CW", indoc) + indoc = re.sub("(?i)</KBD>", r"\\fP", indoc) + indoc = re.sub("(?i)<STRONG>", r"\\fB", indoc) + indoc = re.sub("(?i)</STRONG>", r"\\fP", indoc) + indoc = re.sub("(?i)<SUP>", r"\\u", indoc) + indoc = re.sub("(?i)</SUP>", r"\\d", indoc) + # Paragraph handling + indoc = re.sub("(?i)\n*<P>\n*", r"\n.PP\n", indoc) + indoc = re.sub("(?i)</P>", "", indoc) + lines = indoc.split("\n") + listdepth = 0 + for i in range(len(lines)): + lowered = lines[i].lower() + if "<dl" in lowered or "<ol" in lowered or "<ul" in lowered: + listdepth += 1 + if listdepth: + lines[i] = lines[i].replace(".PP", ".sp") + if "</dl>" in lowered or "</ol>" in lowered or "</ul>" in lowered: + listdepth -= 1 + indoc = "\n".join(lines) + indoc = re.sub(r"\s*\.sp", "\n.sp", indoc) + # Format email addresses as italic + indoc = re.sub('(?i)<A[ \n]+HREF="mailto:[^>]+">([^<]+)</A>', r'\\fI\1\\fP', indoc) + # Format manual crossreferences + def xrefmatch(match): + xrefto = match.group(1) + xrefsection = sectmap.get(xrefto, 1) + if xrefsection == 0: + return "\n.I " + xrefto + else: + return "\n.BR %s (%d)" % (xrefto, xrefsection) + indoc = re.sub(r'(?i)\n* *(?:\\fB)?<A[ \n]+HREF="[^>]+.html">([^<]+)</A>(?:\\fP)?', + xrefmatch, indoc) + # Format URLs + def urlmatch(match): + url = match.group(1).replace('\n', ' ') + txt = match.group(2).replace('\n', ' ') + return "\n.UR %s\n%s\n.UE\n\\&" % (url, txt) + indoc = re.sub(r'(?i)\n*(?:<)?<A[ \n]+HREF *= *"([^>]+)">([^<]+)</A>(?:>)?', + urlmatch, indoc) + # Turn some entities into harmless cookies + indoc = indoc.replace("<", "@#!#@").replace(">", "#@!@#").replace("&", "#!@!@!#") + indoc = indoc.replace("×", r"\(mu") + indoc = indoc.replace("®", r"\*R") + # Turn anchors into .UN tags + indoc = re.sub('(?i)<A NAME *= *"#?([a-zA-Z][a-zA-Z0-9.-]+)">(?: )*</A>\s*', ".UN \\1\n", indoc) + # Strip off the index trailer + trailer = re.compile('<HR */*>.*', re.DOTALL | re.IGNORECASE) + indoc = re.sub(trailer, "", indoc) + # If there was no index trailer, we still need to strip these + indoc = indoc.replace("</BODY>", "").replace("</HTML>", "") + indoc = indoc.replace("</body>", "").replace("</html>", "") + # Recognize sections with IDs + indoc = re.sub('(?i)<H2><A (?:ID|NAME)="([a-zA-Z]+)">([^><]*)</A></H2>', + ".UN \\1\n.SH \\2", indoc) + indoc = re.sub('(?i)<H3><A (?:ID|NAME)="([a-zA-Z]+)">([^><]*)</A></H3>', + ".UN \\1\n.SS \\2", indoc) + indoc = re.sub('(?i)<H4><A (?:ID|NAME)="([a-zA-Z]+)">([^><]*)</A></H4>', + ".UN \\1\n.B \\2", indoc) + indoc = re.sub('(?i)<H2 (?:ID|NAME)="([a-zA-Z]+)">([^><]*)</H2>', + ".UN \\1\n.SH \\2", indoc) + indoc = re.sub('(?i)<H3 (?:ID|NAME)="([a-zA-Z]+)">([^><]*)</H3>', + ".UN \\1\n.SS \\2", indoc) + indoc = re.sub('(?i)<H4 (?:ID|NAME)="([a-zA-Z]+)">([^><]*)</H4>', + ".UN \\1\n.B \\2", indoc) + # Sections without IDs + indoc = re.sub('(?i)<H2>([^><]*)</H2>', ".SH \\1", indoc) + indoc = re.sub('(?i)<H3>([^><]*)</H3>', ".SS \\1", indoc) + indoc = re.sub('(?i)<H4>([^><]*)</H4>', ".B \\1", indoc) + # + # Process definition lists -- just turn them into .TPs + indoc = re.sub("(?i) *<DL *(COMPACT)?>", "", indoc) + indoc = re.sub("(?i) *</DL>", "", indoc) + indoc = re.sub("(?i) *<DT>", ".TP\n", indoc) + indoc = re.sub("(?i) *</DT>", "", indoc) + indoc = re.sub("(?i)\n*<DD>\n*", "\n", indoc) + indoc = re.sub("(?i) *</DD>", "", indoc) + # Process unordered lists -- just turn them into .TPs + indoc = re.sub("(?i)</?[UO]L *(COMPACT)?>", "", indoc) + indoc = re.sub("(?i) *<LI>", ".IP \(bu\n", indoc) + indoc = re.sub("(?i) *</LI>", "", indoc) + # No-print tags + indoc = re.sub("<!--no_print-->.*", "", indoc) + # Passthrough + indoc = re.sub(r"<\?makeman (.*) \?>", r'\1', indoc) + # Comments + indoc = re.sub("<!--([^-])*-->", r'.\"\1', indoc) + # Image tags + indoc = re.sub(' *<img src="([^"]*)" alt="([^"]*)"( *[a-z]*="?[0-9]*"?)*>', ".B \\2\n.IMG -C \\1", indoc) + # Special characters + indoc = indoc.replace(""", "'") + indoc = indoc.replace(" ", "\\ ") + # Tables + indoc = re.sub(' *<table[^>]*>.*', ".TS", indoc) + indoc = re.sub(" *</table>.*", ".TE", indoc) + # First the single-line case + indoc = re.sub("</td> *<td>", "\t", indoc) + indoc = re.sub("<tr> *<td>", "", indoc) + indoc = re.sub("</td> *</tr>", "", indoc) + # Then the multiline case + indoc = re.sub(r'\s*<t[hd][^>]*>([^<\n]*)</t[dh]>\s*', '\t\\1', indoc) + indoc = re.sub(r'\s*<t[hd][^>]*>([^<]*)</t[dh]>\s*', '\tT{\n\\1T}', indoc) + indoc = indoc.replace("\n\\&T}", "\nT}") + indoc = re.sub(" *</tr>", "", indoc) + indoc = re.sub(" *<tr[^>]*>\t*", "", indoc) + indoc = re.sub(r"\.TS\s+<caption>([^<]*)</caption>\s*", ".B \\1\n.TS\n", indoc) + # Debugging + #sys.stderr.write("Name: %s, Title: %s, Date: %s\n" % (name, title, date)) + # Time for error checking now + badlines = [] + for line in indoc.split("\n"): + if "<" in line or ">" in line or re.search("&.*;", line): + badlines.append(line) + if badlines: + sys.stderr.write(("Bad lines from %s:\n-----------------\n" % file) + "\n".join(badlines) + "\n-----------------\n") + # Goes after bad-line check so we don't misinterpret it as an error + indoc = indoc.replace("@#!#@", "<").replace("#@!@#", ">").replace("#!@!@!#", "&") + indoc = re.sub("\n+$", "\n", indoc) + # Single-quote at left margin confuses troff. + # This program never generates these. + indoc = indoc.replace("\n'", "\n\\&'") + # Finish guarding against leading dots. + indoc = indoc.replace("\n@%@%@", "\n\\&.") + # Mark these generated pages so people won't hand-hack them. + indoc = warning + indoc + return indoc + +def main(args, mainout=sys.stdout, mainerr=sys.stderr): + global sectmap + import getopt + (options, arguments) = getopt.getopt(args, "v") + verbosity = 0 + for (switch, val) in options: + if switch == '-v': + verbosity += 1 + try: + # First pass: gather locations for crossreferences: + sectmap = {} + for file in arguments: + try: + infp = open(file) + except: + sys.stderr.write("can't open %s" % name) + continue + indoc = infp.read() + infp.close() + namere = re.compile("<H1>(.*)</H1>", re.I) + namematch = namere.search(indoc) + titlere = re.compile("<TITLE>(.*)</TITLE>", re.I) + titlematch = titlere.search(indoc) + if not namematch: + raise LiftException("name missing from %s" % file) + if not titlematch: + raise LiftException("title missing from %s" % file) + else: + title = titlematch.group(1) + name = titlematch.group(1) + meta = re.compile('(?i)<META NAME="manual_section" CONTENT="([0-9])">') + match = meta.search(indoc) + if match: + section = int(match.group(1)) + sectmap[title] = sectmap[file] = sectmap[name] = section + else: + sectmap[title] = sectmap[file] = sectmap[name] = 1 + hr = re.compile("(?i)<HR>") + firsthr = hr.search(indoc) + if firsthr and hr.search(indoc[firsthr.start(0)+4:]): + LiftException("%s has two <HR> tags!" % file) + # Second pass: do formatting + for file in arguments: + try: + infp = open(file) + except: + sys.stderr.write("can't open %s" % name) + continue + indoc = infp.read() + infp.close() + tempfile = file + ".~%s-%d~" % (name, os.getpid()) + try: + outfp = open(tempfile, "w") + except OSError: + sys.stderr.write("%s: can't open tempfile" % name) + return True + try: + if verbosity: + sys.stderr.write("makeman: %s\n" % file) + outdoc = makeman(name, file, indoc) + except: + os.remove(tempfile) + # Pass the exception upwards + (exc_type, exc_value, exc_traceback) = sys.exc_info() + raise exc_type, exc_value, exc_traceback + if outdoc == indoc: + os.remove(tempfile) + if outdoc is None: + continue + else: + outfp.write(outdoc) + outfp.close() # under Windows you can't rename an open file + stem = file[:file.find(".")] + os.rename(tempfile, stem + "." + `sectmap[file]`) + except LiftException, e: + mainerr.write("makeman: " + e.message + "\n") + return e.retval + except IOError, e: + mainerr.write("makeman: file I/O error: %s\n" % e) + return 3 + except KeyboardInterrupt: + mainerr.write("makeman: bailing out...\n") + return 4 + except: + if verbosity: + (exc_type, exc_value, exc_traceback) = sys.exc_info() + raise exc_type, exc_value, exc_traceback + else: + return 5 + +if __name__ == "__main__": + # Run the main sequence + raise SystemExit, main(sys.argv[1:]) + +# The following sets edit modes for GNU EMACS +# Local Variables: +# mode:python +# End: diff --git a/buildtools/makepointerman b/buildtools/makepointerman new file mode 100755 index 00000000..8fbb0f49 --- /dev/null +++ b/buildtools/makepointerman @@ -0,0 +1,91 @@ +#!/usr/bin/perl -w + +############################################################################# +# makepointerman +############################################################################# +# +# This program creates a Netpbm man page that says nothing except to use a +# web browser to look at a particular URL. +# +# In Netpbm, we believe that man pages, and the Nroff/Troff formats, are +# obsolete; that HTML and web browsers and the world wide web long ago replaced +# them as the best way to deliver documentation. However, documentation is +# useless when people don't know where it is. People are very accustomed to +# typing "man" to get information on a Unix program or library or file type, +# so in the standard Netpbm installation, we install a conventional man page +# for every command, library, and file type, but all it says is to use your +# web browser to look at the real documentation. + +# What would be ideal is if the user simply had Manweb (or something like +# it) installed as the 'man' command and configured to find the Netpbm +# web documentation. + +# But because of the high probability that Netpbm installers will not +# install Manweb, pointer man pages are necessary. + +# Besides making the web documentation accessible, pointer man pages serve +# another important purpose: Installing them causes obsolete man pages from +# before web documentation existed to be discarded. + +use strict; +use Time::gmtime; + +if (@ARGV < 5) { + die("Need 6 arguments: filename, directory URL, man page directory, " . + "man section, format, octal permissions"); +} + +my ($filename, $directoryUrl, $mandir, $section, $format, $permissions) = + @ARGV; + +if ($format ne "nroff" && $format ne "cat") { + die("format argument must be 'nroff' or 'cat', not '$format'."); +} +my $manPageFileName = "$mandir/$filename.$section"; + +unlink($manPageFileName); + +open(MANPAGE, ">$manPageFileName") or + die("Unable to create file '$manPageFileName'"); + +my ($wday, $mon, $mday, $tod, $year) = split(/ /,gmctime()); +if ($format eq "nroff") { + print(MANPAGE ".TH $filename $section Netpbm \"$mday $mon $year\" " . + "\"Netpbm pointer man pages\"\n\n"); + + # NAME and DESCRIPTION section headings help some automated processors, + # such as Doclifter. From ESR 2004.11.14. + + # avoid a double slash in the URL + (my $cleanedUpDirectoryUrl = $directoryUrl) =~ s{^(.*?)/*$}{$1}; + + print(MANPAGE ".SH NAME\n"); + print(MANPAGE "$filename \\- see $cleanedUpDirectoryUrl/$filename.html\n"); + print(MANPAGE ".SH DESCRIPTION\n"); +} else { + print(MANPAGE " NETPBM POINTER MAN PAGES \n\n"); +} +print(MANPAGE "$filename is part of the Netpbm package.\n"); +print(MANPAGE "Netpbm documentation is kept in HTML format.\n"); +print(MANPAGE "\n"); +print(MANPAGE "Please refer to <$directoryUrl/$filename.html>.\n\n"); +print(MANPAGE "If that doesn't work, also try " . + "<http://netpbm.sourceforge.net> and\n"); +print(MANPAGE "emailing Bryan Henderson, bryanh\@giraffe-data.com.\n"); + +print(MANPAGE "\n"); +print(MANPAGE "Note that making the documentation available this way was\n"); +print(MANPAGE "a choice of the person who installed Netpbm on this system.\n"); +print(MANPAGE "It is also possible to install Netpbm such that you would\n"); +print(MANPAGE "simply see the documentation instead of the message you are\n"); +print(MANPAGE "reading now.\n"); +print(MANPAGE "\n"); + +if ($format eq "nroff") { + print(MANPAGE ".\\\" This file was generated by the program " . + "'makepointerman',\n"); + print(MANPAGE ".\\\" as part of Netpbm installation\n"); +} + +chmod(oct("0$permissions"),$manPageFileName); +close(MANPAGE); diff --git a/buildtools/mkinstalldirs b/buildtools/mkinstalldirs new file mode 100755 index 00000000..2c5ab7cb --- /dev/null +++ b/buildtools/mkinstalldirs @@ -0,0 +1,41 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain + +# This program is important because some systems don't have an 'install' +# program that has the -d option to create directories. + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/buildtools/stamp-date b/buildtools/stamp-date new file mode 100755 index 00000000..808bab79 --- /dev/null +++ b/buildtools/stamp-date @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Copyright (C) 1993 by Oliver Trepte. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, provided +# that the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation. This software is provided "as is" without express or +# implied warranty. +# +DATE=`date` +LOGNAME_OR_UNKNOWN=${LOGNAME:-UNKNOWN} +USER=${USER:-$LOGNAME_OR_UNKNOWN} +if [ $USER = "UNKNOWN" ]; then + USER=`whoami` +fi + +echo "/* This file tells the package when it was compiled */" +echo "/* DO NOT EDIT - THIS FILE IS MAINTAINED AUTOMATICALLY */" +echo "/* Created by the program 'stamp-date' */" +echo "#define COMPILE_TIME \"$DATE\"" +echo "#define COMPILED_BY \"$USER\"" diff --git a/buildtools/typegen b/buildtools/typegen new file mode 100755 index 00000000..b76191f3 --- /dev/null +++ b/buildtools/typegen Binary files differdiff --git a/buildtools/typegen.c b/buildtools/typegen.c new file mode 100644 index 00000000..5b32af28 --- /dev/null +++ b/buildtools/typegen.c @@ -0,0 +1,113 @@ +/*---------------------------------------------------------------------------- + typegen +------------------------------------------------------------------------------ + This is a program to create an inttypes.h file for use in building + Netpbm. Ordinarily we use the inttypes.h that comes with the C library + or C compiler, specified by Single Unix Specification. When that isn't + available there is usually some other system header file we should use. + But when there isn't any system header file to define the needed types, + the file we generate is better than nothing. + + The main problem with the inttypes.h we generate is that when we + figure out which type is a 32 bit integer, we aren't necessarily using + the same compile environment as what will actually get used to build + Netpbm, and thus the one where our inttypes.h will be used. + + Right now, it simply generates either + + typedef int int32_t; + + or + + typedef long int32_t; + + based on which type, int, or long, is 32 bits. + + We also include the uint32_t and int_fast32_t typedefs. + + We also include the multiple inclusion guard ifdef. +-----------------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + + +static void +createTypedefForUint32_t(void) { + + if (sizeof(unsigned int) == 4) + printf("typedef unsigned int uint32_t;\n"); + else if (sizeof(unsigned long) == 4) + printf("typedef unsigned long uint32_t;\n"); + else { + fprintf(stderr, "Cannot find a 32 bit unsigned integer type!\n"); + exit(1); + } +} + + + +static void +createTypedefForUintFast32_t(void) { + + if (sizeof(unsigned int) == 4) + printf("typedef unsigned int uint_fast32_t;\n"); + else if (sizeof(unsigned long) == 4) + printf("typedef unsigned long uint_fast32_t;\n"); + else { + fprintf(stderr, "Cannot find a 32 bit unsigned integer type!\n"); + exit(1); + } +} + + + +static void +createTypedefForInt32_t(void) { + + if (sizeof(signed int) == 4) + printf("typedef signed int int32_t;\n"); + else if (sizeof(signed long) == 4) + printf("typedef signed long int32_t;\n"); + else { + fprintf(stderr, "Cannot find a 32 bit signed integer type!\n"); + exit(1); + } +} + + + +static void +createTypedefForIntFast32_t(void) { + + if (sizeof(signed int) == 4) + printf("typedef signed int int_fast32_t;\n"); + else if (sizeof(signed long) == 4) + printf("typedef signed long int_fast32_t;\n"); + else { + fprintf(stderr, "Cannot find a 32 bit signed integer type!\n"); + exit(1); + } +} + + + +int +main(int argc, char **argv) { + + printf("/* This was generated by the program 'typegen' */\n"); + + + printf("#ifndef INTTYPES_H_NETPBM\n"); + printf("#define INTTYPES_H_NETPBM\n"); + + createTypedefForUint32_t(); + createTypedefForInt32_t(); + createTypedefForIntFast32_t(); + createTypedefForUintFast32_t(); + + printf("#endif\n"); + + return 0; +} |