Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/tools/gen_gs1_lint.php @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 <?php | |
| 2 /* Generate GS1 verify include "backend/gs1_lint.h" for "backend/gs1.c" */ | |
| 3 /* | |
| 4 libzint - the open source barcode library | |
| 5 Copyright (C) 2021-2024 <rstuart114@gmail.com> | |
| 6 */ | |
| 7 /* SPDX-License-Identifier: BSD-3-Clause */ | |
| 8 | |
| 9 /* To create "backend/gs1_lint.h" (from project directory): | |
| 10 * | |
| 11 * php backend/tools/gen_gs1_lint.php > backend/gs1_lint.h | |
| 12 * | |
| 13 * or to use local copy of "gs1-syntax-dictionary.txt": | |
| 14 * | |
| 15 * php backend/tools/gen_gs1_lint.php -f <local-path>/gs1-syntax-dictionary.txt backend/gs1_lint.h | |
| 16 * | |
| 17 ************************************************************************************************* | |
| 18 * NOTE: up-to-date version requires syntax dictionary available from | |
| 19 * https://ref.gs1.org/tools/gs1-barcode-syntax-resource/syntax-dictionary/ | |
| 20 ************************************************************************************************* | |
| 21 */ | |
| 22 | |
| 23 $basename = basename(__FILE__); | |
| 24 $dirname = dirname(__FILE__); | |
| 25 $dirdirname = basename(dirname($dirname)) . '/' . basename($dirname); | |
| 26 | |
| 27 $opts = getopt('c:f:h:l:t:'); | |
| 28 | |
| 29 $print_copyright = isset($opts['c']) ? (bool) $opts['c'] : true; | |
| 30 $file = isset($opts['f']) ? $opts['f'] | |
| 31 : 'https://raw.githubusercontent.com/gs1/gs1-syntax-dictionary/main/gs1-syntax-dictionary.txt'; | |
| 32 $print_h_guard = isset($opts['h']) ? (bool) $opts['h'] : true; | |
| 33 $use_length_only = isset($opts['l']) ? (bool) $opts['l'] : true; | |
| 34 $tab = isset($opts['t']) ? $opts['t'] : ' '; | |
| 35 | |
| 36 if (($get = file_get_contents($file)) === false) { | |
| 37 exit("$basename:" . __LINE__ . " ERROR: Could not read file \"$file\"" . PHP_EOL); | |
| 38 } | |
| 39 if (strncasecmp($file, "http", 4) != 0) { | |
| 40 // Strip to last 2 directories | |
| 41 $stripped_dir = dirname($file); | |
| 42 $stripped_file = basename(dirname($stripped_dir)) . '/' . basename($stripped_dir) . '/' . basename($file); | |
| 43 } else { | |
| 44 $stripped_file = $file; | |
| 45 } | |
| 46 | |
| 47 $lines = explode("\n", $get); | |
| 48 | |
| 49 $spec_ais = $spec_parts = $spec_funcs = $spec_comments = $fixed_ais = array(); | |
| 50 $batches = array_fill(0, 100, array()); | |
| 51 | |
| 52 // Parse the lines into AIs and specs | |
| 53 $line_no = 0; | |
| 54 foreach ($lines as $line) { | |
| 55 $line_no++; | |
| 56 if ($line === '' || $line[0] === '#') { | |
| 57 continue; | |
| 58 } | |
| 59 if (!preg_match('/^([0-9]+(?:-[0-9]+)?) +([ *?]* )([NXYZ][0-9.][ NXYZ0-9.,a-z=|+\[\]]*)(?:# (.+))?$/', | |
| 60 $line, $matches)) { | |
| 61 print $line . PHP_EOL; | |
| 62 exit("$basename:" . __LINE__ . " ERROR: Could not parse line $line_no" . PHP_EOL); | |
| 63 } | |
| 64 $ai = $matches[1]; | |
| 65 $flags = trim($matches[2]); | |
| 66 $fixed = strpos($flags, "*") !== false; | |
| 67 $spec = preg_replace('/ +req=[0-9,n+]*/', '', trim($matches[3])); // Strip mandatory association info | |
| 68 $spec = preg_replace('/ +ex=[0-9,n]*/', '', $spec); // Strip invalid pairings info | |
| 69 $spec = preg_replace('/ +dlpkey[=0-9,|]*/', '', $spec); // Strip Digital Link primary key info | |
| 70 $comment = isset($matches[4]) ? trim($matches[4]) : ''; | |
| 71 | |
| 72 if (isset($spec_ais[$spec])) { | |
| 73 $ais = $spec_ais[$spec]; | |
| 74 } else { | |
| 75 $ais = array(); | |
| 76 } | |
| 77 | |
| 78 if (($hyphen = strpos($ai, '-')) !== false) { | |
| 79 if ($fixed !== '') { | |
| 80 $fixed_ais[substr($ai, 0, 2)] = true; | |
| 81 } | |
| 82 $ai_s = (int) substr($ai, 0, $hyphen); | |
| 83 $ai_e = (int) substr($ai, $hyphen + 1); | |
| 84 $ais[] = array($ai_s, $ai_e); | |
| 85 | |
| 86 $batch_s_idx = (int) ($ai_s / 100); | |
| 87 $batch_e_idx = (int) ($ai_e / 100); | |
| 88 if ($batch_s_idx !== $batch_e_idx) { | |
| 89 if (!in_array($spec, $batches[$batch_s_idx])) { | |
| 90 $batches[$batch_s_idx][] = $spec; | |
| 91 } | |
| 92 if (!in_array($spec, $batches[$batch_e_idx])) { | |
| 93 $batches[$batch_e_idx][] = $spec; | |
| 94 } | |
| 95 } else { | |
| 96 if (!in_array($spec, $batches[$batch_s_idx])) { | |
| 97 $batches[$batch_s_idx][] = $spec; | |
| 98 } | |
| 99 } | |
| 100 } else { | |
| 101 if ($fixed !== '') { | |
| 102 $fixed_ais[substr($ai, 0, 2)] = true; | |
| 103 } | |
| 104 $ai = (int) $ai; | |
| 105 $ais[] = $ai; | |
| 106 $batch_idx = (int) ($ai / 100); | |
| 107 if (!in_array($spec, $batches[$batch_idx])) { | |
| 108 $batches[$batch_idx][] = $spec; | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 $spec_ais[$spec] = $ais; | |
| 113 if ($comment !== '') { | |
| 114 if (isset($spec_comments[$spec])) { | |
| 115 if (!in_array($comment, $spec_comments[$spec])) { | |
| 116 $spec_comments[$spec][] = $comment; | |
| 117 } | |
| 118 } else { | |
| 119 $spec_comments[$spec] = array($comment); | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 $spec_parts[$spec] = array(); | |
| 124 $parts = explode(' ', $spec); | |
| 125 foreach ($parts as $part) { | |
| 126 $checkers = explode(',', $part); | |
| 127 $validator = array_shift($checkers); | |
| 128 if (preg_match('/^([NXYZ])([0-9]+)?(\.\.[0-9|]+)?$/', $validator, $matches)) { | |
| 129 if (count($matches) === 3) { | |
| 130 $min = $max = (int) $matches[2]; | |
| 131 } else { | |
| 132 $min = $matches[2] === '' ? 1 : (int) $matches[2]; | |
| 133 $max = (int) substr($matches[3], 2); | |
| 134 } | |
| 135 if ($matches[1] === 'N') { | |
| 136 $validator = "numeric"; | |
| 137 } elseif ($matches[1] === 'X') { | |
| 138 $validator = "cset82"; | |
| 139 } elseif ($matches[1] === 'Y') { | |
| 140 $validator = "cset39"; | |
| 141 } else { // 'Z' | |
| 142 $validator = "cset64"; | |
| 143 } | |
| 144 } else if (preg_match('/^\[([NXYZ])([1-9]+)?(\.\.[0-9|]+)?\]$/', $validator, $matches)) { | |
| 145 if (count($matches) === 3) { | |
| 146 $min = 0; | |
| 147 $max = (int) $matches[2]; | |
| 148 } else { | |
| 149 $min = $matches[2] === '' ? 0 : (int) $matches[2]; | |
| 150 $max = (int) substr($matches[3], 2); | |
| 151 } | |
| 152 if ($matches[1] === 'N') { | |
| 153 $validator = "numeric"; | |
| 154 } elseif ($matches[1] === 'X') { | |
| 155 $validator = "cset82"; | |
| 156 } elseif ($matches[1] === 'Y') { | |
| 157 $validator = "cset39"; | |
| 158 } else { // 'Z' | |
| 159 $validator = "cset64"; | |
| 160 } | |
| 161 } else { | |
| 162 exit("$basename:" . __LINE__ . " ERROR: Could not parse validator \"$validator\" line $line_no" | |
| 163 . PHP_EOL); | |
| 164 } | |
| 165 $spec_parts[$spec][] = array($min, $max, $validator, $checkers); | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 // Calculate total min/maxs and convert the AIs into ranges | |
| 170 | |
| 171 foreach ($spec_ais as $spec => $ais) { | |
| 172 // Total min/maxs | |
| 173 $total_min = $total_max = 0; | |
| 174 foreach ($spec_parts[$spec] as list($min, $max)) { | |
| 175 $total_min += $min; | |
| 176 $total_max += $max; | |
| 177 } | |
| 178 | |
| 179 // Sort the AIs | |
| 180 $sort_ais = array(); | |
| 181 foreach ($ais as $ai) { | |
| 182 if (is_array($ai)) { | |
| 183 $sort_ais[] = $ai[0]; | |
| 184 } else { | |
| 185 $sort_ais[] = $ai; | |
| 186 } | |
| 187 } | |
| 188 array_multisort($sort_ais, $ais); | |
| 189 | |
| 190 // Consolidate contiguous AIs into ranges | |
| 191 $tmp_ais = array(); | |
| 192 foreach ($ais as $ai) { | |
| 193 $cnt = count($tmp_ais); | |
| 194 if ($cnt === 0) { | |
| 195 $tmp_ais[] = $ai; | |
| 196 } else { | |
| 197 $prev_ai = $tmp_ais[$cnt - 1]; | |
| 198 if (is_array($prev_ai)) { | |
| 199 $prev_s = $prev_ai[0]; | |
| 200 $prev_e = $prev_ai[1]; | |
| 201 } else { | |
| 202 $prev_e = $prev_s = $prev_ai; | |
| 203 } | |
| 204 if (is_array($ai)) { | |
| 205 $this_s = $ai[0]; | |
| 206 $this_e = $ai[1]; | |
| 207 } else { | |
| 208 $this_s = $this_e = $ai; | |
| 209 } | |
| 210 if ($this_s === $prev_e + 1 && $this_e - $prev_s < 100) { // Confine to batches of 100 | |
| 211 $tmp_ais[$cnt - 1] = array($prev_s, $this_e); | |
| 212 } else { | |
| 213 $tmp_ais[] = $ai; | |
| 214 } | |
| 215 } | |
| 216 } | |
| 217 | |
| 218 // Unconsolidate ranges of 1 into separate entries | |
| 219 $ais = array(); | |
| 220 foreach ($tmp_ais as $ai) { | |
| 221 if (is_array($ai) && $ai[1] === $ai[0] + 1) { | |
| 222 $ais[] = $ai[0]; | |
| 223 $ais[] = $ai[1]; | |
| 224 } else { | |
| 225 $ais[] = $ai; | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 $spec_ais[$spec] = array($total_min, $total_max, $ais); | |
| 230 } | |
| 231 | |
| 232 // Print output | |
| 233 | |
| 234 print <<<EOD | |
| 235 /* | |
| 236 * GS1 AI checker generated by "$dirdirname/$basename" from | |
| 237 * $stripped_file | |
| 238 */ | |
| 239 | |
| 240 EOD; | |
| 241 | |
| 242 if ($print_copyright) { | |
| 243 print <<<'EOD' | |
| 244 /* | |
| 245 libzint - the open source barcode library | |
| 246 Copyright (C) 2021-2024 Robin Stuart <rstuart114@gmail.com> | |
| 247 | |
| 248 Redistribution and use in source and binary forms, with or without | |
| 249 modification, are permitted provided that the following conditions | |
| 250 are met: | |
| 251 | |
| 252 1. Redistributions of source code must retain the above copyright | |
| 253 notice, this list of conditions and the following disclaimer. | |
| 254 2. Redistributions in binary form must reproduce the above copyright | |
| 255 notice, this list of conditions and the following disclaimer in the | |
| 256 documentation and/or other materials provided with the distribution. | |
| 257 3. Neither the name of the project nor the names of its contributors | |
| 258 may be used to endorse or promote products derived from this software | |
| 259 without specific prior written permission. | |
| 260 | |
| 261 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
| 262 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 263 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 264 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE | |
| 265 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 266 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 267 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 268 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 269 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 270 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 271 SUCH DAMAGE. | |
| 272 */ | |
| 273 /* SPDX-License-Identifier: BSD-3-Clause */ | |
| 274 | |
| 275 | |
| 276 EOD; | |
| 277 } | |
| 278 | |
| 279 if ($print_h_guard) { | |
| 280 print <<<'EOD' | |
| 281 #ifndef Z_GS1_LINT_H | |
| 282 #define Z_GS1_LINT_H | |
| 283 | |
| 284 | |
| 285 EOD; | |
| 286 } | |
| 287 | |
| 288 // Print the spec validator/checkers functions | |
| 289 | |
| 290 foreach ($spec_parts as $spec => $spec_part) { | |
| 291 $spec_funcs[$spec] = $spec_func = str_replace(array(' ', '.', ',', '[', ']'), '_', strtolower($spec)); | |
| 292 $comment = ''; | |
| 293 if (isset($spec_comments[$spec])) { | |
| 294 $comment = ' (Used by'; | |
| 295 foreach ($spec_comments[$spec] as $i => $spec_comment) { | |
| 296 if ($i) { | |
| 297 $comment .= ', '; | |
| 298 } else { | |
| 299 $comment .= ' '; | |
| 300 } | |
| 301 $comment .= $spec_comment; | |
| 302 } | |
| 303 if (strlen($comment) > 118 - 3 /*start comment*/ - 4 /*)end comment*/ - strlen($spec)) { | |
| 304 $comment = substr($comment, 0, 118 - 3 - 4 - strlen($spec) - 3) . '...'; | |
| 305 } | |
| 306 $comment .= ')'; | |
| 307 } | |
| 308 print <<<EOD | |
| 309 /* $spec$comment */ | |
| 310 static int $spec_func(const unsigned char *data, | |
| 311 $tab$tab{$tab}const int data_len, int *p_err_no, int *p_err_posn, char err_msg[50]) { | |
| 312 {$tab}return | |
| 313 EOD; | |
| 314 | |
| 315 list($total_min, $total_max) = $spec_ais[$spec]; | |
| 316 if ($total_min === $total_max) { | |
| 317 print "data_len == $total_max"; | |
| 318 } else { | |
| 319 print "data_len >= $total_min && data_len <= $total_max"; | |
| 320 } | |
| 321 | |
| 322 if ($use_length_only) { | |
| 323 // Call checkers checking for length only first | |
| 324 $length_only_arg = ", 1 /*length_only*/"; | |
| 325 $offset = 0; | |
| 326 foreach ($spec_part as list($min, $max, $validator, $checkers)) { | |
| 327 foreach ($checkers as $checker) { | |
| 328 print <<<EOD | |
| 329 | |
| 330 $tab$tab{$tab}&& $checker(data, data_len, $offset, $min, $max, p_err_no, p_err_posn, err_msg$length_only_arg) | |
| 331 EOD; | |
| 332 } | |
| 333 | |
| 334 $offset += $max; | |
| 335 } | |
| 336 } | |
| 337 | |
| 338 // Validator and full checkers | |
| 339 $length_only_arg = $use_length_only ? ", 0" : ""; | |
| 340 $offset = 0; | |
| 341 foreach ($spec_part as list($min, $max, $validator, $checkers)) { | |
| 342 print <<<EOD | |
| 343 | |
| 344 $tab$tab{$tab}&& $validator(data, data_len, $offset, $min, $max, p_err_no, p_err_posn, err_msg) | |
| 345 EOD; | |
| 346 | |
| 347 foreach ($checkers as $checker) { | |
| 348 print <<<EOD | |
| 349 | |
| 350 $tab$tab{$tab}&& $checker(data, data_len, $offset, $min, $max, p_err_no, p_err_posn, err_msg$length_only_arg) | |
| 351 EOD; | |
| 352 } | |
| 353 | |
| 354 $offset += $max; | |
| 355 } | |
| 356 print ";\n}\n\n"; | |
| 357 } | |
| 358 | |
| 359 // Print main routine | |
| 360 | |
| 361 print <<<EOD | |
| 362 /* Entry point. Returns 1 on success, 0 on failure: `*p_err_no` set to 1 if unknown AI, 2 if bad data length */ | |
| 363 static int gs1_lint(const int ai, const unsigned char *data, const int data_len, int *p_err_no, int *p_err_posn, | |
| 364 $tab$tab{$tab}char err_msg[50]) { | |
| 365 | |
| 366 $tab/* Assume data length failure */ | |
| 367 $tab*p_err_no = 2; | |
| 368 | |
| 369 EOD; | |
| 370 | |
| 371 // Split AIs into batches of 100 to lessen the number of comparisons | |
| 372 | |
| 373 $not_first_batch = false; | |
| 374 $last_batch_e = -1; | |
| 375 foreach ($batches as $batch => $batch_specs) { | |
| 376 if (empty($batch_specs)) { | |
| 377 continue; | |
| 378 } | |
| 379 $batch_s = $batch * 100; | |
| 380 $batch_e = $batch_s + 100; | |
| 381 if ($not_first_batch) { | |
| 382 print "\n$tab} else if (ai < $batch_e) {\n\n"; | |
| 383 } else { | |
| 384 print "\n{$tab}if (ai < $batch_e) {\n\n"; | |
| 385 $not_first_batch = true; | |
| 386 } | |
| 387 foreach ($batch_specs as $spec) { | |
| 388 $total_min = $spec_ais[$spec][0]; | |
| 389 $total_max = $spec_ais[$spec][1]; | |
| 390 $ais = $spec_ais[$spec][2]; | |
| 391 | |
| 392 $str = "$tab{$tab}if ("; | |
| 393 print $str; | |
| 394 $width = strlen($str); | |
| 395 | |
| 396 // Count the applicable AIs | |
| 397 $ais_cnt = 0; | |
| 398 foreach ($ais as $ai) { | |
| 399 if (is_array($ai)) { | |
| 400 if ($ai[1] < $batch_s || $ai[0] >= $batch_e) { | |
| 401 continue; | |
| 402 } | |
| 403 } else { | |
| 404 if ($ai < $batch_s || $ai >= $batch_e) { | |
| 405 continue; | |
| 406 } | |
| 407 } | |
| 408 $ais_cnt++; | |
| 409 } | |
| 410 | |
| 411 // Output | |
| 412 $not_first_ai = false; | |
| 413 foreach ($ais as $ai) { | |
| 414 if (is_array($ai)) { | |
| 415 if ($ai[1] < $batch_s || $ai[0] >= $batch_e) { | |
| 416 continue; | |
| 417 } | |
| 418 } else { | |
| 419 if ($ai < $batch_s || $ai >= $batch_e) { | |
| 420 continue; | |
| 421 } | |
| 422 } | |
| 423 | |
| 424 $str = ''; | |
| 425 if ($not_first_ai) { | |
| 426 $str .= " || "; | |
| 427 } else { | |
| 428 $not_first_ai = true; | |
| 429 } | |
| 430 if (is_array($ai)) { | |
| 431 if ($ai[0] === $last_batch_e) { // Don't need 1st element of range if excluded by previous batch | |
| 432 $str .= "ai <= " . $ai[1]; | |
| 433 } else if ($ai[1] + 1 == $batch_e) { // Don't need 2nd element of range if excluded by this batch | |
| 434 $str .= "ai >= " . $ai[0]; | |
| 435 } else { | |
| 436 if ($ais_cnt > 1) { | |
| 437 $str .= "(ai >= " . $ai[0] . " && ai <= " . $ai[1] . ")"; | |
| 438 } else { | |
| 439 $str .= "ai >= " . $ai[0] . " && ai <= " . $ai[1]; | |
| 440 } | |
| 441 } | |
| 442 } else { | |
| 443 $str .= "ai == " . $ai; | |
| 444 } | |
| 445 if ($width + strlen($str) > 118) { | |
| 446 print "\n"; | |
| 447 $str2 = "$tab$tab$tab "; | |
| 448 print $str2; | |
| 449 $width = strlen($str2); | |
| 450 } | |
| 451 print $str; | |
| 452 $width += strlen($str); | |
| 453 } | |
| 454 $spec_func = $spec_funcs[$spec]; | |
| 455 $str = "$tab$tab{$tab}return $spec_func(data, data_len, p_err_no, p_err_posn, err_msg);"; | |
| 456 if (strlen($str) > 118) { | |
| 457 print ") {\n$tab$tab{$tab}return $spec_func(data,\n"; | |
| 458 print "$tab$tab$tab$tab$tab{$tab}data_len, p_err_no, p_err_posn, err_msg);\n"; | |
| 459 } else { | |
| 460 print ") {\n$str\n"; | |
| 461 } | |
| 462 print <<<EOD | |
| 463 $tab$tab} | |
| 464 | |
| 465 EOD; | |
| 466 } | |
| 467 $last_batch_e = $batch_e; | |
| 468 } | |
| 469 | |
| 470 print <<<EOD | |
| 471 $tab} | |
| 472 | |
| 473 {$tab}/* Unknown AI */ | |
| 474 {$tab}*p_err_no = 1; | |
| 475 {$tab}return 0; | |
| 476 } | |
| 477 | |
| 478 EOD; | |
| 479 | |
| 480 if ($print_h_guard) { | |
| 481 print <<<'EOD' | |
| 482 | |
| 483 #endif /* Z_GS1_LINT_H */ | |
| 484 | |
| 485 EOD; | |
| 486 } | |
| 487 | |
| 488 /* vim: set ts=4 sw=4 et : */ |
