From 5c08226700cea65801d5c18eb26a9e23a68aa971 Mon Sep 17 00:00:00 2001 From: gitlost Date: Sun, 19 Jan 2025 13:44:43 +0000 Subject: [PATCH] general: split up some source files to lessen ZXing-C++ bloat when `ZXING_USE_BUNDLED_ZINT` set --- backend/2of5.c | 249 +----------- backend/2of5inter.c | 134 ++++++ backend/2of5inter_based.c | 197 +++++++++ backend/CMakeLists.txt | 16 +- backend/channel.c | 259 ++++++++++++ backend/codabar.c | 146 +++++++ backend/code.c | 428 +------------------- backend/code11.c | 155 +++++++ backend/code128.c | 277 +------------ backend/code128_based.c | 316 +++++++++++++++ backend/medical.c | 199 ++++----- backend/tests/CMakeLists.txt | 4 +- backend/tests/test_codabar.c | 326 +++++++++++++++ backend/tests/test_code.c | 342 +++++++--------- backend/tests/test_code11.c | 412 +++++++++++++++++++ backend/tests/test_medical.c | 142 ++++--- backend_qt/backend_qt.pro | 6 + backend_qt/backend_vc8.pro | 6 + backend_tcl/configure | 388 +++++++++--------- backend_tcl/configure.ac | 14 +- win32/libzint.vcxproj | 6 + win32/vs2008/libzint.vcproj | 24 ++ win32/vs2015/libzint.vcxproj | 6 + win32/vs2017/libzint.vcxproj | 6 + win32/vs2019/libzint.vcxproj | 6 + win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp | 24 ++ 26 files changed, 2554 insertions(+), 1534 deletions(-) create mode 100644 backend/2of5inter.c create mode 100644 backend/2of5inter_based.c create mode 100644 backend/channel.c create mode 100644 backend/codabar.c create mode 100644 backend/code11.c create mode 100644 backend/code128_based.c create mode 100644 backend/tests/test_codabar.c create mode 100644 backend/tests/test_code11.c diff --git a/backend/2of5.c b/backend/2of5.c index 2f062559..8706eb0d 100644 --- a/backend/2of5.c +++ b/backend/2of5.c @@ -1,7 +1,7 @@ -/* 2of5.c - Handles Code 2 of 5 barcodes */ +/* 2of5.c - Handles non-interleaved Code 2 of 5 barcodes */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -34,7 +34,6 @@ #include "common.h" #include "gs1.h" -/* First 5 of each entry Interleaved also */ static const char C25MatrixTable[10][6] = { {'1','1','3','3','1','1'}, {'3','1','1','1','3','1'}, {'1','3','1','1','3','1'}, {'3','3','1','1','1','1'}, {'1','1','3','1','3','1'}, {'3','1','3','1','1','1'}, {'1','3','3','1','1','1'}, {'1','1','1','3','3','1'}, @@ -138,248 +137,4 @@ INTERNAL int c25logic(struct zint_symbol *symbol, unsigned char source[], int le return c25_common(symbol, source, length, 113, 1 /*is_matrix*/, C25IataLogicStartStop, 4, 307); } -/* Common to Interleaved, ITF-14, DP Leitcode, DP Identcode */ -static int c25_inter_common(struct zint_symbol *symbol, unsigned char source[], int length, - const int checkdigit_option, const int dont_set_height) { - int i, j, error_number = 0; - char dest[638]; /* 4 + (125 + 1) * 5 + 3 + 1 = 638 */ - char *d = dest; - unsigned char temp[125 + 1 + 1]; - const int have_checkdigit = checkdigit_option == 1 || checkdigit_option == 2; - - if (length > 125) { /* 4 + (125 + 1) * 9 + 5 = 1143 */ - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 309, "Input length %d too long (maximum 125)", length); - } - if ((i = not_sane(NEON_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 310, - "Invalid character at position %d in input (digits only)", i); - } - - /* Input must be an even number of characters for Interlaced 2 of 5 to work: - if an odd number of characters has been entered and no check digit or an even number and have check digit - then add a leading zero */ - if (have_checkdigit == !(length & 1)) { - temp[0] = '0'; - memcpy(temp + 1, source, length++); - } else { - memcpy(temp, source, length); - } - temp[length] = '\0'; - - if (have_checkdigit) { - /* Add standard GS1 check digit */ - temp[length] = gs1_check_digit(temp, length); - temp[++length] = '\0'; - } - - /* Start character */ - memcpy(d, "1111", 4); - d += 4; - - for (i = 0; i < length; i += 2) { - /* Look up the bars and the spaces */ - const char *const bars = C25MatrixTable[temp[i] - '0']; - const char *const spaces = C25MatrixTable[temp[i + 1] - '0']; - - /* Then merge (interlace) the strings together */ - for (j = 0; j < 5; j++) { - *d++ = bars[j]; - *d++ = spaces[j]; - } - } - - /* Stop character */ - memcpy(d, "311", 3); - d += 3; - - expand(symbol, dest, d - dest); - - ustrcpy(symbol->text, temp); - if (checkdigit_option == 2) { - /* Remove check digit from HRT */ - symbol->text[length - 1] = '\0'; - } - - if (!dont_set_height) { - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* ISO/IEC 16390:2007 Section 4.4 min height 5mm or 15% of symbol width whichever greater where - (P = character pairs, N = wide/narrow ratio = 3) - width = (P(4N + 6) + N + 6)X = (length / 2) * 18 + 9 */ - /* Taking min X = 0.330mm from Annex D.3.1 (application specification) */ - const float min_height_min = 15.151515f; /* 5.0 / 0.33 */ - float min_height = stripf((18.0f * (length / 2) + 9.0f) * 0.15f); - if (min_height < min_height_min) { - min_height = min_height_min; - } - /* Using 50 as default as none recommended */ - error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, - 0 /*no_errtxt*/); - } else { - (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); - } - } - - return error_number; -} - -/* Code 2 of 5 Interleaved ISO/IEC 16390:2007 */ -INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length) { - return c25_inter_common(symbol, source, length, symbol->option_2 /*checkdigit_option*/, 0 /*dont_set_height*/); -} - -/* Interleaved 2-of-5 (ITF-14) */ -INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, error_number, zeroes; - unsigned char localstr[16] = {0}; - - if (length > 13) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 311, "Input length %d too long (maximum 13)", length); - } - - if ((i = not_sane(NEON_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 312, - "Invalid character at position %d in input (digits only)", i); - } - - /* Add leading zeros as required */ - zeroes = 13 - length; - for (i = 0; i < zeroes; i++) { - localstr[i] = '0'; - } - ustrcpy(localstr + zeroes, source); - - /* Calculate the check digit - the same method used for EAN-13 */ - localstr[13] = gs1_check_digit(localstr, 13); - localstr[14] = '\0'; - error_number = c25_inter_common(symbol, localstr, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); - ustrcpy(symbol->text, localstr); - - if (error_number < ZINT_ERROR) { - if (!(symbol->output_options & (BARCODE_BOX | BARCODE_BIND | BARCODE_BIND_TOP))) { - /* If no option has been selected then uses default box option */ - symbol->output_options |= BARCODE_BOX; - if (symbol->border_width == 0) { /* Allow override if non-zero */ - /* GS1 General Specifications 21.0.1 Sections 5.3.2.4 & 5.3.6 (4.83 / 1.016 ~ 4.75) */ - symbol->border_width = 5; /* Note change from previous value 8 */ - } - } - - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* GS1 General Specifications 21.0.1 5.12.3.2 table 2, including footnote (**): (note bind/box additional - to symbol->height), same as GS1-128: "in case of further space constraints" - height 5.8mm / 1.016mm (X max) ~ 5.7; default 31.75mm / 0.495mm ~ 64.14 */ - const float min_height = 5.70866156f; /* 5.8 / 1.016 */ - const float default_height = 64.1414108f; /* 31.75 / 0.495 */ - error_number = set_height(symbol, min_height, default_height, 0.0f, 0 /*no_errtxt*/); - } else { - (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); - } - } - - return error_number; -} - -/* Deutsche Post check digit */ -static char c25_dp_check_digit(const unsigned int count) { - return itoc((10 - (count % 10)) % 10); -} - -/* Deutsche Post Leitcode */ -/* Documentation (of a very incomplete and non-technical type): -https://www.deutschepost.de/content/dam/dpag/images/D_d/dialogpost-schwer/dp-dialogpost-schwer-broschuere-072021.pdf -*/ -INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, j, error_number; - unsigned int count; - int factor; - unsigned char localstr[16] = {0}; - int zeroes; - - count = 0; - if (length > 13) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 313, "Input length %d too long (maximum 13)", length); - } - if ((i = not_sane(NEON_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 314, - "Invalid character at position %d in input (digits only)", i); - } - - zeroes = 13 - length; - for (i = 0; i < zeroes; i++) - localstr[i] = '0'; - ustrcpy(localstr + zeroes, source); - - factor = 4; - for (i = 12; i >= 0; i--) { - count += factor * ctoi(localstr[i]); - factor ^= 0x0D; /* Toggles 4 and 9 */ - } - localstr[13] = c25_dp_check_digit(count); - localstr[14] = '\0'; - error_number = c25_inter_common(symbol, localstr, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); - - /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do examples at - https://www.philaseiten.de/cgi-bin/index.pl?ST=8615&CP=0&F=1#M147 */ - for (i = 0, j = 0; i <= 14; i++) { - symbol->text[j++] = localstr[i]; - if (i == 4 || i == 7 || i == 10) { - symbol->text[j++] = '.'; - } - } - - /* TODO: Find documentation on BARCODE_DPLEIT dimensions/height */ - /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ - (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); - - return error_number; -} - -/* Deutsche Post Identcode */ -/* See dpleit() for (sort of) documentation reference */ -INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, j, error_number, zeroes; - unsigned int count; - int factor; - unsigned char localstr[16] = {0}; - - count = 0; - if (length > 11) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 315, "Input length %d too long (maximum 11)", length); - } - if ((i = not_sane(NEON_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 316, - "Invalid character at position %d in input (digits only)", i); - } - - zeroes = 11 - length; - for (i = 0; i < zeroes; i++) - localstr[i] = '0'; - ustrcpy(localstr + zeroes, source); - - factor = 4; - for (i = 10; i >= 0; i--) { - count += factor * ctoi(localstr[i]); - factor ^= 0x0D; /* Toggles 4 and 9 */ - } - localstr[11] = c25_dp_check_digit(count); - localstr[12] = '\0'; - error_number = c25_inter_common(symbol, localstr, 12, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); - - /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do other examples (see above) */ - for (i = 0, j = 0; i <= 12; i++) { - symbol->text[j++] = localstr[i]; - if (i == 1 || i == 4 || i == 7) { - symbol->text[j++] = '.'; - } else if (i == 3 || i == 10) { - symbol->text[j++] = ' '; - } - } - - /* TODO: Find documentation on BARCODE_DPIDENT dimensions/height */ - /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ - (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); - - return error_number; -} - /* vim: set ts=4 sw=4 et : */ diff --git a/backend/2of5inter.c b/backend/2of5inter.c new file mode 100644 index 00000000..94cf7a19 --- /dev/null +++ b/backend/2of5inter.c @@ -0,0 +1,134 @@ +/* 2of5inter.c - Handles Code 2 of 5 Interleaved */ +/* + libzint - the open source barcode library + Copyright (C) 2008-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "2of5.c" */ + +#include +#include "common.h" +#include "gs1.h" + +static const char C25InterTable[10][5] = { + {'1','1','3','3','1'}, {'3','1','1','1','3'}, {'1','3','1','1','3'}, {'3','3','1','1','1'}, + {'1','1','3','1','3'}, {'3','1','3','1','1'}, {'1','3','3','1','1'}, {'1','1','1','3','3'}, + {'3','1','1','3','1'}, {'1','3','1','3','1'} +}; + +/* Common to Interleaved, and to ITF-14, DP Leitcode, DP Identcode */ +INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[], int length, + const int checkdigit_option, const int dont_set_height) { + int i, j, error_number = 0; + char dest[638]; /* 4 + (125 + 1) * 5 + 3 + 1 = 638 */ + char *d = dest; + unsigned char temp[125 + 1 + 1]; + const int have_checkdigit = checkdigit_option == 1 || checkdigit_option == 2; + + if (length > 125) { /* 4 + (125 + 1) * 9 + 5 = 1143 */ + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 309, "Input length %d too long (maximum 125)", length); + } + if ((i = not_sane(NEON_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 310, + "Invalid character at position %d in input (digits only)", i); + } + + /* Input must be an even number of characters for Interlaced 2 of 5 to work: + if an odd number of characters has been entered and no check digit or an even number and have check digit + then add a leading zero */ + if (have_checkdigit == !(length & 1)) { + temp[0] = '0'; + memcpy(temp + 1, source, length++); + } else { + memcpy(temp, source, length); + } + temp[length] = '\0'; + + if (have_checkdigit) { + /* Add standard GS1 check digit */ + temp[length] = gs1_check_digit(temp, length); + temp[++length] = '\0'; + } + + /* Start character */ + memcpy(d, "1111", 4); + d += 4; + + for (i = 0; i < length; i += 2) { + /* Look up the bars and the spaces */ + const char *const bars = C25InterTable[temp[i] - '0']; + const char *const spaces = C25InterTable[temp[i + 1] - '0']; + + /* Then merge (interlace) the strings together */ + for (j = 0; j < 5; j++) { + *d++ = bars[j]; + *d++ = spaces[j]; + } + } + + /* Stop character */ + memcpy(d, "311", 3); + d += 3; + + expand(symbol, dest, d - dest); + + ustrcpy(symbol->text, temp); + if (checkdigit_option == 2) { + /* Remove check digit from HRT */ + symbol->text[length - 1] = '\0'; + } + + if (!dont_set_height) { + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* ISO/IEC 16390:2007 Section 4.4 min height 5mm or 15% of symbol width whichever greater where + (P = character pairs, N = wide/narrow ratio = 3) + width = (P(4N + 6) + N + 6)X = (length / 2) * 18 + 9 */ + /* Taking min X = 0.330mm from Annex D.3.1 (application specification) */ + const float min_height_min = 15.151515f; /* 5.0 / 0.33 */ + float min_height = stripf((18.0f * (length / 2) + 9.0f) * 0.15f); + if (min_height < min_height_min) { + min_height = min_height_min; + } + /* Using 50 as default as none recommended */ + error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, + 0 /*no_errtxt*/); + } else { + (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); + } + } + + return error_number; +} + +/* Code 2 of 5 Interleaved ISO/IEC 16390:2007 */ +INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length) { + return c25_inter_common(symbol, source, length, symbol->option_2 /*checkdigit_option*/, 0 /*dont_set_height*/); +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/2of5inter_based.c b/backend/2of5inter_based.c new file mode 100644 index 00000000..18b0e767 --- /dev/null +++ b/backend/2of5inter_based.c @@ -0,0 +1,197 @@ +/* 2of5_based.c - Handles Code 2 of 5 Interleaved derivatives ITF-14, DP Leitcode and DP Identcode */ +/* + libzint - the open source barcode library + Copyright (C) 2008-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "2of5.c" */ + +#include +#include "common.h" +#include "gs1.h" + +INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[], int length, + const int checkdigit_option, const int dont_set_height); + +/* Interleaved 2-of-5 (ITF-14) */ +INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, error_number, zeroes; + unsigned char localstr[16] = {0}; + + if (length > 13) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 311, "Input length %d too long (maximum 13)", length); + } + + if ((i = not_sane(NEON_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 312, + "Invalid character at position %d in input (digits only)", i); + } + + /* Add leading zeros as required */ + zeroes = 13 - length; + for (i = 0; i < zeroes; i++) { + localstr[i] = '0'; + } + ustrcpy(localstr + zeroes, source); + + /* Calculate the check digit - the same method used for EAN-13 */ + localstr[13] = gs1_check_digit(localstr, 13); + localstr[14] = '\0'; + error_number = c25_inter_common(symbol, localstr, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); + ustrcpy(symbol->text, localstr); + + if (error_number < ZINT_ERROR) { + if (!(symbol->output_options & (BARCODE_BOX | BARCODE_BIND | BARCODE_BIND_TOP))) { + /* If no option has been selected then uses default box option */ + symbol->output_options |= BARCODE_BOX; + if (symbol->border_width == 0) { /* Allow override if non-zero */ + /* GS1 General Specifications 21.0.1 Sections 5.3.2.4 & 5.3.6 (4.83 / 1.016 ~ 4.75) */ + symbol->border_width = 5; /* Note change from previous value 8 */ + } + } + + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* GS1 General Specifications 21.0.1 5.12.3.2 table 2, including footnote (**): (note bind/box additional + to symbol->height), same as GS1-128: "in case of further space constraints" + height 5.8mm / 1.016mm (X max) ~ 5.7; default 31.75mm / 0.495mm ~ 64.14 */ + const float min_height = 5.70866156f; /* 5.8 / 1.016 */ + const float default_height = 64.1414108f; /* 31.75 / 0.495 */ + error_number = set_height(symbol, min_height, default_height, 0.0f, 0 /*no_errtxt*/); + } else { + (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); + } + } + + return error_number; +} + +/* Deutsche Post check digit */ +static char c25_dp_check_digit(const unsigned int count) { + return itoc((10 - (count % 10)) % 10); +} + +/* Deutsche Post Leitcode */ +/* Documentation (of a very incomplete and non-technical type): +https://www.deutschepost.de/content/dam/dpag/images/D_d/dialogpost-schwer/dp-dialogpost-schwer-broschuere-072021.pdf +*/ +INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, j, error_number; + unsigned int count; + int factor; + unsigned char localstr[16] = {0}; + int zeroes; + + count = 0; + if (length > 13) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 313, "Input length %d too long (maximum 13)", length); + } + if ((i = not_sane(NEON_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 314, + "Invalid character at position %d in input (digits only)", i); + } + + zeroes = 13 - length; + for (i = 0; i < zeroes; i++) + localstr[i] = '0'; + ustrcpy(localstr + zeroes, source); + + factor = 4; + for (i = 12; i >= 0; i--) { + count += factor * ctoi(localstr[i]); + factor ^= 0x0D; /* Toggles 4 and 9 */ + } + localstr[13] = c25_dp_check_digit(count); + localstr[14] = '\0'; + error_number = c25_inter_common(symbol, localstr, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); + + /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do examples at + https://www.philaseiten.de/cgi-bin/index.pl?ST=8615&CP=0&F=1#M147 */ + for (i = 0, j = 0; i <= 14; i++) { + symbol->text[j++] = localstr[i]; + if (i == 4 || i == 7 || i == 10) { + symbol->text[j++] = '.'; + } + } + + /* TODO: Find documentation on BARCODE_DPLEIT dimensions/height */ + /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ + (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); + + return error_number; +} + +/* Deutsche Post Identcode */ +/* See dpleit() for (sort of) documentation reference */ +INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, j, error_number, zeroes; + unsigned int count; + int factor; + unsigned char localstr[16] = {0}; + + count = 0; + if (length > 11) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 315, "Input length %d too long (maximum 11)", length); + } + if ((i = not_sane(NEON_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 316, + "Invalid character at position %d in input (digits only)", i); + } + + zeroes = 11 - length; + for (i = 0; i < zeroes; i++) + localstr[i] = '0'; + ustrcpy(localstr + zeroes, source); + + factor = 4; + for (i = 10; i >= 0; i--) { + count += factor * ctoi(localstr[i]); + factor ^= 0x0D; /* Toggles 4 and 9 */ + } + localstr[11] = c25_dp_check_digit(count); + localstr[12] = '\0'; + error_number = c25_inter_common(symbol, localstr, 12, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); + + /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do other examples (see above) */ + for (i = 0, j = 0; i <= 12; i++) { + symbol->text[j++] = localstr[i]; + if (i == 1 || i == 4 || i == 7) { + symbol->text[j++] = '.'; + } else if (i == 3 || i == 10) { + symbol->text[j++] = ' '; + } + } + + /* TODO: Find documentation on BARCODE_DPIDENT dimensions/height */ + /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ + (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); + + return error_number; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 0af1802b..eb75db18 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (C) 2008 by BogDan Vatra < bogdan@licentia.eu > -# Copyright (C) 2009-2024 Robin Stuart +# Copyright (C) 2009-2025 Robin Stuart # vim: set ts=4 sw=4 et : cmake_minimum_required(VERSION 3.10) @@ -9,14 +9,16 @@ if(ZINT_USE_PNG) find_package(PNG) endif() -set(zint_COMMON_SRCS common.c library.c large.c reedsol.c gs1.c eci.c filemem.c general_field.c) -set(zint_ONEDIM_SRCS bc412.c code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c dxfilmedge.c) -set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c) -set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c) +set(zint_COMMON_SRCS common.c eci.c filemem.c general_field.c gs1.c large.c library.c reedsol.c) +set(zint_ONEDIM_SRCS 2of5.c 2of5inter.c 2of5inter_based.c bc412.c channel.c codabar.c code.c code11.c code128.c + code128_based.c dxfilmedge.c medical.c plessey.c rss.c telepen.c upcean.c) +set(zint_POSTAL_SRCS auspost.c imail.c mailmark.c postal.c) +set(zint_TWODIM_SRCS aztec.c codablock.c code1.c code16k.c code49.c composite.c dmatrix.c dotcode.c gridmtx.c + hanxin.c maxicode.c pdf417.c qr.c ultra.c) if(ZINT_USE_PNG AND PNG_FOUND) - set(zint_OUTPUT_SRCS vector.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c output.c) + set(zint_OUTPUT_SRCS bmp.c emf.c gif.c output.c pcx.c png.c ps.c raster.c svg.c tif.c vector.c) else() - set(zint_OUTPUT_SRCS vector.c ps.c svg.c emf.c bmp.c pcx.c gif.c tif.c raster.c output.c) + set(zint_OUTPUT_SRCS bmp.c emf.c gif.c output.c pcx.c ps.c raster.c svg.c tif.c vector.c) endif() set(zint_SRCS ${zint_OUTPUT_SRCS} ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS}) diff --git a/backend/channel.c b/backend/channel.c new file mode 100644 index 00000000..d3e8e382 --- /dev/null +++ b/backend/channel.c @@ -0,0 +1,259 @@ +/* channel.c - Handles Channel */ +/* + libzint - the open source barcode library + Copyright (C) 2008-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "code.c" */ + +#include +#include "common.h" + +typedef const struct s_channel_precalc { + int value; unsigned char B[8]; unsigned char S[8]; unsigned char bmax[7]; unsigned char smax[7]; +} channel_precalc; + +#if 0 +#define CHANNEL_GENERATE_PRECALCS +#endif + +#ifdef CHANNEL_GENERATE_PRECALCS +/* To generate precalc tables uncomment CHANNEL_GENERATE_PRECALCS define and run + "backend/tests/test_channel -f generate -g" and place result in "channel_precalcs.h" */ +static void channel_generate_precalc(int channels, int value, int mod, int last, int B[8], int S[8], int bmax[7], + int smax[7]) { + int i; + if (value == mod) printf("static channel_precalc channel_precalcs%d[] = {\n", channels); + printf(" { %7ld, {", value); for (i = 0; i < 8; i++) printf(" %d,", B[i]); fputs(" },", stdout); + fputs(" {", stdout); for (i = 0; i < 8; i++) printf(" %d,", S[i]); fputs(" },", stdout); + fputs(" {", stdout); for (i = 0; i < 7; i++) printf(" %d,", bmax[i]); fputs(" },", stdout); + fputs(" {", stdout); for (i = 0; i < 7; i++) printf(" %d,", smax[i]); fputs(" }, },\n", stdout); + if (value == last) fputs("};\n", stdout); +} +#else +#include "channel_precalcs.h" +#endif + +static int channel_copy_precalc(channel_precalc *const precalc, int B[8], int S[8], int bmax[7], int smax[7]) { + int i; + + for (i = 0; i < 7; i++) { + B[i] = precalc->B[i]; + S[i] = precalc->S[i]; + bmax[i] = precalc->bmax[i]; + smax[i] = precalc->smax[i]; + } + B[7] = precalc->B[7]; + S[7] = precalc->S[7]; + + return precalc->value; +} + +/* CHNCHR is adapted from ANSI/AIM BC12-1998 Annex D Figure D5 and is Copyright (c) AIM 1997 */ + +/* It is used here on the understanding that it forms part of the specification + for Channel Code and therefore its use is permitted under the following terms + set out in that document: + + "It is the intent and understanding of AIM [t]hat the symbology presented in this + specification is entirely in the public domain and free of all use restrictions, + licenses and fees. AIM USA, its member companies, or individual officers + assume no liability for the use of this document." */ +static void CHNCHR(int channels, int target_value, int B[8], int S[8]) { + /* Use of initial pre-calculations taken from Barcode Writer in Pure PostScript (BWIPP) + * Copyright (c) 2004-2020 Terry Burton (MIT/X-Consortium license) */ + static channel_precalc initial_precalcs[6] = { + { 0, { 1, 1, 1, 1, 1, 2, 1, 2, }, { 1, 1, 1, 1, 1, 1, 1, 3, }, { 1, 1, 1, 1, 1, 3, 2, }, + { 1, 1, 1, 1, 1, 3, 3, }, }, + { 0, { 1, 1, 1, 1, 2, 1, 1, 3, }, { 1, 1, 1, 1, 1, 1, 1, 4, }, { 1, 1, 1, 1, 4, 3, 3, }, + { 1, 1, 1, 1, 4, 4, 4, }, }, + { 0, { 1, 1, 1, 2, 1, 1, 2, 3, }, { 1, 1, 1, 1, 1, 1, 1, 5, }, { 1, 1, 1, 5, 4, 4, 4, }, + { 1, 1, 1, 5, 5, 5, 5, }, }, + { 0, { 1, 1, 2, 1, 1, 2, 1, 4, }, { 1, 1, 1, 1, 1, 1, 1, 6, }, { 1, 1, 6, 5, 5, 5, 4, }, + { 1, 1, 6, 6, 6, 6, 6, }, }, + { 0, { 1, 2, 1, 1, 2, 1, 1, 5, }, { 1, 1, 1, 1, 1, 1, 1, 7, }, { 1, 7, 6, 6, 6, 5, 5, }, + { 1, 7, 7, 7, 7, 7, 7, }, }, + { 0, { 2, 1, 1, 2, 1, 1, 2, 5, }, { 1, 1, 1, 1, 1, 1, 1, 8, }, { 8, 7, 7, 7, 6, 6, 6, }, + { 8, 8, 8, 8, 8, 8, 8, }, }, + }; + int bmax[7], smax[7]; + int value = 0; + + channel_copy_precalc(&initial_precalcs[channels - 3], B, S, bmax, smax); + +#ifndef CHANNEL_GENERATE_PRECALCS + if (channels == 7 && target_value >= channel_precalcs7[0].value) { + value = channel_copy_precalc(&channel_precalcs7[(target_value / channel_precalcs7[0].value) - 1], B, S, bmax, + smax); + } else if (channels == 8 && target_value >= channel_precalcs8[0].value) { + value = channel_copy_precalc(&channel_precalcs8[(target_value / channel_precalcs8[0].value) - 1], B, S, bmax, + smax); + } +#endif + + goto chkchr; + +ls0:smax[1] = smax[0] + 1 - S[0]; B[0] = 1; + if (S[0] == 1) goto nb0; +lb0: bmax[1] = bmax[0] + 1 - B[0]; S[1] = 1; +ls1: smax[2] = smax[1] + 1 - S[1]; B[1] = 1; + if (S[0] + B[0] + S[1] == 3) goto nb1; +lb1: bmax[2] = bmax[1] + 1 - B[1]; S[2] = 1; +ls2: smax[3] = smax[2] + 1 - S[2]; B[2] = 1; + if (B[0] + S[1] + B[1] + S[2] == 4) goto nb2; +lb2: bmax[3] = bmax[2] + 1 - B[2]; S[3] = 1; +ls3: smax[4] = smax[3] + 1 - S[3]; B[3] = 1; + if (B[1] + S[2] + B[2] + S[3] == 4) goto nb3; +lb3: bmax[4] = bmax[3] + 1 - B[3]; S[4] = 1; +ls4: smax[5] = smax[4] + 1 - S[4]; B[4] = 1; + if (B[2] + S[3] + B[3] + S[4] == 4) goto nb4; +lb4: bmax[5] = bmax[4] + 1 - B[4]; S[5] = 1; +ls5: smax[6] = smax[5] + 1 - S[5]; B[5] = 1; + if (B[3] + S[4] + B[4] + S[5] == 4) goto nb5; +lb5: bmax[6] = bmax[5] + 1 - B[5]; S[6] = 1; +ls6: S[7] = smax[6] + 1 - S[6]; B[6] = 1; + if (B[4] + S[5] + B[5] + S[6] == 4) goto nb6; +lb6: B[7] = bmax[6] + 1 - B[6]; + if (B[5] + S[6] + B[6] + S[7] + B[7] == 5) goto nb6; +chkchr: +#ifdef CHANNEL_GENERATE_PRECALCS + /* 115338 == (576688 + 2) / 5 */ + if (channels == 7 && value && value % 115338 == 0) { + channel_generate_precalc(channels, value, 115338, + 115338 * (5 - 1), B, S, bmax, smax); + /* 119121 == (7742862 + 3) / 65 */ + } else if (channels == 8 && value && value % 119121 == 0) { + channel_generate_precalc(channels, value, 119121, + 119121 * (65 - 1), B, S, bmax, smax); + } +#endif + if (value == target_value) return; + value++; +nb6: if (++B[6] <= bmax[6]) goto lb6; + if (++S[6] <= smax[6]) goto ls6; +nb5: if (++B[5] <= bmax[5]) goto lb5; + if (++S[5] <= smax[5]) goto ls5; +nb4: if (++B[4] <= bmax[4]) goto lb4; + if (++S[4] <= smax[4]) goto ls4; +nb3: if (++B[3] <= bmax[3]) goto lb3; + if (++S[3] <= smax[3]) goto ls3; +nb2: if (++B[2] <= bmax[2]) goto lb2; + if (++S[2] <= smax[2]) goto ls2; +nb1: if (++B[1] <= bmax[1]) goto lb1; + if (++S[1] <= smax[1]) goto ls1; +nb0: if (++B[0] <= bmax[0]) goto lb0; + if (++S[0] <= smax[0]) goto ls0; +} + +/* Channel Code - According to ANSI/AIM BC12-1998 */ +INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int length) { + static const int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 }; + int S[8] = {0}, B[8] = {0}; + int target_value; + char dest[30]; + char *d = dest; + int channels, i; + int error_number = 0, zeroes; + + if (length > 7) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 333, "Input length %d too long (maximum 7)", length); + } + if ((i = not_sane(NEON_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 334, + "Invalid character at position %d in input (digits only)", i); + } + target_value = to_int(source, length); + + if ((symbol->option_2 < 3) || (symbol->option_2 > 8)) { + channels = 0; + } else { + channels = symbol->option_2; + } + + if (channels == 0) { + channels = length + 1; + if (target_value > 576688 && channels < 8) { + channels = 8; + } else if (target_value > 44072 && channels < 7) { + channels = 7; + } else if (target_value > 3493 && channels < 6) { + channels = 6; + } else if (target_value > 292 && channels < 5) { + channels = 5; + } else if (target_value > 26 && channels < 4) { + channels = 4; + } + } + if (channels == 2) { + channels = 3; + } + + if (target_value > max_ranges[channels]) { + if (channels == 8) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 318, "Input value \"%1$d\" out of range (0 to %2$d)", + target_value, max_ranges[channels]); + } + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 335, + "Input value \"%1$d\" out of range (0 to %2$d for %3$d channels)", + target_value, max_ranges[channels], channels); + } + + CHNCHR(channels, target_value, B, S); + + memcpy(d, "111111111", 9); /* Finder pattern */ + d += 9; + for (i = 8 - channels; i < 8; i++) { + *d++ = itoc(S[i]); + *d++ = itoc(B[i]); + } + + zeroes = channels - 1 - length; + if (zeroes < 0) { + zeroes = 0; + } else if (zeroes) { + memset(symbol->text, '0', zeroes); + } + ustrcpy(symbol->text + zeroes, source); + + expand(symbol, dest, d - dest); + + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* ANSI/AIM BC12-1998 gives min height as 5mm or 15% of length; X left as application specification so use + length = 1X (left qz) + (9 (finder) + 4 * 8 - 2) * X + 2X (right qz); + use 20 as default based on figures in spec */ + const float min_height = stripf((1 + 9 + 4 * channels - 2 + 2) * 0.15f); + error_number = set_height(symbol, min_height, 20.0f, 0.0f, 0 /*no_errtxt*/); + } else { + (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); + } + + return error_number; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/codabar.c b/backend/codabar.c new file mode 100644 index 00000000..be9cfc91 --- /dev/null +++ b/backend/codabar.c @@ -0,0 +1,146 @@ +/* codabar.c - Handles Codabar */ +/* + libzint - the open source barcode library + Copyright (C) 2008-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "medical.c" */ + +#include +#include "common.h" + +static const char CALCIUM[] = "0123456789-$:/.+ABCD"; +#define CALCIUM_INNER_F (IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F) /* CALCIUM_INNER "0123456789-$:/.+" */ + +/* Codabar table checked against EN 798:1995 */ +static const char CodaTable[20][8] = { + {'1','1','1','1','1','2','2','1'}, {'1','1','1','1','2','2','1','1'}, {'1','1','1','2','1','1','2','1'}, + {'2','2','1','1','1','1','1','1'}, {'1','1','2','1','1','2','1','1'}, {'2','1','1','1','1','2','1','1'}, + {'1','2','1','1','1','1','2','1'}, {'1','2','1','1','2','1','1','1'}, {'1','2','2','1','1','1','1','1'}, + {'2','1','1','2','1','1','1','1'}, {'1','1','1','2','2','1','1','1'}, {'1','1','2','2','1','1','1','1'}, + {'2','1','1','1','2','1','2','1'}, {'2','1','2','1','1','1','2','1'}, {'2','1','2','1','2','1','1','1'}, + {'1','1','2','1','2','1','2','1'}, {'1','1','2','2','1','2','1','1'}, {'1','2','1','2','1','1','2','1'}, + {'1','1','1','2','1','2','2','1'}, {'1','1','1','2','2','2','1','1'} +}; + +/* The Codabar system consisting of simple substitution */ +INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length) { + + int i, error_number = 0; + int posns[103]; + char dest[833]; /* (103 + 1) * 8 + 1 == 833 */ + char *d = dest; + int add_checksum, count = 0, checksum = 0; + int d_chars = 0; + + if (length > 103) { /* No stack smashing please (103 + 1) * 11 = 1144 */ + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 356, "Input length %d too long (maximum 103)", length); + } + /* BS EN 798:1995 4.2 "'Codabar' symbols shall consist of ... b) start character; + c) one or more symbol characters representing data ... d) stop character ..." */ + if (length < 3) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 362, "Input length %d too short (minimum 3)", length); + } + to_upper(source, length); + + /* Codabar must begin and end with the characters A, B, C or D */ + if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C') + && (source[0] != 'D')) { + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 358, "Does not begin with \"A\", \"B\", \"C\" or \"D\""); + } + if ((source[length - 1] != 'A') && (source[length - 1] != 'B') && + (source[length - 1] != 'C') && (source[length - 1] != 'D')) { + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 359, "Does not end with \"A\", \"B\", \"C\" or \"D\""); + } + if ((i = not_sane_lookup(CALCIUM, sizeof(CALCIUM) - 1, source, length, posns))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 357, + "Invalid character at position %1$d in input (\"%2$s\" only)", i, CALCIUM); + } + /* And must not use A, B, C or D otherwise (BS EN 798:1995 4.3.2) */ + if ((i = not_sane(CALCIUM_INNER_F, source + 1, length - 2))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 363, + "Invalid character at position %d in input (cannot contain \"A\", \"B\", \"C\" or \"D\")", i); + } + + /* Add check character: 1 don't show to HRT, 2 do show to HRT + (unfortunately to maintain back-compatibility, this is reverse of C25) */ + add_checksum = symbol->option_2 == 1 || symbol->option_2 == 2; + + for (i = 0; i < length; i++, d += 8) { + if (add_checksum) { + /* BS EN 798:1995 A.3 suggests using ISO 7064 algorithm but leaves it application defined. + Following BWIPP and TEC-IT, use this simple mod-16 algorithm (not in ISO 7064) */ + count += posns[i]; + if (i + 1 == length) { + checksum = count % 16; + if (checksum) { + checksum = 16 - checksum; + } + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Codabar: %s, count %d, checksum %d (%c)\n", source, count, checksum, CALCIUM[checksum]); + } + memcpy(d, CodaTable[checksum], 8); + d += 8; + } + } + memcpy(d, CodaTable[posns[i]], 8); + if (source[i] == '/' || source[i] == ':' || source[i] == '.' || source[i] == '+') { /* Wide data characters */ + d_chars++; + } + } + + expand(symbol, dest, d - dest); + + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.43mm (X max) ~ 11.628 or 15% of width where (taking N = + narrow/wide ratio as 2 and I = X) width = ((2 * N + 5) * C + (N – 1) * (D + 2)) * X + I * (C – 1) + 2Q + = ((4 + 5) * C + (D + 2) + C - 1 + 2 * 10) * X = (10 * C + D + 21) * X + Length (C) includes start/stop chars */ + const float min_height_min = 11.6279068f; /* 5.0 / 0.43 */ + float min_height = stripf((10.0f * ((add_checksum ? length + 1 : length) + 2.0f) + d_chars + 21.0f) * 0.15f); + if (min_height < min_height_min) { + min_height = min_height_min; + } + /* Using 50 as default as none recommended */ + error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, 0 /*no_errtxt*/); + } else { + (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); + } + + ustrcpy(symbol->text, source); + if (symbol->option_2 == 2) { + symbol->text[length - 1] = CALCIUM[checksum]; /* Place before final A/B/C/D character (BS EN 798:1995 A.3) */ + symbol->text[length] = source[length - 1]; + symbol->text[length + 1] = '\0'; + } + + return error_number; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/code.c b/backend/code.c index 8b999890..a029d37e 100644 --- a/backend/code.c +++ b/backend/code.c @@ -1,7 +1,7 @@ -/* code.c - Handles Code 11, 39, 39+, 93, PZN, Channel and VIN */ +/* code.c - Handles Code 39, 39+, 93 and VIN */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -36,20 +36,11 @@ #include #include "common.h" -#define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */ - /* Same as TECHNETIUM (HIBC) with "abcd" added for CODE93 */ static const char SILVER[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd"; #define ARSENIC_F (IS_NUM_F | IS_ARS_F) /* ARSENIC "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" */ -static const char C11Table[11 + 1][6] = { - {'1','1','1','1','2','1'}, {'2','1','1','1','2','1'}, {'1','2','1','1','2','1'}, {'2','2','1','1','1','1'}, - {'1','1','2','1','2','1'}, {'2','1','2','1','1','1'}, {'1','2','2','1','1','1'}, {'1','1','1','2','2','1'}, - {'2','1','1','2','1','1'}, {'2','1','1','1','1','1'}, {'1','1','2','1','1','1'}, - {'1','1','2','2','1','1'} /* Start character (full 6), Stop character (first 5) */ -}; - /* Code 39 character assignments (ISO/IEC 16388:2007 Table 1 and Table A.1) */ static const char C39Table[43 + 1][10] = { {'1','1','1','2','2','1','2','1','1','1'}, {'2','1','1','2','1','1','1','1','2','1'}, @@ -127,115 +118,6 @@ static const char C93Table[47][6] = { {'3','1','2','1','1','1'}, {'3','1','1','1','2','1'}, {'1','2','2','2','1','1'} }; -/* Code 11 */ -INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int length) { - - int i; - int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count; - int weight[141]; /* 140 + 1 extra for 1st check */ - char dest[864]; /* 6 + 140 * 6 + 2 * 6 + 5 + 1 = 864 */ - int error_number = 0; - char *d = dest; - int num_check_digits; - char checkstr[3] = {0}; - static const char checkchrs[11] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' }; - - /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */ - assert(length > 0); - - if (length > 140) { /* 8 (Start) + 140 * 8 + 2 * 8 (Check) + 7 (Stop) = 1151 */ - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 320, "Input length %d too long (maximum 140)", length); - } - if ((i = not_sane(SODIUM_MNS_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 321, - "Invalid character at position %d in input (digits and \"-\" only)", i); - } - - if (symbol->option_2 < 0 || symbol->option_2 > 2) { - return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 339, "Invalid check digit version '%d' (1 or 2 only)", - symbol->option_2); - } - if (symbol->option_2 == 2) { - num_check_digits = 0; - } else if (symbol->option_2 == 1) { - num_check_digits = 1; - } else { - num_check_digits = 2; - } - - c_weight = 1; - c_count = 0; - k_weight = 1; - k_count = 0; - - /* start character */ - memcpy(d, C11Table[11], 6); - d += 6; - - /* Draw main body of barcode */ - for (i = 0; i < length; i++, d += 6) { - if (source[i] == '-') - weight[i] = 10; - else - weight[i] = ctoi(source[i]); - memcpy(d, C11Table[weight[i]], 6); - } - - if (num_check_digits) { - /* Calculate C checksum */ - for (h = length - 1; h >= 0; h--) { - c_count += (c_weight * weight[h]); - c_weight++; - - if (c_weight > 10) { - c_weight = 1; - } - } - c_digit = c_count % 11; - - checkstr[0] = checkchrs[c_digit]; - memcpy(d, C11Table[c_digit], 6); - d += 6; - - if (num_check_digits == 2) { - weight[length] = c_digit; - - /* Calculate K checksum */ - for (h = length; h >= 0; h--) { - k_count += (k_weight * weight[h]); - k_weight++; - - if (k_weight > 9) { - k_weight = 1; - } - } - k_digit = k_count % 11; - - checkstr[1] = checkchrs[k_digit]; - memcpy(d, C11Table[k_digit], 6); - d += 6; - } - } - - if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Check digit (%d): %s\n", num_check_digits, num_check_digits ? checkstr : ""); - } - - /* Stop character */ - memcpy(d, C11Table[11], 5); - d += 5; - - expand(symbol, dest, d - dest); - - /* TODO: Find documentation on BARCODE_CODE11 dimensions/height */ - - ustrcpy(symbol->text, source); - if (num_check_digits) { - ustrcat(symbol->text, checkstr); - } - return error_number; -} - /* Code 39 */ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length) { int i; @@ -353,91 +235,6 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng return error_number; } -/* Pharmazentralnummer (PZN) */ -/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf */ -/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/ - IFA-Info_Check_Digit_Calculations_PZN_PPN_UDI_EN.pdf */ -INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) { - - int i, error_number, zeroes; - int count, check_digit; - unsigned char have_check_digit = '\0'; - char localstr[1 + 8 + 1]; /* '-' prefix + 8 digits + NUL */ - const int pzn7 = symbol->option_2 == 1; - - if (length > 8 - pzn7) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 325, "Input length %1$d too long (maximum %2$d)", length, - 8 - pzn7); - } - if (length == 8 - pzn7) { - have_check_digit = source[7 - pzn7]; - length--; - } - if ((i = not_sane(NEON_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 326, - "Invalid character at position %d in input (digits only)", i); - } - - localstr[0] = '-'; - zeroes = 7 - pzn7 - length + 1; - for (i = 1; i < zeroes; i++) - localstr[i] = '0'; - ustrcpy(localstr + zeroes, source); - - count = 0; - for (i = 1; i < 8 - pzn7; i++) { - count += (i + pzn7) * ctoi(localstr[i]); - } - - check_digit = count % 11; - - if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("PZN: %s, check digit %d\n", localstr, (int) check_digit); - } - - if (check_digit == 10) { - return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 327, "Invalid PZN, check digit is '10'"); - } - if (have_check_digit && ctoi(have_check_digit) != check_digit) { - return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 890, "Invalid check digit '%1$c', expecting '%2$c'", - have_check_digit, itoc(check_digit)); - } - - localstr[8 - pzn7] = itoc(check_digit); - localstr[9 - pzn7] = '\0'; - - if (pzn7) { - symbol->option_2 = 0; /* Need to overwrite this so `code39()` doesn't add a check digit itself */ - } - - error_number = code39(symbol, (unsigned char *) localstr, 9 - pzn7); - - if (pzn7) { - symbol->option_2 = 1; /* Restore */ - } - - ustrcpy(symbol->text, "PZN - "); /* Note changed to put space after hyphen */ - ustrcat(symbol->text, localstr + 1); - - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* Technical Information regarding PZN Coding V 2.1 (25 Feb 2019) Code size - https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf - "normal" X 0.25mm (0.187mm - 0.45mm), height 8mm - 20mm for 0.25mm X, 10mm mentioned so use that - as default, 10mm / 0.25mm = 40 */ - if (error_number < ZINT_ERROR) { - const float min_height = 17.7777786f; /* 8.0 / 0.45 */ - const float max_height = 106.951874f; /* 20.0 / 0.187 */ - error_number = set_height(symbol, min_height, 40.0f, max_height, 0 /*no_errtxt*/); - } - } else { - if (error_number < ZINT_ERROR) { - (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); - } - } - - return error_number; -} - /* Extended Code 39 - ISO/IEC 16388:2007 Annex A */ INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int length) { @@ -599,227 +396,6 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng return error_number; } -typedef const struct s_channel_precalc { - int value; unsigned char B[8]; unsigned char S[8]; unsigned char bmax[7]; unsigned char smax[7]; -} channel_precalc; - -#if 0 -#define CHANNEL_GENERATE_PRECALCS -#endif - -#ifdef CHANNEL_GENERATE_PRECALCS -/* To generate precalc tables uncomment CHANNEL_GENERATE_PRECALCS define and run - "backend/tests/test_channel -f generate -g" and place result in "channel_precalcs.h" */ -static void channel_generate_precalc(int channels, int value, int mod, int last, int B[8], int S[8], int bmax[7], - int smax[7]) { - int i; - if (value == mod) printf("static channel_precalc channel_precalcs%d[] = {\n", channels); - printf(" { %7ld, {", value); for (i = 0; i < 8; i++) printf(" %d,", B[i]); fputs(" },", stdout); - fputs(" {", stdout); for (i = 0; i < 8; i++) printf(" %d,", S[i]); fputs(" },", stdout); - fputs(" {", stdout); for (i = 0; i < 7; i++) printf(" %d,", bmax[i]); fputs(" },", stdout); - fputs(" {", stdout); for (i = 0; i < 7; i++) printf(" %d,", smax[i]); fputs(" }, },\n", stdout); - if (value == last) fputs("};\n", stdout); -} -#else -#include "channel_precalcs.h" -#endif - -static int channel_copy_precalc(channel_precalc *const precalc, int B[8], int S[8], int bmax[7], int smax[7]) { - int i; - - for (i = 0; i < 7; i++) { - B[i] = precalc->B[i]; - S[i] = precalc->S[i]; - bmax[i] = precalc->bmax[i]; - smax[i] = precalc->smax[i]; - } - B[7] = precalc->B[7]; - S[7] = precalc->S[7]; - - return precalc->value; -} - -/* CHNCHR is adapted from ANSI/AIM BC12-1998 Annex D Figure D5 and is Copyright (c) AIM 1997 */ - -/* It is used here on the understanding that it forms part of the specification - for Channel Code and therefore its use is permitted under the following terms - set out in that document: - - "It is the intent and understanding of AIM [t]hat the symbology presented in this - specification is entirely in the public domain and free of all use restrictions, - licenses and fees. AIM USA, its member companies, or individual officers - assume no liability for the use of this document." */ -static void CHNCHR(int channels, int target_value, int B[8], int S[8]) { - /* Use of initial pre-calculations taken from Barcode Writer in Pure PostScript (BWIPP) - * Copyright (c) 2004-2020 Terry Burton (MIT/X-Consortium license) */ - static channel_precalc initial_precalcs[6] = { - { 0, { 1, 1, 1, 1, 1, 2, 1, 2, }, { 1, 1, 1, 1, 1, 1, 1, 3, }, { 1, 1, 1, 1, 1, 3, 2, }, - { 1, 1, 1, 1, 1, 3, 3, }, }, - { 0, { 1, 1, 1, 1, 2, 1, 1, 3, }, { 1, 1, 1, 1, 1, 1, 1, 4, }, { 1, 1, 1, 1, 4, 3, 3, }, - { 1, 1, 1, 1, 4, 4, 4, }, }, - { 0, { 1, 1, 1, 2, 1, 1, 2, 3, }, { 1, 1, 1, 1, 1, 1, 1, 5, }, { 1, 1, 1, 5, 4, 4, 4, }, - { 1, 1, 1, 5, 5, 5, 5, }, }, - { 0, { 1, 1, 2, 1, 1, 2, 1, 4, }, { 1, 1, 1, 1, 1, 1, 1, 6, }, { 1, 1, 6, 5, 5, 5, 4, }, - { 1, 1, 6, 6, 6, 6, 6, }, }, - { 0, { 1, 2, 1, 1, 2, 1, 1, 5, }, { 1, 1, 1, 1, 1, 1, 1, 7, }, { 1, 7, 6, 6, 6, 5, 5, }, - { 1, 7, 7, 7, 7, 7, 7, }, }, - { 0, { 2, 1, 1, 2, 1, 1, 2, 5, }, { 1, 1, 1, 1, 1, 1, 1, 8, }, { 8, 7, 7, 7, 6, 6, 6, }, - { 8, 8, 8, 8, 8, 8, 8, }, }, - }; - int bmax[7], smax[7]; - int value = 0; - - channel_copy_precalc(&initial_precalcs[channels - 3], B, S, bmax, smax); - -#ifndef CHANNEL_GENERATE_PRECALCS - if (channels == 7 && target_value >= channel_precalcs7[0].value) { - value = channel_copy_precalc(&channel_precalcs7[(target_value / channel_precalcs7[0].value) - 1], B, S, bmax, - smax); - } else if (channels == 8 && target_value >= channel_precalcs8[0].value) { - value = channel_copy_precalc(&channel_precalcs8[(target_value / channel_precalcs8[0].value) - 1], B, S, bmax, - smax); - } -#endif - - goto chkchr; - -ls0:smax[1] = smax[0] + 1 - S[0]; B[0] = 1; - if (S[0] == 1) goto nb0; -lb0: bmax[1] = bmax[0] + 1 - B[0]; S[1] = 1; -ls1: smax[2] = smax[1] + 1 - S[1]; B[1] = 1; - if (S[0] + B[0] + S[1] == 3) goto nb1; -lb1: bmax[2] = bmax[1] + 1 - B[1]; S[2] = 1; -ls2: smax[3] = smax[2] + 1 - S[2]; B[2] = 1; - if (B[0] + S[1] + B[1] + S[2] == 4) goto nb2; -lb2: bmax[3] = bmax[2] + 1 - B[2]; S[3] = 1; -ls3: smax[4] = smax[3] + 1 - S[3]; B[3] = 1; - if (B[1] + S[2] + B[2] + S[3] == 4) goto nb3; -lb3: bmax[4] = bmax[3] + 1 - B[3]; S[4] = 1; -ls4: smax[5] = smax[4] + 1 - S[4]; B[4] = 1; - if (B[2] + S[3] + B[3] + S[4] == 4) goto nb4; -lb4: bmax[5] = bmax[4] + 1 - B[4]; S[5] = 1; -ls5: smax[6] = smax[5] + 1 - S[5]; B[5] = 1; - if (B[3] + S[4] + B[4] + S[5] == 4) goto nb5; -lb5: bmax[6] = bmax[5] + 1 - B[5]; S[6] = 1; -ls6: S[7] = smax[6] + 1 - S[6]; B[6] = 1; - if (B[4] + S[5] + B[5] + S[6] == 4) goto nb6; -lb6: B[7] = bmax[6] + 1 - B[6]; - if (B[5] + S[6] + B[6] + S[7] + B[7] == 5) goto nb6; -chkchr: -#ifdef CHANNEL_GENERATE_PRECALCS - /* 115338 == (576688 + 2) / 5 */ - if (channels == 7 && value && value % 115338 == 0) { - channel_generate_precalc(channels, value, 115338, - 115338 * (5 - 1), B, S, bmax, smax); - /* 119121 == (7742862 + 3) / 65 */ - } else if (channels == 8 && value && value % 119121 == 0) { - channel_generate_precalc(channels, value, 119121, - 119121 * (65 - 1), B, S, bmax, smax); - } -#endif - if (value == target_value) return; - value++; -nb6: if (++B[6] <= bmax[6]) goto lb6; - if (++S[6] <= smax[6]) goto ls6; -nb5: if (++B[5] <= bmax[5]) goto lb5; - if (++S[5] <= smax[5]) goto ls5; -nb4: if (++B[4] <= bmax[4]) goto lb4; - if (++S[4] <= smax[4]) goto ls4; -nb3: if (++B[3] <= bmax[3]) goto lb3; - if (++S[3] <= smax[3]) goto ls3; -nb2: if (++B[2] <= bmax[2]) goto lb2; - if (++S[2] <= smax[2]) goto ls2; -nb1: if (++B[1] <= bmax[1]) goto lb1; - if (++S[1] <= smax[1]) goto ls1; -nb0: if (++B[0] <= bmax[0]) goto lb0; - if (++S[0] <= smax[0]) goto ls0; -} - -/* Channel Code - According to ANSI/AIM BC12-1998 */ -INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int length) { - static const int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 }; - int S[8] = {0}, B[8] = {0}; - int target_value; - char dest[30]; - char *d = dest; - int channels, i; - int error_number = 0, zeroes; - - if (length > 7) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 333, "Input length %d too long (maximum 7)", length); - } - if ((i = not_sane(NEON_F, source, length))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 334, - "Invalid character at position %d in input (digits only)", i); - } - target_value = to_int(source, length); - - if ((symbol->option_2 < 3) || (symbol->option_2 > 8)) { - channels = 0; - } else { - channels = symbol->option_2; - } - - if (channels == 0) { - channels = length + 1; - if (target_value > 576688 && channels < 8) { - channels = 8; - } else if (target_value > 44072 && channels < 7) { - channels = 7; - } else if (target_value > 3493 && channels < 6) { - channels = 6; - } else if (target_value > 292 && channels < 5) { - channels = 5; - } else if (target_value > 26 && channels < 4) { - channels = 4; - } - } - if (channels == 2) { - channels = 3; - } - - if (target_value > max_ranges[channels]) { - if (channels == 8) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 318, "Input value \"%1$d\" out of range (0 to %2$d)", - target_value, max_ranges[channels]); - } - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 335, - "Input value \"%1$d\" out of range (0 to %2$d for %3$d channels)", - target_value, max_ranges[channels], channels); - } - - CHNCHR(channels, target_value, B, S); - - memcpy(d, "111111111", 9); /* Finder pattern */ - d += 9; - for (i = 8 - channels; i < 8; i++) { - *d++ = itoc(S[i]); - *d++ = itoc(B[i]); - } - - zeroes = channels - 1 - length; - if (zeroes < 0) { - zeroes = 0; - } else if (zeroes) { - memset(symbol->text, '0', zeroes); - } - ustrcpy(symbol->text + zeroes, source); - - expand(symbol, dest, d - dest); - - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* ANSI/AIM BC12-1998 gives min height as 5mm or 15% of length; X left as application specification so use - length = 1X (left qz) + (9 (finder) + 4 * 8 - 2) * X + 2X (right qz); - use 20 as default based on figures in spec */ - const float min_height = stripf((1 + 9 + 4 * channels - 2 + 2) * 0.15f); - error_number = set_height(symbol, min_height, 20.0f, 0.0f, 0 /*no_errtxt*/); - } else { - (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); - } - - return error_number; -} - /* Vehicle Identification Number (VIN) */ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) { diff --git a/backend/code11.c b/backend/code11.c new file mode 100644 index 00000000..e103ba12 --- /dev/null +++ b/backend/code11.c @@ -0,0 +1,155 @@ +/* code11.c - Handles Code 11 */ +/* + libzint - the open source barcode library + Copyright (C) 2008-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "code.c" */ + +#include +#include +#include "common.h" + +#define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */ + +static const char C11Table[11 + 1][6] = { + {'1','1','1','1','2','1'}, {'2','1','1','1','2','1'}, {'1','2','1','1','2','1'}, {'2','2','1','1','1','1'}, + {'1','1','2','1','2','1'}, {'2','1','2','1','1','1'}, {'1','2','2','1','1','1'}, {'1','1','1','2','2','1'}, + {'2','1','1','2','1','1'}, {'2','1','1','1','1','1'}, {'1','1','2','1','1','1'}, + {'1','1','2','2','1','1'} /* Start character (full 6), Stop character (first 5) */ +}; + +/* Code 11 */ +INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int length) { + + int i; + int h; + int weight[141]; /* 140 + 1 extra for 1st check */ + char dest[864]; /* 6 + 140 * 6 + 2 * 6 + 5 + 1 = 864 */ + int error_number = 0; + char *d = dest; + int num_check_digits; + char checkstr[3] = {0}; + static const char checkchrs[11] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' }; + + /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */ + assert(length > 0); + + if (length > 140) { /* 8 (Start) + 140 * 8 + 2 * 8 (Check) + 7 (Stop) = 1151 */ + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 320, "Input length %d too long (maximum 140)", length); + } + if ((i = not_sane(SODIUM_MNS_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 321, + "Invalid character at position %d in input (digits and \"-\" only)", i); + } + + if (symbol->option_2 < 0 || symbol->option_2 > 2) { + return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 339, "Invalid check digit version '%d' (1 or 2 only)", + symbol->option_2); + } + if (symbol->option_2 == 2) { + num_check_digits = 0; + } else if (symbol->option_2 == 1) { + num_check_digits = 1; + } else { + num_check_digits = 2; + } + + + /* start character */ + memcpy(d, C11Table[11], 6); + d += 6; + + /* Draw main body of barcode */ + for (i = 0; i < length; i++, d += 6) { + if (source[i] == '-') + weight[i] = 10; + else + weight[i] = ctoi(source[i]); + memcpy(d, C11Table[weight[i]], 6); + } + + if (num_check_digits) { + int c_weight = 1, c_count = 0, c_digit; + /* Calculate C checksum */ + for (h = length - 1; h >= 0; h--) { + c_count += (c_weight * weight[h]); + c_weight++; + + if (c_weight > 10) { + c_weight = 1; + } + } + c_digit = c_count % 11; + + checkstr[0] = checkchrs[c_digit]; + memcpy(d, C11Table[c_digit], 6); + d += 6; + + if (num_check_digits == 2) { + int k_weight = 1, k_count = 0, k_digit; + weight[length] = c_digit; + + /* Calculate K checksum */ + for (h = length; h >= 0; h--) { + k_count += (k_weight * weight[h]); + k_weight++; + + if (k_weight > 9) { + k_weight = 1; + } + } + k_digit = k_count % 11; + + checkstr[1] = checkchrs[k_digit]; + memcpy(d, C11Table[k_digit], 6); + d += 6; + } + } + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Check digit (%d): %s\n", num_check_digits, num_check_digits ? checkstr : ""); + } + + /* Stop character */ + memcpy(d, C11Table[11], 5); + d += 5; + + expand(symbol, dest, d - dest); + + /* TODO: Find documentation on BARCODE_CODE11 dimensions/height */ + + ustrcpy(symbol->text, source); + if (num_check_digits) { + ustrcat(symbol->text, checkstr); + } + return error_number; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/code128.c b/backend/code128.c index 55d63c04..f9d5590c 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -1,7 +1,7 @@ -/* code128.c - Handles Code 128 and derivatives */ +/* code128.c - Handles Code 128 and GS1-128 */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Bugfixes thanks to Christian Sakowski and BogDan Vatra Redistribution and use in source and binary forms, with or without @@ -663,277 +663,4 @@ INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int len return gs1_128_cc(symbol, source, length, 0 /*cc_mode*/, 0 /*cc_rows*/); } -/* Helper to do NVE18 or EAN14 */ -static int nve18_or_ean14(struct zint_symbol *symbol, unsigned char source[], const int length, const int data_len) { - static const char prefix[2][2][5] = { - { "(01)", "[01]" }, /* EAN14 */ - { "(00)", "[00]" }, /* NVE18 */ - }; - unsigned char ean128_equiv[23]; - int error_number, zeroes; - int i; - - if (length > data_len) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 345, "Input length %1$d too long (maximum %2$d)", length, - data_len); - } - - if ((i = not_sane(NEON_F, source, length))) { - /* Note: for all "at position" error messages, escape sequences not accounted for */ - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 346, - "Invalid character at position %d in input (digits only)", i); - } - - zeroes = data_len - length; - ustrcpy(ean128_equiv, prefix[data_len == 17][!(symbol->input_mode & GS1PARENS_MODE)]); - memset(ean128_equiv + 4, '0', zeroes); - ustrcpy(ean128_equiv + 4 + zeroes, source); - - ean128_equiv[data_len + 4] = gs1_check_digit(ean128_equiv + 4, data_len); - ean128_equiv[data_len + 5] = '\0'; - - error_number = gs1_128(symbol, ean128_equiv, data_len + 5); - - return error_number; -} - - -/* Add check digit if encoding an NVE18 symbol */ -INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length) { - return nve18_or_ean14(symbol, source, length, 17 /*data_len*/); -} - -/* EAN-14 - A version of EAN-128 */ -INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int length) { - return nve18_or_ean14(symbol, source, length, 13 /*data_len*/); -} - -static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -#define KRSET_F (IS_NUM_F | IS_UPR_F) - -/* DPD (Deutscher Paketdienst) Code */ -/* Specification at https://esolutions.dpd.com/dokumente/DPD_Parcel_Label_Specification_2.4.1_EN.pdf - * and identification tag info (Barcode ID) at https://esolutions.dpd.com/dokumente/DPD_Routing_Database_1.3_EN.pdf */ -INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) { - int error_number = 0; - int i, p; - unsigned char ident_tag; - unsigned char local_source_buf[29]; - unsigned char *local_source; - const int mod = 36; - const int relabel = symbol->option_2 == 1; /* A "relabel" has no identification tag */ - int cd; /* Check digit */ - - if ((length != 27 && length != 28) || (length == 28 && relabel)) { - if (relabel) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 830, "DPD relabel input length %d wrong (27 only)", length); - } - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 349, "DPD input length %d wrong (27 or 28 only)", length); - } - - if (length == 27 && !relabel) { - local_source_buf[0] = '%'; - ustrcpy(local_source_buf + 1, source); - local_source = local_source_buf; - length++; - } else { - local_source = source; - } - - ident_tag = local_source[0]; - - to_upper(local_source + !relabel, length - !relabel); - if ((i = not_sane(KRSET_F, local_source + !relabel, length - !relabel))) { - if (local_source == local_source_buf || relabel) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 300, - "Invalid character at position %d in input (alphanumerics only)", i); - } - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 299, - "Invalid character at position %d in input (alphanumerics only after first)", i); - } - - if ((ident_tag < 32) || (ident_tag > 127)) { - return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 343, - "Invalid DPD identification tag (first character), ASCII values 32 to 127 only"); - } - - (void) code128(symbol, local_source, length); /* Only error returned is for large text which can't happen */ - - if (!(symbol->output_options & (BARCODE_BOX | BARCODE_BIND | BARCODE_BIND_TOP))) { - /* If no option has been selected then uses default bind top option */ - symbol->output_options |= BARCODE_BIND_TOP; /* Note won't extend over quiet zones for DPD */ - if (symbol->border_width == 0) { /* Allow override if non-zero */ - symbol->border_width = 3; /* From examples, not mentioned in spec */ - } - } - - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* DPD Parcel Label Specification Version 2.4.1 (19.01.2021) Section 4.6.1.2 - 25mm / 0.4mm (X max) = 62.5 min, 25mm / 0.375 (X) ~ 66.66 default */ - if (relabel) { /* If relabel then half-size */ - const float default_height = 33.3333321f; /* 12.5 / 0.375 */ - error_number = set_height(symbol, 31.25f, default_height, 0.0f, 0 /*no_errtxt*/); - } else { - const float default_height = 66.6666641f; /* 25.0 / 0.375 */ - error_number = set_height(symbol, 62.5f, default_height, 0.0f, 0 /*no_errtxt*/); - } - } else { - (void) set_height(symbol, 0.0f, relabel ? 25.0f : 50.0f, 0.0f, 1 /*no_errtxt*/); - } - - cd = mod; - - p = 0; - for (i = !relabel; i < length; i++) { - symbol->text[p] = local_source[i]; - p++; - - cd += posn(KRSET, local_source[i]); - if (cd > mod) cd -= mod; - cd *= 2; - if (cd >= (mod + 1)) cd -= mod + 1; - - switch (i + relabel) { - case 4: - case 7: - case 11: - case 15: - case 19: - case 21: - case 24: - case 27: - symbol->text[p++] = ' '; - break; - } - } - - cd = mod + 1 - cd; - if (cd == mod) cd = 0; - - if (cd < 10) { - symbol->text[p] = cd + '0'; - } else { - symbol->text[p] = (cd - 10) + 'A'; - } - p++; - - symbol->text[p] = '\0'; - - /* Some compliance checks */ - if (not_sane(NEON_F, local_source + length - 16, 16)) { - if (not_sane(NEON_F, local_source + length - 3, 3)) { /* 3-digit Country Code (ISO 3166-1) */ - errtxt(0, symbol, 831, "Destination Country Code (last 3 characters) should be numeric"); - } else if (not_sane(NEON_F, local_source + length - 6, 3)) { /* 3-digit Service Code */ - errtxt(0, symbol, 832, "Service Code (characters 6-4 from end) should be numeric"); - } else { /* Last 10 characters of Tracking No. */ - errtxt(0, symbol, 833, - "Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric"); - } - error_number = ZINT_WARN_NONCOMPLIANT; - } - - return error_number; -} - -/* Universal Postal Union S10 */ -/* https://www.upu.int/UPU/media/upu/files/postalSolutions/programmesAndServices/standards/S10-12.pdf */ -INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, j; - unsigned char local_source[13 + 1]; - unsigned char have_check_digit = '\0'; - int check_digit; - static const char weights[8] = { 8, 6, 4, 2, 3, 5, 9, 7 }; - int error_number = 0; - - if (length != 12 && length != 13) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 834, "Input length %d wrong (12 or 13 only)", length); - } - if (length == 13) { /* Includes check digit - remove for now */ - have_check_digit = source[10]; - memcpy(local_source, source, 10); - ustrcpy(local_source + 10, source + 11); - } else { - ustrcpy(local_source, source); - } - to_upper(local_source, length); - - if (!z_isupper(local_source[0]) || !z_isupper(local_source[1])) { - return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 835, - "Invalid character in Service Indictor (first 2 characters) (alphabetic only)"); - } - if (not_sane(NEON_F, local_source + 2, 12 - 4) || (have_check_digit && !z_isdigit(have_check_digit))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 836, - "Invalid character in Serial Number (middle %d characters) (digits only)", - have_check_digit ? 9 : 8); - } - if (!z_isupper(local_source[10]) || !z_isupper(local_source[11])) { - return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 837, - "Invalid character in Country Code (last 2 characters) (alphabetic only)"); - } - - check_digit = 0; - for (i = 2; i < 10; i++) { /* Serial Number only */ - check_digit += ctoi(local_source[i]) * weights[i - 2]; - } - check_digit %= 11; - check_digit = 11 - check_digit; - if (check_digit == 10) { - check_digit = 0; - } else if (check_digit == 11) { - check_digit = 5; - } - if (have_check_digit && ctoi(have_check_digit) != check_digit) { - return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 838, "Invalid check digit '%1$c', expecting '%2$c'", - have_check_digit, itoc(check_digit)); - } - /* Add in (back) check digit */ - local_source[12] = local_source[11]; - local_source[11] = local_source[10]; - local_source[10] = itoc(check_digit); - local_source[13] = '\0'; - - /* Do some checks on the Service Indicator (first char only) and Country Code */ - if (strchr("JKSTW", local_source[0]) != NULL) { /* These are reserved & cannot be assigned */ - error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 839, - "Invalid Service Indicator (first character should not be any of \"JKSTW\")"); - } else if (strchr("FHIOXY", local_source[0]) != NULL) { /* These aren't allocated as of spec Oct 2017 */ - error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 840, - "Non-standard Service Indicator (first 2 characters)"); - } else if (!gs1_iso3166_alpha2(local_source + 11)) { - error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 841, - "Country code (last two characters) is not ISO 3166-1"); - } - - (void) code128(symbol, local_source, 13); /* Only error returned is for large text which can't happen */ - - j = 0; - for (i = 0; i < 13; i++) { - if (i == 2 || i == 5 || i == 8 || i == 11) { - symbol->text[j++] = ' '; - } - symbol->text[j++] = local_source[i]; - } - symbol->text[j] = '\0'; - - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* Universal Postal Union S10 Section 8, using max X 0.51mm & minimum height 12.5mm or 15% of width */ - const float min_height_min = 24.5098038f; /* 12.5 / 0.51 */ - float min_height = stripf(symbol->width * 0.15f); - if (min_height < min_height_min) { - min_height = min_height_min; - } - /* Using 50 as default as none recommended */ - if (error_number == 0) { - error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, - 0 /*no_errtxt*/); - } else { - (void) set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, 1 /*no_errtxt*/); - } - } else { - (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); - } - - return error_number; -} - /* vim: set ts=4 sw=4 et : */ diff --git a/backend/code128_based.c b/backend/code128_based.c new file mode 100644 index 00000000..db498119 --- /dev/null +++ b/backend/code128_based.c @@ -0,0 +1,316 @@ +/* code128_based.c - Handles Code 128 derivatives NVE-18, EAN-14, DPD and Universal Postal Union S10 */ +/* + libzint - the open source barcode library + Copyright (C) 2008-2025 Robin Stuart + Bugfixes thanks to Christian Sakowski and BogDan Vatra + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include +#include "common.h" +#include "code128.h" +#include "gs1.h" + +/* Was in "code128.c" */ + +INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int length); + +/* Helper to do NVE18 or EAN14 */ +static int nve18_or_ean14(struct zint_symbol *symbol, unsigned char source[], const int length, const int data_len) { + static const char prefix[2][2][5] = { + { "(01)", "[01]" }, /* EAN14 */ + { "(00)", "[00]" }, /* NVE18 */ + }; + unsigned char ean128_equiv[23]; + int error_number, zeroes; + int i; + + if (length > data_len) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 345, "Input length %1$d too long (maximum %2$d)", length, + data_len); + } + + if ((i = not_sane(NEON_F, source, length))) { + /* Note: for all "at position" error messages, escape sequences not accounted for */ + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 346, + "Invalid character at position %d in input (digits only)", i); + } + + zeroes = data_len - length; + ustrcpy(ean128_equiv, prefix[data_len == 17][!(symbol->input_mode & GS1PARENS_MODE)]); + memset(ean128_equiv + 4, '0', zeroes); + ustrcpy(ean128_equiv + 4 + zeroes, source); + + ean128_equiv[data_len + 4] = gs1_check_digit(ean128_equiv + 4, data_len); + ean128_equiv[data_len + 5] = '\0'; + + error_number = gs1_128(symbol, ean128_equiv, data_len + 5); + + return error_number; +} + + +/* Add check digit if encoding an NVE18 symbol */ +INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length) { + return nve18_or_ean14(symbol, source, length, 17 /*data_len*/); +} + +/* EAN-14 - A version of EAN-128 */ +INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int length) { + return nve18_or_ean14(symbol, source, length, 13 /*data_len*/); +} + +static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +#define KRSET_F (IS_NUM_F | IS_UPR_F) + +/* DPD (Deutscher Paketdienst) Code */ +/* Specification at https://esolutions.dpd.com/dokumente/DPD_Parcel_Label_Specification_2.4.1_EN.pdf + * and identification tag info (Barcode ID) at https://esolutions.dpd.com/dokumente/DPD_Routing_Database_1.3_EN.pdf */ +INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) { + int error_number = 0; + int i, p; + unsigned char ident_tag; + unsigned char local_source_buf[29]; + unsigned char *local_source; + const int mod = 36; + const int relabel = symbol->option_2 == 1; /* A "relabel" has no identification tag */ + int cd; /* Check digit */ + + if ((length != 27 && length != 28) || (length == 28 && relabel)) { + if (relabel) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 830, "DPD relabel input length %d wrong (27 only)", length); + } + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 349, "DPD input length %d wrong (27 or 28 only)", length); + } + + if (length == 27 && !relabel) { + local_source_buf[0] = '%'; + ustrcpy(local_source_buf + 1, source); + local_source = local_source_buf; + length++; + } else { + local_source = source; + } + + ident_tag = local_source[0]; + + to_upper(local_source + !relabel, length - !relabel); + if ((i = not_sane(KRSET_F, local_source + !relabel, length - !relabel))) { + if (local_source == local_source_buf || relabel) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 300, + "Invalid character at position %d in input (alphanumerics only)", i); + } + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 299, + "Invalid character at position %d in input (alphanumerics only after first)", i); + } + + if ((ident_tag < 32) || (ident_tag > 127)) { + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 343, + "Invalid DPD identification tag (first character), ASCII values 32 to 127 only"); + } + + (void) code128(symbol, local_source, length); /* Only error returned is for large text which can't happen */ + + if (!(symbol->output_options & (BARCODE_BOX | BARCODE_BIND | BARCODE_BIND_TOP))) { + /* If no option has been selected then uses default bind top option */ + symbol->output_options |= BARCODE_BIND_TOP; /* Note won't extend over quiet zones for DPD */ + if (symbol->border_width == 0) { /* Allow override if non-zero */ + symbol->border_width = 3; /* From examples, not mentioned in spec */ + } + } + + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* DPD Parcel Label Specification Version 2.4.1 (19.01.2021) Section 4.6.1.2 + 25mm / 0.4mm (X max) = 62.5 min, 25mm / 0.375 (X) ~ 66.66 default */ + if (relabel) { /* If relabel then half-size */ + const float default_height = 33.3333321f; /* 12.5 / 0.375 */ + error_number = set_height(symbol, 31.25f, default_height, 0.0f, 0 /*no_errtxt*/); + } else { + const float default_height = 66.6666641f; /* 25.0 / 0.375 */ + error_number = set_height(symbol, 62.5f, default_height, 0.0f, 0 /*no_errtxt*/); + } + } else { + (void) set_height(symbol, 0.0f, relabel ? 25.0f : 50.0f, 0.0f, 1 /*no_errtxt*/); + } + + cd = mod; + + p = 0; + for (i = !relabel; i < length; i++) { + symbol->text[p] = local_source[i]; + p++; + + cd += posn(KRSET, local_source[i]); + if (cd > mod) cd -= mod; + cd *= 2; + if (cd >= (mod + 1)) cd -= mod + 1; + + switch (i + relabel) { + case 4: + case 7: + case 11: + case 15: + case 19: + case 21: + case 24: + case 27: + symbol->text[p++] = ' '; + break; + } + } + + cd = mod + 1 - cd; + if (cd == mod) cd = 0; + + if (cd < 10) { + symbol->text[p] = cd + '0'; + } else { + symbol->text[p] = (cd - 10) + 'A'; + } + p++; + + symbol->text[p] = '\0'; + + /* Some compliance checks */ + if (not_sane(NEON_F, local_source + length - 16, 16)) { + if (not_sane(NEON_F, local_source + length - 3, 3)) { /* 3-digit Country Code (ISO 3166-1) */ + errtxt(0, symbol, 831, "Destination Country Code (last 3 characters) should be numeric"); + } else if (not_sane(NEON_F, local_source + length - 6, 3)) { /* 3-digit Service Code */ + errtxt(0, symbol, 832, "Service Code (characters 6-4 from end) should be numeric"); + } else { /* Last 10 characters of Tracking No. */ + errtxt(0, symbol, 833, + "Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric"); + } + error_number = ZINT_WARN_NONCOMPLIANT; + } + + return error_number; +} + +/* Universal Postal Union S10 */ +/* https://www.upu.int/UPU/media/upu/files/postalSolutions/programmesAndServices/standards/S10-12.pdf */ +INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, j; + unsigned char local_source[13 + 1]; + unsigned char have_check_digit = '\0'; + int check_digit; + static const char weights[8] = { 8, 6, 4, 2, 3, 5, 9, 7 }; + int error_number = 0; + + if (length != 12 && length != 13) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 834, "Input length %d wrong (12 or 13 only)", length); + } + if (length == 13) { /* Includes check digit - remove for now */ + have_check_digit = source[10]; + memcpy(local_source, source, 10); + ustrcpy(local_source + 10, source + 11); + } else { + ustrcpy(local_source, source); + } + to_upper(local_source, length); + + if (!z_isupper(local_source[0]) || !z_isupper(local_source[1])) { + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 835, + "Invalid character in Service Indictor (first 2 characters) (alphabetic only)"); + } + if (not_sane(NEON_F, local_source + 2, 12 - 4) || (have_check_digit && !z_isdigit(have_check_digit))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 836, + "Invalid character in Serial Number (middle %d characters) (digits only)", + have_check_digit ? 9 : 8); + } + if (!z_isupper(local_source[10]) || !z_isupper(local_source[11])) { + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 837, + "Invalid character in Country Code (last 2 characters) (alphabetic only)"); + } + + check_digit = 0; + for (i = 2; i < 10; i++) { /* Serial Number only */ + check_digit += ctoi(local_source[i]) * weights[i - 2]; + } + check_digit %= 11; + check_digit = 11 - check_digit; + if (check_digit == 10) { + check_digit = 0; + } else if (check_digit == 11) { + check_digit = 5; + } + if (have_check_digit && ctoi(have_check_digit) != check_digit) { + return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 838, "Invalid check digit '%1$c', expecting '%2$c'", + have_check_digit, itoc(check_digit)); + } + /* Add in (back) check digit */ + local_source[12] = local_source[11]; + local_source[11] = local_source[10]; + local_source[10] = itoc(check_digit); + local_source[13] = '\0'; + + /* Do some checks on the Service Indicator (first char only) and Country Code */ + if (strchr("JKSTW", local_source[0]) != NULL) { /* These are reserved & cannot be assigned */ + error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 839, + "Invalid Service Indicator (first character should not be any of \"JKSTW\")"); + } else if (strchr("FHIOXY", local_source[0]) != NULL) { /* These aren't allocated as of spec Oct 2017 */ + error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 840, + "Non-standard Service Indicator (first 2 characters)"); + } else if (!gs1_iso3166_alpha2(local_source + 11)) { + error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 841, + "Country code (last two characters) is not ISO 3166-1"); + } + + (void) code128(symbol, local_source, 13); /* Only error returned is for large text which can't happen */ + + j = 0; + for (i = 0; i < 13; i++) { + if (i == 2 || i == 5 || i == 8 || i == 11) { + symbol->text[j++] = ' '; + } + symbol->text[j++] = local_source[i]; + } + symbol->text[j] = '\0'; + + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* Universal Postal Union S10 Section 8, using max X 0.51mm & minimum height 12.5mm or 15% of width */ + const float min_height_min = 24.5098038f; /* 12.5 / 0.51 */ + float min_height = stripf(symbol->width * 0.15f); + if (min_height < min_height_min) { + min_height = min_height_min; + } + /* Using 50 as default as none recommended */ + if (error_number == 0) { + error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, + 0 /*no_errtxt*/); + } else { + (void) set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, 1 /*no_errtxt*/); + } + } else { + (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); + } + + return error_number; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/medical.c b/backend/medical.c index 8f375c00..ebe5776c 100644 --- a/backend/medical.c +++ b/backend/medical.c @@ -1,7 +1,7 @@ -/* medical.c - Handles 1 track and 2 track pharmacode and Codabar */ +/* medical.c - Handles Pharmacode One-Track, Pharmacode Two-Track, Italian Pharmacode and PZN */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -35,20 +35,7 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length); -static const char CALCIUM[] = "0123456789-$:/.+ABCD"; -#define CALCIUM_INNER_F (IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F) /* CALCIUM_INNER "0123456789-$:/.+" */ - -/* Codabar table checked against EN 798:1995 */ -static const char CodaTable[20][8] = { - {'1','1','1','1','1','2','2','1'}, {'1','1','1','1','2','2','1','1'}, {'1','1','1','2','1','1','2','1'}, - {'2','2','1','1','1','1','1','1'}, {'1','1','2','1','1','2','1','1'}, {'2','1','1','1','1','2','1','1'}, - {'1','2','1','1','1','1','2','1'}, {'1','2','1','1','2','1','1','1'}, {'1','2','2','1','1','1','1','1'}, - {'2','1','1','2','1','1','1','1'}, {'1','1','1','2','2','1','1','1'}, {'1','1','2','2','1','1','1','1'}, - {'2','1','1','1','2','1','2','1'}, {'2','1','2','1','1','1','2','1'}, {'2','1','2','1','2','1','1','1'}, - {'1','1','2','1','2','1','2','1'}, {'1','1','2','2','1','2','1','1'}, {'1','2','1','2','1','1','2','1'}, - {'1','1','1','2','1','2','2','1'}, {'1','1','1','2','2','2','1','1'} -}; - +/* Pharmacode One-Track */ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int length) { /* "Pharmacode can represent only a single integer from 3 to 131070. Unlike other commonly used one-dimensional barcode schemes, pharmacode does not store the data in a @@ -149,6 +136,7 @@ static int pharma_two_calc(int tester, char *d) { return h; } +/* Pharmacode Two-Track */ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length) { /* Draws the patterns for two track pharmacode */ int i; @@ -197,100 +185,6 @@ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int return error_number; } -/* The Codabar system consisting of simple substitution */ -INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length) { - - int i, error_number = 0; - int posns[103]; - char dest[833]; /* (103 + 1) * 8 + 1 == 833 */ - char *d = dest; - int add_checksum, count = 0, checksum = 0; - int d_chars = 0; - - if (length > 103) { /* No stack smashing please (103 + 1) * 11 = 1144 */ - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 356, "Input length %d too long (maximum 103)", length); - } - /* BS EN 798:1995 4.2 "'Codabar' symbols shall consist of ... b) start character; - c) one or more symbol characters representing data ... d) stop character ..." */ - if (length < 3) { - return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 362, "Input length %d too short (minimum 3)", length); - } - to_upper(source, length); - - /* Codabar must begin and end with the characters A, B, C or D */ - if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C') - && (source[0] != 'D')) { - return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 358, "Does not begin with \"A\", \"B\", \"C\" or \"D\""); - } - if ((source[length - 1] != 'A') && (source[length - 1] != 'B') && - (source[length - 1] != 'C') && (source[length - 1] != 'D')) { - return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 359, "Does not end with \"A\", \"B\", \"C\" or \"D\""); - } - if ((i = not_sane_lookup(CALCIUM, sizeof(CALCIUM) - 1, source, length, posns))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 357, - "Invalid character at position %1$d in input (\"%2$s\" only)", i, CALCIUM); - } - /* And must not use A, B, C or D otherwise (BS EN 798:1995 4.3.2) */ - if ((i = not_sane(CALCIUM_INNER_F, source + 1, length - 2))) { - return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 363, - "Invalid character at position %d in input (cannot contain \"A\", \"B\", \"C\" or \"D\")", i); - } - - /* Add check character: 1 don't show to HRT, 2 do show to HRT - (unfortunately to maintain back-compatibility, this is reverse of C25) */ - add_checksum = symbol->option_2 == 1 || symbol->option_2 == 2; - - for (i = 0; i < length; i++, d += 8) { - if (add_checksum) { - /* BS EN 798:1995 A.3 suggests using ISO 7064 algorithm but leaves it application defined. - Following BWIPP and TEC-IT, use this simple mod-16 algorithm (not in ISO 7064) */ - count += posns[i]; - if (i + 1 == length) { - checksum = count % 16; - if (checksum) { - checksum = 16 - checksum; - } - if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Codabar: %s, count %d, checksum %d (%c)\n", source, count, checksum, CALCIUM[checksum]); - } - memcpy(d, CodaTable[checksum], 8); - d += 8; - } - } - memcpy(d, CodaTable[posns[i]], 8); - if (source[i] == '/' || source[i] == ':' || source[i] == '.' || source[i] == '+') { /* Wide data characters */ - d_chars++; - } - } - - expand(symbol, dest, d - dest); - - if (symbol->output_options & COMPLIANT_HEIGHT) { - /* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.43mm (X max) ~ 11.628 or 15% of width where (taking N = - narrow/wide ratio as 2 and I = X) width = ((2 * N + 5) * C + (N – 1) * (D + 2)) * X + I * (C – 1) + 2Q - = ((4 + 5) * C + (D + 2) + C - 1 + 2 * 10) * X = (10 * C + D + 21) * X - Length (C) includes start/stop chars */ - const float min_height_min = 11.6279068f; /* 5.0 / 0.43 */ - float min_height = stripf((10.0f * ((add_checksum ? length + 1 : length) + 2.0f) + d_chars + 21.0f) * 0.15f); - if (min_height < min_height_min) { - min_height = min_height_min; - } - /* Using 50 as default as none recommended */ - error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, 0 /*no_errtxt*/); - } else { - (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); - } - - ustrcpy(symbol->text, source); - if (symbol->option_2 == 2) { - symbol->text[length - 1] = CALCIUM[checksum]; /* Place before final A/B/C/D character (BS EN 798:1995 A.3) */ - symbol->text[length] = source[length - 1]; - symbol->text[length + 1] = '\0'; - } - - return error_number; -} - /* Italian Pharmacode */ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length) { static const char TABELLA[] = "0123456789BCDFGHJKLMNPQRSTUVWXYZ"; @@ -374,4 +268,89 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng return error_number; } +/* Pharmazentralnummer (PZN) */ +/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf */ +/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/ + IFA-Info_Check_Digit_Calculations_PZN_PPN_UDI_EN.pdf */ +INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) { + + int i, error_number, zeroes; + int count, check_digit; + unsigned char have_check_digit = '\0'; + char localstr[1 + 8 + 1]; /* '-' prefix + 8 digits + NUL */ + const int pzn7 = symbol->option_2 == 1; + + if (length > 8 - pzn7) { + return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 325, "Input length %1$d too long (maximum %2$d)", length, + 8 - pzn7); + } + if (length == 8 - pzn7) { + have_check_digit = source[7 - pzn7]; + length--; + } + if ((i = not_sane(NEON_F, source, length))) { + return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 326, + "Invalid character at position %d in input (digits only)", i); + } + + localstr[0] = '-'; + zeroes = 7 - pzn7 - length + 1; + for (i = 1; i < zeroes; i++) + localstr[i] = '0'; + ustrcpy(localstr + zeroes, source); + + count = 0; + for (i = 1; i < 8 - pzn7; i++) { + count += (i + pzn7) * ctoi(localstr[i]); + } + + check_digit = count % 11; + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("PZN: %s, check digit %d\n", localstr, (int) check_digit); + } + + if (check_digit == 10) { + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 327, "Invalid PZN, check digit is '10'"); + } + if (have_check_digit && ctoi(have_check_digit) != check_digit) { + return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 890, "Invalid check digit '%1$c', expecting '%2$c'", + have_check_digit, itoc(check_digit)); + } + + localstr[8 - pzn7] = itoc(check_digit); + localstr[9 - pzn7] = '\0'; + + if (pzn7) { + symbol->option_2 = 0; /* Need to overwrite this so `code39()` doesn't add a check digit itself */ + } + + error_number = code39(symbol, (unsigned char *) localstr, 9 - pzn7); + + if (pzn7) { + symbol->option_2 = 1; /* Restore */ + } + + ustrcpy(symbol->text, "PZN - "); /* Note changed to put space after hyphen */ + ustrcat(symbol->text, localstr + 1); + + if (symbol->output_options & COMPLIANT_HEIGHT) { + /* Technical Information regarding PZN Coding V 2.1 (25 Feb 2019) Code size + https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf + "normal" X 0.25mm (0.187mm - 0.45mm), height 8mm - 20mm for 0.25mm X, 10mm mentioned so use that + as default, 10mm / 0.25mm = 40 */ + if (error_number < ZINT_ERROR) { + const float min_height = 17.7777786f; /* 8.0 / 0.45 */ + const float max_height = 106.951874f; /* 20.0 / 0.187 */ + error_number = set_height(symbol, min_height, 40.0f, max_height, 0 /*no_errtxt*/); + } + } else { + if (error_number < ZINT_ERROR) { + (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); + } + } + + return error_number; +} + /* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt index e07341b8..42a8ba62 100644 --- a/backend/tests/CMakeLists.txt +++ b/backend/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2009-2024 Robin Stuart +# Copyright (C) 2009-2025 Robin Stuart # Adapted from qrencode/tests/CMakeLists.txt # Copyright (C) 2006-2017 Kentaro Fukuchi # vim: set ts=4 sw=4 et : @@ -46,9 +46,11 @@ zint_add_test(bc412 test_bc412) zint_add_test(big5 test_big5) zint_add_test(bmp test_bmp) zint_add_test(channel test_channel) +zint_add_test(codabar test_codabar) zint_add_test(codablock test_codablock) zint_add_test(code test_code) zint_add_test(code1 test_code1) +zint_add_test(code11 test_code11) zint_add_test(code128 test_code128) zint_add_test(code16k test_code16k) zint_add_test(code49 test_code49) diff --git a/backend/tests/test_codabar.c b/backend/tests/test_codabar.c new file mode 100644 index 00000000..4db07cf0 --- /dev/null +++ b/backend/tests/test_codabar.c @@ -0,0 +1,326 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "test_medical.c */ + +#include "testcommon.h" + +static void test_large(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *pattern; + int length; + int ret; + int expected_rows; + int expected_width; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODABAR, -1, "A+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 103, 0, 1, 1133 }, + /* 1*/ { BARCODE_CODABAR, -1, "A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 104, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 2*/ { BARCODE_CODABAR, 1, "A+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 103, 0, 1, 1143 }, + /* 3*/ { BARCODE_CODABAR, 1, "A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 104, ZINT_ERROR_TOO_LONG, -1, -1 }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + char data_buf[128]; + + testStartSymbol("test_large", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length); + assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf)); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (ret < ZINT_ERROR) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_hrt(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *data; + + char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODABAR, -1, "A1234B", "A1234B" }, + /* 1*/ { BARCODE_CODABAR, -1, "a1234c", "A1234C" }, /* Converts to upper */ + /* 2*/ { BARCODE_CODABAR, 1, "A1234B", "A1234B" }, /* Check not included */ + /* 3*/ { BARCODE_CODABAR, 2, "A1234B", "A12345B" }, /* Check included */ + /* 4*/ { BARCODE_CODABAR, 1, "A123456A", "A123456A" }, /* Check not included */ + /* 5*/ { BARCODE_CODABAR, 2, "A123456A", "A123456$A" }, /* Check included */ + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + testStartSymbol("test_hrt", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + char *data; + int ret; + int expected_rows; + int expected_width; + const char *expected_errtxt; + int bwipp_cmp; + const char *comment; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODABAR, "A1234B", 0, 1, 62, "", 1, "" }, + /* 1*/ { BARCODE_CODABAR, "1234B", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 358: Does not begin with \"A\", \"B\", \"C\" or \"D\"", 1, "" }, + /* 2*/ { BARCODE_CODABAR, "A1234", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 359: Does not end with \"A\", \"B\", \"C\" or \"D\"", 1, "" }, + /* 3*/ { BARCODE_CODABAR, "A1234E", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 359: Does not end with \"A\", \"B\", \"C\" or \"D\"", 1, "" }, + /* 4*/ { BARCODE_CODABAR, "C123.D", 0, 1, 63, "", 1, "" }, + /* 5*/ { BARCODE_CODABAR, "C123,D", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 357: Invalid character at position 5 in input (\"0123456789-$:/.+ABCD\" only)", 1, "" }, + /* 6*/ { BARCODE_CODABAR, "D:C", 0, 1, 33, "", 1, "" }, + /* 7*/ { BARCODE_CODABAR, "DCC", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 363: Invalid character at position 1 in input (cannot contain \"A\", \"B\", \"C\" or \"D\")", 1, "" }, + /* 8*/ { BARCODE_CODABAR, "A234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123B", ZINT_ERROR_TOO_LONG, -1, -1, "Error 356: Input length 104 too long (maximum 103)", 1, "" }, + /* 9*/ { BARCODE_CODABAR, "AB", ZINT_ERROR_TOO_LONG, -1, -1, "Error 362: Input length 2 too short (minimum 3)", 1, "" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + char cmp_buf[8192]; + char cmp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */ + + testStartSymbol("test_input", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d symbol->errtxt %s != %s\n", i, symbol->errtxt, data[i].expected_errtxt); + + if (ret < ZINT_ERROR) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { + if (!data[i].bwipp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else { + char modules_dump[4096]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf), NULL); + assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilBwippCmp(symbol, cmp_msg, cmp_buf, modules_dump); + assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", + i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_buf, modules_dump); + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_encode(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + char *expected; + }; + static const struct item data[] = { + /* 0*/ { BARCODE_CODABAR, -1, "A37859B", 0, 1, 72, "BS EN 798:1995 Figure 1", + "101100100101100101010100101101010011010101101010010110100101010010010110" + }, + /* 1*/ { BARCODE_CODABAR, -1, "A0123456789-$:/.+D", 0, 1, 186, "Verified manually against tec-it", + "101100100101010100110101011001010100101101100101010101101001011010100101001010110100101101010011010101101001010101001101010110010101101011011011011010110110110110101011011011010100110010" + }, + /* 2*/ { BARCODE_CODABAR, 1, "A1B", 0, 1, 43, "Verified manually against tec-it", + "1011001001010101100101101101101010010010110" + }, + /* 3*/ { BARCODE_CODABAR, 1, "A+B", 0, 1, 43, "Verified manually against tec-it", + "1011001001010110110110101010011010010010110" + }, + /* 4*/ { BARCODE_CODABAR, 1, "B0123456789-$:/.+B", 0, 1, 196, "Verified manually against tec-it", + "1001001011010101001101010110010101001011011001010101011010010110101001010010101101001011010100110101011010010101010011010101100101011010110110110110101101101101101010110110110100101011010010010110" + }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + char escaped[1024]; + char cmp_buf[8192]; + char cmp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */ + int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); /* Only do ZXing-C++ test if asked, too slow otherwise */ + + testStartSymbol("test_encode", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (p_ctx->generate) { + printf(" /*%3d*/ { %s, %d, \"%s\", %s, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); + + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf), NULL); + assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilBwippCmp(symbol, cmp_msg, cmp_buf, data[i].expected); + assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", + i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_buf, data[i].expected); + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data[i].data, length, debug)) { + int cmp_len, ret_len; + char modules_dump[8192 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, data[i].data, length, modules_dump, cmp_buf, sizeof(cmp_buf), &cmp_len); + assert_zero(ret, "i:%d %s testUtilZXingCPP ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilZXingCPPCmp(symbol, cmp_msg, cmp_buf, cmp_len, data[i].data, length, NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmp %d != 0 %s\n actual: %.*s\nexpected: %.*s\n", + i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_len, cmp_buf, ret_len, escaped); + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +int main(int argc, char *argv[]) { + + testFunction funcs[] = { /* name, func */ + { "test_large", test_large }, + { "test_hrt", test_hrt }, + { "test_input", test_input }, + { "test_encode", test_encode }, + }; + + testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); + + testReport(); + + return 0; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_code.c b/backend/tests/test_code.c index 3f3f4655..09af49a5 100644 --- a/backend/tests/test_code.c +++ b/backend/tests/test_code.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020-2024 Robin Stuart + Copyright (C) 2020-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -46,34 +46,28 @@ static void test_large(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODE11, -1, "13", 140, 0, 1, 1151, "" }, /* 8 (Start) + 140*8 + 2*8 (Checks) + 7 (Stop) == 1151 */ - /* 1*/ { BARCODE_CODE11, -1, "13", 141, ZINT_ERROR_TOO_LONG, -1, -1, "Error 320: Input length 141 too long (maximum 140)" }, - /* 2*/ { BARCODE_CODE39, -1, "1", 86, 0, 1, 1143, "" }, /* 13 (Start) + 86*13 + 12 (Stop) == 1143 */ - /* 3*/ { BARCODE_CODE39, -1, "1", 87, ZINT_ERROR_TOO_LONG, -1, -1, "Error 323: Input length 87 too long (maximum 86)" }, - /* 4*/ { BARCODE_EXCODE39, -1, "1", 86, 0, 1, 1143, "" }, - /* 5*/ { BARCODE_EXCODE39, -1, "1", 87, ZINT_ERROR_TOO_LONG, -1, -1, "Error 328: Input length 87 too long (maximum 86)" }, - /* 6*/ { BARCODE_EXCODE39, -1, "a", 43, 0, 1, 1143, "" }, /* Takes 2 encoding chars per char */ - /* 7*/ { BARCODE_EXCODE39, -1, "a", 44, ZINT_ERROR_TOO_LONG, -1, -1, "Error 317: Input too long, requires 88 symbol characters (maximum 86)" }, - /* 8*/ { BARCODE_EXCODE39, -1, "a", 86, ZINT_ERROR_TOO_LONG, -1, -1, "Error 317: Input too long, requires 172 symbol characters (maximum 86)" }, - /* 9*/ { BARCODE_LOGMARS, -1, "1", 30, 0, 1, 511, "" }, /* 16 (Start) + 30*16 + 15 (Stop) == 511 */ - /* 10*/ { BARCODE_LOGMARS, -1, "1", 31, ZINT_ERROR_TOO_LONG, -1, -1, "Error 322: Input length 31 too long (maximum 30)" }, - /* 11*/ { BARCODE_CODE93, -1, "1", 123, 0, 1, 1144, "" }, /* 9 (Start) + 123*9 + 2*9 (Checks) + 10 (Stop) == 1144 */ - /* 12*/ { BARCODE_CODE93, -1, "1", 124, ZINT_ERROR_TOO_LONG, -1, -1, "Error 330: Input length 124 too long (maximum 123)" }, - /* 13*/ { BARCODE_CODE93, -1, "a", 61, 0, 1, 1135, "" }, /* Takes 2 encoding chars per char */ - /* 14*/ { BARCODE_CODE93, -1, "a", 62, ZINT_ERROR_TOO_LONG, -1, -1, "Error 332: Input too long, requires 124 symbol characters (maximum 123)" }, - /* 15*/ { BARCODE_CODE93, -1, "a", 124, ZINT_ERROR_TOO_LONG, -1, -1, "Error 330: Input length 124 too long (maximum 123)" }, - /* 16*/ { BARCODE_CODE93, -1, "a1", 82, 0, 1, 1144, "" }, /* Takes 1.5 encoding chars (1.5*82 == 123) */ - /* 17*/ { BARCODE_CODE93, -1, "a1", 83, ZINT_ERROR_TOO_LONG, -1, -1, "Error 332: Input too long, requires 125 symbol characters (maximum 123)" }, - /* 18*/ { BARCODE_PZN, -1, "1", 7, 0, 1, 142, "" }, /* Takes 8 with correct check digit */ - /* 19*/ { BARCODE_PZN, -1, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1, "Error 325: Input length 9 too long (maximum 8)" }, - /* 20*/ { BARCODE_PZN, 1, "1", 6, 0, 1, 129, "" }, /* PZN7 takes 7 with correct check digit */ - /* 21*/ { BARCODE_PZN, 1, "1", 8, ZINT_ERROR_TOO_LONG, -1, -1, "Error 325: Input length 8 too long (maximum 7)" }, - /* 22*/ { BARCODE_VIN, -1, "1", 17, 0, 1, 246, "" }, - /* 23*/ { BARCODE_VIN, -1, "1", 18, ZINT_ERROR_TOO_LONG, -1, -1, "Error 336: Input length 18 wrong (17 only)" }, - /* 24*/ { BARCODE_VIN, -1, "1", 16, ZINT_ERROR_TOO_LONG, -1, -1, "Error 336: Input length 16 wrong (17 only)" }, - /* 25*/ { BARCODE_VIN, 1, "1", 17, 0, 1, 259, "" }, - /* 26*/ { BARCODE_HIBC_39, -1, "1", 68, 0, 1, 1151, "" }, /* 70 - 2 ('+' and check digit) */ - /* 27*/ { BARCODE_HIBC_39, -1, "1", 69, ZINT_ERROR_TOO_LONG, -1, -1, "Error 319: Input length 69 too long (maximum 68)" }, + /* 0*/ { BARCODE_CODE39, -1, "1", 86, 0, 1, 1143, "" }, /* 13 (Start) + 86*13 + 12 (Stop) == 1143 */ + /* 1*/ { BARCODE_CODE39, -1, "1", 87, ZINT_ERROR_TOO_LONG, -1, -1, "Error 323: Input length 87 too long (maximum 86)" }, + /* 2*/ { BARCODE_EXCODE39, -1, "1", 86, 0, 1, 1143, "" }, + /* 3*/ { BARCODE_EXCODE39, -1, "1", 87, ZINT_ERROR_TOO_LONG, -1, -1, "Error 328: Input length 87 too long (maximum 86)" }, + /* 4*/ { BARCODE_EXCODE39, -1, "a", 43, 0, 1, 1143, "" }, /* Takes 2 encoding chars per char */ + /* 5*/ { BARCODE_EXCODE39, -1, "a", 44, ZINT_ERROR_TOO_LONG, -1, -1, "Error 317: Input too long, requires 88 symbol characters (maximum 86)" }, + /* 6*/ { BARCODE_EXCODE39, -1, "a", 86, ZINT_ERROR_TOO_LONG, -1, -1, "Error 317: Input too long, requires 172 symbol characters (maximum 86)" }, + /* 7*/ { BARCODE_LOGMARS, -1, "1", 30, 0, 1, 511, "" }, /* 16 (Start) + 30*16 + 15 (Stop) == 511 */ + /* 8*/ { BARCODE_LOGMARS, -1, "1", 31, ZINT_ERROR_TOO_LONG, -1, -1, "Error 322: Input length 31 too long (maximum 30)" }, + /* 9*/ { BARCODE_CODE93, -1, "1", 123, 0, 1, 1144, "" }, /* 9 (Start) + 123*9 + 2*9 (Checks) + 10 (Stop) == 1144 */ + /* 10*/ { BARCODE_CODE93, -1, "1", 124, ZINT_ERROR_TOO_LONG, -1, -1, "Error 330: Input length 124 too long (maximum 123)" }, + /* 11*/ { BARCODE_CODE93, -1, "a", 61, 0, 1, 1135, "" }, /* Takes 2 encoding chars per char */ + /* 12*/ { BARCODE_CODE93, -1, "a", 62, ZINT_ERROR_TOO_LONG, -1, -1, "Error 332: Input too long, requires 124 symbol characters (maximum 123)" }, + /* 13*/ { BARCODE_CODE93, -1, "a", 124, ZINT_ERROR_TOO_LONG, -1, -1, "Error 330: Input length 124 too long (maximum 123)" }, + /* 14*/ { BARCODE_CODE93, -1, "a1", 82, 0, 1, 1144, "" }, /* Takes 1.5 encoding chars (1.5*82 == 123) */ + /* 15*/ { BARCODE_CODE93, -1, "a1", 83, ZINT_ERROR_TOO_LONG, -1, -1, "Error 332: Input too long, requires 125 symbol characters (maximum 123)" }, + /* 16*/ { BARCODE_VIN, -1, "1", 17, 0, 1, 246, "" }, + /* 17*/ { BARCODE_VIN, -1, "1", 18, ZINT_ERROR_TOO_LONG, -1, -1, "Error 336: Input length 18 wrong (17 only)" }, + /* 18*/ { BARCODE_VIN, -1, "1", 16, ZINT_ERROR_TOO_LONG, -1, -1, "Error 336: Input length 16 wrong (17 only)" }, + /* 19*/ { BARCODE_VIN, 1, "1", 17, 0, 1, 259, "" }, + /* 20*/ { BARCODE_HIBC_39, -1, "1", 68, 0, 1, 1151, "" }, /* 70 - 2 ('+' and check digit) */ + /* 21*/ { BARCODE_HIBC_39, -1, "1", 69, ZINT_ERROR_TOO_LONG, -1, -1, "Error 319: Input length 69 too long (maximum 68)" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -124,48 +118,36 @@ static void test_hrt(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODE11, -1, "123-45", -1, "123-4552" }, /* 2 checksums */ - /* 1*/ { BARCODE_CODE11, 1, "123-45", -1, "123-455" }, /* 1 check digit */ - /* 2*/ { BARCODE_CODE11, 2, "123-45", -1, "123-45" }, /* No checksums */ - /* 3*/ { BARCODE_CODE11, -1, "123456789012", -1, "123456789012-8" }, /* First check digit 10 (A) goes to hyphen */ - /* 4*/ { BARCODE_CODE39, -1, "ABC1234", -1, "*ABC1234*" }, - /* 5*/ { BARCODE_CODE39, 1, "ABC1234", -1, "*ABC12340*" }, /* With visible check digit */ - /* 6*/ { BARCODE_CODE39, -1, "abc1234", -1, "*ABC1234*" }, /* Converts to upper */ - /* 7*/ { BARCODE_CODE39, 1, "abc1234", -1, "*ABC12340*" }, /* Converts to upper */ - /* 8*/ { BARCODE_CODE39, -1, "123456789", -1, "*123456789*" }, - /* 9*/ { BARCODE_CODE39, 1, "123456789", -1, "*1234567892*" }, /* With visible check digit */ - /* 10*/ { BARCODE_CODE39, 2, "123456789", -1, "*123456789*" }, /* With hidden check digit */ - /* 11*/ { BARCODE_EXCODE39, -1, "ABC1234", -1, "ABC1234" }, - /* 12*/ { BARCODE_EXCODE39, 1, "ABC1234", -1, "ABC12340" }, /* With visible check digit */ - /* 13*/ { BARCODE_EXCODE39, -1, "abc1234", -1, "abc1234" }, - /* 14*/ { BARCODE_EXCODE39, 1, "abc1234", -1, "abc1234." }, /* With visible check digit (previously was hidden) */ - /* 15*/ { BARCODE_EXCODE39, 2, "abc1234", -1, "abc1234" }, /* With hidden check digit */ - /* 16*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~" }, /* NUL, ctrls and DEL replaced with spaces */ - /* 17*/ { BARCODE_EXCODE39, 1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~L" }, /* With visible check digit */ - /* 18*/ { BARCODE_EXCODE39, 2, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~" }, /* With hidden check digit */ - /* 19*/ { BARCODE_LOGMARS, -1, "ABC1234", -1, "ABC1234" }, - /* 20*/ { BARCODE_LOGMARS, -1, "abc1234", -1, "ABC1234" }, /* Converts to upper */ - /* 21*/ { BARCODE_LOGMARS, 1, "abc1234", -1, "ABC12340" }, /* With check digit */ - /* 22*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, "12345/ABCDET" }, /* With visible check digit */ - /* 23*/ { BARCODE_LOGMARS, 2, "12345/ABCDE", -1, "12345/ABCDE" }, /* With hidden check digit */ - /* 24*/ { BARCODE_CODE93, -1, "ABC1234", -1, "ABC1234" }, /* No longer shows 2 check chars added (same as BWIPP and TEC-IT) */ - /* 25*/ { BARCODE_CODE93, 1, "ABC1234", -1, "ABC1234S5" }, /* Unless requested */ - /* 26*/ { BARCODE_CODE93, -1, "abc1234", -1, "abc1234" }, - /* 27*/ { BARCODE_CODE93, 1, "abc1234", -1, "abc1234ZG" }, - /* 28*/ { BARCODE_CODE93, -1, "A\001a\000b\177d\037e", 9, "A a b d e" }, /* NUL, ctrls and DEL replaced with spaces */ - /* 29*/ { BARCODE_PZN, -1, "12345", -1, "PZN - 00123458" }, /* Pads with zeroes if length < 7 */ - /* 30*/ { BARCODE_PZN, -1, "123456", -1, "PZN - 01234562" }, - /* 31*/ { BARCODE_PZN, -1, "1234567", -1, "PZN - 12345678" }, - /* 32*/ { BARCODE_PZN, -1, "12345678", -1, "PZN - 12345678" }, - /* 33*/ { BARCODE_PZN, 1, "1234", -1, "PZN - 0012345" }, /* PZN7, pads with zeroes if length < 6 */ - /* 34*/ { BARCODE_PZN, 1, "12345", -1, "PZN - 0123458" }, - /* 35*/ { BARCODE_PZN, 1, "123456", -1, "PZN - 1234562" }, - /* 36*/ { BARCODE_PZN, 1, "1234562", -1, "PZN - 1234562" }, - /* 37*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, "1FTCR10UXTPA78180" }, - /* 38*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, "2FTPX28L0XCA15511" }, /* Include Import char - no change */ - /* 39*/ { BARCODE_HIBC_39, -1, "ABC1234", -1, "*+ABC1234+*" }, - /* 40*/ { BARCODE_HIBC_39, -1, "abc1234", -1, "*+ABC1234+*" }, /* Converts to upper */ - /* 41*/ { BARCODE_HIBC_39, -1, "123456789", -1, "*+1234567890*" }, + /* 0*/ { BARCODE_CODE39, -1, "ABC1234", -1, "*ABC1234*" }, + /* 1*/ { BARCODE_CODE39, 1, "ABC1234", -1, "*ABC12340*" }, /* With visible check digit */ + /* 2*/ { BARCODE_CODE39, -1, "abc1234", -1, "*ABC1234*" }, /* Converts to upper */ + /* 3*/ { BARCODE_CODE39, 1, "abc1234", -1, "*ABC12340*" }, /* Converts to upper */ + /* 4*/ { BARCODE_CODE39, -1, "123456789", -1, "*123456789*" }, + /* 5*/ { BARCODE_CODE39, 1, "123456789", -1, "*1234567892*" }, /* With visible check digit */ + /* 6*/ { BARCODE_CODE39, 2, "123456789", -1, "*123456789*" }, /* With hidden check digit */ + /* 7*/ { BARCODE_EXCODE39, -1, "ABC1234", -1, "ABC1234" }, + /* 8*/ { BARCODE_EXCODE39, 1, "ABC1234", -1, "ABC12340" }, /* With visible check digit */ + /* 9*/ { BARCODE_EXCODE39, -1, "abc1234", -1, "abc1234" }, + /* 10*/ { BARCODE_EXCODE39, 1, "abc1234", -1, "abc1234." }, /* With visible check digit (previously was hidden) */ + /* 11*/ { BARCODE_EXCODE39, 2, "abc1234", -1, "abc1234" }, /* With hidden check digit */ + /* 12*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~" }, /* NUL, ctrls and DEL replaced with spaces */ + /* 13*/ { BARCODE_EXCODE39, 1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~L" }, /* With visible check digit */ + /* 14*/ { BARCODE_EXCODE39, 2, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~" }, /* With hidden check digit */ + /* 15*/ { BARCODE_LOGMARS, -1, "ABC1234", -1, "ABC1234" }, + /* 16*/ { BARCODE_LOGMARS, -1, "abc1234", -1, "ABC1234" }, /* Converts to upper */ + /* 17*/ { BARCODE_LOGMARS, 1, "abc1234", -1, "ABC12340" }, /* With check digit */ + /* 18*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, "12345/ABCDET" }, /* With visible check digit */ + /* 19*/ { BARCODE_LOGMARS, 2, "12345/ABCDE", -1, "12345/ABCDE" }, /* With hidden check digit */ + /* 20*/ { BARCODE_CODE93, -1, "ABC1234", -1, "ABC1234" }, /* No longer shows 2 check chars added (same as BWIPP and TEC-IT) */ + /* 21*/ { BARCODE_CODE93, 1, "ABC1234", -1, "ABC1234S5" }, /* Unless requested */ + /* 22*/ { BARCODE_CODE93, -1, "abc1234", -1, "abc1234" }, + /* 23*/ { BARCODE_CODE93, 1, "abc1234", -1, "abc1234ZG" }, + /* 24*/ { BARCODE_CODE93, -1, "A\001a\000b\177d\037e", 9, "A a b d e" }, /* NUL, ctrls and DEL replaced with spaces */ + /* 25*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, "1FTCR10UXTPA78180" }, + /* 26*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, "2FTPX28L0XCA15511" }, /* Include Import char - no change */ + /* 27*/ { BARCODE_HIBC_39, -1, "ABC1234", -1, "*+ABC1234+*" }, + /* 28*/ { BARCODE_HIBC_39, -1, "abc1234", -1, "*+ABC1234+*" }, /* Converts to upper */ + /* 29*/ { BARCODE_HIBC_39, -1, "123456789", -1, "*+1234567890*" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -209,74 +191,59 @@ static void test_input(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODE11, -1, -1, "-", -1, 0, 1, 37, "" }, - /* 1*/ { BARCODE_CODE11, -1, -1, "0123456789-", -1, 0, 1, 115, "" }, - /* 2*/ { BARCODE_CODE11, -1, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 1 in input (digits and \"-\" only)" }, - /* 3*/ { BARCODE_CODE11, -1, -1, "12+", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 3 in input (digits and \"-\" only)" }, - /* 4*/ { BARCODE_CODE11, -1, -1, "1.2", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 2 in input (digits and \"-\" only)" }, - /* 5*/ { BARCODE_CODE11, -1, -1, "12!", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 3 in input (digits and \"-\" only)" }, - /* 6*/ { BARCODE_CODE11, -1, -1, " ", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 1 in input (digits and \"-\" only)" }, - /* 7*/ { BARCODE_CODE11, ESCAPE_MODE, -1, "\\d048 ", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 2 in input (digits and \"-\" only)" }, /* Note position doesn't account for escape sequences */ - /* 8*/ { BARCODE_CODE11, -1, 3, "1", -1, ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 339: Invalid check digit version '3' (1 or 2 only)" }, - /* 9*/ { BARCODE_CODE39, -1, -1, "a", -1, 0, 1, 38, "" }, /* Converts to upper */ - /* 10*/ { BARCODE_CODE39, -1, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584, "" }, - /* 11*/ { BARCODE_CODE39, -1, -1, "AB!", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 3 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 12*/ { BARCODE_CODE39, -1, -1, "A\"B", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 2 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 13*/ { BARCODE_CODE39, -1, -1, "#AB", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 14*/ { BARCODE_CODE39, -1, -1, "&", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 15*/ { BARCODE_CODE39, -1, -1, "'", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 16*/ { BARCODE_CODE39, -1, -1, "(", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 17*/ { BARCODE_CODE39, -1, -1, ")", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 18*/ { BARCODE_CODE39, -1, -1, "*", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 19*/ { BARCODE_CODE39, -1, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 20*/ { BARCODE_CODE39, -1, -1, ":", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 21*/ { BARCODE_CODE39, -1, -1, "@", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 22*/ { BARCODE_CODE39, -1, -1, "[", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 23*/ { BARCODE_CODE39, -1, -1, "`", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 24*/ { BARCODE_CODE39, -1, -1, "{", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 25*/ { BARCODE_CODE39, -1, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 26*/ { BARCODE_CODE39, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 27*/ { BARCODE_CODE39, -1, 0, "1", -1, 0, 1, 38, "" }, - /* 28*/ { BARCODE_CODE39, -1, 1, "1", -1, 0, 1, 51, "" }, /* Check digit */ - /* 29*/ { BARCODE_CODE39, -1, 2, "1", -1, 0, 1, 51, "" }, /* Hidden check digit */ - /* 30*/ { BARCODE_CODE39, -1, 3, "1", -1, 0, 1, 38, "" }, /* option_2 > 2 ignored */ - /* 31*/ { BARCODE_EXCODE39, -1, -1, "A", -1, 0, 1, 38, "" }, - /* 32*/ { BARCODE_EXCODE39, -1, 3, "A", -1, 0, 1, 38, "" }, /* option_2 > 2 ignored */ - /* 33*/ { BARCODE_EXCODE39, -1, -1, "a", -1, 0, 1, 51, "" }, - /* 34*/ { BARCODE_EXCODE39, -1, -1, ",", -1, 0, 1, 51, "" }, - /* 35*/ { BARCODE_EXCODE39, -1, -1, "\000", 1, 0, 1, 51, "" }, - /* 36*/ { BARCODE_EXCODE39, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 329: Invalid character at position 1 in input, extended ASCII not allowed" }, - /* 37*/ { BARCODE_EXCODE39, -1, -1, "ABCDé", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 329: Invalid character at position 5 in input, extended ASCII not allowed" }, - /* 38*/ { BARCODE_LOGMARS, -1, -1, "A", -1, 0, 1, 47, "" }, - /* 39*/ { BARCODE_LOGMARS, -1, -1, "a", -1, 0, 1, 47, "" }, - /* 40*/ { BARCODE_LOGMARS, -1, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 41*/ { BARCODE_LOGMARS, -1, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 42*/ { BARCODE_LOGMARS, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 43*/ { BARCODE_LOGMARS, -1, 3, "A", -1, 0, 1, 47, "" }, /* option_2 > 2 ignored */ - /* 44*/ { BARCODE_CODE93, -1, -1, "A", -1, 0, 1, 46, "" }, - /* 45*/ { BARCODE_CODE93, -1, -1, "a", -1, 0, 1, 55, "" }, - /* 46*/ { BARCODE_CODE93, -1, -1, ",", -1, 0, 1, 55, "" }, - /* 47*/ { BARCODE_CODE93, -1, -1, "\000", 1, 0, 1, 55, "" }, - /* 48*/ { BARCODE_CODE93, -1, -1, "12\3004", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 331: Invalid character at position 3 in input, extended ASCII not allowed" }, - /* 49*/ { BARCODE_CODE93, -1, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 331: Invalid character at position 1 in input, extended ASCII not allowed" }, - /* 50*/ { BARCODE_PZN, -1, -1, "1", -1, 0, 1, 142, "" }, - /* 51*/ { BARCODE_PZN, -1, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 326: Invalid character at position 1 in input (digits only)" }, - /* 52*/ { BARCODE_PZN, -1, -1, "1000006", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 327: Invalid PZN, check digit is '10'" }, /* Check digit == 10 so can't be used */ - /* 53*/ { BARCODE_PZN, -1, -1, "00000011", -1, ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 890: Invalid check digit '1', expecting '7'" }, - /* 54*/ { BARCODE_PZN, -1, 1, "100009", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 327: Invalid PZN, check digit is '10'" }, /* Check digit == 10 so can't be used */ - /* 55*/ { BARCODE_PZN, -1, 1, "0000011", -1, ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 890: Invalid check digit '1', expecting '7'" }, - /* 56*/ { BARCODE_VIN, -1, -1, "5GZCZ43D13S812715", -1, 0, 1, 246, "" }, - /* 57*/ { BARCODE_VIN, -1, -1, "5GZCZ43D23S812715", -1, ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 338: Invalid check digit '2' (position 9), expecting '1'" }, /* North American with invalid check character */ - /* 58*/ { BARCODE_VIN, -1, -1, "WP0ZZZ99ZTS392124", -1, 0, 1, 246, "" }, /* Not North American so no check */ - /* 59*/ { BARCODE_VIN, -1, -1, "WP0ZZZ99ZTS392I24", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 337: Invalid character at position 15 in input (alphanumerics only, excluding \"IOQ\")" }, /* I not allowed */ - /* 60*/ { BARCODE_VIN, -1, -1, "WPOZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 337: Invalid character at position 3 in input (alphanumerics only, excluding \"IOQ\")" }, /* O not allowed */ - /* 61*/ { BARCODE_VIN, -1, -1, "WPQZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 337: Invalid character at position 3 in input (alphanumerics only, excluding \"IOQ\")" }, /* Q not allowed */ - /* 62*/ { BARCODE_HIBC_39, -1, -1, "a", -1, 0, 1, 79, "" }, /* Converts to upper */ - /* 63*/ { BARCODE_HIBC_39, -1, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 64*/ { BARCODE_HIBC_39, -1, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 65*/ { BARCODE_HIBC_39, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, - /* 66*/ { BARCODE_HIBC_39, -1, 1, "a", -1, 0, 1, 79, "" }, /* option_2 ignored */ - /* 67*/ { BARCODE_HIBC_39, -1, 2, "a", -1, 0, 1, 79, "" }, /* option_2 ignored */ + /* 0*/ { BARCODE_CODE39, -1, -1, "a", -1, 0, 1, 38, "" }, /* Converts to upper */ + /* 1*/ { BARCODE_CODE39, -1, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584, "" }, + /* 2*/ { BARCODE_CODE39, -1, -1, "AB!", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 3 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 3*/ { BARCODE_CODE39, -1, -1, "A\"B", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 2 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 4*/ { BARCODE_CODE39, -1, -1, "#AB", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 5*/ { BARCODE_CODE39, -1, -1, "&", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 6*/ { BARCODE_CODE39, -1, -1, "'", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 7*/ { BARCODE_CODE39, -1, -1, "(", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 8*/ { BARCODE_CODE39, -1, -1, ")", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 9*/ { BARCODE_CODE39, -1, -1, "*", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 10*/ { BARCODE_CODE39, -1, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 11*/ { BARCODE_CODE39, -1, -1, ":", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 12*/ { BARCODE_CODE39, -1, -1, "@", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 13*/ { BARCODE_CODE39, -1, -1, "[", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 14*/ { BARCODE_CODE39, -1, -1, "`", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 15*/ { BARCODE_CODE39, -1, -1, "{", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 16*/ { BARCODE_CODE39, -1, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 17*/ { BARCODE_CODE39, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 18*/ { BARCODE_CODE39, -1, 0, "1", -1, 0, 1, 38, "" }, + /* 19*/ { BARCODE_CODE39, -1, 1, "1", -1, 0, 1, 51, "" }, /* Check digit */ + /* 20*/ { BARCODE_CODE39, -1, 2, "1", -1, 0, 1, 51, "" }, /* Hidden check digit */ + /* 21*/ { BARCODE_CODE39, -1, 3, "1", -1, 0, 1, 38, "" }, /* option_2 > 2 ignored */ + /* 22*/ { BARCODE_EXCODE39, -1, -1, "A", -1, 0, 1, 38, "" }, + /* 23*/ { BARCODE_EXCODE39, -1, 3, "A", -1, 0, 1, 38, "" }, /* option_2 > 2 ignored */ + /* 24*/ { BARCODE_EXCODE39, -1, -1, "a", -1, 0, 1, 51, "" }, + /* 25*/ { BARCODE_EXCODE39, -1, -1, ",", -1, 0, 1, 51, "" }, + /* 26*/ { BARCODE_EXCODE39, -1, -1, "\000", 1, 0, 1, 51, "" }, + /* 27*/ { BARCODE_EXCODE39, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 329: Invalid character at position 1 in input, extended ASCII not allowed" }, + /* 28*/ { BARCODE_EXCODE39, -1, -1, "ABCDé", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 329: Invalid character at position 5 in input, extended ASCII not allowed" }, + /* 29*/ { BARCODE_LOGMARS, -1, -1, "A", -1, 0, 1, 47, "" }, + /* 30*/ { BARCODE_LOGMARS, -1, -1, "a", -1, 0, 1, 47, "" }, + /* 31*/ { BARCODE_LOGMARS, -1, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 32*/ { BARCODE_LOGMARS, -1, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 33*/ { BARCODE_LOGMARS, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 324: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 34*/ { BARCODE_LOGMARS, -1, 3, "A", -1, 0, 1, 47, "" }, /* option_2 > 2 ignored */ + /* 35*/ { BARCODE_CODE93, -1, -1, "A", -1, 0, 1, 46, "" }, + /* 36*/ { BARCODE_CODE93, -1, -1, "a", -1, 0, 1, 55, "" }, + /* 37*/ { BARCODE_CODE93, -1, -1, ",", -1, 0, 1, 55, "" }, + /* 38*/ { BARCODE_CODE93, -1, -1, "\000", 1, 0, 1, 55, "" }, + /* 39*/ { BARCODE_CODE93, -1, -1, "12\3004", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 331: Invalid character at position 3 in input, extended ASCII not allowed" }, + /* 40*/ { BARCODE_CODE93, -1, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 331: Invalid character at position 1 in input, extended ASCII not allowed" }, + /* 41*/ { BARCODE_VIN, -1, -1, "5GZCZ43D13S812715", -1, 0, 1, 246, "" }, + /* 42*/ { BARCODE_VIN, -1, -1, "5GZCZ43D23S812715", -1, ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 338: Invalid check digit '2' (position 9), expecting '1'" }, /* North American with invalid check character */ + /* 43*/ { BARCODE_VIN, -1, -1, "WP0ZZZ99ZTS392124", -1, 0, 1, 246, "" }, /* Not North American so no check */ + /* 44*/ { BARCODE_VIN, -1, -1, "WP0ZZZ99ZTS392I24", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 337: Invalid character at position 15 in input (alphanumerics only, excluding \"IOQ\")" }, /* I not allowed */ + /* 45*/ { BARCODE_VIN, -1, -1, "WPOZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 337: Invalid character at position 3 in input (alphanumerics only, excluding \"IOQ\")" }, /* O not allowed */ + /* 46*/ { BARCODE_VIN, -1, -1, "WPQZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 337: Invalid character at position 3 in input (alphanumerics only, excluding \"IOQ\")" }, /* Q not allowed */ + /* 47*/ { BARCODE_HIBC_39, -1, -1, "a", -1, 0, 1, 79, "" }, /* Converts to upper */ + /* 48*/ { BARCODE_HIBC_39, -1, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 49*/ { BARCODE_HIBC_39, -1, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 50*/ { BARCODE_HIBC_39, -1, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 203: Invalid character at position 1 in input (alphanumerics, space and \"-.$/+%\" only)" }, + /* 51*/ { BARCODE_HIBC_39, -1, 1, "a", -1, 0, 1, 79, "" }, /* option_2 ignored */ + /* 52*/ { BARCODE_HIBC_39, -1, 2, "a", -1, 0, 1, 79, "" }, /* option_2 ignored */ }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -325,133 +292,106 @@ static void test_encode(const testCtx *const p_ctx) { char *expected; }; static const struct item data[] = { - /* 0*/ { BARCODE_CODE11, -1, "123-45", -1, 0, 1, 78, "2 check digits (52); verified manually against TEC-IT", - "101100101101011010010110110010101011010101101101101101011011010100101101011001" - }, - /* 1*/ { BARCODE_CODE11, -1, "93", -1, 0, 1, 44, "2 check digits (--); verified manually against TEC-IT", - "10110010110101011001010101101010110101011001" - }, - /* 2*/ { BARCODE_CODE11, 1, "123-455", -1, 0, 1, 78, "1 check digit (2); verified manually against TEC-IT", - "101100101101011010010110110010101011010101101101101101011011010100101101011001" - }, - /* 3*/ { BARCODE_CODE11, 2, "123-4552", -1, 0, 1, 78, "0 check digits; verified manually against TEC-IT", - "101100101101011010010110110010101011010101101101101101011011010100101101011001" - }, - /* 4*/ { BARCODE_CODE11, 1, "123-45", -1, 0, 1, 70, "1 check digit; verified manually against TEC-IT", - "1011001011010110100101101100101010110101011011011011010110110101011001" - }, - /* 5*/ { BARCODE_CODE11, 2, "123-45", -1, 0, 1, 62, "0 check digits; verified manually against TEC-IT", - "10110010110101101001011011001010101101010110110110110101011001" - }, - /* 6*/ { BARCODE_CODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", + /* 0*/ { BARCODE_CODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", "100101101101011010010101101101010010110100101101101" }, - /* 7*/ { BARCODE_CODE39, 1, "1A", -1, 0, 1, 64, "With check digit (B)", + /* 1*/ { BARCODE_CODE39, 1, "1A", -1, 0, 1, 64, "With check digit (B)", "1001011011010110100101011011010100101101011010010110100101101101" }, - /* 8*/ { BARCODE_CODE39, 1, "Z1", -1, 0, 1, 64, "Check digit '-'", + /* 2*/ { BARCODE_CODE39, 1, "Z1", -1, 0, 1, 64, "Check digit '-'", "1001011011010100110110101011010010101101001010110110100101101101" }, - /* 9*/ { BARCODE_CODE39, 1, "Z2", -1, 0, 1, 64, "Check digit '.'", + /* 3*/ { BARCODE_CODE39, 1, "Z2", -1, 0, 1, 64, "Check digit '.'", "1001011011010100110110101010110010101101100101011010100101101101" }, - /* 10*/ { BARCODE_CODE39, 1, "Z3", -1, 0, 1, 64, "Check digit space, displayed as underscore", + /* 4*/ { BARCODE_CODE39, 1, "Z3", -1, 0, 1, 64, "Check digit space, displayed as underscore", "1001011011010100110110101011011001010101001101011010100101101101" }, - /* 11*/ { BARCODE_CODE39, 1, "Z4", -1, 0, 1, 64, "Check digit '$'", + /* 5*/ { BARCODE_CODE39, 1, "Z4", -1, 0, 1, 64, "Check digit '$'", "1001011011010100110110101010100110101101001001001010100101101101" }, - /* 12*/ { BARCODE_CODE39, 1, "Z5", -1, 0, 1, 64, "Check digit '/'", + /* 6*/ { BARCODE_CODE39, 1, "Z5", -1, 0, 1, 64, "Check digit '/'", "1001011011010100110110101011010011010101001001010010100101101101" }, - /* 13*/ { BARCODE_CODE39, 1, "Z6", -1, 0, 1, 64, "Check digit '+'", + /* 7*/ { BARCODE_CODE39, 1, "Z6", -1, 0, 1, 64, "Check digit '+'", "1001011011010100110110101010110011010101001010010010100101101101" }, - /* 14*/ { BARCODE_CODE39, 1, "Z7", -1, 0, 1, 64, "Check digit '%'", + /* 8*/ { BARCODE_CODE39, 1, "Z7", -1, 0, 1, 64, "Check digit '%'", "1001011011010100110110101010100101101101010010010010100101101101" }, - /* 15*/ { BARCODE_CODE39, -1, "+A/E%U$A/D%T+Z", -1, 0, 1, 207, "Same as BARCODE_EXCODE39 'a%\000\001$\177z' below", + /* 9*/ { BARCODE_CODE39, -1, "+A/E%U$A/D%T+Z", -1, 0, 1, 207, "Same as BARCODE_EXCODE39 'a%\000\001$\177z' below", "100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101" }, - /* 16*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584, "Full CODE39 set", + /* 10*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584, "Full CODE39 set", "10010110110101010011011010110100101011010110010101101101100101010101001101011011010011010101011001101010101001011011011010010110101011001011010110101001011010110100101101101101001010101011001011011010110010101011011001010101010011011011010100110101011010011010101011001101011010101001101011010100110110110101001010101101001101101011010010101101101001010101011001101101010110010101101011001010101101100101100101010110100110101011011001101010101001011010110110010110101010011011010101001010110110110010101101010011010110101001001001010100100101001010010100100101010010010010100101101101" }, - /* 17*/ { BARCODE_EXCODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", + /* 11*/ { BARCODE_EXCODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", "100101101101011010010101101101010010110100101101101" }, - /* 18*/ { BARCODE_EXCODE39, 1, "1A", -1, 0, 1, 64, "With check digit", + /* 12*/ { BARCODE_EXCODE39, 1, "1A", -1, 0, 1, 64, "With check digit", "1001011011010110100101011011010100101101011010010110100101101101" }, - /* 19*/ { BARCODE_EXCODE39, 1, "Z4", -1, 0, 1, 64, "Check digit $", + /* 13*/ { BARCODE_EXCODE39, 1, "Z4", -1, 0, 1, 64, "Check digit $", "1001011011010100110110101010100110101101001001001010100101101101" }, - /* 20*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z", 7, 0, 1, 207, "Verified manually against TEC-IT", + /* 14*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z", 7, 0, 1, 207, "Verified manually against TEC-IT", "100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101" }, - /* 21*/ { BARCODE_EXCODE39, -1, "\033\037!+/\\@A~", -1, 0, 1, 246, "Verified manually against TEC-IT", + /* 15*/ { BARCODE_EXCODE39, -1, "\033\037!+/\\@A~", -1, 0, 1, 246, "Verified manually against TEC-IT", "100101101101010100100100101101010010110101001001001011010110010101001001010010110101001011010010010100101101010100110100100101001011010110100101010010010010101101010011010100100100101001101010110110101001011010100100100101011010110010100101101101" }, - /* 22*/ { BARCODE_EXCODE39, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]", -1, 0, 1, 1130, "Visible ASCII 1st 85 symbol chars", + /* 16*/ { BARCODE_EXCODE39, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]", -1, 0, 1, 1130, "Visible ASCII 1st 85 symbol chars", "10010110110101001101011010100100101001011010100101101001001010010101101001011010010010100101101101001010100100101001010101100101101001001010010110101100101010010010100101011011001010100100101001010101001101101001001010010110101001101010010010100101011010011010100100101001010101100110101001001010010110101010011010010010100101011010100110100101011011011001010110101001001010010110101101001010100110110101101001010110101100101011011011001010101010011010110110100110101010110011010101010010110110110100101101010110010110101001001010010100110110101010100100100101011011001010101001001001010101001101101010010010010110101001101010100100100101011010011010101001001001010101100110101010010010010100110101011011010100101101011010010110110110100101010101100101101101011001010101101100101010101001101101101010011010101101001101010101100110101101010100110101101010011011011010100101010110100110110101101001010110110100101010101100110110101011001010110101100101010110110010110010101011010011010101101100110101010100101101011011001011010101001101101010101001001001011010101001101010010010010101101010011010100100100101101101010010100101101101" }, - /* 23*/ { BARCODE_EXCODE39, -1, "^_`abcdefghijklmnopqrstuvwxyz{|}~", -1, 0, 1, 883, "Visible ASCII last part", + /* 17*/ { BARCODE_EXCODE39, -1, "^_`abcdefghijklmnopqrstuvwxyz{|}~", -1, 0, 1, 883, "Visible ASCII last part", "1001011011010101001001001010101101001101010010010010110101101001010100100100101100110101010100101001001011010100101101001010010010101101001011010010100100101101101001010100101001001010101100101101001010010010110101100101010010100100101011011001010100101001001010101001101101001010010010110101001101010010100100101011010011010100101001001010101100110101001010010010110101010011010010100100101011010100110100101001001011011010100101001010010010101011010011010010100100101101011010010100101001001010110110100101001010010010101010110011010010100100101101010110010100101001001010110101100101001010010010101011011001010010100100101100101010110100101001001010011010101101001010010010110011010101010010100100101001011010110100101001001011001011010101001010010010100110110101010100100100101011011010010101001001001010101011001101010010010010110101011001010100100100101011010110010100101101101" }, - /* 24*/ { BARCODE_LOGMARS, -1, "1A", -1, 0, 1, 63, "Verified manually against TEC-IT", + /* 18*/ { BARCODE_LOGMARS, -1, "1A", -1, 0, 1, 63, "Verified manually against TEC-IT", "100010111011101011101000101011101110101000101110100010111011101" }, - /* 25*/ { BARCODE_LOGMARS, 1, "1A", -1, 0, 1, 79, "With check digit; verified manually against TEC-IT", + /* 19*/ { BARCODE_LOGMARS, 1, "1A", -1, 0, 1, 79, "With check digit; verified manually against TEC-IT", "1000101110111010111010001010111011101010001011101011101000101110100010111011101" }, - /* 26*/ { BARCODE_LOGMARS, -1, "ABC", -1, 0, 1, 79, "MIL-STD-1189 Rev. B Figure 1", + /* 20*/ { BARCODE_LOGMARS, -1, "ABC", -1, 0, 1, 79, "MIL-STD-1189 Rev. B Figure 1", "1000101110111010111010100010111010111010001011101110111010001010100010111011101" }, - /* 27*/ { BARCODE_LOGMARS, -1, "SAMPLE 1", -1, 0, 1, 159, "MIL-STD-1189 Rev. B Figure 2 top", + /* 21*/ { BARCODE_LOGMARS, -1, "SAMPLE 1", -1, 0, 1, 159, "MIL-STD-1189 Rev. B Figure 2 top", "100010111011101010111010111000101110101000101110111011101010001010111011101000101011101010001110111010111000101010001110101110101110100010101110100010111011101" }, - /* 28*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, 0, 1, 223, "MIL-STD-1189 Rev. B Section 6.2.1 check character example; verified manually against TEC-IT", + /* 22*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, 0, 1, 223, "MIL-STD-1189 Rev. B Section 6.2.1 check character example; verified manually against TEC-IT", "1000101110111010111010001010111010111000101011101110111000101010101000111010111011101000111010101000100010100010111010100010111010111010001011101110111010001010101011100010111011101011100010101010111011100010100010111011101" }, - /* 29*/ { BARCODE_CODE93, -1, "C93", -1, 0, 1, 64, "ANSI/AIM BC5-1995 Figure 1; verified manually against TEC-IT", + /* 23*/ { BARCODE_CODE93, -1, "C93", -1, 0, 1, 64, "ANSI/AIM BC5-1995 Figure 1; verified manually against TEC-IT", "1010111101101000101000010101010000101101010001110110101010111101" }, - /* 30*/ { BARCODE_CODE93, -1, "CODE\01593", -1, 0, 1, 109, "ANSI/AIM BC5-1995 Figure B1; verified manually against TEC-IT", + /* 24*/ { BARCODE_CODE93, -1, "CODE\01593", -1, 0, 1, 109, "ANSI/AIM BC5-1995 Figure B1; verified manually against TEC-IT", "1010111101101000101001011001100101001100100101001001101010011001000010101010000101100101001000101101010111101" }, - /* 31*/ { BARCODE_CODE93, -1, "1A", -1, 0, 1, 55, "Verified manually against TEC-IT", + /* 25*/ { BARCODE_CODE93, -1, "1A", -1, 0, 1, 55, "Verified manually against TEC-IT", "1010111101010010001101010001101000101001110101010111101" }, - /* 32*/ { BARCODE_CODE93, -1, "TEST93", -1, 0, 1, 91, "Verified manually against TEC-IT", + /* 26*/ { BARCODE_CODE93, -1, "TEST93", -1, 0, 1, 91, "Verified manually against TEC-IT", "1010111101101001101100100101101011001101001101000010101010000101011101101001000101010111101" }, - /* 33*/ { BARCODE_CODE93, -1, "\000a\177", 3, 0, 1, 91, "Verified manually against TEC-IT", + /* 27*/ { BARCODE_CODE93, -1, "\000a\177", 3, 0, 1, 91, "Verified manually against TEC-IT", "1010111101110110101100101101001100101101010001110110101101001101011011101010010001010111101" }, - /* 34*/ { BARCODE_CODE93, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghij", -1, 0, 1, 1000, "Visible ASCII 1st 107 symbol chars", + /* 28*/ { BARCODE_CODE93, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghij", -1, 0, 1, 1000, "Visible ASCII 1st 107 symbol chars", "1010111101110100101110101101101010001110101101101001001110101101101000101110010101101011101110101101100010101110101101011010001110101101011001001110101101011000101110101101001101001011101101110101101010110001001011101110101001011011101000101001010010001010001001010000101001010001001001001001000101010100001000100101000010101110101101001110101110110101100010101110110101011010001110110101011001001110110101011000101110110101001101001110110101100110101101010001101001001101000101100101001100100101100010101011010001011001001011000101001101001000110101010110001010011001010001101001011001000101101101101001101100101101011001101001101100101101100110101011011001011001101001101101001110101110110101000110101110110101010110001110110101010011001110110101010001101110110101001011001110110101011011001001100101101010001001100101101001001001100101101000101001100101100101001001100101100100101001100101100010101001100101011010001001100101011001001001100101011000101001100101001101001010001101101001101010111101" }, - /* 35*/ { BARCODE_CODE93, -1, "klmnopqrstuvwxyz{|}~", -1, 0, 1, 397, "Visible ASCII last part", + /* 29*/ { BARCODE_CODE93, -1, "klmnopqrstuvwxyz{|}~", -1, 0, 1, 397, "Visible ASCII last part", "1010111101001100101000110101001100101010110001001100101010011001001100101010001101001100101001011001001100101000101101001100101101101001001100101101100101001100101101011001001100101101001101001100101100101101001100101100110101001100101011011001001100101011001101001100101001101101001100101001110101110110101000101101110110101101101001110110101101100101110110101101011001101001001101100101010111101" }, - /* 36*/ { BARCODE_PZN, -1, "1234567", -1, 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against TEC-IT", - "1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101" - }, - /* 37*/ { BARCODE_PZN, -1, "2758089", -1, 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against TEC-IT", - "1001011011010100101011011010110010101101010010110110110100110101011010010110101010011011010110100101101010110010110101011001011010100101101101" - }, - /* 38*/ { BARCODE_PZN, 1, "123456", -1, 0, 1, 129, "Example from BWIPP; verified manually against TEC-IT", - "100101101101010010101101101101001010110101100101011011011001010101010011010110110100110101010110011010101011001010110100101101101" - }, - /* 39*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, 0, 1, 246, "https://www.vinquery.com/img/vinbarcode/vinbarcode4.jpg", + /* 30*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, 0, 1, 246, "https://www.vinquery.com/img/vinbarcode/vinbarcode4.jpg", "100101101101011010010101101011011001010101011011001011011010010101101010110010110100101011010100110110101100101010110100101101011010101101100101011011010010110101001011010100101101101101001011010110100101011011010010110101010011011010100101101101" }, - /* 40*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, 0, 1, 259, "With Import 'I' prefix; https://www.vinquery.com/img/vinbarcode/vinbarcode1.jpg", + /* 31*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, 0, 1, 259, "With Import 'I' prefix; https://www.vinquery.com/img/vinbarcode/vinbarcode1.jpg", "1001011011010101101001101010110010101101011011001010101011011001010110110100101001011010110101100101011011010010110101011010100110101001101101010010110101101101101001010110101001011011010010101101101001101010110100110101011010010101101101001010110100101101101" }, - /* 41*/ { BARCODE_HIBC_39, -1, "A123BJC5D6E71", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 2, same", + /* 32*/ { BARCODE_HIBC_39, -1, "A123BJC5D6E71", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 2, same", "1000101110111010100010100010001011101010001011101110100010101110101110001010111011101110001010101011101000101110101011100011101011101110100010101110100011101010101011100010111010111000111010101110101110001010101000101110111011101000101011101010100011101110100010111011101" }, - /* 42*/ { BARCODE_HIBC_39, -1, "$$52001510X3G", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 6, same", + /* 33*/ { BARCODE_HIBC_39, -1, "$$52001510X3G", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 6, same", "1000101110111010100010100010001010001000100010101000100010001010111010001110101010111000101011101010001110111010101000111011101011101000101011101110100011101010111010001010111010100011101110101000101110101110111011100010101010101000111011101010111000101110100010111011101" }, }; @@ -551,8 +491,6 @@ static void test_perf(const testCtx *const p_ctx) { "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !\"#$%&'()*+,-./0123456789ABCDEFGHIJ", 0, 1, 1000, "CODE93 107 symbol chars" }, /* 3*/ { BARCODE_CODE93, -1, "123456ABCD", 0, 1, 127, "CODE93 10" }, - /* 4*/ { BARCODE_CODE11, -1, "1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-", 0, 1, 966, "CODE11 121" }, - /* 5*/ { BARCODE_CODE11, -1, "1234567890-", 0, 1, 116, "CODE11 5" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_code11.c b/backend/tests/test_code11.c new file mode 100644 index 00000000..fa92f95f --- /dev/null +++ b/backend/tests/test_code11.c @@ -0,0 +1,412 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020-2025 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. Neither the name of the project nor the names of its 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Was in "test_code.c" */ + +#include "testcommon.h" + +static void test_large(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *pattern; + int length; + int ret; + int expected_rows; + int expected_width; + char *expected_errtxt; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODE11, -1, "13", 140, 0, 1, 1151, "" }, /* 8 (Start) + 140*8 + 2*8 (Checks) + 7 (Stop) == 1151 */ + /* 1*/ { BARCODE_CODE11, -1, "13", 141, ZINT_ERROR_TOO_LONG, -1, -1, "Error 320: Input length 141 too long (maximum 140)" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + char data_buf[4096]; + + testStartSymbol("test_large", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length); + assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf)); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n", i, ret ? "set" : "empty", symbol->errtxt); + assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt); + + if (ret < ZINT_ERROR) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_hrt(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *data; + int length; + + char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODE11, -1, "123-45", -1, "123-4552" }, /* 2 checksums */ + /* 1*/ { BARCODE_CODE11, 1, "123-45", -1, "123-455" }, /* 1 check digit */ + /* 2*/ { BARCODE_CODE11, 2, "123-45", -1, "123-45" }, /* No checksums */ + /* 3*/ { BARCODE_CODE11, -1, "123456789012", -1, "123456789012-8" }, /* First check digit 10 (A) goes to hyphen */ + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + testStartSymbol("test_hrt", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int input_mode; + int option_2; + char *data; + int length; + int ret; + int expected_rows; + int expected_width; + char *expected_errtxt; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODE11, -1, -1, "-", -1, 0, 1, 37, "" }, + /* 1*/ { BARCODE_CODE11, -1, -1, "0123456789-", -1, 0, 1, 115, "" }, + /* 2*/ { BARCODE_CODE11, -1, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 1 in input (digits and \"-\" only)" }, + /* 3*/ { BARCODE_CODE11, -1, -1, "12+", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 3 in input (digits and \"-\" only)" }, + /* 4*/ { BARCODE_CODE11, -1, -1, "1.2", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 2 in input (digits and \"-\" only)" }, + /* 5*/ { BARCODE_CODE11, -1, -1, "12!", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 3 in input (digits and \"-\" only)" }, + /* 6*/ { BARCODE_CODE11, -1, -1, " ", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 1 in input (digits and \"-\" only)" }, + /* 7*/ { BARCODE_CODE11, ESCAPE_MODE, -1, "\\d048 ", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 321: Invalid character at position 2 in input (digits and \"-\" only)" }, /* Note position doesn't account for escape sequences */ + /* 8*/ { BARCODE_CODE11, -1, 3, "1", -1, ZINT_ERROR_INVALID_OPTION, -1, -1, "Error 339: Invalid check digit version '3' (1 or 2 only)" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + testStartSymbol("test_input", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n", i, ret ? "set" : "empty", symbol->errtxt); + assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt); + + if (ret < ZINT_ERROR) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_encode(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *data; + int length; + int ret; + + int expected_rows; + int expected_width; + char *comment; + char *expected; + }; + static const struct item data[] = { + /* 0*/ { BARCODE_CODE11, -1, "123-45", -1, 0, 1, 78, "2 check digits (52); verified manually against TEC-IT", + "101100101101011010010110110010101011010101101101101101011011010100101101011001" + }, + /* 1*/ { BARCODE_CODE11, -1, "93", -1, 0, 1, 44, "2 check digits (--); verified manually against TEC-IT", + "10110010110101011001010101101010110101011001" + }, + /* 2*/ { BARCODE_CODE11, 1, "123-455", -1, 0, 1, 78, "1 check digit (2); verified manually against TEC-IT", + "101100101101011010010110110010101011010101101101101101011011010100101101011001" + }, + /* 3*/ { BARCODE_CODE11, 2, "123-4552", -1, 0, 1, 78, "0 check digits; verified manually against TEC-IT", + "101100101101011010010110110010101011010101101101101101011011010100101101011001" + }, + /* 4*/ { BARCODE_CODE11, 1, "123-45", -1, 0, 1, 70, "1 check digit; verified manually against TEC-IT", + "1011001011010110100101101100101010110101011011011011010110110101011001" + }, + /* 5*/ { BARCODE_CODE11, 2, "123-45", -1, 0, 1, 62, "0 check digits; verified manually against TEC-IT", + "10110010110101101001011011001010101101010110110110110101011001" + }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + char escaped[1024]; + char cmp_buf[8192]; + char cmp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); /* Only do BWIPP test if asked, too slow otherwise */ + int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); /* Only do ZXing-C++ test if asked, too slow otherwise */ + + testStartSymbol("test_encode", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (p_ctx->generate) { + printf(" /*%3d*/ { %s, %d, \"%s\", %d, %s, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); + + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf), NULL); + assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilBwippCmp(symbol, cmp_msg, cmp_buf, data[i].expected); + assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", + i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_buf, data[i].expected); + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data[i].data, length, debug)) { + int cmp_len, ret_len; + char modules_dump[8192 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, data[i].data, length, modules_dump, cmp_buf, sizeof(cmp_buf), &cmp_len); + assert_zero(ret, "i:%d %s testUtilZXingCPP ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilZXingCPPCmp(symbol, cmp_msg, cmp_buf, cmp_len, data[i].data, length, NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmp %d != 0 %s\n actual: %.*s\nexpected: %.*s\n", + i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_len, cmp_buf, ret_len, escaped); + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +#include + +#define TEST_PERF_ITER_MILLES 5 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC) + +/* Not a real test, just performance indicator */ +static void test_perf(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + static const struct item data[] = { + /* 0*/ { BARCODE_CODE11, -1, "1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-", 0, 1, 966, "CODE11 121" }, + /* 1*/ { BARCODE_CODE11, -1, "1234567890-", 0, 1, 116, "CODE11 5" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (testContinue(p_ctx, i)) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; /* Undo */ + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (p_ctx->index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + +int main(int argc, char *argv[]) { + + testFunction funcs[] = { /* name, func */ + { "test_large", test_large }, + { "test_hrt", test_hrt }, + { "test_input", test_input }, + { "test_encode", test_encode }, + { "test_perf", test_perf }, + }; + + testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); + + testReport(); + + return 0; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_medical.c b/backend/tests/test_medical.c index 261575af..d166b3b1 100644 --- a/backend/tests/test_medical.c +++ b/backend/tests/test_medical.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020-2024 Robin Stuart + Copyright (C) 2020-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -42,19 +42,20 @@ static void test_large(const testCtx *const p_ctx) { int ret; int expected_rows; int expected_width; + char *expected_errtxt; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODABAR, -1, "A+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 103, 0, 1, 1133 }, - /* 1*/ { BARCODE_CODABAR, -1, "A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 104, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 2*/ { BARCODE_CODABAR, 1, "A+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 103, 0, 1, 1143 }, - /* 3*/ { BARCODE_CODABAR, 1, "A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++B", 104, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 4*/ { BARCODE_PHARMA, -1, "131070", 6, 0, 1, 78 }, - /* 5*/ { BARCODE_PHARMA, -1, "1", 7, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 6*/ { BARCODE_PHARMA_TWO, -1, "64570080", 8, 0, 2, 31 }, - /* 7*/ { BARCODE_PHARMA_TWO, -1, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 8*/ { BARCODE_CODE32, -1, "1", 8, 0, 1, 103 }, - /* 9*/ { BARCODE_CODE32, -1, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 0*/ { BARCODE_PHARMA, -1, "131070", 6, 0, 1, 78, "", }, + /* 1*/ { BARCODE_PHARMA, -1, "1", 7, ZINT_ERROR_TOO_LONG, -1, -1, "Error 350: Input length 7 too long (maximum 6)" }, + /* 2*/ { BARCODE_PHARMA_TWO, -1, "64570080", 8, 0, 2, 31, "", }, + /* 3*/ { BARCODE_PHARMA_TWO, -1, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1, "Error 354: Input length 9 too long (maximum 8)" }, + /* 4*/ { BARCODE_CODE32, -1, "1", 8, 0, 1, 103, "", }, + /* 5*/ { BARCODE_CODE32, -1, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1, "Error 360: Input length 9 too long (maximum 8)" }, + /* 6*/ { BARCODE_PZN, -1, "1", 7, 0, 1, 142, "" }, /* Takes 8 with correct check digit */ + /* 7*/ { BARCODE_PZN, -1, "1", 9, ZINT_ERROR_TOO_LONG, -1, -1, "Error 325: Input length 9 too long (maximum 8)" }, + /* 8*/ { BARCODE_PZN, 1, "1", 6, 0, 1, 129, "" }, /* PZN7 takes 7 with correct check digit */ + /* 9*/ { BARCODE_PZN, 1, "1", 8, ZINT_ERROR_TOO_LONG, -1, -1, "Error 325: Input length 8 too long (maximum 7)" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -78,6 +79,8 @@ static void test_large(const testCtx *const p_ctx) { ret = ZBarcode_Encode(symbol, (unsigned char *) data_buf, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n", i, ret ? "set" : "empty", symbol->errtxt); + assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt); if (ret < ZINT_ERROR) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows); @@ -102,16 +105,18 @@ static void test_hrt(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODABAR, -1, "A1234B", "A1234B" }, - /* 1*/ { BARCODE_CODABAR, -1, "a1234c", "A1234C" }, /* Converts to upper */ - /* 2*/ { BARCODE_CODABAR, 1, "A1234B", "A1234B" }, /* Check not included */ - /* 3*/ { BARCODE_CODABAR, 2, "A1234B", "A12345B" }, /* Check included */ - /* 4*/ { BARCODE_CODABAR, 1, "A123456A", "A123456A" }, /* Check not included */ - /* 5*/ { BARCODE_CODABAR, 2, "A123456A", "A123456$A" }, /* Check included */ - /* 6*/ { BARCODE_PHARMA, -1, "123456", "" }, /* None */ - /* 7*/ { BARCODE_PHARMA_TWO, -1, "123456", "" }, /* None */ - /* 8*/ { BARCODE_CODE32, -1, "123456", "A001234564" }, - /* 9*/ { BARCODE_CODE32, -1, "12345678", "A123456788" }, + /* 0*/ { BARCODE_PHARMA, -1, "123456", "" }, /* None */ + /* 1*/ { BARCODE_PHARMA_TWO, -1, "123456", "" }, /* None */ + /* 2*/ { BARCODE_CODE32, -1, "123456", "A001234564" }, + /* 3*/ { BARCODE_CODE32, -1, "12345678", "A123456788" }, + /* 4*/ { BARCODE_PZN, -1, "12345", "PZN - 00123458" }, /* Pads with zeroes if length < 7 */ + /* 5*/ { BARCODE_PZN, -1, "123456", "PZN - 01234562" }, + /* 6*/ { BARCODE_PZN, -1, "1234567", "PZN - 12345678" }, + /* 7*/ { BARCODE_PZN, -1, "12345678", "PZN - 12345678" }, + /* 8*/ { BARCODE_PZN, 1, "1234", "PZN - 0012345" }, /* PZN7, pads with zeroes if length < 6 */ + /* 9*/ { BARCODE_PZN, 1, "12345", "PZN - 0123458" }, + /* 10*/ { BARCODE_PZN, 1, "123456", "PZN - 1234562" }, + /* 11*/ { BARCODE_PZN, 1, "1234562", "PZN - 1234562" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -144,6 +149,7 @@ static void test_input(const testCtx *const p_ctx) { struct item { int symbology; + int option_2; char *data; int ret; int expected_rows; @@ -154,37 +160,33 @@ static void test_input(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODABAR, "A1234B", 0, 1, 62, "", 1, "" }, - /* 1*/ { BARCODE_CODABAR, "1234B", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 358: Does not begin with \"A\", \"B\", \"C\" or \"D\"", 1, "" }, - /* 2*/ { BARCODE_CODABAR, "A1234", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 359: Does not end with \"A\", \"B\", \"C\" or \"D\"", 1, "" }, - /* 3*/ { BARCODE_CODABAR, "A1234E", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 359: Does not end with \"A\", \"B\", \"C\" or \"D\"", 1, "" }, - /* 4*/ { BARCODE_CODABAR, "C123.D", 0, 1, 63, "", 1, "" }, - /* 5*/ { BARCODE_CODABAR, "C123,D", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 357: Invalid character at position 5 in input (\"0123456789-$:/.+ABCD\" only)", 1, "" }, - /* 6*/ { BARCODE_CODABAR, "D:C", 0, 1, 33, "", 1, "" }, - /* 7*/ { BARCODE_CODABAR, "DCC", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 363: Invalid character at position 1 in input (cannot contain \"A\", \"B\", \"C\" or \"D\")", 1, "" }, - /* 8*/ { BARCODE_CODABAR, "A234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123B", ZINT_ERROR_TOO_LONG, -1, -1, "Error 356: Input length 104 too long (maximum 103)", 1, "" }, - /* 9*/ { BARCODE_CODABAR, "AB", ZINT_ERROR_TOO_LONG, -1, -1, "Error 362: Input length 2 too short (minimum 3)", 1, "" }, - /* 10*/ { BARCODE_PHARMA, "131070", 0, 1, 78, "", 1, "" }, - /* 11*/ { BARCODE_PHARMA, "1310700", ZINT_ERROR_TOO_LONG, -1, -1, "Error 350: Input length 7 too long (maximum 6)", 1, "" }, - /* 12*/ { BARCODE_PHARMA, "131071", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 352: Input value '131071' out of range (3 to 131070)", 1, "" }, - /* 13*/ { BARCODE_PHARMA, "3", 0, 1, 4, "", 1, "" }, - /* 14*/ { BARCODE_PHARMA, "2", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 352: Input value '2' out of range (3 to 131070)", 1, "" }, - /* 15*/ { BARCODE_PHARMA, "1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 352: Input value '1' out of range (3 to 131070)", 1, "" }, - /* 16*/ { BARCODE_PHARMA, "12A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 351: Invalid character at position 3 in input (digits only)", 1, "" }, - /* 17*/ { BARCODE_PHARMA_TWO, "64570080", 0, 2, 31, "", 1, "" }, - /* 18*/ { BARCODE_PHARMA_TWO, "64570081", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '64570081' out of range (4 to 64570080)", 1, "" }, - /* 19*/ { BARCODE_PHARMA_TWO, "064570080", ZINT_ERROR_TOO_LONG, -1, -1, "Error 354: Input length 9 too long (maximum 8)", 1, "" }, - /* 20*/ { BARCODE_PHARMA_TWO, "4", 0, 2, 3, "", 1, "" }, - /* 21*/ { BARCODE_PHARMA_TWO, "3", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '3' out of range (4 to 64570080)", 1, "" }, - /* 22*/ { BARCODE_PHARMA_TWO, "2", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '2' out of range (4 to 64570080)", 1, "" }, - /* 23*/ { BARCODE_PHARMA_TWO, "1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '1' out of range (4 to 64570080)", 1, "" }, - /* 24*/ { BARCODE_PHARMA_TWO, "123A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 355: Invalid character at position 4 in input (digits only)", 1, "" }, - /* 25*/ { BARCODE_CODE32, "12345678", 0, 1, 103, "", 1, "" }, - /* 26*/ { BARCODE_CODE32, "9", 0, 1, 103, "", 0, "BWIPP requires length 8 or 9" }, - /* 27*/ { BARCODE_CODE32, "0", 0, 1, 103, "", 0, "BWIPP requires length 8 or 9" }, - /* 28*/ { BARCODE_CODE32, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 360: Input length 9 too long (maximum 8)", 1, "" }, - /* 29*/ { BARCODE_CODE32, "A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 361: Invalid character at position 1 in input (digits only)", 1, "" }, - /* 30*/ { BARCODE_CODE32, "99999999", 0, 1, 103, "", 1, "" }, + /* 0*/ { BARCODE_PHARMA, -1, "131070", 0, 1, 78, "", 1, "" }, + /* 1*/ { BARCODE_PHARMA, -1, "1310700", ZINT_ERROR_TOO_LONG, -1, -1, "Error 350: Input length 7 too long (maximum 6)", 1, "" }, + /* 2*/ { BARCODE_PHARMA, -1, "131071", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 352: Input value '131071' out of range (3 to 131070)", 1, "" }, + /* 3*/ { BARCODE_PHARMA, -1, "3", 0, 1, 4, "", 1, "" }, + /* 4*/ { BARCODE_PHARMA, -1, "2", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 352: Input value '2' out of range (3 to 131070)", 1, "" }, + /* 5*/ { BARCODE_PHARMA, -1, "1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 352: Input value '1' out of range (3 to 131070)", 1, "" }, + /* 6*/ { BARCODE_PHARMA, -1, "12A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 351: Invalid character at position 3 in input (digits only)", 1, "" }, + /* 7*/ { BARCODE_PHARMA_TWO, -1, "64570080", 0, 2, 31, "", 1, "" }, + /* 8*/ { BARCODE_PHARMA_TWO, -1, "64570081", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '64570081' out of range (4 to 64570080)", 1, "" }, + /* 9*/ { BARCODE_PHARMA_TWO, -1, "064570080", ZINT_ERROR_TOO_LONG, -1, -1, "Error 354: Input length 9 too long (maximum 8)", 1, "" }, + /* 10*/ { BARCODE_PHARMA_TWO, -1, "4", 0, 2, 3, "", 1, "" }, + /* 11*/ { BARCODE_PHARMA_TWO, -1, "3", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '3' out of range (4 to 64570080)", 1, "" }, + /* 12*/ { BARCODE_PHARMA_TWO, -1, "2", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '2' out of range (4 to 64570080)", 1, "" }, + /* 13*/ { BARCODE_PHARMA_TWO, -1, "1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 353: Input value '1' out of range (4 to 64570080)", 1, "" }, + /* 14*/ { BARCODE_PHARMA_TWO, -1, "123A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 355: Invalid character at position 4 in input (digits only)", 1, "" }, + /* 15*/ { BARCODE_CODE32, -1, "12345678", 0, 1, 103, "", 1, "" }, + /* 16*/ { BARCODE_CODE32, -1, "9", 0, 1, 103, "", 0, "BWIPP requires length 8 or 9" }, + /* 17*/ { BARCODE_CODE32, -1, "0", 0, 1, 103, "", 0, "BWIPP requires length 8 or 9" }, + /* 18*/ { BARCODE_CODE32, -1, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 360: Input length 9 too long (maximum 8)", 1, "" }, + /* 19*/ { BARCODE_CODE32, -1, "A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 361: Invalid character at position 1 in input (digits only)", 1, "" }, + /* 20*/ { BARCODE_CODE32, -1, "99999999", 0, 1, 103, "", 1, "" }, + /* 21*/ { BARCODE_PZN, -1, "1", 0, 1, 142, "", 0, "BWIPP requires 7 or 8 digits" }, + /* 22*/ { BARCODE_PZN, -1, "A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 326: Invalid character at position 1 in input (digits only)", 1, "" }, + /* 23*/ { BARCODE_PZN, -1, "1000006", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 327: Invalid PZN, check digit is '10'", 1, "" }, /* Check digit == 10 so can't be used */ + /* 24*/ { BARCODE_PZN, -1, "00000011", ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 890: Invalid check digit '1', expecting '7'", 1, "" }, + /* 25*/ { BARCODE_PZN, 1, "100009", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 327: Invalid PZN, check digit is '10'", 1, "" }, /* Check digit == 10 so can't be used */ + /* 26*/ { BARCODE_PZN, 1, "0000011", ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 890: Invalid check digit '1', expecting '7'", 1, "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -204,7 +206,7 @@ static void test_input(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); @@ -251,38 +253,32 @@ static void test_encode(const testCtx *const p_ctx) { char *expected; }; static const struct item data[] = { - /* 0*/ { BARCODE_CODABAR, -1, "A37859B", 0, 1, 72, "BS EN 798:1995 Figure 1", - "101100100101100101010100101101010011010101101010010110100101010010010110" - }, - /* 1*/ { BARCODE_CODABAR, -1, "A0123456789-$:/.+D", 0, 1, 186, "Verified manually against tec-it", - "101100100101010100110101011001010100101101100101010101101001011010100101001010110100101101010011010101101001010101001101010110010101101011011011011010110110110110101011011011010100110010" - }, - /* 2*/ { BARCODE_CODABAR, 1, "A1B", 0, 1, 43, "Verified manually against tec-it", - "1011001001010101100101101101101010010010110" - }, - /* 3*/ { BARCODE_CODABAR, 1, "A+B", 0, 1, 43, "Verified manually against tec-it", - "1011001001010110110110101010011010010010110" - }, - /* 4*/ { BARCODE_CODABAR, 1, "B0123456789-$:/.+B", 0, 1, 196, "Verified manually against tec-it", - "1001001011010101001101010110010101001011011001010101011010010110101001010010101101001011010100110101011010010101010011010101100101011010110110110110101101101101101010110110110100101011010010010110" - }, - /* 5*/ { BARCODE_PHARMA, -1, "131070", 0, 1, 78, "", + /* 0*/ { BARCODE_PHARMA, -1, "131070", 0, 1, 78, "", "111001110011100111001110011100111001110011100111001110011100111001110011100111" }, - /* 6*/ { BARCODE_PHARMA, -1, "123456", 0, 1, 58, "", + /* 1*/ { BARCODE_PHARMA, -1, "123456", 0, 1, 58, "", "1110011100111001001001001110010010011100100100100100100111" }, - /* 7*/ { BARCODE_PHARMA_TWO, -1, "64570080", 0, 2, 31, "Verified manually against tec-it", + /* 2*/ { BARCODE_PHARMA_TWO, -1, "64570080", 0, 2, 31, "Verified manually against TEC-IT", "1010101010101010101010101010101" "1010101010101010101010101010101" }, - /* 8*/ { BARCODE_PHARMA_TWO, -1, "29876543", 0, 2, 31, "Verified manually against tec-it", + /* 3*/ { BARCODE_PHARMA_TWO, -1, "29876543", 0, 2, 31, "Verified manually against TEC-IT", "0010100010001010001010001000101" "1000101010100000100000101010000" }, - /* 9*/ { BARCODE_CODE32, -1, "34567890", 0, 1, 103, "Verified manually against tec-it", + /* 4*/ { BARCODE_CODE32, -1, "34567890", 0, 1, 103, "Verified manually against TEC-IT", "1001011011010101101001011010110010110101011011010010101100101101011010010101101010101100110100101101101" }, + /* 5*/ { BARCODE_PZN, -1, "1234567", 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against TEC-IT", + "1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101" + }, + /* 6*/ { BARCODE_PZN, -1, "2758089", 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against TEC-IT", + "1001011011010100101011011010110010101101010010110110110100110101011010010110101010011011010110100101101010110010110101011001011010100101101101" + }, + /* 7*/ { BARCODE_PZN, 1, "123456", 0, 1, 129, "Example from BWIPP; verified manually against TEC-IT", + "100101101101010010101101101101001010110101100101011011011001010101010011010110110100110101010110011010101011001010110100101101101" + }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend_qt/backend_qt.pro b/backend_qt/backend_qt.pro index 6777a32f..382595c4 100644 --- a/backend_qt/backend_qt.pro +++ b/backend_qt/backend_qt.pro @@ -71,14 +71,20 @@ HEADERS += ../backend/aztec.h \ qzint.h SOURCES += ../backend/2of5.c \ + ../backend/2of5inter.c \ + ../backend/2of5inter_based.c \ ../backend/auspost.c \ ../backend/aztec.c \ ../backend/bc412.c \ ../backend/bmp.c \ + ../backend/channel.c \ + ../backend/codabar.c \ ../backend/codablock.c \ ../backend/code.c \ ../backend/code1.c \ + ../backend/code11.c \ ../backend/code128.c \ + ../backend/code128_based.c \ ../backend/code16k.c \ ../backend/code49.c \ ../backend/common.c \ diff --git a/backend_qt/backend_vc8.pro b/backend_qt/backend_vc8.pro index becfbbf6..f5c3e86b 100644 --- a/backend_qt/backend_vc8.pro +++ b/backend_qt/backend_vc8.pro @@ -54,14 +54,20 @@ HEADERS += ../backend/aztec.h \ qzint.h SOURCES += ../backend/2of5.c \ + ../backend/2of5inter.c \ + ../backend/2of5inter_based.c \ ../backend/auspost.c \ ../backend/aztec.c \ ../backend/bc412.c \ ../backend/bmp.c \ + ../backend/channel.c \ + ../backend/codabar.c \ ../backend/codablock.c \ ../backend/code.c \ ../backend/code1.c \ + ../backend/code11.c \ ../backend/code128.c \ + ../backend/code128_based.c \ ../backend/code16k.c \ ../backend/code49.c \ ../backend/common.c \ diff --git a/backend_tcl/configure b/backend_tcl/configure index 1d33f2b8..070ccdc1 100755 --- a/backend_tcl/configure +++ b/backend_tcl/configure @@ -643,6 +643,7 @@ TCLSH_PROG VC_MANIFEST_EMBED_EXE VC_MANIFEST_EMBED_DLL RANLIB_STUB +PKG_STUB_LIB_FILE MAKE_STUB_LIB MAKE_STATIC_LIB MAKE_SHARED_LIB @@ -706,7 +707,6 @@ PKG_HEADERS PKG_TCL_SOURCES PKG_STUB_OBJECTS PKG_STUB_SOURCES -PKG_STUB_LIB_FILE PKG_LIB_FILE9 PKG_LIB_FILE8 PKG_LIB_FILE @@ -2580,8 +2580,6 @@ printf "%s\n" "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} - # Substitute STUB_LIB_FILE in case package creates a stub library too. - # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... @@ -2770,10 +2768,16 @@ printf "%s\n" "$as_me: WARNING: --with-tcl argument should refer to directory co `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tcl9.0 2>/dev/null` \ + `ls -d /usr/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do @@ -3849,11 +3853,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu printf %s "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: loading" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: loading" >&5 printf "%s\n" "loading" >&6; } . "${TCL_BIN_DIR}/tclConfig.sh" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf "%s\n" "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi @@ -3864,9 +3868,9 @@ printf "%s\n" "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then - TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" - TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" - TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works @@ -5175,10 +5179,14 @@ printf "%s\n" "$tcl_cv_cc_pipe" >&6; } fi fi + if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then + +printf "%s\n" "#define Tcl_Size int" >>confdefs.h + + fi + #-------------------------------------------------------------------- # Common compiler flag setup - # ####GL Suppress "warning: AC_C_BIGENDIAN should be used with AC_CONFIG_HEADERS", taken from - # ####GL https://git.ruby-lang.org/ruby.git/commit/?id=ca3cc677b31897e7306ac3b4565a0dd928168b08 #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 @@ -5412,8 +5420,7 @@ printf "%s\n" "$ac_cv_c_bigendian" >&6; } no) ;; #( universal) - printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h - + # ;; #( *) as_fn_error $? "unknown endianness @@ -5435,16 +5442,22 @@ printf "%s\n" "$ac_cv_c_bigendian" >&6; } vars=" ../backend/2of5.c + ../backend/2of5inter.c + ../backend/2of5inter_based.c ../backend/auspost.c ../backend/aztec.c ../backend/bc412.c ../backend/bmp.c + ../backend/channel.c + ../backend/codabar.c ../backend/codablock.c - ../backend/code128.c - ../backend/code16k.c - ../backend/code1.c - ../backend/code49.c ../backend/code.c + ../backend/code1.c + ../backend/code11.c + ../backend/code128.c + ../backend/code128_based.c + ../backend/code16k.c + ../backend/code49.c ../backend/common.c ../backend/composite.c ../backend/dllversion.c @@ -6132,7 +6145,7 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5 printf "%s\n" "shared" >&6; } SHARED_BUILD=1 - STUBS_BUILD=1 + STUBS_BUILD=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5 printf "%s\n" "static" >&6; } @@ -6140,11 +6153,11 @@ printf "%s\n" "static" >&6; } printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h - if test "$stubs_ok" = "yes" ; then - STUBS_BUILD=1 - else - STUBS_BUILD=0 - fi + if test "$stubs_ok" = "yes" ; then + STUBS_BUILD=1 + else + STUBS_BUILD=0 + fi fi if test "${STUBS_BUILD}" = "1" ; then @@ -6583,14 +6596,14 @@ fi fi if test "$GCC" != "yes" ; then - if test "${SHARED_BUILD}" = "0" ; then + if test "${SHARED_BUILD}" = "0" ; then runtime=-MT - else + else runtime=-MD - fi - case "x`echo \${VisualStudioVersion}`" in - x1[4-9]*) - lflags="${lflags} -nodefaultlib:libucrt.lib" + fi + case "x`echo \${VisualStudioVersion}`" in + x1[4-9]*) + lflags="${lflags} -nodefaultlib:libucrt.lib" vars="ucrt.lib" for i in $vars; do @@ -6602,12 +6615,12 @@ fi done - ;; - *) - ;; - esac + ;; + *) + ;; + esac - if test "$do64bit" != "no" ; then + if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " @@ -6830,7 +6843,7 @@ printf "%s\n" "$ac_cv_cross" >&6; } SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots - ;; + ;; AIX-*) if test "$GCC" != "yes" then : @@ -6842,7 +6855,7 @@ then : ;; *) # Make sure only first arg gets _r - CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` + CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 @@ -7324,19 +7337,19 @@ fi if test "$do64bit" = yes then : - if test "$GCC" = yes + if test "$GCC" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} else case e in #( e) - do64bit_ok=yes - SHLIB_LD="ld -64 -shared -rdata_shared" - CFLAGS="$CFLAGS -64" - LDFLAGS_ARCH="-64" - ;; + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + ;; esac fi @@ -7364,7 +7377,7 @@ then : LDFLAGS="$LDFLAGS $PTHREAD_LIBS" fi ;; - esac + esac if test $doRpath = yes then : @@ -7612,46 +7625,6 @@ esac fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 -printf %s "checking if ld accepts -single_module flag... " >&6; } -if test ${tcl_cv_ld_single_module+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) - hold_ldflags=$LDFLAGS - LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main (void) -{ -int i; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - tcl_cv_ld_single_module=yes -else case e in #( - e) tcl_cv_ld_single_module=no ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$hold_ldflags ;; -esac -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 -printf "%s\n" "$tcl_cv_ld_single_module" >&6; } - if test $tcl_cv_ld_single_module = yes -then : - - SHLIB_LD="${SHLIB_LD} -Wl,-single_module" - -fi # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" @@ -7828,11 +7801,11 @@ printf "%s\n" "#define _OE_SOCKETS 1" >>confdefs.h if test "$SHARED_BUILD" = 1 then : - SHLIB_LD='ld -shared -expect_unresolved "*"' + SHLIB_LD='ld -shared -expect_unresolved "*"' else case e in #( e) - SHLIB_LD='ld -non_shared -expect_unresolved "*"' + SHLIB_LD='ld -non_shared -expect_unresolved "*"' ;; esac fi @@ -8121,7 +8094,7 @@ esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$hold_ldflags ;; + LDFLAGS=$hold_ldflags ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 @@ -8469,8 +8442,9 @@ printf "%s\n" "#define _ISOC99_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _ISOC99_SOURCE" fi + if test "${TCL_MAJOR_VERSION}" -ne 8 ; then - if test ${tcl_cv_flag__largefile64_source+y} + if test ${tcl_cv_flag__file_offset_bits+y} then : printf %s "(cached) " >&6 else case e in #( @@ -8480,32 +8454,32 @@ else case e in #( int main (void) { -struct stat64 buf; int i = stat64("/", &buf); +switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - tcl_cv_flag__largefile64_source=no + tcl_cv_flag__file_offset_bits=no else case e in #( e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#define _LARGEFILE64_SOURCE 1 +#define _FILE_OFFSET_BITS 64 #include int main (void) { -struct stat64 buf; int i = stat64("/", &buf); +switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - tcl_cv_flag__largefile64_source=yes + tcl_cv_flag__file_offset_bits=yes else case e in #( - e) tcl_cv_flag__largefile64_source=no ;; + e) tcl_cv_flag__file_offset_bits=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; @@ -8515,66 +8489,14 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; esac fi - if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then + if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then -printf "%s\n" "#define _LARGEFILE64_SOURCE 1" >>confdefs.h +printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h - tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" + tcl_flags="$tcl_flags _FILE_OFFSET_BITS" fi - - if test ${tcl_cv_flag__largefile_source64+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main (void) -{ -char *p = (char *)open64; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - tcl_cv_flag__largefile_source64=no -else case e in #( - e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#define _LARGEFILE_SOURCE64 1 -#include -int -main (void) -{ -char *p = (char *)open64; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - tcl_cv_flag__largefile_source64=yes -else case e in #( - e) tcl_cv_flag__largefile_source64=no ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; -esac -fi - - if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then - -printf "%s\n" "#define _LARGEFILE_SOURCE64 1" >>confdefs.h - - tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" fi - if test "x${tcl_flags}" = "x" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } @@ -8615,15 +8537,15 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { switch (0) { - case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; - } + case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; + } ; return 0; } @@ -8656,6 +8578,79 @@ printf "%s\n" "#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}" >>confdefs.h printf "%s\n" "${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations + if test "${TCL_MAJOR_VERSION}" -ne 8 ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5 +printf %s "checking for 64-bit time_t... " >&6; } +if test ${tcl_cv_time_t_64+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + tcl_cv_time_t_64=yes +else case e in #( + e) tcl_cv_time_t_64=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5 +printf "%s\n" "$tcl_cv_time_t_64" >&6; } + if test "x${tcl_cv_time_t_64}" = "xno" ; then + # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 + # which SC_TCL_EARLY_FLAGS has defined if necessary. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5 +printf %s "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; } +if test ${tcl_cv__time_bits+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _TIME_BITS 64 +#include +int +main (void) +{ +switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + tcl_cv__time_bits=yes +else case e in #( + e) tcl_cv__time_bits=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5 +printf "%s\n" "$tcl_cv__time_bits" >&6; } + if test "x${tcl_cv__time_bits}" = "xyes" ; then + +printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h + + fi + fi + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 printf %s "checking for struct dirent64... " >&6; } if test ${tcl_cv_struct_dirent64+y} @@ -8708,7 +8703,7 @@ int main (void) { struct dirent64 *p; DIR64 d = opendir64("."); - p = readdir64(d); rewinddir64(d); closedir64(d); + p = readdir64(d); rewinddir64(d); closedir64(d); ; return 0; } @@ -8812,8 +8807,8 @@ esac fi if test "x${tcl_cv_type_off64_t}" = "xyes" && \ - test "x${ac_cv_func_lseek64}" = "xyes" && \ - test "x${ac_cv_func_open64}" = "xyes" ; then + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then printf "%s\n" "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h @@ -9069,13 +9064,18 @@ rm -rf conftest* PACKAGE_LIB_PREFIX8="${PACKAGE_LIB_PREFIX}" PACKAGE_LIB_PREFIX9="${PACKAGE_LIB_PREFIX}tcl9" - if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" == x; then + if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h + fi + if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tk8}" != x; then + +printf "%s\n" "#define TK_MAJOR_VERSION 8" >>confdefs.h + fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then @@ -9100,7 +9100,11 @@ printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries - eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" + else + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi @@ -9119,12 +9123,16 @@ printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else - eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" - eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries - eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" + else + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi fi # These are escaped so that only CFLAGS is picked up at configure time. @@ -9138,6 +9146,8 @@ printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h + # Substitute STUB_LIB_FILE in case package creates a stub library too. + @@ -9155,37 +9165,37 @@ printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 printf %s "checking for tclsh... " >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then - # tclConfig.sh is in Tcl build directory - if test "${TEA_PLATFORM}" = "windows"; then - if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then - TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" - elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then - TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" - elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then - TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" - elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then - TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" - fi - else - TCLSH_PROG="${TCL_BIN_DIR}/tclsh" - fi + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" + elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" + fi + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi else - # tclConfig.sh is in install location - if test "${TEA_PLATFORM}" = "windows"; then - TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" - else - TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" - fi - list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ - `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ - `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" - for i in $list ; do - if test -f "$i/${TCLSH_PROG}" ; then - REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" - break - fi - done - TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 printf "%s\n" "${TCLSH_PROG}" >&6; } diff --git a/backend_tcl/configure.ac b/backend_tcl/configure.ac index bb4b933d..4e6aa8a5 100644 --- a/backend_tcl/configure.ac +++ b/backend_tcl/configure.ac @@ -73,16 +73,22 @@ TEA_SETUP_COMPILER TEA_ADD_SOURCES([ ../backend/2of5.c + ../backend/2of5inter.c + ../backend/2of5inter_based.c ../backend/auspost.c ../backend/aztec.c ../backend/bc412.c ../backend/bmp.c + ../backend/channel.c + ../backend/codabar.c ../backend/codablock.c - ../backend/code128.c - ../backend/code16k.c - ../backend/code1.c - ../backend/code49.c ../backend/code.c + ../backend/code1.c + ../backend/code11.c + ../backend/code128.c + ../backend/code128_based.c + ../backend/code16k.c + ../backend/code49.c ../backend/common.c ../backend/composite.c ../backend/dllversion.c diff --git a/win32/libzint.vcxproj b/win32/libzint.vcxproj index 57fc894a..11aa6f11 100644 --- a/win32/libzint.vcxproj +++ b/win32/libzint.vcxproj @@ -122,14 +122,20 @@ + + + + + + diff --git a/win32/vs2008/libzint.vcproj b/win32/vs2008/libzint.vcproj index 7a6ff52a..26b1833b 100644 --- a/win32/vs2008/libzint.vcproj +++ b/win32/vs2008/libzint.vcproj @@ -197,6 +197,14 @@ RelativePath="..\..\backend\2of5.c" > + + + + @@ -213,6 +221,14 @@ RelativePath="..\..\backend\bmp.c" > + + + + @@ -225,10 +241,18 @@ RelativePath="..\..\backend\code1.c" > + + + + diff --git a/win32/vs2015/libzint.vcxproj b/win32/vs2015/libzint.vcxproj index 977cad8e..d1dbd0a2 100644 --- a/win32/vs2015/libzint.vcxproj +++ b/win32/vs2015/libzint.vcxproj @@ -296,14 +296,20 @@ + + + + + + diff --git a/win32/vs2017/libzint.vcxproj b/win32/vs2017/libzint.vcxproj index 7388b398..e5ee4937 100644 --- a/win32/vs2017/libzint.vcxproj +++ b/win32/vs2017/libzint.vcxproj @@ -122,14 +122,20 @@ + + + + + + diff --git a/win32/vs2019/libzint.vcxproj b/win32/vs2019/libzint.vcxproj index 7f17a2be..662e98b5 100644 --- a/win32/vs2019/libzint.vcxproj +++ b/win32/vs2019/libzint.vcxproj @@ -122,14 +122,20 @@ + + + + + + diff --git a/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp b/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp index 08aae636..20d16c97 100644 --- a/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp +++ b/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp @@ -92,6 +92,14 @@ SOURCE=..\..\backend\2of5.c # End Source File # Begin Source File +SOURCE=..\..\backend\2of5inter.c +# End Source File +# Begin Source File + +SOURCE=..\..\backend\2of5inter_based.c +# End Source File +# Begin Source File + SOURCE=..\..\backend\auspost.c # End Source File # Begin Source File @@ -108,6 +116,14 @@ SOURCE=..\..\backend\bmp.c # End Source File # Begin Source File +SOURCE=..\..\backend\channel.c +# End Source File +# Begin Source File + +SOURCE=..\..\backend\codabar.c +# End Source File +# Begin Source File + SOURCE=..\..\backend\codablock.c # End Source File # Begin Source File @@ -120,10 +136,18 @@ SOURCE=..\..\backend\code1.c # End Source File # Begin Source File +SOURCE=..\..\backend\code11.c +# End Source File +# Begin Source File + SOURCE=..\..\backend\code128.c # End Source File # Begin Source File +SOURCE=..\..\backend\code128_based.c +# End Source File +# Begin Source File + SOURCE=..\..\backend\code16k.c # End Source File # Begin Source File