/* Copyright (C) 2017-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: wxd2lat.ctr */ /** @file wxd2lat.c The wxd2lat module. */ #line 284 "wxd2lat.ctr" #ifndef FIG2LAT_H_INCLUDED #include "wxd2lat.h" #endif #ifndef DK4GETCWDD_H_INCLUDED #include "dk4getcwdd.h" #endif #ifndef DK4CHDIRD_H_INCLUDED #include "dk4chdird.h" #endif #ifndef DK4UNUSED_H_INCLUDED #include "dk4unused.h" #endif #ifndef DK4WMAIN_H_INCLUDED #include "dk4wmain.h" #endif #line 307 "wxd2lat.ctr" /** Default help text, shown if help text file is not found. */ static const dkChar * const wxd2lat_help_text[] = { dkT(""), dkT("Convert *.wxd to PDF+TeX/EPS+TeX/PGF"), dkT(""), dkT("wxd2lat -l ,=... [-d] [-m] "), dkT(""), dkT("Driver:"), dkT(" eps EPS+TeX file pair."), dkT(" pdf PDF+TeX file pair."), dkT(" tex TeX file containing PGF graphics instructions."), dkT(""), dkT("Options:"), dkT(" -d Produce document instead of object."), dkT(" -m Check file modification times when processing directories."), dkT(" -b Base line width in bp, pt, mm, cm or in."), dkT(" -p Pattern line width in bp, pt, mm, cm or in."), dkT(" -w Explicitly create white background."), dkT(" --help Show this short help text."), dkT(" --version Show version information."), dkT(" --manual *** SHOW FULL MANUAL. ***"), dkT(" --license Show license information."), dkT(""), NULL #line 336 "wxd2lat.ctr" }; #if 0 /** Output language names. */ static const dkChar * const output_language_names[] = { /* 0 */ dkT("pgf"), /* 1 */ dkT("pdf"), /* 2 */ dkT("eps"), NULL #line 350 "wxd2lat.ctr" }; #endif /** Constant text fragments, not localized. */ static const dkChar * const wxd2lat_kwnl[] = { /* 0 */ dkT("dktools"), /* 1 */ dkT("wxd2lat.txt"), /* 2 */ dkT("wxd2lat.str"), /* 3 */ dkT(".wxd"), /* 4 */ dkT(".tex"), /* 5 */ dkT(".pdf"), /* 6 */ dkT("-i.pdf"), /* 7 */ dkT(".eps"), /* 8 */ dkT(".pgf"), /* 9 */ dkT("."), NULL #line 404 "wxd2lat.ctr" }; /** Text fragments, replaced by localized versions if available. */ static const dkChar * const wxd2lat_kw_def[] = { /* 0 */ dkT("\n"), /* 1 */ dkT("Failed to set up signal handlers!"), /* 2 */ dkT("Failed to restore signal handlers!"), /* 3 */ dkT("Destination files are up to date."), /* 4 */ dkT("Not a wxd file!"), /* 5 */ dkT("Start processing directory."), /* 6 */ dkT("Finished processing directory."), /* 7 */ dkT("Failed to chdir into directory!"), /* 8 */ dkT("Failed to find current directory!"), /* 9 */ dkT("Destination files are up to date."), /* 10 */ dkT("Skipping non-wxd file."), /* 11 */ dkT("Failed to construct full path name!"), /* 12 */ dkT("Failed to change back to original directory!"), /* 13 */ dkT("Failed to construct absolute path!"), /* 14 */ dkT("Not a regular file!"), /* 15 */ dkT("No such file!"), /* 16 */ dkT("Start processing file name pattern."), /* 17 */ dkT("Finished processing file name pattern."), /* 18 */ dkT("Unknown unit name \""), /* 19 */ dkT("\"!"), /* 20 */ dkT("Failed to read number from \""), /* 21 */ dkT("\"!"), /* 22 */ dkT("Syntax, not a floating point number: \""), /* 23 */ dkT("\"!"), /* 24 */ dkT("Positive length required for arrowhead!"), /* 25 */ dkT("Positive width required for arrowhead!"), /* 26 */ dkT("Positive length and width required for arrowhead!"), /* 27 */ dkT("Positive line width required for arrowhead!"), /* 28 */ dkT("Failed to calculate arrowhead angle!"), /* 29 */ dkT("Illegal arrow type!"), /* 30 */ dkT("Mathematical overflow in arrow calculation!"), /* 31 */ dkT("Iteration failed in arrow calculation!"), /* 32 */ dkT("Memory allocation failed in arrow calculation!"), /* 33 */ dkT("Failed to calculate number of points for arrow!"), /* 34 */ dkT("Mathematical error in arrow calculation!"), /* 35 */ dkT("Arrowhead calculation on spline failed!"), /* 36 */ dkT("Mathematical overflow in width/height calculation!"), /* 37 */ dkT("File name too long!"), /* 38 */ dkT("Failed to clip region!"), /* 39 */ dkT("X-spline calculation failed!"), /* 40 */ dkT("Failed to write text!"), /* 41 */ dkT("Failed to set fill colour!"), /* 42 */ dkT("UTF-8 decoding failed!"), /* 43 */ dkT("Failed to create graphics object!"), /* 44 */ dkT("Failed to create forward arrowhead!"), /* 45 */ dkT("Failed to create backward arrowhead!"), /* 46 */ dkT("Line width 0, skipping object."), /* 47 */ dkT("Failed to create filled circle!"), /* 48 */ dkT("Failed to set up filling!"), /* 49 */ dkT("Failed to set up filling and stroking!"), /* 50 */ dkT("Failed to stroke path!"), /* 51 */ dkT("Failed to set up stroking!"), /* 52 */ dkT("Failed to add bitmap image!"), /* 53 */ dkT("Not a supported bitmap image type!"), /* 54 */ dkT("Failed to UTF-8 decode file name!"), /* 55 */ dkT("Font size 0!"), /* 56 */ dkT("No text available!"), /* 57 */ dkT("First segment too short for arrowhead!"), /* 58 */ dkT("Final segment too short for arrowhead!"), /* 59 */ dkT("Too few points!"), /* 60 */ dkT("No points for object!"), /* 61 */ dkT("Spline too short for arrowheads!"), /* 62 */ dkT("Forward arrowhead too long!"), /* 63 */ dkT("Backward arrowhead too long!"), /* 64 */ dkT("Arc too short for arrowheads!"), /* 65 */ dkT("Radius must not be 0!"), /* 66 */ dkT("Box radius too large!"), /* 67 */ dkT("Diameter must not be 0!"), /* 68 */ dkT("Positive width and height required!"), /* 69 */ dkT("File name for image required!"), /* 70 */ dkT("Illegal object type!"), /* 71 */ dkT("Object check failed!"), /* 72 */ dkT("Failed to write graphics object!"), /* 73 */ dkT("Forward arrowhead calculation failed!"), /* 74 */ dkT("Backward arrowhead calculation failed!"), /* 75 */ dkT("Spline segment calculation failed!"), /* 76 */ dkT("Failed to open output file(s)!"), /* 77 */ dkT("Failed to write output!"), /* 78 */ dkT("Skipping output due to previous errors!"), /* 79 */ dkT("Segment length calculation failed!"), /* 80 */ dkT("Cut calculation for arrowhead failed!"), /* 81 */ dkT("Memory allocation failed!"), /* 82 */ dkT("Not an 8-bit unsigned number: \""), /* 83 */ dkT("\"!"), /* 84 */ dkT("Not an 8-bit number: \""), /* 85 */ dkT("\"!"), /* 86 */ dkT("Not a 16-bit unsigned number: \""), /* 87 */ dkT("\"!"), /* 88 */ dkT("Not a 16-bit number: \""), /* 89 */ dkT("\"!"), /* 90 */ dkT("Not a 32-bit unsigned number: \""), /* 91 */ dkT("\"!"), /* 92 */ dkT("Not a 32-bit number: \""), /* 93 */ dkT("\"!"), /* 94 */ dkT("File format version newer than reader module!"), /* 95 */ dkT("Syntax, bounding box width or height is 0!"), /* 96 */ dkT("Syntax, invalid number of texts in line!"), /* 97 */ dkT("Syntax, base line width must be positive!"), /* 98 */ dkT("Syntax, too few numbers in line!"), /* 99 */ dkT("Syntax, line style corrected."), /* 100 */ dkT("Syntax, style length corrected."), /* 101 */ dkT("Syntax, cap style corrected."), /* 102 */ dkT("Syntax, join style corrected."), /* 103 */ dkT("Syntax, miter limit corrected."), /* 104 */ dkT("Syntax, forward arrow type corrected."), /* 105 */ dkT("Syntax, backward arrow type corrected."), /* 106 */ dkT("Syntax, forward arrow length corrected."), /* 107 */ dkT("Syntax, backward arrow length corrected."), /* 108 */ dkT("Syntax, forward arrow width corrected."), /* 109 */ dkT("Syntax, backward arrow width corrected."), /* 110 */ dkT("Syntax, fill style corrected."), /* 111 */ dkT("Syntax, closing too many groups!"), /* 112 */ dkT("Syntax, opening too many groups!"), /* 113 */ dkT("Skipping object!"), /* 114 */ dkT("Syntax, illegal object type!"), /* 115 */ dkT("Syntax, missing object type!"), /* 116 */ dkT("Syntax, font index corrected."), /* 117 */ dkT("Syntax, text align corrected."), /* 118 */ dkT("Syntax, s parameter corrected."), /* 119 */ dkT("Syntax, radius corrected."), /* 120 */ dkT("Syntax, very small radius."), /* 121 */ dkT("Syntax, RGB to gray conversion method corrected."), /* 122 */ dkT("Syntax, invalid image dimensions!"), /* 123 */ dkT("Syntax, dot diameter corrected."), /* 124 */ dkT("Syntax, dot line width corrected."), /* 125 */ dkT("Syntax, empty export text!"), /* 126 */ dkT("Syntax, empty file name!"), /* 127 */ dkT("Syntax, object start line expected!"), /* 128 */ dkT("Syntax, details line expected!"), /* 129 */ dkT("Syntax, screen text expected!"), /* 130 */ dkT("Syntax, unexpected end of file!"), NULL #line 898 "wxd2lat.ctr" }; /** Unit names usable in base line width specifications. */ static const dkChar *unit_names[] = { /* 0 */ dkT("bp"), /* 1 */ dkT("pt"), /* 2 */ dkT("mm"), /* 3 */ dkT("cm"), /* 4 */ dkT("in"), /* 5 */ dkT("inch"), /* 6 */ dkT("inches"), /* 7 */ dkT("mil"), /* 8 */ dkT("um"), NULL #line 916 "wxd2lat.ctr" }; /** Options to use with the program. */ static const dk4_option_specification_t wxd2lat_options[] = { /* Output language: tex (PGF), pdf (PDF+TeX), eps (EPS+TeX). */ { dkT('l'), dkT("language"), DK4_OPT_ARG_STRING }, /* Make mode, only convert if necessary. */ { dkT('m'), dkT("make"), DK4_OPT_ARG_NONE }, /* Reset (do not use configuration files or preferences). */ { dkT('R'), dkT("reset"), DK4_OPT_ARG_NONE }, /* Produce document instead of object. */ { dkT('d'), dkT("document"), DK4_OPT_ARG_NONE }, /* Base line width. */ { dkT('b'), dkT("base-linewidth"), DK4_OPT_ARG_STRING }, /* Line width for pattern drawing (default: base linewidth). */ { dkT('p'), dkT("pattern-linewidth"), DK4_OPT_ARG_STRING }, { dkT('w'), dkT("white-background"), DK4_OPT_ARG_NONE } }; /** Number of options in wxd2lat_options array. */ static const size_t sz_wxd2lat_options = sizeof(wxd2lat_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 at start of program. @param job Structure to initialize. */ static void job_init(wxd2lat_job_t *job) { dk4gra_conf_init(&(job->grco)); job->ppp = NULL; job->app = NULL; job->msg = wxd2lat_kw_def; job->sz_msg = (sizeof(wxd2lat_kw_def)/sizeof(DK4_PDKCHAR) - 1); job->exval = EXIT_FAILURE; job->make = 0; job->uc2l = NULL; job->baselw = -1.0; /* Use default from file or 0.45bp */ job->patlw = -1.0; /* Use default */ job->xsprec = 1.0 / 512.0; job->xslprec = job->xsprec / 4.0; job->use_prefs = 1; job->fnb = NULL; job->fno1 = NULL; job->fno2 = NULL; job->szfnb = 0; job->whitebg = 0; job->szwidth = 0; job->szheight = 0; job->shiftx = 0.0; job->shifty = 0.0; } /** Check whether the file name ends on wxd. @param filename File name to check. @return 1 on success, 0 on error. */ static int is_wxd_file(const dkChar *filename) { const dkChar *ptr; int back = 0; #line 1134 "wxd2lat.ctr" if (NULL != filename) { ptr = dk4path_get_suffix(filename, NULL); if (NULL != ptr) { #line 1137 "wxd2lat.ctr" if (0 == dk4str_casecmp(ptr, wxd2lat_kwnl[3])) { back = 1; } } } #line 1143 "wxd2lat.ctr" return back; } /** Check whether we must produce one output file. @param fno Buffer for output file name, containing base name. @param szfno Size of fno buffer. @param fn Source file name. @param su Suffix to add to buffer. @return 1 to run conversion, 0 to skip. */ static int check_one(dkChar *fno, size_t szfno, const dkChar *fn, const dkChar *su) { int back = 1; #line 1161 "wxd2lat.ctr" if (0 != dk4str_cat_s(fno, szfno, su, NULL)) { #line 1163 "wxd2lat.ctr" #line 1164 "wxd2lat.ctr" back = dk4makemode_must_rebuild(fno, fn); } #line 1167 "wxd2lat.ctr" return back; } /** Check whether we really must run a conversion. @param job Job structure. @param fn Source file name. @return 1 to run conversion, 0 to skip. */ static int check_make(wxd2lat_job_t *job, const dkChar *fn) { dkChar *pso = NULL; int back = 1; int res = 0; #line 1185 "wxd2lat.ctr" if (0 != job->make) { if (0 != dk4str_cpy_s(job->fno1, job->szfnb, fn, NULL)) { if (0 != dk4str_cpy_s(job->fno2, job->szfnb, fn, NULL)) { pso = dk4path_get_suffix(job->fno1, NULL); if (NULL != pso) { *pso = dkT('\0'); } pso = dk4path_get_suffix(job->fno2, NULL); if (NULL != pso) { *pso = dkT('\0'); } switch (job->grco.driver) { case DK4_GRA_DRIVER_PGF : { back = check_one( job->fno1, job->szfnb, fn, wxd2lat_kwnl[8] ); } break; case DK4_GRA_DRIVER_PS: case DK4_GRA_DRIVER_EPS : { res = check_one( job->fno1, job->szfnb, fn, wxd2lat_kwnl[7] ); if (0 == res) { back = check_one( job->fno2, job->szfnb, fn, wxd2lat_kwnl[4] ); } } break; case DK4_GRA_DRIVER_PDF : { res = check_one( job->fno1, job->szfnb, fn, wxd2lat_kwnl[ (DK4_GRA_PURPOSE_DOCUMENT == job->grco.purpose) ? (6) : (5) ] ); if (0 == res) { back = check_one( job->fno2, job->szfnb, fn, wxd2lat_kwnl[4] ); } } break; } } } } #line 1227 "wxd2lat.ctr" return back; } /** Process one regular file. @param job Job structure. @param xargv Name of file to process. */ static void process_one_file(wxd2lat_job_t *job, const dkChar *xargv) { wxd_drawing_t *drw = NULL; /* Drawing to convert */ const dkChar *osf = NULL; /* Original source file */ dk4_um_t osl = 0UL; /* Original source line */ #line 1245 "wxd2lat.ctr" osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, xargv); dk4app_set_log_source_line(job->app, 0UL); if (0 != is_wxd_file(xargv)) { if (0 != check_make(job, xargv)) { drw = wxdrd_open_from_file(xargv,job); if (NULL != drw) { #line 1253 "wxd2lat.ctr" wxd2lat_output(drw, job, xargv); wxdrd_close(drw); } else { /* ERROR: Failed to read drawing, already reported */ job->exval = EXIT_FAILURE; } } else { /* INFO: Destination files up to date */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_INFO, 3); } } else { /* ERROR: Not a wxd file */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 4); job->exval = EXIT_FAILURE; } dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); #line 1274 "wxd2lat.ctr" } #if 0 /** Process a directory. @param job Job structure. @param xargv Directory name. @param docd Flag: chdir to specified directory. */ static void process_one_directory(wxd2lat_job_t *job, const dkChar *xargv, int docd) { dkChar cdbuf[DK4_MAX_PATH]; /* Current directory */ dk4_er_t er; /* Error report */ dk4_dir_t *dir = NULL; /* Directory structure */ const dkChar *osf = NULL; /* Original source file */ const dkChar *shn = NULL; /* Short file name */ dk4_um_t osl = 0UL; /* Original source line */ int cc = 1; /* Flag: Can continue */ int res = 0; /* Operation result */ int canrun = 1; /* Flag: Can run */ #line 1298 "wxd2lat.ctr" osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, xargv); dk4app_set_log_source_line(job->app, 0UL); /* PROGRESS: Start processing directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 5); dk4error_init(&er); if (0 != docd) { canrun = 0; if (0 != dk4getcwd(cdbuf, DK4_SIZEOF(cdbuf,dkChar), &er)) { #if 0 if (0 != dk4chdir(xargv, &er)) { canrun = 1; } else { /* ##### ERROR: Failed to change directory */ job->exval = EXIT_FAILURE; } #endif } else { /* ##### ERROR: Failed to find current directory */ job->exval = EXIT_FAILURE; } } if (0 != canrun) { dir = dk4dir_open_app(xargv, DK4_DIR_OPEN_SORTED, job->app); if (NULL != dir) { while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_file(dir); if (NULL != shn) { dk4error_init(&er); res = dk4dir_full_name_buffer( job->fnb, job->szfnb, dir, shn, &er ); if (0 != res) { if (0 != is_wxd_file(job->fnb)) { if (0 != check_make(job, job->fnb)) { process_one_file(job, job->fnb); } else { /* ##### PROGRESS: Destination files up to date */ } } else { /* ##### PROGRESS: Skipping non-wxd file */ } } else { cc = 0; job->exval = EXIT_FAILURE; /* ##### ERROR: Failed to construct full path name */ } } else { cc = 0; } } dk4dir_close(dir); } else { job->exval = EXIT_FAILURE; } } if (0 != docd) { if (0 == dk4chdir(cdbuf, &er)) { /* ##### ERROR: Failed to return to directory */ job->exval = EXIT_FAILURE; } } /* PROGRESS: Finished processing directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 6); dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); #line 1378 "wxd2lat.ctr" } #endif /** Process a directory specified by absolute path. @param job Job structure. @param xargv Directory name. @param docd Flag: chdir to specified directory. */ static void process_absolute_directory(wxd2lat_job_t *job, const dkChar *dn, int docd) { dk4_er_t er; /* Error report */ dkChar *cdbuf = NULL; /* Current directory */ dk4_dir_t *dir = NULL; /* Directory structure */ const dkChar *osf = NULL; /* Original source file */ const dkChar *shn = NULL; /* Short file name */ dk4_um_t osl = 0UL; /* Original source line */ int canrun = 1; /* Flag: Can run */ int cc = 1; /* Flag: Can continue */ int res = 0; /* Operation result */ #line 1403 "wxd2lat.ctr" osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, dn); dk4app_set_log_source_line(job->app, 0UL); /* PROGRESS: Start processing directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 5); if (0 != docd) { cdbuf = dk4getcwd_dup(NULL); if (NULL != cdbuf) { if (0 == dk4chdir(dn, NULL)) { /* ERROR: Failed to change into directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 7); job->exval = EXIT_FAILURE; canrun = 0; } } else { /* ERROR: Failed to find current directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 8); job->exval = EXIT_FAILURE; canrun = 0; } } if (0 != canrun) { dir = dk4dir_open_app(dn, DK4_DIR_OPEN_SORTED, job->app); if (NULL != dir) { while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_file(dir); if (NULL != shn) { dk4error_init(&er); res = dk4dir_full_name_buffer( job->fnb, job->szfnb, dir, shn, &er ); if (0 != res) { if (0 != is_wxd_file(job->fnb)) { if (0 != check_make(job, job->fnb)) { process_one_file(job, job->fnb); } else { /* PROGRESS: Destination files are up to date */ dk4app_log_1( job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 9 ); } } else { /* PROGRESS: Skipping non-wxd file */ dk4app_log_1( job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 10 ); } } else { cc = 0; job->exval = EXIT_FAILURE; /* ERROR: Failed to construct full path name */ dk4app_log_1( job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 11 ); } } else { cc = 0; } } dk4dir_close(dir); } else { job->exval = EXIT_FAILURE; } } if (NULL != cdbuf) { if (docd) { if (0 == dk4chdir(cdbuf, NULL)) { /* ERROR: Failed to change back to original directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 12); job->exval = EXIT_FAILURE; } } dk4mem_free(cdbuf); cdbuf = NULL; } /* PROGRESS: Finished processing directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 6); dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); #line 1492 "wxd2lat.ctr" } /** Process a directory specified by relative path. @param job Job structure. @param xargv Directory name. @param docd Flag: chdir to specified directory. */ static void process_relative_directory(wxd2lat_job_t *job, const dkChar *dn, int docd) { dkChar cdbuf[DK4_MAX_PATH]; if (0 != dk4getcwd(cdbuf, DK4_SIZEOF(cdbuf,dkChar), NULL)) { if (0 != dk4path_append(cdbuf, DK4_SIZEOF(cdbuf,dkChar), dn, NULL)) { process_absolute_directory(job, cdbuf, docd); } else { /* ERROR: Failed to construct absolute path */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 13); job->exval = EXIT_FAILURE; } } else { /* ERROR: Failed to find current working directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 8); job->exval = EXIT_FAILURE; } } /** Process a directory. @param job Job structure. @param xargv Directory name. @param docd Flag: chdir to specified directory. */ static void process_one_directory(wxd2lat_job_t *job, const dkChar *dn, int docd) { if (0 != dk4path_is_absolute(dn)) { process_absolute_directory(job, dn, docd); } else { process_relative_directory(job, dn, docd); } } /** Process one command line argument. @param job Job structure. @param xargv Command line argument to process. */ static void process_one_name(wxd2lat_job_t *job, const dkChar *xargv) { const dkChar *osf = NULL; /* Original source file */ dk4_um_t osl = 0UL; /* Original source line */ #line 1556 "wxd2lat.ctr" osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, xargv); dk4app_set_log_source_line(job->app, 0UL); if (0 != dk4file_is_directory(xargv, NULL)) { #line 1561 "wxd2lat.ctr" process_one_directory(job, xargv, 1); } else { if (0 != dk4file_is_regular(xargv, NULL)) { #line 1565 "wxd2lat.ctr" process_one_file(job, xargv); } else { if (0 != dk4file_exists(xargv, NULL)) { #line 1569 "wxd2lat.ctr" /* ERROR: Not a reglar file */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 14); } else { #line 1573 "wxd2lat.ctr" /* ERROR: No such file */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 15); } job->exval = EXIT_FAILURE; } } dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); #line 1582 "wxd2lat.ctr" } #if DK4_ON_WINDOWS static void expand_and_process(wxd2lat_job_t *job, const dkChar *xargv) { dkChar fnb[DK4_MAX_PATH]; /* Buffer for full path name */ dk4_er_t er; /* Error report */ dk4_dir_t *fne; /* File name expander */ const dkChar *osf = NULL; /* Original source file */ const dkChar *shn = NULL; /* Short file name */ dk4_um_t osl = 0UL; /* Original source line */ int anyfound = 0; /* Flag: Any matching file found */ int cc = 1; /* Flag: Can continue */ int res = 0; /* Operation result */ #line 1602 "wxd2lat.ctr" osf = dk4app_get_log_source_file(job->app); osl = dk4app_get_log_source_line(job->app); dk4app_set_log_source_file(job->app, xargv); dk4app_set_log_source_line(job->app, 0UL); /* PROGRESS: Start processing file name pattern */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 16); fne = dk4app_fne_open(xargv, job->app); if (NULL != fne) { cc = 1; dk4error_init(&er); while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_dir(fne); if (NULL != shn) { res = dk4dir_full_name_buffer( fnb, DK4_SIZEOF(fnb,dkChar), fne, shn, &er ); if (0 != res) { process_one_directory(job, fnb, 1); } else { cc = 0; job->exval = EXIT_FAILURE; /* ERROR: Failed to construct full path name */ dk4app_log_1( job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 11 ); } } else { cc = 0; } } cc = 1; while ((1 == cc) && (0 != sig_can_continue(0))) { shn = dk4dir_next_file(fne); if (NULL != shn) { res = dk4dir_full_name_buffer( fnb, DK4_SIZEOF(fnb,dkChar), fne, shn, &er ); if (0 != res) { process_one_file(job, fnb); } else { cc = 0; job->exval = EXIT_FAILURE; /* ERROR: Failed to construct full path name */ dk4app_log_1( job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 11 ); } } else { cc = 0; } } dk4dir_close(fne); if ((0 != sig_can_continue(0)) && (0 == anyfound)) { job->exval = EXIT_FAILURE; /* ERROR: No such file */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 15); } } else { job->exval = EXIT_FAILURE; } /* PROGRESS: Finished processing file name pattern */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_PROGRESS, 17); dk4app_set_log_source_file(job->app, osf); dk4app_set_log_source_line(job->app, osl); #line 1672 "wxd2lat.ctr" } #endif static void process_current_directory(wxd2lat_job_t *job) { dkChar dnb[DK4_MAX_PATH]; if (0 != dk4getcwd(dnb, DK4_SIZEOF(dnb,dkChar), NULL)) { process_one_directory(job, dnb, 0); } else { /* ERROR: Failed to find current directory */ dk4app_log_1(job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 8); } } /** Run for file specified on the command line. If no file on command line specified, run on current directory. @param job Job structure. */ static void process_all_input_files(wxd2lat_job_t *job) { dkChar const *xargv; /* Current cmd line arg to process */ int xargc; /* Number of command line arguments */ int i; /* Index of current cmd line arg */ #line 1707 "wxd2lat.ctr" xargc = dk4app_get_argc(job->app); if (0 < xargc) { for (i = 0; ((i < xargc) && (0 != sig_can_continue(0))); i++) { xargv = dk4app_get_argv(job->app, i); if (NULL != xargv) { #if DK4_ON_WINDOWS if (0 != dk4path_must_expand(xargv)) { expand_and_process(job, xargv); } else { process_one_name(job, xargv); } #else process_one_name(job, xargv); #endif } else { } } } else { /* No names specified, process current directory */ process_current_directory(job); } #line 1733 "wxd2lat.ctr" } /** Get base line width from string. @param job Job structure to modify. @param src Source text. @return 1 on success, 0 on error. */ static int get_line_width_from_text(wxd2lat_job_t *job, double *dptr, dkChar const *src) { dk4_er_t er; const dkChar *ep = NULL; double v; int back = 0; int res = 0; dk4error_init(&er); #line 1754 "wxd2lat.ctr" if ((NULL != job) && (NULL != src)) { back = dk4ma_input_dk_double(&v, src, &ep, 2, &er); if (1 == back) { if ((NULL != ep) && (0U != dk4str_len(ep))) { res = dk4str_array_index(unit_names, ep, 0); if (0 <= res) { switch (res) { case 0: { /* bp */ } break; case 1: { /* pt */ v *= (72.0 / 72.27); } break; case 2: { /* mm */ v *= (72.0 / 25.4); } break; case 3: { /* cm */ v *= (72.0 / 2.54); } break; case 4: case 5: case 6: { /* in */ v *= 72.0; } break; case 7: { /* mil */ v *= (72.0 / 1000.0); } break; case 8: { /* um */ v *= (72.0 / 25400.0); } break; } } else { #line 1784 "wxd2lat.ctr" back = 0; /* ERROR: Unknown unit name */ dk4app_log_3( job->app, job->msg, job->sz_msg, DK4_LL_INFO, 18,19,ep ); } } } else { /* ERROR: Failed to read number */ dk4app_log_3( job->app, job->msg, job->sz_msg, DK4_LL_INFO, 20, 21, src ); } if (1 == back) { *dptr = v; } } #line 1803 "wxd2lat.ctr" return back; } /** Run normally after applying signal handlers. @param job Job structure. */ static void w2l_normal_run(wxd2lat_job_t *job) { const dkChar *lpo; int ok = 1; #line 1819 "wxd2lat.ctr" 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 = 1; #line 1824 "wxd2lat.ctr" } if (0 != dk4app_opt_is_set_short(job->app, dkT('d'), NULL)) { (job->grco).purpose = DK4_GRA_PURPOSE_DOCUMENT; } if (0 != dk4app_opt_is_set_short(job->app, dkT('b'), NULL)) { lpo = dk4app_opt_get_string_ptr_short(job->app, dkT('b'), NULL); if (NULL != lpo) { if (0 == get_line_width_from_text(job, &(job->baselw), lpo)) { ok = 0; } } } if (0 != dk4app_opt_is_set_short(job->app, dkT('p'), NULL)) { lpo = dk4app_opt_get_string_ptr_short(job->app, dkT('p'), NULL); if (NULL != lpo) { if (0 == get_line_width_from_text(job, &(job->patlw), lpo)) { ok = 0; } } } if (0 != dk4app_opt_is_set_short(job->app, dkT('w'), NULL)) { job->whitebg = 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); if (NULL != lpo) { #if 0 job->ot = dk4str_array_index(output_language_names, lpo, 0); if (0 > job->ot) { #line 1854 "wxd2lat.ctr" ok = 0; /* ##### ERROR: Illegal output language name */ } #endif ok = dk4gra_conf_setup( &(job->grco), lpo, job->use_prefs, DK4_GRA_CONF_SCOPE_FIG2LAT, job->app ); } #if TRACE_DEBUG else { #line 1865 "wxd2lat.ctr" } #endif } if (0 != ok) { job->uc2l = dk4uc2l_open_from_app(job->app); if (NULL != job->uc2l) { job->exval = EXIT_SUCCESS; process_all_input_files(job); dk4uc2l_close(job->uc2l); job->uc2l = NULL; } else { #line 1877 "wxd2lat.ctr" /* ERROR: No Unicode to LaTeX structure, already reported */ } } #if TRACE_DEBUG else { #line 1882 "wxd2lat.ctr" } #endif #line 1885 "wxd2lat.ctr" } #if DK4_HAVE_SIGACTION /** Set signal handlers and run. @param job Job structure. */ static void w2l_run_with_signal_handlers(wxd2lat_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; #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, 1); 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, 1); 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, 1); 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, 1); 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, 1); 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, 1); 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, 1); 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, 1); 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, 1); goto restore_old_int; } success = 1; w2l_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, 2); 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, 2); 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, 2); success = 0; } #endif /* Set exit status code if error occured. */ finished: if (0 == success) { job->exval = EXIT_FAILURE; } } #else #if DK4_HAVE_SIGSET /** Set signal handlers and run. @param job Job structure. */ static void w2l_run_with_signal_handlers(wxd2lat_job_t *job) { #ifdef SIGPIPE dk4_sig_handler_t *oldpipe = NULL; #endif dk4_sig_handler_t *oldint = NULL; dk4_sig_handler_t *oldterm = NULL; #ifdef SIGPIPE oldpipe = sigset(SIGPIPE, sig_handler_pipe); #endif oldint = sigset(SIGINT, sig_handler_int); oldterm = sigset(SIGTERM, sig_handler_term); w2l_normal_run(job); sigset(SIGTERM, oldterm); sigset(SIGINT, oldint); #ifdef SIGPIPE sigset(SIGPIPE, oldpipe); #endif } #else #if DK4_HAVE_SIGNAL /** Set signal handlers and run. @param job Job structure. */ static void w2l_run_with_signal_handlers(wxd2lat_job_t *job) { #ifdef SIGPIPE dk4_sig_handler_t *oldpipe = NULL; #endif dk4_sig_handler_t *oldint = NULL; dk4_sig_handler_t *oldterm = NULL; #ifdef SIGPIPE oldpipe = signal(SIGPIPE, sig_handler_pipe); #endif oldint = signal(SIGINT, sig_handler_int); oldterm = signal(SIGTERM, sig_handler_term); w2l_normal_run(job); signal(SIGTERM, oldterm); signal(SIGINT, oldint); #ifdef SIGPIPE signal(SIGPIPE, oldpipe); #endif } #else /** Set signal handlers and run. */ static void w2l_run_with_signal_handlers(void) { w2l_normal_run(); } #endif #endif #endif /** Buffer for full file name. */ static dkChar wxd2lat_filename_buffer[DK4_MAX_PATH]; /** Buffer for output file name. */ static dkChar wxd2lat_filename_o1[ DK4_SIZEOF(wxd2lat_filename_buffer,dkChar) ]; /** Buffer for second output file name. */ static dkChar wxd2lat_filename_o2[ DK4_SIZEOF(wxd2lat_filename_buffer,dkChar) ]; /** 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 { wxd2lat_job_t job; #line 2105 "wxd2lat.ctr" #line 2106 "wxd2lat.ctr" dk4fput_initialize_stderr(); job_init(&job); job.fnb = wxd2lat_filename_buffer; job.fno1 = wxd2lat_filename_o1; job.fno2 = wxd2lat_filename_o2; job.szfnb = DK4_SIZEOF(wxd2lat_filename_buffer,dkChar); job.app = dk4app_open_cmd( argc, argv, wxd2lat_options, sz_wxd2lat_options, wxd2lat_kwnl[0], DKT_VERSION_DK, wxd2lat_kwnl[1], wxd2lat_help_text, w2llic_get_text() ); if (NULL != job.app) { job.sz_msg = dk4app_string_table_size(wxd2lat_kw_def); job.msg = dk4app_string_table( job.app, wxd2lat_kwnl[2], wxd2lat_kw_def ); if (0 != dk4app_can_run_normally(job.app)) { w2l_run_with_signal_handlers(&job); } else { if (0 != dk4app_help_version_license(job.app)) { job.exval = EXIT_SUCCESS; } } dk4app_close(job.app); } else { } fflush(stderr); dk4fput_cleanup_stderr(); #line 2137 "wxd2lat.ctr" #line 2138 "wxd2lat.ctr" exit(job.exval); return job.exval; } /* vim: set ai sw=4 ts=4 : */