/* Copyright (C) 2012-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: fig2lat.ctr */ /** @file fig2lat.c The fig2lat module. */ #line 210 "fig2lat.ctr" /** Test flag to show Beziervalues. */ #define FIG2LAT_TEST_BEZIER 0 #include "dk3all.h" #include "dk3bezcu.h" #include "fig2lat.h" #include "f2lud.h" #include "f2lsvg.h" #include "dk3figto.h" #if 0 #include "dkt-version.h" #endif #include "dk4vers.h" #line 231 "fig2lat.ctr" /** Keywords used by the module, not localized. */ static dkChar const * const f2l_kw[] = { /* 0 */ dkT("dktools"), /* 1 */ dkT("fig2lat.str"), /* 2 */ dkT("fig2lat.txt"), /* 3 */ dkT(".fig"), /* 4 */ dkT(".pgf"), /* 5 */ dkT(".svg"), /* 6 */ dkT(".eps"), /* 7 */ dkT(".tex"), /* 8 */ dkT(".pdf"), /* 9 */ dkT("-i.pdf"), NULL #line 279 "fig2lat.ctr" }; /** Version number. */ static dkChar const *fig2lat_version[] = { dkT("fig2lat "), DKT_VERSION_DK }; /** License conditions. */ static dkChar const * const fig2lat_license[] = { dkT(""), dkT("Copyright (c) 2013-2016, Dirk Krause"), dkT("All rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms,"), dkT("with or without modification, are permitted provided"), dkT("that the following conditions are met:"), dkT(""), dkT("* Redistributions of source code must retain the above"), dkT(" copyright notice, this list of conditions and the"), dkT(" following disclaimer."), dkT("* Redistributions in binary form must reproduce the above "), dkT(" copyright notice, this list of conditions and the following"), dkT(" disclaimer in the documentation and/or other materials"), dkT(" provided with the distribution."), dkT("* Neither the name of the copyright holder(s) nor the names of"), dkT(" contributors may be used to endorse or promote"), dkT(" products derived from this software without specific"), dkT(" prior written permission."), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\""), dkT("AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"), dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), dkT("ARE DISCLAIMED."), dkT("IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY"), dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES"), dkT("(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR"), dkT("SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER"), dkT("CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,"), dkT("STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN"), dkT("ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE"), dkT("POSSIBILITY OF SUCH DAMAGE."), dkT(""), NULL #line 330 "fig2lat.ctr" }; /** Default help text, shown if no help file is found. */ static dkChar const * const fig2lat_help_text[] = { dkT(""), dkT("NAME"), dkT(""), dkT("fig2lat - Fig to LaTeX conversion"), dkT(""), dkT("SYNOPSIS"), dkT(""), dkT(" fig2lat [-l ] [] [-o =]* "), dkT(""), dkT("DESCRIPTION"), dkT(""), dkT("Fig2lat converts *.fig drawings created using XFig or jFig"), dkT("to other graphics formats, mainly for use with the LaTeX typesetting"), dkT("system."), dkT(""), dkT("OPTIONS"), dkT(""), dkT("-l "), dkT(" \tDriver, one from the following:"), dkT(""), dkT("\tDrivers to use a Fig file with latex or pdflatex:"), dkT(""), dkT("\tpdf.tex\t\tProduce a *.tex/*.pdf file pair."), dkT("\t\t\tInclude the *.tex file in your LaTeX source, the"), dkT("\t\t\t*.tex file includes the *.pdf file."), dkT(""), dkT("\teps.tex\t\tProduce a *.tex/*.eps file pair."), dkT("\t\t\tInclude the *.tex file in your LaTeX source, the"), dkT("\t\t\t*.tex file includes the *.eps file."), dkT(""), dkT("\tpgf\t\tProduce a *.pgf file for inclusion in a *.tex"), dkT("\t\t\tsource."), dkT(""), dkT("\tDrivers to produce a standalone image:"), dkT(""), dkT("\ttex.pdf\t\tProduce a full *.tex file for use with pdflatex."), dkT("\t\t\tA file file-i.pdf is produced additionally,"), dkT("\t\t\tthis file is included by the *.tex file."), dkT(""), dkT("\ttex\t\tProduce a full *.tex file for use with pdflatex."), dkT("\t\t\tThe image is embedded as a PGF image."), dkT(""), dkT("\teps\t\tProduce a standalone EPS file."), dkT(""), dkT("\tsvg\t\tProduce a standalone SVG file."), dkT(""), dkT("-m"), dkT("\tMake mode when running on a directory: Convert"), dkT("\tfiles only if no destination files up to date are found."), dkT(""), dkT("-o key=value"), dkT("\tKey/value options, may be used multiple times."), dkT("\tThe following keys can be used:"), dkT(""), dkT(""), dkT("\tGeneral options:"), dkT(""), dkT("\tlw=\t\tLine width base."), dkT("\t\t\t\tThe default for Fig files is 1/80 inch."), dkT("\t\t\t\tWidth can be one of the following:"), dkT("\t\t\t\tbp\tPS points"), dkT("\t\t\t\tpt\tWidth in pt"), dkT("\t\t\t\tin\tWidth in inch"), dkT("\t\t\t\tcm\tWidth in cm"), dkT("\t\t\t\tmm\tWidth in mm"), dkT("\t\t\t\tlighten\t\tUse 1/160 inch"), dkT("\t\t\t\tauto\t\t0.4pt * textsize / 10"), dkT(""), dkT("\tText handling options"), dkT(""), dkT("\ttf=\t\tText font selection for normal (non-special)"), dkT("\t\t\t\ttext. Either ``similar'' or ``fig''."), dkT(""), dkT("\tts=\t\tFont size factor for normal (non-special) text."), dkT("\t\t\t\tEither the keyword ``none'' or a scale factor"), dkT("\t\t\t\t(typically in the range 0.95 ... 1.0)."), dkT(""), dkT("\tbbts[=]\tUse text size in bounding box calculaion."), dkT(""), dkT("\tsmash[=]\tUse \\smash instruction in LaTeX output."), dkT(""), dkT("\tmbox[=]\tUse \\mbos instruction in LaTeX output."), dkT(""), dkT("\treset@font[=]\tUse \\reset@font instruction in LaTeX output."), dkT(""), dkT("\tste[=]\tEncoding used when writing special text"), dkT("\t\t\t\tto output file. Either ``plain'' or"), dkT("\t\t\t\t``utf-8''."), dkT(""), dkT(""), dkT("\tX-Spline and Bezier-Spline options"), dkT(""), dkT("\txsss[=]\t\tNumber of Bezier-Spline subsegments per"), dkT("\t\t\t\tX-spline segment. Default: 8, minimum: 2."), dkT(""), dkT(""), dkT("\tArrowhead options:"), dkT(""), dkT("\tahas=\t\tNumber of X-spline segments for a 90 degree"), dkT("\t\t\t\tangle on arcs. Default: 4."), dkT(""), dkT("\tahss=\t\tNumber of arrowhead X-spline segments"), dkT("\t\t\t\tfor each original X-spline segment for"), dkT("\t\t\t\tarrowheads on splines. Default: 4."), dkT(""), dkT("\tahms=\t\tMinimum number of X-spline segments for"), dkT("\t\t\t\teach arrowhead edge. Default: 4"), dkT("\t"), dkT("\tahbs[=]\tUse bisection iteration on spline arrowheads."), dkT(""), dkT("\tahip=\t\tArrowhead iteration precision. Default: 0.04."), dkT(""), dkT(""), dkT("\tOutput options:"), dkT(""), dkT("\tcodi=[]\t\tNumber of digits used for colors. Default: 3."), dkT(""), dkT(""), dkT("\tCompatibility options (compatibility to fig2dev):"), dkT(""), dkT("\tcosp[=]\tCompatible splines."), dkT(""), dkT("\tcoah[=]\tCompatible arrowheads."), dkT(""), dkT("\txsah[=]\tX-spline arrowheads (not together with coah)."), dkT(""), dkT("\tcols[=]\tCompatible line styles."), dkT(""), dkT("\tcofop[=]\tCompatible fill for open paths."), dkT(""), dkT(""), dkT("\tSource type (mutually exclusive):"), dkT(""), dkT("\txfig\t\t\tFile produced by XFig"), dkT(""), dkT("\tjfig\t\t\tFile produced by jFig."), dkT(""), dkT("\twinfig\t\t\tFile produced by WinFIG."), dkT(""), dkT(""), dkT("\tDriver specific options (tex, tex.pdf):"), dkT(""), dkT("\tdcts[=]\t\tFont size in pt used in the document class."), dkT(""), dkT(""), dkT("\tDriver specific options (eps, eps.tex):"), dkT(""), dkT("\tshowpage[=]\tUse showpage operator."), dkT(""), dkT("\tlevel=\t\tPS level, 2 or 3."), dkT(""), dkT("\tDriver specific options (svg)"), dkT(""), dkT("\tcss[=]\t\tUse CSS styling."), dkT(""), dkT("\tgroup[=]\tGroup arrowhead objects with the object they"), dkT("\t\t\t\tare attached to."), dkT(""), dkT("\tfragment[=]\tWrite an SVG fragment instead of a complete"), dkT("\t\t\t\tfile."), dkT(""), dkT("\tfontbase[=]\tSpecify source for GhostScript fonts"), dkT("\t\t\t\tconverted to TTF, \"none\", \"local\", or \"web\"."), dkT(""), dkT("\treplacementfonts=[]\tenables/disables use of replacement"), dkT("\t\t\t\t\tfont families."), dkT(""), dkT("\tmiterlimit[=]\tEnables or disables use of \"stroke-miterlimit\""), dkT("\t\t\t\tstyle setting."), dkT(""), dkT(""), dkT("EXIT STATUS"), dkT(""), dkT("0 on success, all other exit status codes indicate an error."), dkT(""), dkT("FILES"), dkT(""), dkT("Fig2lat uses the following files from the current working directory:"), dkT(""), dkT("f2lfonts.tex\tis used in the preamble of tex and tex.pdf output, the file"), dkT("\t\tcontents replaces the font selection packages."), dkT(""), dkT("f2lother.tex\tis used in the preamble of tex and tex.pdf output, the file"), dkT("\t\tcontents replaces the packages for \"other setup\"."), dkT(""), dkT("NOTES"), dkT(""), dkT("There are differences between the output from fig2lat and the output"), dkT("from fig2dev. This is intended, otherwise we would not need an additional"), dkT("program."), dkT(""), dkT("* Interpolated X-splines: Fig2lat uses the correct formula q=-0.5*s"), dkT(" as described in [BS1995]."), dkT(""), dkT("* Arrowheads: All arrowhead types introduced in xfig 3.2.5 are supported."), dkT(" On splines and arcs we have curved arrowheads. The same line width as"), dkT(" for the original line is used for the arrowhead too, the arrowhead"), dkT(" linewidth specified in the Fig file is ignored."), dkT(""), dkT("* Text: When using LaTeX/pdfLaTeX related drivers (tex, tex.pdf, pdf.tex,"), dkT(" eps.tex, pgf) all text is handled by LaTeX/pdfLaTeX. The tf setting"), dkT(" controls whether to use PS fonts or similar feature LaTeX fonts for"), dkT(" normal text. For special text no font selection instructions are written"), dkT(" at all, so document default fonts are used."), dkT(""), dkT("* Fill patterns: Fill patterns are vector graphics in fig2lat."), dkT(""), dkT("* Splines: X-splines are converted to a sequence of Bezier splines instead"), dkT(" of polylines."), dkT(""), dkT("KNOWN ISSUES"), dkT(""), dkT("* The curved arrowheads on arcs and splines are implemented as sequences"), dkT(" of short - sometimes very short - Bezier curves."), dkT(" At least for my arrowtest.fig test file I saw malformed arrowheads"), dkT(" in some renderers although the same graphics were shown fine in other"), dkT(" renderers."), dkT(" You can avoid the problem by using the coah option (compatible arrowheads)."), dkT(" For Batik 1.7 Squiggle you can also attempt the miterlimit=no option."), dkT(""), dkT("AUTHOR"), dkT(""), dkT("Dirk Krause"), dkT(""), dkT("HISTORY"), dkT(""), dkT("This program replaces the fig2vect program seen in previous versions"), dkT("of dktools."), dkT(""), dkT("COPYRIGHT AND LICENSE"), dkT(""), dkT("Run"), dkT(" fig2lat --license-terms"), dkT("to see the license conditions."), dkT(""), dkT("SEE ALSO"), dkT(""), dkT("[BS1995]\tCarole Blanc, Christophe Schlick:"), dkT("\t\tX-Splines: A Spline Model Designed for the End-User"), dkT("\t\tProceedings of the SIGGRAPH 1995"), dkT(""), dkT("[fig2lat]\thttp://sourceforge.net/p/dktools/wiki/fig2lat%20manual/"), dkT(""), NULL #line 582 "fig2lat.ctr" }; /** Default texts, used if localized texts are not found. */ static dkChar const * const f2l_default_messages[] = { /* 0 */ dkT("Invalid PS level preference value \""), /* 1 */ dkT("\"!"), /* 2 */ dkT("Input file name too long:\n"), /* 3 */ dkT("Failed to read input file!"), /* 4 */ dkT("Failed to process input file!"), /* 5 */ dkT("Not a regular file, not a directory!"), /* 6 */ dkT("Command line options processing failed!"), /* 7 */ dkT("Unknown driver \""), /* 8 */ dkT("\"!"), /* 9 */ dkT("Invalid value \""), /* 10 */ dkT("\" for tf, use \"fig\" or \"similar\"!"), /* 11 */ dkT("Invalid font size specification \""), /* 12 */ dkT("\"!"), /* 13 */ dkT("Invalid size specification \""), /* 14 */ dkT("\" (overflow)!"), /* 15 */ dkT("Value \""), /* 16 */ dkT("\" is below the required minimum \""), /* 17 */ dkT("\"!"), /* 18 */ dkT("\" is above the required maximum \""), /* 19 */ dkT("Option \""), /* 20 */ dkT("\" requires a positive argument!"), /* 21 */ dkT("Option \""), /* 22 */ dkT("\" requires a numeric argument!"), /* 23 */ dkT("Source type already set!"), /* 24 */ dkT("Option \""), /* 25 */ dkT("\" requires an unsigned numeric argument!"), /* 26 */ dkT("Can not handle negative font size!"), /* 27 */ dkT("Illegal option/key name \""), /* 28 */ dkT("\"!"), /* 29 */ dkT("Option too long:\n\""), /* 30 */ dkT("\""), /* 31 */ dkT("Option argument too long:\n\""), /* 32 */ dkT("Option -l requires an argument!"), /* 33 */ dkT("PS level must be 2 or 3!"), /* 34 */ dkT("Minimum of arrowhead segments corrected to 2!"), /* 35 */ dkT("Mathematical problem (coordinates transformation)!"), /* 36 */ dkT("Mathematical problem (spline calculation)!"), /* 37 */ dkT("Arrowhead too long for spline!"), /* 38 */ dkT("Mathematical problem (path construction)!"), /* 39 */ dkT("Arrowheads in summary too long for spline!"), /* 40 */ dkT("Failed to calculate graphics state transformation!"), /* 41 */ dkT("Failed to add instructions to PDF graphics!"), /* 42 */ dkT("Skipping special text!"), /* 43 */ dkT("Unknown object type!"), /* 44 */ dkT("Special text found!"), /* 45 */ dkT("Not a line width: \""), /* 46 */ dkT("\"!"), NULL #line 737 "fig2lat.ctr" }; /** PS level preference name. */ static dkChar const fig2lat_pref_psl[] = { dkT("/print/ps/level") }; /** Preference name for compatible splines. */ static dkChar const fig2lat_pref_cosp[] = { dkT("/fig/compatible-splines") }; #if 0 /** Initialize a configuration structure. @param conf Structure to initialize. */ static void fig2lat_config_init(fig2lat_config_t *conf) { #line 766 "fig2lat.ctr" dk3mem_res((void *)conf, sizeof(fig2lat_config_t)); conf->nts = 1.0; conf->ntf = 0; #line 770 "fig2lat.ctr" } #endif /** Set PS level from preferences. @param job Job structure. */ static void fig2lat_set_ps_level_from_preferences(f2l_job_t *job) { dkChar buf[256]; /* Buffer to retrieve preference value. */ int i; /* Conversion result. */ if(dk3app_get_pref(job->app,fig2lat_pref_psl,buf,DK3_SIZEOF(buf,dkChar))) { #if VERSION_BEFORE_20140716 if(dk3sf_sscanf3(buf, dkT("%d"), &i)) #else if (0 != dk3ma_i_from_string(&i, buf, NULL)) #endif { if((i >= 2) && (i <= 3)) { job->pslevel = i; } else { /* Warning: Preference value is not a number! */ dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 0, 1, buf); } } else { /* Warning: Preference value is not a number! */ dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 0, 1, buf); } } } /** Initialize job structure. @param job Job structure to initialize. @param app Application structure for diagnostics. @param msg Localized message texts. @param figmsg Localized message texts for the dk3fig module. @return 1 on success, 0 on error. */ static int fig2lat_job_init( f2l_job_t *job, dk3_app_t *app, dkChar const * const *msg, dkChar const * const *figmsg ) { int back = 0; #line 824 "fig2lat.ctr" dk3mem_res((void*)job, sizeof(f2l_job_t)); dk3fig_gs_init(&(job->gs)); job->app = app; job->msg = msg; job->figmsg = figmsg; job->opt = NULL; job->drw = NULL; job->on1 = NULL; job->on2 = NULL; job->of1 = NULL; job->of2 = NULL; job->nts = 1.0; job->tts = 12.0; #if 0 fig2lat_config_init(&(job->confProgram)); fig2lat_config_init(&(job->confFile)); fig2lat_config_init(&(job->confObject)); #endif job->dr = FIG2LAT_DRIVER_PDF_WITH_TEX; job->exval = FIG2LAT_EXIT_ERROR_UNKNOWN; job->mm = 0; job->cmd = 0; job->cosp = dk3app_get_pref_bool(app, fig2lat_pref_cosp, 1); job->coah = 0; #line 848 "fig2lat.ctr" job->xsah = 0; job->xssbs = 8; job->qbs = 4; job->debug = 0; job->showpage = 0; job->pslevel = 3; job->dsc = 0; job->arcspp = 8.0; job->splspp = 8.0; job->minspp = 4; job->xsprec = 0.04; /* originally 1200 / 25400 */ job->srctype = DK3_FIG_SRCTYPE_UNKNOWN; job->smash = 1; job->mbox = 0; job->resfont = 1; job->codi = 3; job->css = 1; job->fragment = 0; job->svgfontbase = 0; job->group = 0; job->miterlim = 1; job->cols = 0; job->otherfonts = 1; job->bbts = 0; job->stu8 = 0; job->cofop = 1; job->ahbs = 0; job->lwbp = 0.9; /* 1/80 inch */ job->lwauto = 0; if(dk3app_get_encoding(app) == DK3_ENCODING_UTF8) { job->stu8 = 1; } fig2lat_set_ps_level_from_preferences(job); (job->ct2d).mx = (job->ct2d).my = (job->ct2d).nx = (job->ct2d).ny = 0.0; job->width = job->height = job->w2 = job->h2 = 0.0; job->lwidth = job->lheight = 0L; /* @DRIVER@ If you added components to the f2l_job_t structure, initialize them to default values here. */ back = 1; #line 890 "fig2lat.ctr" return back; } /** Clean up job structure. @param job Job structure to clean up. */ static void fig2lat_job_end(f2l_job_t *job) { #line 903 "fig2lat.ctr" /* @DRIVER@ If you added components to the f2l_job_t structure make sure to release resources here. */ if(job->opt) { dk3opt_close(job->opt); job->opt = NULL; } #line 911 "fig2lat.ctr" } /** Show version information. @param job Job structure. */ static void fig2lat_show_version(void) { dk3sf_initialize_stdout(); dk3sf_fputs(fig2lat_version[0], stdout); dk3sf_fputs(fig2lat_version[1], stdout); dk3sf_fputc(dkT('\n'), stdout); } /** Show license terms. @param job Job structure. */ static void fig2lat_show_license(void) { dkChar const * const *ptr; /* Pointer to traverse all text lines. */ ptr = fig2lat_license; dk3sf_initialize_stdout(); while(*ptr) { dk3sf_fputs(*(ptr++), stdout); dk3sf_fputc(dkT('\n'), stdout); } } /** Show help text. @param job Job structure. */ static void fig2lat_show_help(f2l_job_t *job) { dk3app_help(job->app, f2l_kw[2], fig2lat_help_text); } /** Check whether a file has a fig suffix. @param fn File name. @return 1 for fig files, 0 for other or no suffix. */ static int fig2lat_is_fig_file(dkChar const *fn) { dkChar const *sp; /* Suffix found in file name. */ int back = 0; sp = dk3str_get_suffix(fn); if(sp) { if(0 == dk3str_cmp(sp, f2l_kw[3])) { back = 1; } } return back; } /** Create output file name. @param job Job structure. @param ifn Input file name. @param osf Output suffix. @return Valid pointer to new output name on success, NULL on error. */ static dkChar const * fig2lat_set_one_output_name( f2l_job_t *job, dkChar const *ifn, dkChar const *osf ) { dkChar buf[DK3_MAX_PATH]; /* Buffer for modification. */ dkChar *sp; /* File name suffix in buffer. */ dkChar const *back = NULL; #line 998 "fig2lat.ctr" if(dk3str_len(ifn) < DK3_SIZEOF(buf,dkChar)) { dk3str_cpy_not_overlapped(buf, ifn); sp = dk3str_get_suffix(buf); if(sp) { *sp = dkT('\0'); } if((dk3str_len(buf) + dk3str_len(osf)) < DK3_SIZEOF(buf,dkChar)) { dk3str_cat(buf, osf); back = dk3str_dup_app(buf, job->app); if(!(back)) { job->exval = FIG2LAT_EXIT_ERROR_SYSTEM; #line 1007 "fig2lat.ctr" } } else { #line 1009 "fig2lat.ctr" /* ERROR: Input file name too long! */ job->exval = FIG2LAT_EXIT_FILENAME_TOO_LONG; #line 1011 "fig2lat.ctr" dk3app_log_2(job->app, DK3_LL_ERROR, job->msg, 2, buf); } } else { #line 1014 "fig2lat.ctr" /* ERROR: Input file name too long! */ job->exval = FIG2LAT_EXIT_FILENAME_TOO_LONG; #line 1016 "fig2lat.ctr" dk3app_log_2(job->app, DK3_LL_ERROR, job->msg, 2, ifn); } #line 1018 "fig2lat.ctr" return back; } /** Set output file name(s) depending on input name and output driver. @param job Job structure. @param ifn Input file name. @return 1 on success, 0 on error. */ static int fig2lat_set_output_names(f2l_job_t *job, dkChar const *ifn) { int back = 0; #line 1034 "fig2lat.ctr" switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[7]); if(job->on1) { back = 1; } } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[7]); job->on2 = fig2lat_set_one_output_name(job, ifn, f2l_kw[9]); if((job->on1) && (job->on2)) { back = 1; } } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[7]); job->on2 = fig2lat_set_one_output_name(job, ifn, f2l_kw[6]); if((job->on1) && (job->on2)) { back = 1; } } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[7]); job->on2 = fig2lat_set_one_output_name(job, ifn, f2l_kw[8]); if((job->on1) && (job->on2)) { back = 1; } } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[6]); if(job->on1) { back = 1; } } break; case FIG2LAT_DRIVER_SVG_STANDALONE: { job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[5]); if(job->on1) { back = 1; } } break; default: { /* PGF */ job->on1 = fig2lat_set_one_output_name(job, ifn, f2l_kw[4]); if(job->on1) { back = 1; } } break; } #line 1068 "fig2lat.ctr" #line 1069 "fig2lat.ctr" if(!(back)) { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 1071 "fig2lat.ctr" } #line 1073 "fig2lat.ctr" return back; } /** Run for one file. @param job Job structure. @param fn File name (no wildcards contained). */ static void fig2lat_run_for_file(f2l_job_t *job, dkChar const *fn) { dkChar const *oldsrcname; /* Saved source file name. */ #if DK3_HAVE_SETLOCALE && defined(LC_NUMERIC) && DK3_HAVE_LOCALE_H char *oldlocale; /* Old locale setting. */ #endif unsigned long oldsrcline; /* Saved source file line number. */ #line 1092 "fig2lat.ctr" oldsrcname = dk3app_get_source_file(job->app); oldsrcline = dk3app_get_source_line(job->app); dk3app_set_source_file(job->app, fn); dk3app_set_source_line(job->app, 0UL); #if 0 /* Copy program configuration to file configuration. */ dk3mem_cpy( (void *)(&(job->confFile)), (void *)(&(job->confProgram)), sizeof(fig2lat_config_t) ); #endif job->on1 = NULL; job->on2 = NULL; if(fig2lat_set_output_names(job, fn)) { job->drw = dk3fig_drawing_new(job->app, job->figmsg); if(job->drw) { dk3fig_set_options_bsegs(job->drw, job->xssbs, job->qbs); dk3fig_set_options_lwbp(job->drw, job->lwbp); dk3fig_set_options_coah(job->drw, job->coah); dk3fig_set_options_xsah(job->drw, job->xsah); dk3fig_set_options_cosp(job->drw, job->cosp); dk3fig_set_options_bbts(job->drw, job->bbts); dk3fig_set_options_srctype(job->drw, job->srctype); dk3fig_set_options_arrows(job->drw,job->arcspp,job->splspp,job->minspp); dk3fig_set_options_iteration_precision(job->drw, job->xsprec); dk3fig_set_options_codi(job->drw, job->codi); dk3fig_set_options_cofop(job->drw, job->cofop); dk3fig_set_options_ah_bisection(job->drw, job->ahbs); if(dk3fig_read_file_name(job->drw, fn)) { #line 1124 "fig2lat.ctr" if(dk3fig_prepare(job->drw)) { #line 1125 "fig2lat.ctr" #if DK3_HAVE_SETLOCALE && defined(LC_NUMERIC) && DK3_HAVE_LOCALE_H oldlocale = setlocale(LC_NUMERIC, "C"); #endif dk3fig_gs_init(&(job->gs)); switch(job->dr) { case FIG2LAT_DRIVER_SVG_STANDALONE: { f2lsvg_output(job); } break; /* @DRIVER@ Add a case branch to call your output driver here. If any error occurs in the driver function, set job->exval to indicate the error. */ default: { f2lud_output(job); } break; } #if DK3_HAVE_SETLOCALE && defined(LC_NUMERIC) && DK3_HAVE_LOCALE_H setlocale(LC_NUMERIC, oldlocale); #endif } else { #line 1146 "fig2lat.ctr" /* ERROR while preparing drawing! */ f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 1148 "fig2lat.ctr" dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 4); } } else { #line 1151 "fig2lat.ctr" /* ERROR while reading input file! */ f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN); #line 1153 "fig2lat.ctr" dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 3); } dk3fig_drawing_delete(job->drw); job->drw = NULL; } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 1158 "fig2lat.ctr" } } dk3_release(job->on1); dk3_release(job->on2); dk3app_set_source_file(job->app, oldsrcname); dk3app_set_source_line(job->app, oldsrcline); #line 1165 "fig2lat.ctr" } /** Check whether there is an up-to-date output file for the given file name and output suffix. @param job Job structure. @param fn Source file name. @param sn Suffix for output file name. @return 1 if output file is available, 0 otherwise. */ static int fig2lat_up_to_date_output(f2l_job_t *job, dkChar const *fn, dkChar const *sn) { dk3_stat_t stbs; /* Source file information. */ dk3_stat_t stbd; /* Destination file information. */ dkChar fnb[DK3_MAX_PATH]; /* File name buffer. */ dkChar *sp; /* File name suffix in buffer. */ int back = 0; #line 1186 "fig2lat.ctr" if(dk3str_len(fn) < DK3_SIZEOF(fnb,dkChar)) { dk3str_cpy_not_overlapped(fnb, fn); sp = dk3str_get_suffix(fnb); if(sp) { *sp = dkT('\0'); if((dk3str_len(fnb) + dk3str_len(sn)) < DK3_SIZEOF(fnb,dkChar)) { dk3str_cpy_not_overlapped(sp, sn); if(dk3sf_stat_app(&stbs, fn, job->app)) { if(dk3sf_stat_app(&stbd, fnb, NULL)) { if(stbd.mod > stbs.mod) { back = 1; #line 1197 "fig2lat.ctr" } } } } } } #line 1203 "fig2lat.ctr" return back; } /** Check whether we need to process a fig file found in a directory. @param job Job structure. @param fn File name to check. @return 1 to process the file, 0 to skip processing. */ static int fig2lat_must_process_file(f2l_job_t *job, dkChar const *fn) { int back = 1; #line 1219 "fig2lat.ctr" if(job->mm) { switch(job->dr) { case FIG2LAT_DRIVER_TEX_FULL_PGF: { if(fig2lat_up_to_date_output(job, fn, f2l_kw[7])) { back = 0; } } break; case FIG2LAT_DRIVER_TEX_FULL_PDF: { if(fig2lat_up_to_date_output(job, fn, f2l_kw[7])) { if(fig2lat_up_to_date_output(job, fn, f2l_kw[9])) { back = 0; } } } break; case FIG2LAT_DRIVER_EPS_WITH_TEX: { if(fig2lat_up_to_date_output(job, fn, f2l_kw[6])) { if(fig2lat_up_to_date_output(job, fn, f2l_kw[7])) { back = 0; } } } break; case FIG2LAT_DRIVER_PDF_WITH_TEX: { if(fig2lat_up_to_date_output(job, fn, f2l_kw[7])) { if(fig2lat_up_to_date_output(job, fn, f2l_kw[8])) { back = 0; } } } break; case FIG2LAT_DRIVER_EPS_STANDALONE: { if(fig2lat_up_to_date_output(job, fn, f2l_kw[6])) { back = 0; } } break; case FIG2LAT_DRIVER_SVG_STANDALONE: { if(fig2lat_up_to_date_output(job, fn, f2l_kw[5])) { back = 0; } } break; default: { /* PGF */ if(fig2lat_up_to_date_output(job, fn, f2l_kw[4])) { back = 0; } } break; } } #line 1264 "fig2lat.ctr" return back; } /** Process a directory. @param job Job structure. @param fn Directory name. */ static void fig2lat_run_for_directory(f2l_job_t *job, dkChar const *fn) { dk3_dir_t *dir; /* Directory traversal. */ dkChar const *filename; /* Found file name. */ #line 1280 "fig2lat.ctr" dir = dk3dir_open_app(fn, job->app); if(dir) { while(dk3dir_get_next_file(dir)) { filename = dk3dir_get_fullname(dir); if(filename) { if(fig2lat_is_fig_file(filename)) { if(fig2lat_must_process_file(job, filename)) { fig2lat_run_for_file(job, filename); } } } else { #line 1291 "fig2lat.ctr" } } dk3dir_close(dir); } else { f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 1296 "fig2lat.ctr" } #line 1298 "fig2lat.ctr" } /** Run for file or directory name directly (no wildcards). @param job Job structure. @param fn File name (wildcards already resolved). */ static void fig2lat_run_for_file_directly(f2l_job_t *job, dkChar const *fn) { dk3_stat_t stb; /* File information. */ #line 1312 "fig2lat.ctr" if(dk3sf_stat_app(&stb, fn, job->app)) { switch((stb.ft) & (~(DK3_FT_SYMLINK))) { case DK3_FT_REGULAR: { fig2lat_run_for_file(job, fn); } break; case DK3_FT_DIRECTORY: { fig2lat_run_for_directory(job, fn); } break; default: { /* ERROR: Neither directory nor regular file! */ job->exval = FIG2LAT_EXIT_ERROR_NO_SUCH_FILE; #line 1323 "fig2lat.ctr" dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 5); } break; } } else { #line 1327 "fig2lat.ctr" job->exval = FIG2LAT_EXIT_ERROR_NO_SUCH_FILE; #line 1328 "fig2lat.ctr" } #line 1330 "fig2lat.ctr" } /** Run for file or directory name (may contain wildcards). @param job Job structure. @param fn File name (may contain wildcards). */ static void fig2lat_run_for_name(f2l_job_t *job, dkChar const *fn) { dkChar fnb[DK3_MAX_PATH]; /* Name buffer for modification. */ dkChar const *filename; /* File name found. */ dk3_dir_t *dir; /* Expander for wildcards. */ int found; /* Flag: Source file found. */ #line 1347 "fig2lat.ctr" if(dk3str_len(fn) < DK3_SIZEOF(fnb,dkChar)) { dk3str_cpy_not_overlapped(fnb, fn); dk3str_correct_filename(fnb); if(dk3sf_must_expand(fnb)) { dir = dk3dir_fne_open_app(fnb, job->app); if(dir) { found = 0; while(dk3dir_get_next_file(dir)) { filename = dk3dir_get_fullname(dir); if(filename) { if(fig2lat_is_fig_file(filename)) { #line 1358 "fig2lat.ctr" found = 1; fig2lat_run_for_file(job, filename); } else { #line 1361 "fig2lat.ctr" } } else { #line 1363 "fig2lat.ctr" } } if(0 == found) { job->exval = FIG2LAT_EXIT_ERROR_NO_SUCH_FILE; #line 1367 "fig2lat.ctr" } dk3dir_close(dir); } else { #line 1370 "fig2lat.ctr" job->exval = FIG2LAT_EXIT_ERROR_SYSTEM; #line 1371 "fig2lat.ctr" } } else { fig2lat_run_for_file_directly(job, fnb); } } else { #line 1376 "fig2lat.ctr" /* ERROR: File name too long! */ job->exval = FIG2LAT_EXIT_FILENAME_TOO_LONG; #line 1378 "fig2lat.ctr" dk3app_log_2(job->app, DK3_LL_ERROR, job->msg, 2, fn); } #line 1380 "fig2lat.ctr" } /** Run for current directory. @param job Job structure. */ static void fig2lat_run_for_current_directory(f2l_job_t *job) { dkChar cwdbu[DK3_MAX_PATH]; /* Buffer for current working directory. */ #line 1393 "fig2lat.ctr" if(dk3sf_getcwd_app(cwdbu, DK3_SIZEOF(cwdbu,dkChar), job->app)) { fig2lat_run_for_file_directly(job, cwdbu); } else { #line 1396 "fig2lat.ctr" f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYSTEM); #line 1397 "fig2lat.ctr" } #line 1399 "fig2lat.ctr" } /** Run conversion as indicated by command line arguments. @param job Job structure. */ static void fig2lat_run(f2l_job_t *job) { dkChar const *fn; /* File name. */ int argc; /* Number of command line arguments. */ int i; /* Current command line argument processed. */ #line 1414 "fig2lat.ctr" if((argc = dk3opt_get_num_args(job->opt)) > 0) { #line 1415 "fig2lat.ctr" job->exval = FIG2LAT_EXIT_SUCCESS; #line 1416 "fig2lat.ctr" for(i = 0; i < argc; i++) { fn = dk3opt_get_arg(job->opt, i); if(fn) { fig2lat_run_for_name(job, fn); } else { job->exval = FIG2LAT_EXIT_ERROR_NO_SUCH_FILE; #line 1422 "fig2lat.ctr" } } } else { #line 1425 "fig2lat.ctr" fig2lat_run_for_current_directory(job); } #line 1428 "fig2lat.ctr" } #if TRACE_DEBUG #if FIG2LAT_TEST_BEZIER static void fig2lat_test_bezier(void) { double t; size_t i; t = 0.0; for(i = 0; i <= 10; i++) { printf("%g\t%g\n",t,dk3bezier_value(0.0,1.0,9.0,10.0,t,NULL)); t += 0.1; } } #endif #endif /** Entry point. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, any other value indicates an error. */ DK3_MAIN { f2l_job_t job; /* Job structure. */ dk3_app_t *app = NULL; /* Application structure. */ dkChar const * const *msg = NULL; /* Localized texts. */ dkChar const * const *figmsg = NULL; /* dk3fig module localized texts. */ int exval = FIG2LAT_EXIT_ERROR_UNKNOWN; /* Exit code. */ int testcmd; /* Mask for help/version/license. */ #line 1464 "fig2lat.ctr" #line 1465 "fig2lat.ctr" #if VERSION_BEFORE_20150821 exval = FIG2LAT_EXIT_ERROR_UNKNOWN; #endif job.opt = NULL; app = dk3app_open_command( argc, (dkChar const * const *)argv, f2l_kw[0] ); if(app) { #line 1473 "fig2lat.ctr" msg = dk3app_messages( app, f2l_kw[1], (dkChar const **)f2l_default_messages ); figmsg = dk3fig_get_localized_messages(app); #if TRACE_DEBUG #if FIG2LAT_TEST_BEZIER fig2lat_test_bezier(); #endif #endif if(fig2lat_job_init(&job,app,msg,figmsg)) { #line 1483 "fig2lat.ctr" if(f2lopt_process(&job)) { #line 1484 "fig2lat.ctr" testcmd = DK3_APP_CMD_HELP | DK3_APP_CMD_VERSION | DK3_APP_CMD_LICENSE; if((job.cmd) & testcmd) { #line 1486 "fig2lat.ctr" if(job.cmd) { #line 1487 "fig2lat.ctr" fig2lat_show_version(); } if((job.cmd) & DK3_APP_CMD_LICENSE) { #line 1490 "fig2lat.ctr" fig2lat_show_license(); } if((job.cmd) & DK3_APP_CMD_HELP) { #line 1493 "fig2lat.ctr" fig2lat_show_help(&job); } job.exval = FIG2LAT_EXIT_SUCCESS; } else { #line 1497 "fig2lat.ctr" fig2lat_run(&job); } } else { #line 1500 "fig2lat.ctr" dk3app_log_1(job.app, DK3_LL_ERROR, job.msg, 6); } } else { #line 1503 "fig2lat.ctr" } exval = job.exval; dk3app_close(app); app = NULL; } else { #line 1507 "fig2lat.ctr" fputs("fig2lat: ERROR: Not enough memory (RAM/swap)!\n", stderr); fflush(stderr); exval = FIG2LAT_EXIT_ERROR_SYSTEM; } fig2lat_job_end(&job); #line 1513 "fig2lat.ctr" #line 1514 "fig2lat.ctr" fflush(stdout); exit(exval); return exval; }