%% options copyright owner = Dirk Krause copyright year = 2017-xxxx SPDX-License-Identifier: BSD-3-Clause %% header #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4PAPER_H_INCLUDED #include "dk4paper.h" #endif #ifndef DK4FILED_H_INCLUDED #include "dk4filed.h" #endif #ifndef DK4DIR_H_INCLUDED #include "dk4dir.h" #endif #ifndef DK4CS_H_INCLUDED #include "dk4cs.h" #endif #ifndef DK4APP_H_INCLUDED #include "dk4app.h" #endif #ifndef DK4DIRA_H_INCLUDED #include "dk4dira.h" #endif #ifndef DK4GRAA_H_INCLUDED #include "dk4graa.h" #endif #ifndef DK4GRCO_H_INCLUDED #include "dk4grco.h" #endif #ifndef DK4BIF_H_INCLUDED #include "dk4bif.h" #endif #ifndef DK4BIFAP_H_INCLUDED #include "dk4bifap.h" #endif /** Job structure. */ typedef struct { dkChar exbuf[DK4_MAX_PATH]; /**< File name expansion. */ dkChar dtbuf[DK4_MAX_PATH]; /**< Dir traversal. */ dkChar onbuf[DK4_MAX_PATH]; /**< Output file name. */ dk4_gra_conf_t grco; /**< Graphics configuration. */ dk4_app_t *app; /**< Application structure. */ const dkChar * const *msg; /**< Localized texts. */ size_t sz_msg; /**< Number of elements in msg. */ int use_prefs; /**< Flag: Use preferences. */ int make_mode; /**< Flag: Run in make mode. */ int exval; /**< Exit status code. */ } bmpp_job_t; /* vim: set ai sw=4 ts=4 : */ %% module #include "dk4conf.h" #include #if DK4_HAVE_MATH_H #ifndef MATH_H_INCLUDED #if DK4_ON_WINDOWS #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES 1 #endif #endif #include #define MATH_H_INCLUDED 1 #endif #endif #if DK4_HAVE_FCNTL_H #ifndef FCNTL_H_INCLUDED #include #define FCNTL_H_INCLUDED 1 #endif #endif #if DK4_HAVE_IO_H #ifndef IO_H_INCLUDED #include #define IO_H_INCLUDED 1 #endif #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4MATH_H_INCLUDED #include "dk4math.h" #endif #ifndef DK4VERS_H_INCLUDED #include "dk4vers.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4FPUT_H_INCLUDED #include "dk4fput.h" #endif #ifndef DK4APP_H_INCLUDED #include "dk4app.h" #endif #ifndef DK4AOPT_H_INCLUDED #include "dk4aopt.h" #endif #ifndef DK4PATHD_H_INCLUDED #include "dk4pathd.h" #endif #ifndef DK4DIR_H_INCLUDED #include "dk4dir.h" #endif #ifndef DK4DIRA_H_INCLUDED #include "dk4dira.h" #endif #ifndef DK4MM_H_INCLUDED #include "dk4mm.h" #endif #ifndef DK4MAO8D_H_INCLUDED #include "dk4mao8d.h" #endif #ifndef DK4FOPDA_H_INCLUDED #include "dk4fopda.h" #endif #ifndef DK4ISADM_H_INCLUDED #include "dk4isadm.h" #endif #ifndef BMPP_H_INCLUDED #include "bmpp.h" #endif #ifndef DK4GRCOA_H_INCLUDED #include "dk4grcoa.h" #endif #ifndef DK4UNUSED_H_INCLUDED #include "dk4unused.h" #endif #ifndef DK4WMAIN_H_INCLUDED #include "dk4wmain.h" #endif $!trace-include /** Default help text, shown if help text file is not found. */ static const dkChar * const bmpp_help_text[] = { $!text macro=dkT Convert PNG/JPEG/NetPBM/TIFF to PS/EPS/PDF bmpp -l .,=... [] Drivers: ps eps pdf bb Purposes: image object document Options: -l Set driver and purpose, add key=value options. -m Check modifications times, avoid unnecessary conversions. -R Reset program options to builtin defaults (skip configuration files). --help Show this short help text. --version Show version information. --manual *** SHOW FULL MANUAL. *** --license Show license information. See the full manual for the key=value options, run: bmpp --manual | more $!end }; /** License text. */ static const dkChar * const bmpp_license_text[] = { $!text macro=dkT,preprocessor Overview ======== This software uses code from the following projects either directly or as a library: dktools Dirk Krause's tools and libraries. See http://sourceforge.net/p/dktools/wiki/Home/ for information. #if DK4_HAVE_PNG_H libpng PNG reference library. See http://www.libpng.org/pub/png/libpng.html for information. #endif #if DK4_HAVE_JPEGLIB_H jpeg Independent JPEG groups free JPEG library. See http://www.ijg.org/ for information. #endif #if DK4_HAVE_TIFF_H libtiff TIFF library. See http://www.remotesensing.org/libtiff/ for information. #endif #if DK4_HAVE_ZLIB_H zlib Compression library. See http://www.zlib.net/ for information. #endif Your use of the bmpp program must be in compliance with the license conditions for the dktools project and the license conditions for all the libraries used by bmpp. License for the dktools project =============================== Copyright (c) 2011-2018, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder(s) nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if DK4_HAVE_PNG_H libpng license ============== This copy of the libpng notices is provided for your convenience. In case of any discrepancy between this copy and the notices in the file png.h that is included in the libpng distribution, the latter shall prevail. COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: If you modify libpng you may insert additional notices immediately following this sentence. This code is released under the libpng license. libpng versions 1.2.6, August 15, 2004, through 1.2.46, July 9, 2011, are Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors Cosmin Truta libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors Simon-Pierre Cadieux Eric S. Raymond Gilles Vollant and with the following additions to the disclaimer: There is no warranty against interference with your enjoyment of the library or against infringement. There is no warranty that our efforts or the library will fulfill any of your particular purposes or needs. This library is provided with all faults, and the entire risk of satisfactory quality, performance, accuracy, and effort is with the user. libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-0.96, with the following individuals added to the list of Contributing Authors: Tom Lane Glenn Randers-Pehrson Willem van Schaik libpng versions 0.89, June 1996, through 0.96, May 1997, are Copyright (c) 1996, 1997 Andreas Dilger Distributed according to the same disclaimer and license as libpng-0.88, with the following individuals added to the list of Contributing Authors: John Bowler Kevin Bracey Sam Bushell Magnus Holmgren Greg Roelofs Tom Tanner libpng versions 0.5, May 1995, through 0.88, January 1996, are Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. For the purposes of this copyright and license, "Contributing Authors" is defined as the following set of individuals: Andreas Dilger Dave Martindale Guy Eric Schalnat Paul Schmidt Tim Wegner The PNG Reference Library is supplied "AS IS". The Contributing Authors and Group 42, Inc. disclaim all warranties, expressed or implied, including, without limitation, the warranties of merchantability and of fitness for any purpose. The Contributing Authors and Group 42, Inc. assume no liability for direct, indirect, incidental, special, exemplary, or consequential damages, which may result from the use of the PNG Reference Library, even if advised of the possibility of such damage. Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, for any purpose, without fee, subject to the following restrictions: 1. The origin of this source code must not be misrepresented. 2. Altered versions must be plainly marked as such and must not be misrepresented as being the original source. 3. This Copyright notice may not be removed or altered from any source or altered source distribution. The Contributing Authors and Group 42, Inc. specifically permit, without fee, and encourage the use of this source code as a component to supporting the PNG file format in commercial products. If you use this source code in a product, acknowledgment is not required but would be appreciated. A "png_get_copyright" function is available, for convenient use in "about" boxes and the like: printf("%s",png_get_copyright(NULL)); Also, the PNG logo (in PNG format, of course) is supplied in the files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net July 9, 2011 #endif #if DK4_HAVE_JPEGLIB_H jpeglib license =============== In plain English: 1. We don't promise that this software works. (But if you find any bugs, please let us know!) 2. You can use this software for whatever you want. You don't have to pay us. 3. You may not pretend that you wrote this software. If you use it in a program, you must acknowledge somewhere in your documentation that you've used the IJG code. In legalese: The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. This software is copyright (C) 1991-1998, Thomas G. Lane. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this software (or portions thereof) for any purpose, without fee, subject to these conditions: (1) If any part of the source code for this software is distributed, then this README file must be included, with this copyright and no-warranty notice unaltered; and any additions, deletions, or changes to the original files must be clearly indicated in accompanying documentation. (2) If only executable code is distributed, then the accompanying documentation must state that "this software is based in part on the work of the Independent JPEG Group". (3) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. These conditions apply to any software derived from or based on the IJG code, not just to the unmodified library. If you use our work, you ought to acknowledge us. Permission is NOT granted for the use of any IJG author's name or company name in advertising or publicity relating to this software or products derived from it. This software may be referred to only as "the Independent JPEG Group's software". We specifically permit and encourage the use of this software as the basis of commercial products, provided that all warranty or liability claims are assumed by the product vendor. ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. ansi2knr.c is NOT covered by the above copyright and conditions, but instead by the usual distribution terms of the Free Software Foundation; principally, that you must include source code if you redistribute it. (See the file ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part of any program generated from the IJG code, this does not limit you more than the foregoing paragraphs do. The Unix configuration script "configure" was produced with GNU Autoconf. It is copyright by the Free Software Foundation but is freely distributable. The same holds for its supporting scripts (config.guess, config.sub, ltconfig, ltmain.sh). Another support script, install-sh, is copyright by M.I.T. but is also freely distributable. It appears that the arithmetic coding option of the JPEG spec is covered by patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot legally be used without obtaining one or more licenses. For this reason, support for arithmetic coding has been removed from the free JPEG software. (Since arithmetic coding provides only a marginal gain over the unpatented Huffman mode, it is unlikely that very many implementations will support it.) So far as we are aware, there are no patent restrictions on the remaining code. The IJG distribution formerly included code to read and write GIF files. To avoid entanglement with the Unisys LZW patent, GIF reading support has been removed altogether, and the GIF writer has been simplified to produce "uncompressed GIFs". This technique does not use the LZW algorithm; the resulting GIF files are larger than usual, but are readable by all standard GIF decoders. We are required to state that "The Graphics Interchange Format(c) is the Copyright property of CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated." #endif #if DK4_HAVE_TIFF_H libtiff license =============== Copyright (c) 1988-1997 Sam Leffler Copyright (c) 1991-1997 Silicon Graphics, Inc. Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that (i) the above copyright notices and this permission notice appear in all copies of the software and related documentation, and (ii) the names of Sam Leffler and Silicon Graphics may not be used in any advertising or publicity relating to the software without the specific, prior written permission of Sam Leffler and Silicon Graphics. THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #endif #if DK4_HAVE_ZLIB_H zlib license ============ (C) 1995-2004 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. #endif $!end }; /** Keywords, not localized. */ static const dkChar * const bmpp_kwnl[] = { $!string-table macro=dkT # # 0 Program group name # dktools # # 1 Help text file name (full manual) # bmpp.txt # # 2 String table file name # bmpp.str # # 3 Dummy file name when processing standard input # # # 4-9 File name suffixes for output files # .pdf .eps .ps .pgf .bb .tex $!end }; /** Default text fragments if localized fragments are not found. */ static const dkChar * const bmpp_kw_def[] = { $!string-table macro=dkT # # 0-1 Signal handler installation # Failed to install signal handlers! Failed to restore signal handleres! # # 2 ERROR: The bmpp program can not produce TeX output! # The bmpp program can not produce TeX output! # # 3 ERROR: Illegal paper size # Incorrect paper size information, unusable! # # 4 ERROR: Failed to read NetPBM image from standard input! # Failed to read NetPBM image from standard input! # # 5 # Failed to construct output file name!\n\tInput file name probably too long! # # 6 # Failed to construct full path name!\n\tDirectory or file name too long! # # 7 # Not a regular file! # # 8 # No such file! # # 9 # Preparing output (start). # # 10 # Preparing output (finished). # # 11 # Writing output file (start). # # 12 # Writing output file (finished). # # 13 # Processing standard input to standard output (start). # # 14 # Processing standard input to standard output (finished). # # 15 # Reading NetPBM image from standard input (start). # # 16 # Reading NetPBM image from standard input (finished). # # 17-18 # Writing output to standard output (start). Writing output to standard output (finished). # # 19-20 # Reading input file (start). Reading input file (finished). # # 21-22 # Processing file (start). Processing file (finished). # # 23-24 # Processing directory (start). Processing directory (finished). # # 25-26 # Not a usable input file: " ". # # 27-28 # Processing file name pattern (start). Processing file name pattern (finished). $!end }; static const char * const bmpp_c8_kwnl[] = { $!string-table \%\%BoundingBox: 0 0 \n # # # $!end }; /** Options used by the program. */ static const dk4_option_specification_t bmpp_options[] = { /* Language, purpose and key=value options */ { dkT('l'), dkT("language"), DK4_OPT_ARG_STRING }, /* Make mode to avoid unnecessary conversions when processing directories */ { dkT('m'), dkT("make"), DK4_OPT_ARG_NONE }, /* Skip preferences */ { dkT('R'), dkT("reset"), DK4_OPT_ARG_NONE } }; /** Number of options in bmpp_options array. */ static const size_t bmpp_sz_options = sizeof(bmpp_options) / sizeof(dk4_option_specification_t); #ifdef SIGPIPE /** Indicator: SIGPIPE signal received. */ static DK4_VOLATILE dk4_sig_atomic_t sig_had_pipe = 0; #endif /** Indicator: SIGINT signal received. */ static DK4_VOLATILE dk4_sig_atomic_t sig_had_int = 0; /** Indicator: SIGTERM signal received. */ static DK4_VOLATILE dk4_sig_atomic_t sig_had_term = 0; /** Pass a volatile pointer to an atomic integer. This function is necessary as some compilers mis-optimize direct access to volatile variables (at least if you believe one of the coding standards). @param ptr Address of atomic integer variable. @return The unmodified pointer. */ static DK4_VOLATILE dk4_sig_atomic_t * sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr) { return ptr; } #ifdef SIGPIPE /** Handler for SIGPIPE signal. @param signo Signal number (always SIGPIPE, ignored). */ static void sig_handler_pipe(int DK4_ARG_UNUSED(signo) ) { DK4_UNUSED_ARG(signo) *sig_pass_pointer(&sig_had_pipe) = 1; } #endif /** Handler for SIGINT signal. @param signo Signal number (always SIGINT, ignored). */ static void sig_handler_int(int DK4_ARG_UNUSED(signo) ) { DK4_UNUSED_ARG(signo) *sig_pass_pointer(&sig_had_int) = 1; } /** Handler for SIGTERM signal. @param signo Signal number (always SIGTERM, ignored). */ static void sig_handler_term(int DK4_ARG_UNUSED(signo) ) { DK4_UNUSED_ARG(signo) *sig_pass_pointer(&sig_had_term) = 1; } /** Read value from volatile atomic type. This function is necessary as some compilers mis-optimize direct access to volatile variables (at least if you believe one of the coding standards). @param ap Pointer to volatile atomic variable. @return Contents of the variable. */ static dk4_sig_atomic_t sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap) { return (*ap); } /** Check whether we can continue or if a signal was received. @param check_pipe Flag: Check for occured SIGPIPE signal too. @return 1 if the program can continue, 0 if a signal was received. */ static int sig_can_continue( #ifdef SIGPIPE int check_pipe #else int DK4_ARG_UNUSED(check_pipe) #endif ) { int back = 1; #ifndef SIGPIPE DK4_UNUSED_ARG(check_pipe) #else if (0 != check_pipe) { if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; } } #endif if (0 != sig_read_atomic(&sig_had_int )) { back = 0; } if (0 != sig_read_atomic(&sig_had_term)) { back = 0; } return back; } /** Initialize job structure. @param job Structure to initialize. */ static void bmpp_job_init(bmpp_job_t *job) { $? "+ bmpp_job_init" dk4gra_conf_init(&(job->grco)); job->app = NULL; job->msg = bmpp_kw_def; job->sz_msg = ((sizeof(bmpp_kw_def)/sizeof(DK4_PDKCHAR)) - 1); job->use_prefs = 1; job->make_mode = 0; job->exval = EXIT_FAILURE; DK4_MEMRES(&(job->exbuf[0]), (DK4_MAX_PATH * sizeof(dkChar))); DK4_MEMRES(&(job->dtbuf[0]), (DK4_MAX_PATH * sizeof(dkChar))); DK4_MEMRES(&(job->onbuf[0]), (DK4_MAX_PATH * sizeof(dkChar))); $? "- bmpp_job_init" } /** Calculate bounding box dimensions for bitmap image file. @param job Job structure. @param pw Address of width variable. @param ph Address of height variable. @param bif Bitmap image file. */ static void bmpp_calculate_bounding_box( bmpp_job_t *job, size_t *pw, size_t *ph, double *cotra, dk4_bif_t *bif ) { double xres; double yres; size_t w; size_t h; dk4_bif_dim_t orig_w; dk4_bif_dim_t orig_h; $? "+ bmpp_calculate_bounding_box" orig_w = dk4bif_get_width(bif); orig_h = dk4bif_get_height(bif); w = (size_t)orig_w; h = (size_t)orig_h; if (NULL != cotra) { cotra[0] = 0.0; cotra[1] = 0.0; cotra[2] = 0.0; cotra[3] = (double)w; cotra[4] = (double)h; } if (0 == job->grco.img_ign_res) { xres = dk4bif_get_xres(bif); yres = dk4bif_get_yres(bif); if ((0.0 < xres) && (0.0 < yres)) { if ((1.0e-5 < fabs(xres - 72.0)) || (1.0e-5 < fabs(yres - 72.0))) { xres = (72.0 * (double)orig_w) / xres; yres = (72.0 * (double)orig_h) / yres; if (0 != dk4ma_is_finite(xres)) { if (0 != dk4ma_is_finite(yres)) { if ((double)(SIZE_MAX) > xres) { if ((double)(SIZE_MAX) > yres) { w = (size_t)ceil(xres); h = (size_t)ceil(yres); if (NULL != cotra) { cotra[0] = ((double)w - xres) / 2.0; cotra[1] = ((double)h - yres) / 2.0; cotra[3] = xres; cotra[4] = yres; if (0.0 > cotra[0]) { cotra[0] = 0.0; } if (0.0 > cotra[1]) { cotra[1] = 0.0; } if (1.0e-5 > fabs(cotra[0])) { cotra[0] = 0.0; } if (1.0e-5 > fabs(cotra[1])) { cotra[1] = 0.0; } } } } } } } } } *pw = w; *ph = h; $? "- bmpp_calculate_bounding_box" } /** Produce bounding box file. @param job Job structure. @param bif Bitmap image file. @param filename Input file name currently processed, NULL for stdin. */ static void bmpp_produce_bb( bmpp_job_t *job, dk4_bif_t *bif, dkChar const *filename ) { char wbuf[16*sizeof(dk4_um_t)]; /* Buffer for width as text */ char hbuf[16*sizeof(dk4_um_t)]; /* Buffer for height as text */ FILE *fipo; /* Output file */ double deltares; /* Resolution difference */ size_t w; /* Image width */ size_t h; /* Image height */ int res; /* Operation result */ int tests = DK4_FOPEN_SC_USER; /* Tests for fopen */ $? "+ bmpp_produce_bb \"%!ds\"", TR_STR(filename) if (0 != dk4isadmin()) { tests = DK4_FOPEN_SC_PRIVILEGED; } /* Check for different resolutions and ignore res option */ if (0 != job->grco.img_ign_res) { deltares = fabs(bif->cf->res_y - bif->cf->res_x); if (DK4_BIF_EPSILON_ASPECT <= deltares) { dk4bif_warn_aspect_ratio_change( bif, 72.0, 72.0, job->app ); } } bmpp_calculate_bounding_box(job, &w, &h, NULL, bif); res = dk4ma_write_c8_decimal_unsigned( wbuf, sizeof(wbuf), (dk4_um_t)w, 0, NULL ); if (0 != res) { res = dk4ma_write_c8_decimal_unsigned( hbuf, sizeof(hbuf), (dk4_um_t)h, 0, NULL ); if (0 != res) { if (NULL != filename) { fipo = dk4fopen_app(&(job->onbuf[0]),dkT("w"),tests,job->app); if (NULL != fipo) { fputs(bmpp_c8_kwnl[0], fipo); fputs(wbuf, fipo); fputs(bmpp_c8_kwnl[1], fipo); fputs(hbuf, fipo); fputs(bmpp_c8_kwnl[2], fipo); if (0 != fclose(fipo)) { job->exval = EXIT_FAILURE; /* ERROR: Failed to close fipo */ dk4app_log_base1(job->app, DK4_LL_ERROR, 128); } } else { job->exval = EXIT_FAILURE; /* ERROR: Failed to open file, already reported */ } } else { fputs(bmpp_c8_kwnl[0], stdout); fputs(wbuf, stdout); fputs(bmpp_c8_kwnl[1], stdout); fputs(hbuf, stdout); fputs(bmpp_c8_kwnl[2], stdout); } } else { $? "! h" /* ERROR: Failed to convert h to string */ } } else { $? "! w" /* ERROR: Failed to convert w to string */ } $? "- bmpp_produce_bb" } /** Check paper size in job configuration. @param job Job structure. @return 1 on success, 0 on error. */ static int bmpp_check_papersize( bmpp_job_t *job ) { double xl; /* Left x position */ double xr; /* Right x position */ double yb; /* Bottom y position */ double yt; /* Top y position */ int back = 0; xl = job->grco.media.i; xr = job->grco.media.w - job->grco.media.o; yb = job->grco.media.b; yt = job->grco.media.h - job->grco.media.t; if ((isgreater(xr,xl)) && (isgreater(yt,yb))) { back = 1; } if (0 == back) { /* ERROR: Illegal paper size */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 3); job->exval = EXIT_FAILURE; } return back; } /** Produce document. @param job Job structure. @param bif Bitmap image file. @param filename Input file name currently processed, NULL for stdin. */ static void bmpp_produce_document( bmpp_job_t *job, dk4_bif_t *bif, dkChar const *filename ) { dk4_gra_t *gra = NULL; /* Graphics output structure */ dkChar const *osf; /* Old source file name */ double xl; /* Left image border */ double xr; /* Right image border */ double yb; /* Bottom image border */ double yt; /* Top image border */ double deltares; /* Resolution difference */ dk4_um_t osl; /* Old source line number */ size_t w = 0; /* Paper width */ size_t h = 0; /* Paper height */ size_t nfrm = 0; /* Number of frames in bitmap image */ size_t cf = 0; /* Current frame */ int docfl = 0; /* Document flags */ int imgfl = 0; /* Image flags */ int ok = 0; /* Flag: No error occured */ $? "+ bmpp_produce_document \"%!ds\"", TR_STR(filename) if (0 != bmpp_check_papersize(job)) { $? ". paper size ok" /* Retrieve document and image flag from configuration structure */ docfl = dk4gra_conf_flags_document(&(job->grco)); imgfl = dk4gra_conf_flags_image(&(job->grco)); /* Apply some corrections to the flags */ imgfl &= (~(DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO)); imgfl &= (~(DK4_GRA_IMG_FLAG_ALLOW_ROTATION)); imgfl |= DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS; if (DK4_GRA_DRIVER_PDF == job->grco.driver) { imgfl |= DK4_GRA_IMG_FLAG_FILL_BACKGROUND; $? ". fill bg" } /* Obtain image dimensions */ w = (size_t)ceil(job->grco.media.w); $? ". w = %u", (unsigned)w h = (size_t)ceil(job->grco.media.h); $? ". h = %u", (unsigned)h /* Open graphics output structure */ switch (job->grco.driver) { case DK4_GRA_DRIVER_PDF : { $? ". open pdf" imgfl |= DK4_GRA_IMG_FLAG_FILL_BACKGROUND; gra = dk4gra_app_open_pdf( ((NULL != filename) ? (&(job->onbuf[0])) : NULL), w, h, docfl, job->app ); } break; case DK4_GRA_DRIVER_PS : { $? ". open ps" gra = dk4gra_app_open_ps( ((NULL != filename) ? (&(job->onbuf[0])) : NULL), w, h, docfl, job->app ); } break; case DK4_GRA_DRIVER_PGF : { $? ". open pgf" gra = dk4gra_app_open_pgf( ((NULL != filename) ? (&(job->onbuf[0])) : NULL), w, h, docfl, 0, job->app ); } break; } if (NULL != gra) { $? ". gra" ok = 1; /* PROGRESS: Preparing output (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 9); /* Traverse all frames of source image */ nfrm = dk4bif_get_number_of_frames(bif); $? ". nfrm = %u", (unsigned)nfrm for (cf = 0; cf < nfrm; cf++) { $? ". frame %u / %u", (unsigned)cf, (unsigned)nfrm /* Switch to selected frame */ if (0 != dk4bif_set_current_frame(bif, cf)) { /* Check for different resolutions and ignore res option */ if (0 != job->grco.img_ign_res) { deltares = fabs(bif->cf->res_y - bif->cf->res_x); if (DK4_BIF_EPSILON_ASPECT <= deltares) { dk4bif_warn_aspect_ratio_change( bif, 72.0, 72.0, job->app ); } } /* If a resolution was configured, use it */ if ((0.0 < job->grco.xres) && (0.0 < job->grco.yres)) { dk4bif_set_res_app( bif, job->grco.xres, job->grco.yres, job->app ); } /* Add new page to graphics output */ dk4gra_app_page(gra, &ok, job->app); $? ". page" /* Calculate paper range available for image */ xl = job->grco.media.i; xr = job->grco.media.w - job->grco.media.o; yb = job->grco.media.b; yt = job->grco.media.h - job->grco.media.t; if ((size_t)0U != (cf % (size_t)2U)) { $? ". tumble" if (0 != job->grco.doc_tumble) { yb = job->grco.media.t; yt = job->grco.media.h - job->grco.media.b; } else { if (0 != job->grco.doc_duplex) { $? ". duplex" xl = job->grco.media.o; xr = job->grco.media.w - job->grco.media.i; } } } /* Add image to paper range */ dk4gra_app_bif_image( gra /* gra */ , xl /* xl */ , xr /* xr */ , yb /* yb */ , yt /* yt */ , bif /* bif */ , filename /* filename */ , cf /* frameno */ , imgfl /* Image flags */ , NULL /* bbptr */ , &ok /* backptr */ , job->app /* app */ ); } else { $? "! failed to set frame" ok = 0; } $? ". ok = %d at end of frame %u", ok, (unsigned)cf } /* PROGRESS: Preparing output (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 10); /* Write output file and close graphics output if succeeded so for, otherwise simply close graphics */ if (1 == ok) { $? ". write and close" /* Use output file name in diagnostics, save previous settings */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, &(job->onbuf[0])); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* PROGRESS: Writing output file (start) */ dk4app_log_1(job->app,job->msg,job->sz_msg,DK4_LL_PROGRESS,11); /* Write output file and close graphics structure */ dk4gra_app_write_and_close(gra, &ok, job->app); gra = NULL; /* PROGRESS: Writing output file (finished) */ dk4app_log_1(job->app,job->msg,job->sz_msg,DK4_LL_PROGRESS,12); /* Restore previous settings for file and line */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); } else { $? ". simply close" dk4gra_close(gra); } } #if TRACE_DEBUG else { $? "! gra" } #endif if (0 == ok) { job->exval = EXIT_FAILURE; } } #if TRACE_DEBUG else { $? "! paper size" } #endif $? "- bmpp_produce_document" } /** Produce image or object. @param job Job structure. @param bif Bitmap image file. @param filename Input file name currently processed, NULL for stdin. */ static void bmpp_produce_image_or_object( bmpp_job_t *job, dk4_bif_t *bif, dkChar const *filename ) { double cotra[8]; /* 5 used: xshift yshift rotation xscale yscale */ dkChar const *osf; /* Old source file name */ dk4_gra_t *gra = NULL; /* Graphics output structure */ double deltares; /* Resolution difference */ dk4_um_t osl; /* Old source line number */ size_t w; /* Image width */ size_t h; /* Image height */ int docfl; /* Document flags for opening graphics structure */ int imgfl; /* Image flags */ int ok = 0; /* Flag: No errors */ $? "+ bmpp_produce_image_or_object \"%!ds\"", TR_STR(filename) /* Set flags used to open graphics output and to apply image */ docfl = dk4gra_conf_flags_document(&(job->grco)); docfl |= DK4_GRA_PAGE_FLAG_NO_BG; imgfl = dk4gra_conf_flags_image(&(job->grco)); imgfl |= DK4_GRA_IMG_FLAG_FILL_BACKGROUND; imgfl |= DK4_GRA_IMG_FLAG_ONLY_PAGE_CONTENTS; if (DK4_GRA_DRIVER_PDF == job->grco.driver) { if (DK4_GRA_PURPOSE_OBJECT == job->grco.purpose) { imgfl &= (~(DK4_GRA_IMG_FLAG_FILL_BACKGROUND)); } } /* Check for different resolutions and ignore res option */ if (0 != job->grco.img_ign_res) { deltares = fabs(bif->cf->res_y - bif->cf->res_x); if (DK4_BIF_EPSILON_ASPECT <= deltares) { dk4bif_warn_aspect_ratio_change(bif, 72.0, 72.0, job->app); } } /* If a resolution was configured, use it */ if ((0.0 < job->grco.xres) && (0.0 < job->grco.yres)) { dk4bif_set_res_app(bif, job->grco.xres, job->grco.yres, job->app); } /* Calculate bounding box and coordinates transformations */ bmpp_calculate_bounding_box(job, &w, &h, cotra, bif); /* Open graphics output structure */ $? ". open graphics output structure" switch (job->grco.driver) { case DK4_GRA_DRIVER_PDF : { $? ". open pdf" gra = dk4gra_app_open_pdf( ((NULL != filename) ? (&(job->onbuf[0])) : NULL), w, h, docfl, job->app ); } break; case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : { $? ". open ps" gra = dk4gra_app_open_ps( ((NULL != filename) ? (&(job->onbuf[0])) : NULL), w, h, docfl, job->app ); } break; case DK4_GRA_DRIVER_PGF : { $? ". open pgf" gra = dk4gra_app_open_pgf( ((NULL != filename) ? (&(job->onbuf[0])) : NULL), w, h, docfl, 0, job->app ); } break; } if (NULL != gra) { $? ". gra" /* Add page and apply image */ ok = 1; /* PROGRESS: Preparing output (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 9); /* Start new page */ dk4gra_app_page(gra, &ok, job->app); /* Add bitmap image to page */ dk4gra_app_bif_cotra_image( gra, cotra, bif, filename, 0, imgfl, &ok, job->app ); /* PROGRESS: Preparing output (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 10); /* If success so far, write output file */ if (1 == ok) { $? ". ok" /* Prepare output file name for diagnostics */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, &(job->onbuf[0])); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* PROGRESS: Writing output file (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 11); /* Write output file */ $? ". going to write and close graphics" dk4gra_app_write_and_close(gra, &ok, job->app); gra = NULL; /* PROGRESS: Writing output file (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 12); /* Restore previous source file and line */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); } else { $? "! ok" dk4gra_close(gra); } } #if TRACE_DEBUG else { $? "! gra" } #endif if (0 == ok) { job->exval = EXIT_FAILURE; } $? "- bmpp_produce_image_or_object" } /** Process one bitmap image file. @param job Job structure. @param bif Bitmap image file. @param filename Input file name currently processed, NULL for stdin. */ static void bmpp_run_for_bif( bmpp_job_t *job, dk4_bif_t *bif, dkChar const *filename ) { $? "+ bmpp_run_for_bif \"%!ds\"", TR_STR(filename) dk4bif_set_current_frame(bif, 0); switch (job->grco.driver) { case DK4_GRA_DRIVER_BB : { bmpp_produce_bb(job, bif, filename); } break; default : { switch (job->grco.purpose) { case DK4_GRA_PURPOSE_DOCUMENT : { bmpp_produce_document(job, bif, filename); } break; default : { bmpp_produce_image_or_object(job, bif, filename); } break; } } break; } $? "- bmpp_run_for_bif" } /** Run as filter if no file names were specified on the command line. @param job Job structure. */ static void bmpp_run_as_filter(bmpp_job_t *job) { dk4_er_t er; /* Error report */ dkChar const *osf; /* Old source file name */ dk4_bif_t *bif; /* Bitmap image file */ dk4_um_t osl; /* Old source line number */ #if DK4_ON_WINDOWS int osm; /* Old stdin mode */ #endif $? "+ bmpp_run_as_filter" /* Save current source file name and source line number */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); /* Set source file name and line number */ dk4app_set_log_source_file(job->app, bmpp_kwnl[3]); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* PROGRESS: Processing stdin to stdout (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 13); /* Read and process image */ dk4error_init(&er); /* On Windows we have to set stdin to binary mode exlicitly and restore previous mode when done */ #if DK4_ON_WINDOWS osm = _setmode(_fileno(stdin), _O_BINARY); #endif /* PROGRESS: Reading NetPBM from stdin (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 15); bif = dk4bif_open_file( stdin, NULL, DK4_BIF_TYPE_NETPBM, 0, &(job->grco.ctx), &er ); /* PROGRESS: Reading NetPBM from stdin (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 16); #if DK4_ON_WINDOWS _setmode(_fileno(stdin), osm); #endif if (NULL != bif) { /* PROGRESS: Writing output to stdout (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 17); /* Write the output */ bmpp_run_for_bif(job, bif, NULL); /* PROGRESS: Writing output to stdout (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 18); dk4bif_close(bif); } else { /* ERROR: Failed to open BIF */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 4); job->exval = EXIT_FAILURE; } /* PROGRESS: Processing stdin to stdout (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 14); /* Restore previous source file name and line number */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); $? "- bmpp_run_as_filter" } /** Run for one input file. @param job Job structure. @param filename Input file name to process. */ static void bmpp_run_for_file( bmpp_job_t *job, dkChar const *filename ) { dk4_bif_t *bif; /* Bitmap image file */ int ho = 0; /* Flag: Read image header only */ $? "+ bmpp_run_for_file \"%!ds\"", filename /* To calculate the bounding box it is sufficient to read image header */ if (DK4_GRA_DRIVER_BB == job->grco.driver) { ho = 1; } /* Read and process image */ /* PROGRESS: Reading input file (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 19); bif = dk4bif_open_app(filename, ho, &(job->grco.ctx), job->app); if (NULL != bif) { /* PROGRESS: Reading input file (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 20); /* Process and close input */ bmpp_run_for_bif(job, bif, filename); dk4bif_close(bif); } else { job->exval = EXIT_FAILURE; } $? "- bmpp_run_for_file" } /** Construct output file name in job->onbuf. @param job Job structure. @param filename Source file name. @return 1 on success, 0 on error. */ static int bmpp_construct_output_file_name( bmpp_job_t *job, dkChar const *filename ) { dk4_er_t er; dkChar const *psuf = NULL; int back = 0; $? "+ bmpp_construct_output_file_name \"%!ds\"", filename switch (job->grco.driver) { case DK4_GRA_DRIVER_PDF : { psuf = bmpp_kwnl[4]; } break; case DK4_GRA_DRIVER_EPS : { psuf = bmpp_kwnl[5]; } break; case DK4_GRA_DRIVER_PS : { psuf = bmpp_kwnl[6]; } break; case DK4_GRA_DRIVER_PGF : { psuf = bmpp_kwnl[7]; if (DK4_GRA_PURPOSE_DOCUMENT == job->grco.purpose) { psuf = bmpp_kwnl[9]; } } break; case DK4_GRA_DRIVER_BB : { psuf = bmpp_kwnl[8]; } break; } if (NULL != psuf) { dk4error_init(&er); back = dk4path_set_suffix( &(job->onbuf[0]), DK4_MAX_PATH, filename, psuf, &er ); if (0 == back) { /* ERROR: Failed to construct output file name */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 5); job->exval = EXIT_FAILURE; } #if TRACE_DEBUG else { $? ". ofn=\"%!ds\"", &(job->onbuf[0]) } #endif } else { $? "! bug" /* ERROR: BUG */ } $? "- bmpp_construct_output_file_name %d", back return back; } /** Process one real file. @param job Job structure. @param filename File name to process. @param tsc Flag: Timestamp check. */ static void bmpp_process_one_file(bmpp_job_t *job, dkChar const *filename, int tsc) { dkChar const *osf; /* Source file name */ dk4_um_t osl; /* Source line number */ int res; /* Operation result */ $? "+ bmpp_process_one_file \"%!ds\"", filename /* Save current source file name and line number settings */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); /* Set file to process as current source file */ dk4app_set_log_source_file(job->app, filename); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* PROGRESS: Processing file (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 21); /* Construct output file name */ res = bmpp_construct_output_file_name(job, filename); if (0 != res) { $? ". have output file name" /* If the -m option was specified and the file name was obtained from directory traversal we must check whether to build a new output file or not */ if (0 == job->make_mode) { $? ". make mode is 0" tsc = 0; } if (0 != tsc) { $? ". must check timestamps" res = dk4makemode_must_rebuild(&(job->onbuf[0]), filename); if (0 != res) { $? ". must build new output file" tsc = 0; } } if (0 == tsc) { $? ". must run" bmpp_run_for_file(job, filename); } else { $? ". must not run" } } /* PROGRESS: Processing file (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 22); /* Restore previous source file and line number */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); $? "- bmpp_process_one_file" } /** Process one directory. @param job Job structure. @param dirname Directory name. */ static void bmpp_process_one_directory(bmpp_job_t *job, dkChar const *dirname) { dk4_er_t er; /* Error report */ dkChar const *shn; /* Short file name */ dk4_dir_t *dir; /* Directory traversal structure */ dkChar const *osf; /* Old source file name */ dk4_um_t osl; /* Old source line number */ int cc; /* Flag: Can continue */ int res; /* Operation result */ $? "+ bmpp_process_one_directory \"%!ds\"", dirname /* Save current source file name and line number */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); /* Set current directory to process as source file name */ dk4app_set_log_source_file(job->app, dirname); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* PROGRESS: Processing directory (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 23); dir = dk4dir_open_app(dirname, DK4_DIR_OPEN_SORTED, job->app); if (NULL != dir) { cc = 1; while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_file(dir); if (NULL != shn) { /* Check for item available */ dk4error_init(&er); res = dk4dir_full_name_buffer( &(job->dtbuf[0]), DK4_MAX_PATH, dir, shn, &er ); /* If item available check file name suffix whether it is an image, process the file */ if (0 != res) { if (-1 < dk4bif_type_for_suffix(&(job->dtbuf[0]))) { bmpp_process_one_file(job, &(job->dtbuf[0]), 1); } else { /* PROGRESS: Skipping unusable input file */ dk4app_log_3( job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 25, 26, shn ); } } else { cc = 0; job->exval = EXIT_FAILURE; /* ERROR: Failed to construct full path */ dk4app_log_1(job->app,job->msg,job->sz_msg,DK4_LL_ERROR,6); } } else { cc = 0; } } dk4dir_close(dir); } else { job->exval = EXIT_FAILURE; } /* PROGRESS: Processing directory (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 24); /* Restore previous source file and line number settings */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); $? "- bmpp_process_one_directory" } /** Process one file name from the command line. @param job Job structure. @param filename File name, may be a file or a directory. */ static void bmpp_process_one_name(bmpp_job_t *job, dkChar const *filename) { dk4_er_t er; /* Error report if check for regular file fails */ dkChar const *osf; /* Old source file name */ dk4_um_t osl; /* Old source line number */ $? "+ bmpp_process_one_name \"%!ds\"", filename /* Save old source file name and line number */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); /* Set file name for error reporting to file name to process */ dk4app_set_log_source_file(job->app, filename); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* Check whether to handle a directory or a regular file */ if (0 != dk4file_is_directory(filename, NULL)) { bmpp_process_one_directory(job, filename); } else { dk4error_init(&er); if (0 != dk4file_is_regular(filename, &er)) { bmpp_process_one_file(job, filename, 0); } else { /* ERROR: Not a regular file */ job->exval = EXIT_FAILURE; dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 7); } } /* Restore previous source file name and line number settings */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); $? "- bmpp_process_one_name" } #if DK4_ON_WINDOWS /** Expand and process one file name. @param job Job structure. @param filename File name to expand, may be a file or a directory. */ static void bmpp_process_expand(bmpp_job_t *job, dkChar const *filename) { dk4_er_t er; /* Error report */ dkChar const *shn; /* Short file name */ dkChar const *osf; /* Old source file name */ dk4_dir_t *fne; /* File name expander */ dk4_um_t osl; /* Old source line number */ int anyfound; /* Flag: Fount at least one file */ int cc; /* Flag: Can continue */ int res; /* Operation result */ $? "+ bmpp_process_expand \"%!ds\"", filename /* Save current source file name and source line number */ osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); /* Set source file name and line number */ dk4app_set_log_source_file(job->app, filename); dk4app_set_log_source_line(job->app, (dk4_um_t)0UL); /* Open file name expander */ /* PROGRESS: Processing pattern (start) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 27); fne = dk4app_fne_open(filename, job->app); if (NULL != fne) { anyfound = 0; /* Process directories */ cc = 1; while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_dir(fne); if (NULL != shn) { anyfound = 1; dk4error_init(&er); res = dk4dir_full_name_buffer( &(job->exbuf[0]), DK4_MAX_PATH, fne, shn, &er ); if (0 != res) { bmpp_process_one_directory(job, &(job->exbuf[0])); } else { cc = 0; job->exval = EXIT_FAILURE; /* ERROR: Failed to construct full path */ dk4app_log_1(job->app,job->msg,job->sz_msg,DK4_LL_ERROR,6); } } else { cc = 0; } } /* Process regular files */ cc = 1; while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_file(fne); if (NULL != shn) { anyfound = 1; dk4error_init(&er); res = dk4dir_full_name_buffer( &(job->exbuf[0]), DK4_MAX_PATH, fne, shn, &er ); if (0 != res) { bmpp_process_one_file(job, &(job->exbuf[0]), 0); } else { cc = 0; job->exval = EXIT_FAILURE; /* ERROR: Failed to construct full path */ dk4app_log_1(job->app,job->msg,job->sz_msg,DK4_LL_ERROR,6); } } else { cc = 0; } } dk4dir_close(fne); if ((0 != sig_can_continue(0)) && (0 == anyfound)) { /* ERROR: No such file */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 8); job->exval = EXIT_FAILURE; } } else { job->exval = EXIT_FAILURE; } /* PROGRESS: Processing pattern (finished) */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 28); /* Restore previous source file name and line number */ dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); $? "- bmpp_process_expand" } #endif /** Process command line arguments. @param job Job structure. */ static void bmpp_run_processing(bmpp_job_t *job) { dkChar const *xargv; /* Current cmd line argument to process */ int xargc; /* Number of cmd line arguments */ int i; /* Traverse cmd line arguments */ $? "+ bmpp_run_processing" /* Retrieve number of command line file names */ xargc = dk4app_get_argc(job->app); if (0 < xargc) { /* Process command line file names, program name is already stripped, so start index is 0 */ for (i = 0; ((i < xargc) && (0 != sig_can_continue(0))); i++) { /* For each file name: retrieve and process */ xargv = dk4app_get_argv(job->app, i); if (NULL != xargv) { #if DK4_ON_WINDOWS /* On Windows command line arguments may use wildcards (* or ?), we must expand such names to real directory and file names */ if (0 != dk4path_must_expand(xargv)) { bmpp_process_expand(job, xargv); } else { bmpp_process_one_name(job, xargv); } #else bmpp_process_one_name(job, xargv); #endif } } } else { /* No file names specified on command line, run as filter */ bmpp_run_as_filter(job); } $? "- bmpp_run_processing" } #if 0 static void bmpp_resolution_handling( dk4_gra_conf_t *conf ) { #if 0 if (0 != conf->img_ign_res) { conf->img_ign_res = 0; conf->xres = 72.0; conf->yres = 72.0; } #endif } #endif /** Run functionality after installing signal handlers: Process options and configuration files, on success start processing. @param job Job structure. */ static void bmpp_normal_run(bmpp_job_t *job) { const dkChar *lpo = NULL; /* Arguments of -l options */ int ok = 1; /* Flag: No error occured */ $? "+ bmpp_normal_run" /* Process command line options */ if (0 != dk4app_opt_is_set_short(job->app, dkT('R'), NULL)) { job->use_prefs = 0; } if (0 != dk4app_opt_is_set_short(job->app, dkT('m'), NULL)) { job->make_mode = 1; } if (0 != dk4app_opt_is_set_short(job->app, dkT('l'), NULL)) { lpo = dk4app_opt_get_string_ptr_short(job->app, dkT('l'), NULL); } /* Process argument of -l option, if any */ if (NULL != lpo) { ok = dk4gra_conf_setup( &(job->grco), lpo, job->use_prefs, DK4_GRA_CONF_SCOPE_BMPP, job->app ); #if 0 bmpp_resolution_handling(&(job->grco)); #endif } else { if (0 != job->use_prefs) { ok = dk4gra_conf_setup( &(job->grco), NULL, 1, DK4_GRA_CONF_SCOPE_BMPP, job->app ); #if 0 bmpp_resolution_handling(&(job->grco)); #endif } else { ok = 1; } } /* Do not use TeX output driver */ if (DK4_GRA_DRIVER_PGF == job->grco.driver) { ok = 0; /* ERROR: Can not produce TeX output */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 2); job->exval = EXIT_FAILURE; } /* Start processing if no errors yet */ if (0 != ok) { $? ". can run" job->exval = EXIT_SUCCESS; bmpp_run_processing(job); } $? "- bmpp_normal_run" } #if DK4_HAVE_SIGACTION /** Set signal handlers and run. @param job Job structure. */ static void bmpp_run_with_signal_handlers(bmpp_job_t *job) { #ifdef SIGPIPE struct sigaction opipe; #endif struct sigaction oint; #ifdef SIGPIPE struct sigaction npipe; #endif struct sigaction nint; struct sigaction oterm; struct sigaction nterm; int success = 0; $? "+ bmpp_run_with_signal_handlers (sigaction)" #ifdef SIGPIPE /* Set up signal handling for SIGPIPE. */ DK4_MEMRES(&npipe, sizeof(npipe)); npipe.sa_handler = sig_handler_pipe; npipe.sa_flags = 0; if (0 != sigemptyset(&npipe.sa_mask)) { /* ERROR: Failed to set up masked signal set for SIGPIPE */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto finished; } if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { /* ERROR: Failed to set up masked signal set for SIGPIPE */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto finished; } if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { /* ERROR: Failed to set up signal handler for SIGPIPE */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto finished; } #endif /* Set up signal handling for SIGINT. */ DK4_MEMRES(&nint, sizeof(nint)); nint.sa_handler = sig_handler_int; nint.sa_flags = 0; if (0 != sigemptyset(&nint.sa_mask)) { /* ERROR: Failed to set up masked signal set for SIGINT */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto restore_old_pipe; } if (0 != sigaddset(&nint.sa_mask, SIGINT)) { /* ERROR: Failed to set up masked signal set for SIGINT */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto restore_old_pipe; } if (0 != sigaction(SIGINT, &nint, &oint)) { /* ERROR: Failed to set up signal handler for SIGINT */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto restore_old_pipe; } /* Set up signal handling for SIGTERM */ DK4_MEMRES(&nterm, sizeof(nterm)); nterm.sa_handler = sig_handler_term; nterm.sa_flags = 0; if (0 != sigemptyset(&nterm.sa_mask)) { /* ERROR: Failed to set up masked signal set for SIGTERM */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto restore_old_int; } if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) { /* ERROR: Failed to set up masked signal set for SIGTERM */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto restore_old_int; } if (0 != sigaction(SIGTERM, &nterm, &oterm)) { /* ERROR: Failed to set up signal handler for SIGTERM */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 0); goto restore_old_int; } success = 1; bmpp_normal_run(job); /* Restore signal handling for SIGTERM. */ if (0 != sigaction(SIGTERM, &oterm, NULL)) { /* ERROR: Failed to restore old SIGTERM settings */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 1); success = 0; } /* Restore signal handling for SIGINT. */ restore_old_int: if (0 != sigaction(SIGINT, &oint, NULL)) { /* ERROR: Failed to restore old SIGPIPE settings */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 1); success = 0; } #ifdef SIGPIPE /* Restore signal handling for SIGPIPE. */ restore_old_pipe: if (0 != sigaction(SIGPIPE, &opipe, NULL)) { /* ERROR: Failed to restore old SIGPIPE settings */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 1); success = 0; } #endif /* Set exit status code if error occured. */ finished: if (0 == success) { job->exval = EXIT_FAILURE; } $? "- bmpp_run_with_signal_handlers" } #else #if DK4_HAVE_SIGSET /** Set signal handlers and run. @param job Job structure. */ static void bmpp_run_with_signal_handlers(bmpp_job_t *job) { #ifdef SIGPIPE dk4_sig_handler_t *oldpipe = NULL; #endif dk4_sig_handler_t *oldint = NULL; dk4_sig_handler_t *oldterm = NULL; $? "+ bmpp_run_with_signal_handlers (sigset)" #ifdef SIGPIPE oldpipe = sigset(SIGPIPE, sig_handler_pipe); #endif oldint = sigset(SIGINT, sig_handler_int); oldterm = sigset(SIGTERM, sig_handler_term); bmpp_normal_run(job); sigset(SIGTERM, oldterm); sigset(SIGINT, oldint); #ifdef SIGPIPE sigset(SIGPIPE, oldpipe); #endif $? "- bmpp_run_with_signal_handlers" } #else #if DK4_HAVE_SIGNAL /** Set signal handlers and run. @param job Job structure. */ static void bmpp_run_with_signal_handlers(bmpp_job_t *job) { #ifdef SIGPIPE dk4_sig_handler_t *oldpipe = NULL; #endif dk4_sig_handler_t *oldint = NULL; dk4_sig_handler_t *oldterm = NULL; $? "+ bmpp_run_with_signal_handlers (signal)" #ifdef SIGPIPE oldpipe = signal(SIGPIPE, sig_handler_pipe); #endif oldint = signal(SIGINT, sig_handler_int); oldterm = signal(SIGTERM, sig_handler_term); bmpp_normal_run(job); signal(SIGTERM, oldterm); signal(SIGINT, oldint); #ifdef SIGPIPE signal(SIGPIPE, oldpipe); #endif $? "- bmpp_run_with_signal_handlers" } #else /** Set signal handlers and run. @param job Job structure. */ static void bmpp_run_with_signal_handlers(bmpp_job_t *job) { bmpp_normal_run(job); } #endif #endif #endif /** Job structure, not on the stack because it is large. */ static bmpp_job_t job; /** Main function. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, all other values indicate errors. */ #if DK4_CHAR_SIZE > 1 int wmain(int argc, wchar_t *argv[]) #else int main(int argc, char *argv[]) #endif { $!trace-init bmpp.deb $? "+ main" /* Initialize job structure */ bmpp_job_init(&job); /* Prepare stderr for diagnostic messages with dkChar strings */ dk4fput_initialize_stderr(); /* Create application structure */ job.app = dk4app_open_cmd( argc, argv, bmpp_options, bmpp_sz_options, bmpp_kwnl[0], DKT_VERSION_DK, bmpp_kwnl[1], bmpp_help_text, bmpp_license_text ); if (NULL != job.app) { /* Retrieve localized string tables */ job.sz_msg = dk4app_string_table_size(bmpp_kw_def); job.msg = dk4app_string_table(job.app, bmpp_kwnl[2], bmpp_kw_def); /* Either run normally (do conversions) or show help, version, and/or license information */ if (0 != dk4app_can_run_normally(job.app)) { bmpp_run_with_signal_handlers(&job); } else { if (0 != dk4app_help_version_license(job.app)) { job.exval = EXIT_SUCCESS; } } /* Finally close application structure */ dk4app_close(job.app); } fflush(stderr); dk4fput_cleanup_stderr(); $? "- main %d", job.exval $!trace-end exit(job.exval); return job.exval; } /* vim: set ai sw=4 ts=4 : */