From 15fdca2a0348de00892e7f3ebdf29f3ac301576a Mon Sep 17 00:00:00 2001 From: gitlost Date: Wed, 10 May 2023 00:47:44 +0100 Subject: [PATCH] For Windows, assume `outfile` & API filename args are in UTF-8, & use xxxW() APIs accordingly, ticket #288, props Marcel **Backwards-incompatible change** --- ChangeLog | 2 ++ backend/library.c | 9 ++++++ backend/output.c | 39 +++++++++++++++++++++-- backend/output.h | 5 +++ backend/tests/test_output.c | 4 ++- backend/tests/testcommon.c | 62 ++++++++++++++++++++++++++++++++----- backend/tests/testcommon.h | 1 + docs/manual.pmd | 32 ++++++++++--------- docs/manual.txt | 34 +++++++++++--------- docs/zint.1 | 2 +- docs/zint.1.pmd | 2 +- frontend/main.c | 6 ++-- 12 files changed, 151 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index a8ee7b60..ce35d336 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,8 @@ Version 2.12.0.9 (dev) not released yet - Text (HRT) placement for vector (EMF/EPS/SVG) output changed - for EAN/UPC slightly further away from barcode, for all others slightly nearer. Some horizontal alignments of EAN/UPC vector text also tweaked +- For Windows, filenames are now assumed to be UTF-8 encoded. Affects `outfile` + in `zint_symbol` and all API filename arguments Changes ------- diff --git a/backend/library.c b/backend/library.c index 5948d3dc..96c4b74c 100644 --- a/backend/library.c +++ b/backend/library.c @@ -38,6 +38,7 @@ #include "common.h" #include "eci.h" #include "gs1.h" +#include "output.h" #include "zfiletypes.h" /* It's assumed that int is at least 32 bits, the following will compile-time fail if not @@ -257,7 +258,11 @@ static int dump_plot(struct zint_symbol *symbol) { if (output_to_stdout) { f = stdout; } else { +#ifdef _WIN32 + f = out_win_fopen(symbol->outfile, "w"); +#else f = fopen(symbol->outfile, "w"); +#endif if (!f) { strcpy(symbol->errtxt, "201: Could not open output file"); return ZINT_ERROR_FILE_ACCESS; @@ -1453,7 +1458,11 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) { file = stdin; fileLen = ZINT_MAX_DATA_LEN; } else { +#ifdef _WIN32 + file = out_win_fopen(filename, "rb"); +#else file = fopen(filename, "rb"); +#endif if (!file) { sprintf(symbol->errtxt, "229: Unable to read input file (%d: %.30s)", errno, strerror(errno)); return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); diff --git a/backend/output.c b/backend/output.c index 458bd5e3..98ca5ed4 100644 --- a/backend/output.c +++ b/backend/output.c @@ -871,15 +871,40 @@ INTERNAL void out_upcean_split_text(const int upceanflag, const unsigned char te } } +#ifdef _WIN32 +/* Convert UTF-8 to Windows wide chars. Ticket #288, props Marcel */ +#define utf8_to_wide(u, w, r) \ + { \ + int lenW; /* Includes NUL terminator */ \ + if ((lenW = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, NULL, 0)) == 0) return r; \ + w = (wchar_t *) z_alloca(sizeof(wchar_t) * lenW); \ + if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, w, lenW) == 0) return r; \ + } + +/* Do `fopen()` on Windows, assuming `filename` is UTF-8 encoded. Ticket #288, props Marcel */ +INTERNAL FILE *out_win_fopen(const char *filename, const char *mode) { + wchar_t *filenameW, *modeW; + + utf8_to_wide(filename, filenameW, NULL); + utf8_to_wide(mode, modeW, NULL); + + return _wfopen(filenameW, modeW); +} +#endif + /* Make a directory; already existing dir okay */ /* Adapted from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950 and https://nachtimwald.com/2019/07/10/recursive-create-directory-in-c-revisited/ */ -static int out_maybe_mkdir(const char* path) { +static int out_maybe_mkdir(const char *path) { #ifdef _WIN32 DWORD dwAttrib; + wchar_t *pathW; + + /* Assumes `path` is UTF-8 encoded */ + utf8_to_wide(path, pathW, 0); /* Try to make the directory */ - if (CreateDirectoryA(path, NULL) != 0) { /* Non-zero on success */ + if (CreateDirectoryW(pathW, NULL) != 0) { /* Non-zero on success */ return 0; } /* If it fails for any reason but already exists, fail */ @@ -887,7 +912,7 @@ static int out_maybe_mkdir(const char* path) { return -1; } /* Check if the existing path is a directory */ - if ((dwAttrib = GetFileAttributesA(path)) == (DWORD) -1 || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { + if ((dwAttrib = GetFileAttributesW(pathW)) == (DWORD) -1 || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { return -1; } #else @@ -914,7 +939,11 @@ static int out_maybe_mkdir(const char* path) { INTERNAL FILE *out_fopen(const char filename[256], const char *mode) { FILE *outfile; +#ifdef _WIN32 + if (!(outfile = out_win_fopen(filename, mode))) { +#else if (!(outfile = fopen(filename, mode))) { +#endif char dirname[256]; char *d; #ifdef _WIN32 @@ -950,7 +979,11 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode) { *d = '/'; /* Restore */ } } +#ifdef _WIN32 + outfile = out_win_fopen(filename, mode); +#else outfile = fopen(filename, mode); +#endif } return outfile; diff --git a/backend/output.h b/backend/output.h index c8496676..4b047b81 100644 --- a/backend/output.h +++ b/backend/output.h @@ -71,6 +71,11 @@ INTERNAL void out_upcean_split_text(const int upceanflag, const unsigned char te /* Create output file, creating sub-directories if necessary. Returns `fopen()` FILE pointer */ INTERNAL FILE *out_fopen(const char filename[256], const char *mode); +#ifdef _WIN32 +/* Do `fopen()` on Windows, assuming `filename` is UTF-8 encoded. Props Marcel, ticket #288 */ +INTERNAL FILE *out_win_fopen(const char *filename, const char *mode); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/backend/tests/test_output.c b/backend/tests/test_output.c index 2cffdfea..bb2f1ad5 100644 --- a/backend/tests/test_output.c +++ b/backend/tests/test_output.c @@ -259,6 +259,8 @@ static void test_fopen(const testCtx *const p_ctx) { /* 11*/ { "out_test//", "", "out.png", 1 }, /* 12*/ { "out_test/", "/out_test_subdir/", "out.png", 1 }, /* 13*/ { "out_test\\", "\\out_test_subdir\\", "out.png", 1 }, + /* 14*/ { "", "", "outé.png", 1 }, + /* 15*/ { "outé_test", "", "outé.png", 1 }, }; int data_size = ARRAY_SIZE(data); int i, len; @@ -305,7 +307,7 @@ static void test_fopen(const testCtx *const p_ctx) { if (data[i].dir[0]) { assert_nonzero(testUtilDirExists(dirname), "i:%d testUtilDirExists(%s) != 0 (%d: %s)\n", i, dirname, errno, strerror(errno)); } - assert_zero(remove(outfile), "i:%d remove(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno)); + assert_zero(testUtilRemove(outfile), "i:%d testUtilRemove(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno)); if (data[i].dir[0]) { if (data[i].subdir[0] && !subdir_exists) { assert_zero(testUtilRmDir(subdirname), "i:%d rmdir(%s) != 0 (%d: %s)\n", i, subdirname, errno, strerror(errno)); diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index b2863b2b..baaa712f 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -49,6 +49,7 @@ #include "testcommon.h" #include "../eci.h" +#include "../output.h" static int tests = 0; static int failed = 0; @@ -107,6 +108,16 @@ void assert_notequal(int e1, int e2, const char *fmt, ...) { } #endif +#ifdef _WIN32 +#define utf8_to_wide(u, w) \ + { \ + int lenW; /* Includes NUL terminator */ \ + if ((lenW = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, NULL, 0)) == 0) return 0; \ + w = (wchar_t *) z_alloca(sizeof(wchar_t) * lenW); \ + if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, w, lenW) == 0) return 0; \ + } +#endif + /* Begin individual test function */ void testStartReal(const char *func, const char *name) { tests++; @@ -1325,7 +1336,11 @@ int testUtilDataPath(char *buffer, int buffer_size, const char *subdir, const ch /* Does file exist? */ int testUtilExists(const char *filename) { +#ifdef _WIN32 + FILE *fp = out_win_fopen(filename, "r"); +#else FILE *fp = fopen(filename, "r"); +#endif if (fp == NULL) { return 0; } @@ -1333,10 +1348,24 @@ int testUtilExists(const char *filename) { return 1; } +/* Remove a file (Windows compatibility). Returns 0 if successful, non-zero if not */ +int testUtilRemove(const char *filename) { +#ifdef _WIN32 + wchar_t *filenameW; + utf8_to_wide(filename, filenameW); + return DeleteFileW(filenameW) == 0; /* Non-zero on success */ +#else + return remove(filename); +#endif +} + /* Does directory exist? (Windows compatibility) */ int testUtilDirExists(const char *dirname) { #ifdef _WIN32 - DWORD dwAttrib = GetFileAttributes(dirname); + DWORD dwAttrib; + wchar_t *dirnameW; + utf8_to_wide(dirname, dirnameW); + dwAttrib = GetFileAttributesW(dirnameW); return dwAttrib != (DWORD) -1 && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); #else return testUtilExists(dirname); @@ -1346,7 +1375,9 @@ int testUtilDirExists(const char *dirname) { /* Make a directory (Windows compatibility). Returns 0 if successful, non-zero if not */ int testUtilMkDir(const char *dirname) { #ifdef _WIN32 - return CreateDirectory(dirname, NULL) == 0; + wchar_t *dirnameW; + utf8_to_wide(dirname, dirnameW); + return CreateDirectoryW(dirnameW, NULL) == 0; #else return mkdir(dirname, S_IRWXU); #endif @@ -1355,7 +1386,9 @@ int testUtilMkDir(const char *dirname) { /* Remove a directory (Windows compatibility). Returns 0 if successful, non-zero if not */ int testUtilRmDir(const char *dirname) { #ifdef _WIN32 - return RemoveDirectory(dirname) == 0; + wchar_t *dirnameW; + utf8_to_wide(dirname, dirnameW); + return RemoveDirectoryW(dirnameW) == 0; #else return rmdir(dirname); #endif @@ -1364,15 +1397,25 @@ int testUtilRmDir(const char *dirname) { /* Rename a file (Windows compatibility) */ int testUtilRename(const char *oldpath, const char *newpath) { #ifdef _MSVC - int ret = remove(newpath); + wchar_t *oldpathW, *newpathW; + int ret = testUtilRemove(newpath); if (ret != 0) return ret; -#endif + utf8_to_wide(oldpath, oldpathW); + utf8_to_wide(newpath, newpathW); + return _wrename(oldpathW, newpathW); +#else return rename(oldpath, newpath); +#endif } /* Create read-only file */ int testUtilCreateROFile(const char *filename) { +#ifdef _WIN32 + wchar_t *filenameW; + FILE *fp = out_win_fopen(filename, "w+"); +#else FILE *fp = fopen(filename, "w+"); +#endif if (fp == NULL) { return 0; } @@ -1380,7 +1423,8 @@ int testUtilCreateROFile(const char *filename) { return 0; } #ifdef _WIN32 - if (SetFileAttributesA(filename, GetFileAttributesA(filename) | FILE_ATTRIBUTE_READONLY) == 0) { + utf8_to_wide(filename, filenameW); + if (SetFileAttributesW(filenameW, GetFileAttributesW(filenameW) | FILE_ATTRIBUTE_READONLY) == 0) { return 0; } #else @@ -1394,11 +1438,13 @@ int testUtilCreateROFile(const char *filename) { /* Remove read-only file (Windows compatibility) */ int testUtilRmROFile(const char *filename) { #ifdef _WIN32 - if (SetFileAttributesA(filename, GetFileAttributesA(filename) & ~FILE_ATTRIBUTE_READONLY) == 0) { + wchar_t *filenameW; + utf8_to_wide(filename, filenameW); + if (SetFileAttributesW(filenameW, GetFileAttributesW(filenameW) & ~FILE_ATTRIBUTE_READONLY) == 0) { return -1; } #endif - return remove(filename); + return testUtilRemove(filename); } /* Compare 2 PNG files */ diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index 2ff123dc..f4c461e0 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -160,6 +160,7 @@ int testUtilBitmapCmp(const struct zint_symbol *symbol, const char *expected, in int testUtilDataPath(char *buffer, int buffer_size, const char *subdir, const char *filename); int testUtilExists(const char *filename); +int testUtilRemove(const char *filename); int testUtilDirExists(const char *dirname); int testUtilMkDir(const char *dirname); int testUtilRmDir(const char *dirname); diff --git a/docs/manual.pmd b/docs/manual.pmd index fe7a4d3c..7d816ae1 100644 --- a/docs/manual.pmd +++ b/docs/manual.pmd @@ -1,6 +1,6 @@ % Zint Barcode Generator and Zint Barcode Studio User Manual % Version 2.12.0.9 -% February 2023 +% May 2023 # 1. Introduction @@ -561,6 +561,8 @@ created if they don't already exist: zint -o "dir/subdir/filename.eps" -d "This Text" ``` +Note that on Windows, filenames are assumed to be UTF-8 encoded. + ## 4.3 Selecting Barcode Type Selecting which type of barcode you wish to produce (i.e. which symbology to @@ -1626,7 +1628,8 @@ values are 0, 90, 180 and 270. The `ZBarcode_Encode_File()` and `ZBarcode_Encode_File_and_Print()` functions can be used to encode data read directly from a text file where the filename is given in the `NUL`-terminated `filename` string. The special filename `"-"` -(single hyphen) can be used to read from stdin. +(single hyphen) can be used to read from stdin. Note that on Windows, filenames +are assumed to be UTF-8 encoded. If printing more than one barcode, the `zint_symbol` structure may be re-used by calling the `ZBarcode_Clear()` function after each barcode to free any output @@ -1809,7 +1812,7 @@ Variable Name Type Meaning Default Value `.emf`, `.eps`, `.pcx`, `.svg`, `.tif` or `.txt` followed by a terminating - `NUL`. + `NUL`.[^8] `primary` character Primary message data for `""` (empty) string more complex symbols, with @@ -1910,6 +1913,8 @@ QR Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which have a fixed width-to-height ratio (or, in the case of Code One, a fixed height). +[^8]: For Windows, `outfile` is assumed to be UTF-8 encoded. + To alter these values use the syntax shown in the example below. This code has the same result as the previous example except the output is now taller and plotted in green. @@ -1939,9 +1944,8 @@ background alpha to `"00"` where the values for R, G and B will be ignored: ## 5.7 Handling Errors If errors occur during encoding a non-zero integer value is passed back to the -calling application. In addition the `errtxt` variable is used to give a message -detailing the nature of the error. The errors generated by Zint are given in the -table below: +calling application. In addition the `errtxt` variable is set to a message +detailing the nature of the error. The errors generated by Zint are: -------------------------------------------------------------------------------- Return Value Meaning @@ -2067,10 +2071,10 @@ Value Effect ------------------------- ----------------------------------------------------- 0 No options selected. -`BARCODE_BIND_TOP` Boundary bar above the symbol only.[^8] +`BARCODE_BIND_TOP` Boundary bar above the symbol only.[^9] `BARCODE_BIND` Boundary bars above and below the symbol and between - rows if stacking multiple symbols.[^9] + rows if stacking multiple symbols.[^10] `BARCODE_BOX` Add a box surrounding the symbol and whitespace. @@ -2095,7 +2099,7 @@ Value Effect separate colour channels (`OUT_BUFFER` only). `BARCODE_QUIET_ZONES` Add compliant quiet zones (additional to any - specified whitespace).[^10] + specified whitespace).[^11] `BARCODE_NO_QUIET_ZONES` Disable quiet zones, notably those with defaults. @@ -2105,13 +2109,13 @@ Value Effect Table: API `output_options` Values {#tbl:api_output_options tag="$ $"} -[^8]: The `BARCODE_BIND_TOP` flag is set by default for DPD - see [6.1.10.7 DPD +[^9]: The `BARCODE_BIND_TOP` flag is set by default for DPD - see [6.1.10.7 DPD Code]. -[^9]: The `BARCODE_BIND` flag is always set for Codablock-F, Code 16K and Code +[^10]: The `BARCODE_BIND` flag is always set for Codablock-F, Code 16K and Code 49. Special considerations apply to ITF-14 - see [6.1.2.6 ITF-14]. -[^10]: Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and +[^11]: Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and UPC-E have compliant quiet zones added by default. \clearpage @@ -2865,13 +2869,13 @@ Alphabet No. 1 (ISO/IEC 8859-1)]. ![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg) It is sometimes advantageous to stop Code 128 from using Code Set C which -compresses numerical data. The `BARCODE_CODE128AB`[^11] variant (symbology 60) +compresses numerical data. The `BARCODE_CODE128AB`[^12] variant (symbology 60) suppresses Code Set C in favour of Code Sets A and B. Note that the special escapes to manually switch Code Sets mentioned above are not available for this variant (nor for any other). -[^11]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is +[^12]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is still recognised. #### 6.1.10.3 GS1-128 diff --git a/docs/manual.txt b/docs/manual.txt index df6f6c3c..3feb1fc0 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1,6 +1,6 @@ Zint Barcode Generator and Zint Barcode Studio User Manual Version 2.12.0.9 -February 2023 +May 2023 ******************************************************************************* * For reference the following is a text-only version of the Zint manual, * @@ -701,6 +701,8 @@ created if they don’t already exist: zint -o "dir/subdir/filename.eps" -d "This Text" +Note that on Windows, filenames are assumed to be UTF-8 encoded. + 4.3 Selecting Barcode Type Selecting which type of barcode you wish to produce (i.e. which symbology to @@ -1668,7 +1670,8 @@ values are 0, 90, 180 and 270. The ZBarcode_Encode_File() and ZBarcode_Encode_File_and_Print() functions can be used to encode data read directly from a text file where the filename is given in the NUL-terminated filename string. The special filename "-" (single hyphen) -can be used to read from stdin. +can be used to read from stdin. Note that on Windows, filenames are assumed to +be UTF-8 encoded. If printing more than one barcode, the zint_symbol structure may be re-used by calling the ZBarcode_Clear() function after each barcode to free any output @@ -1836,7 +1839,7 @@ encoding stages. The zint_symbol structure consists of the following variables: in .png, .gif, .bmp, .emf, .eps, .pcx, .svg, .tif or .txt followed by a - terminating NUL. + terminating NUL.[8] primary character Primary message data for "" (empty) string more complex symbols, with a @@ -1956,9 +1959,8 @@ background alpha to "00" where the values for R, G and B will be ignored: 5.7 Handling Errors If errors occur during encoding a non-zero integer value is passed back to the -calling application. In addition the errtxt variable is used to give a message -detailing the nature of the error. The errors generated by Zint are given in the -table below: +calling application. In addition the errtxt variable is set to a message +detailing the nature of the error. The errors generated by Zint are: ------------------------------------------------------------------------------- Return Value Meaning @@ -2077,10 +2079,10 @@ together when adjusting this value: -------------------------- ---------------------------------------------------- 0 No options selected. - BARCODE_BIND_TOP Boundary bar above the symbol only.[8] + BARCODE_BIND_TOP Boundary bar above the symbol only.[9] BARCODE_BIND Boundary bars above and below the symbol and between - rows if stacking multiple symbols.[9] + rows if stacking multiple symbols.[10] BARCODE_BOX Add a box surrounding the symbol and whitespace. @@ -2105,7 +2107,7 @@ together when adjusting this value: separate colour channels (OUT_BUFFER only). BARCODE_QUIET_ZONES Add compliant quiet zones (additional to any - specified whitespace).[10] + specified whitespace).[11] BARCODE_NO_QUIET_ZONES Disable quiet zones, notably those with defaults. @@ -2806,7 +2808,7 @@ Alphabet No. 1 (ISO/IEC 8859-1). [zint -b CODE128AB -d "130170X178"] It is sometimes advantageous to stop Code 128 from using Code Set C which -compresses numerical data. The BARCODE_CODE128AB[11] variant (symbology 60) +compresses numerical data. The BARCODE_CODE128AB[12] variant (symbology 60) suppresses Code Set C in favour of Code Sets A and B. Note that the special escapes to manually switch Code Sets mentioned above are @@ -4406,7 +4408,7 @@ defined. Annex B. Man Page ZINT(1) -% ZINT(1) Version 2.12.0.9 % % February 2023 +% ZINT(1) Version 2.12.0.9 % % May 2023 NAME @@ -4999,13 +5001,15 @@ Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which have a fixed width-to-height ratio (or, in the case of Code One, a fixed height). -[8] The BARCODE_BIND_TOP flag is set by default for DPD - see 6.1.10.7 DPD Code. +[8] For Windows, outfile is assumed to be UTF-8 encoded. -[9] The BARCODE_BIND flag is always set for Codablock-F, Code 16K and Code 49. +[9] The BARCODE_BIND_TOP flag is set by default for DPD - see 6.1.10.7 DPD Code. + +[10] The BARCODE_BIND flag is always set for Codablock-F, Code 16K and Code 49. Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14. -[10] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and +[11] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and UPC-E have compliant quiet zones added by default. -[11] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still +[12] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still recognised. diff --git a/docs/zint.1 b/docs/zint.1 index c948d9a2..830e9509 100644 --- a/docs/zint.1 +++ b/docs/zint.1 @@ -14,7 +14,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "ZINT" "1" "February 2023" "Version 2.12.0.9" "" +.TH "ZINT" "1" "May 2023" "Version 2.12.0.9" "" .hy .SH NAME .PP diff --git a/docs/zint.1.pmd b/docs/zint.1.pmd index 97984afa..2d0b5ae3 100644 --- a/docs/zint.1.pmd +++ b/docs/zint.1.pmd @@ -1,6 +1,6 @@ % ZINT(1) Version 2.12.0.9 % -% February 2023 +% May 2023 # NAME diff --git a/frontend/main.c b/frontend/main.c index 764d9d60..97f3f7a6 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -1162,7 +1162,6 @@ int main(int argc, char **argv) { float float_opt; char errbuf[64]; /* For `validate_float()` */ arg_opt *arg_opts = (arg_opt *) z_alloca(sizeof(arg_opt) * argc); - int no_getopt_error = 1; const int no_png = ZBarcode_NoPng(); @@ -1183,7 +1182,7 @@ int main(int argc, char **argv) { #endif opterr = 0; /* Disable `getopt_long_only()` printing errors */ - while (no_getopt_error) { + while (1) { enum options { OPT_ADDONGAP = 128, OPT_BATCH, OPT_BINARY, OPT_BG, OPT_BIND, OPT_BIND_TOP, OPT_BOLD, OPT_BORDER, OPT_BOX, OPT_CMYK, OPT_COLS, OPT_COMPLIANTHEIGHT, OPT_DIRECT, OPT_DMRE, OPT_DOTSIZE, OPT_DOTTY, OPT_DUMP, @@ -1196,7 +1195,6 @@ int main(int argc, char **argv) { OPT_SEPARATOR, OPT_SMALL, OPT_SQUARE, OPT_STRUCTAPP, OPT_TEXTGAP, OPT_VERBOSE, OPT_VERS, OPT_VWHITESP, OPT_WERROR }; - int option_index = 0; static const struct option long_options[] = { {"addongap", 1, NULL, OPT_ADDONGAP}, {"barcode", 1, NULL, 'b'}, @@ -1279,7 +1277,7 @@ int main(int argc, char **argv) { {"whitesp", 1, NULL, 'w'}, {NULL, 0, NULL, 0} }; - const int c = getopt_long_only(argc, argv, "b:d:ehi:o:rtvw:", long_options, &option_index); + const int c = getopt_long_only(argc, argv, "b:d:ehi:o:rtvw:", long_options, NULL); if (c == -1) break; switch (c) {