1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org> 5 * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/types.h> 34 35 #include <errno.h> 36 #include <err.h> 37 #include <langinfo.h> 38 #include <limits.h> 39 #include <math.h> 40 #include <md5.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <wchar.h> 44 #include <wctype.h> 45 46 #include "coll.h" 47 #include "vsort.h" 48 49 struct key_specs *keys; 50 size_t keys_num = 0; 51 52 wint_t symbol_decimal_point = L'.'; 53 /* there is no default thousands separator in collate rules: */ 54 wint_t symbol_thousands_sep = 0; 55 wint_t symbol_negative_sign = L'-'; 56 wint_t symbol_positive_sign = L'+'; 57 58 static int wstrcoll(struct key_value *kv1, struct key_value *kv2, size_t offset); 59 static int gnumcoll(struct key_value*, struct key_value *, size_t offset); 60 static int monthcoll(struct key_value*, struct key_value *, size_t offset); 61 static int numcoll(struct key_value*, struct key_value *, size_t offset); 62 static int hnumcoll(struct key_value*, struct key_value *, size_t offset); 63 static int randomcoll(struct key_value*, struct key_value *, size_t offset); 64 static int versioncoll(struct key_value*, struct key_value *, size_t offset); 65 66 /* 67 * Allocate keys array 68 */ 69 struct keys_array * 70 keys_array_alloc(void) 71 { 72 struct keys_array *ka; 73 size_t sz; 74 75 sz = keys_array_size(); 76 ka = sort_calloc(1, sz); 77 78 return (ka); 79 } 80 81 /* 82 * Calculate whether we need key hint space 83 */ 84 static size_t 85 key_hint_size(void) 86 { 87 88 return (need_hint ? sizeof(struct key_hint) : 0); 89 } 90 91 /* 92 * Calculate keys array size 93 */ 94 size_t 95 keys_array_size(void) 96 { 97 98 return (keys_num * (sizeof(struct key_value) + key_hint_size())); 99 } 100 101 /* 102 * Clean data of keys array 103 */ 104 void 105 clean_keys_array(const struct bwstring *s, struct keys_array *ka) 106 { 107 108 if (ka) { 109 for (size_t i = 0; i < keys_num; ++i) { 110 const struct key_value *kv; 111 112 kv = get_key_from_keys_array(ka, i); 113 if (kv->k && kv->k != s) 114 bwsfree(kv->k); 115 } 116 memset(ka, 0, keys_array_size()); 117 } 118 } 119 120 /* 121 * Get pointer to a key value in the keys set 122 */ 123 struct key_value * 124 get_key_from_keys_array(struct keys_array *ka, size_t ind) 125 { 126 127 return ((struct key_value *)((caddr_t)ka->key + 128 ind * (sizeof(struct key_value) + key_hint_size()))); 129 } 130 131 /* 132 * Set value of a key in the keys set 133 */ 134 void 135 set_key_on_keys_array(struct keys_array *ka, struct bwstring *s, size_t ind) 136 { 137 138 if (ka && keys_num > ind) { 139 struct key_value *kv; 140 141 kv = get_key_from_keys_array(ka, ind); 142 143 if (kv->k && kv->k != s) 144 bwsfree(kv->k); 145 kv->k = s; 146 } 147 } 148 149 /* 150 * Initialize a sort list item 151 */ 152 struct sort_list_item * 153 sort_list_item_alloc(void) 154 { 155 struct sort_list_item *si; 156 size_t sz; 157 158 sz = sizeof(struct sort_list_item) + keys_array_size(); 159 si = sort_calloc(1, sz); 160 161 return (si); 162 } 163 164 size_t 165 sort_list_item_size(struct sort_list_item *si) 166 { 167 size_t ret = 0; 168 169 if (si) { 170 ret = sizeof(struct sort_list_item) + keys_array_size(); 171 if (si->str) 172 ret += bws_memsize(si->str); 173 for (size_t i = 0; i < keys_num; ++i) { 174 const struct key_value *kv; 175 176 kv = get_key_from_keys_array(&si->ka, i); 177 178 if (kv->k != si->str) 179 ret += bws_memsize(kv->k); 180 } 181 } 182 return (ret); 183 } 184 185 /* 186 * Calculate key for a sort list item 187 */ 188 static void 189 sort_list_item_make_key(struct sort_list_item *si) 190 { 191 192 preproc(si->str, &(si->ka)); 193 } 194 195 /* 196 * Set value of a sort list item. 197 * Return combined string and keys memory size. 198 */ 199 void 200 sort_list_item_set(struct sort_list_item *si, struct bwstring *str) 201 { 202 203 if (si) { 204 clean_keys_array(si->str, &(si->ka)); 205 if (si->str) { 206 if (si->str == str) { 207 /* we are trying to reset the same string */ 208 return; 209 } else { 210 bwsfree(si->str); 211 si->str = NULL; 212 } 213 } 214 si->str = str; 215 sort_list_item_make_key(si); 216 } 217 } 218 219 /* 220 * De-allocate a sort list item object memory 221 */ 222 void 223 sort_list_item_clean(struct sort_list_item *si) 224 { 225 226 if (si) { 227 clean_keys_array(si->str, &(si->ka)); 228 if (si->str) { 229 bwsfree(si->str); 230 si->str = NULL; 231 } 232 } 233 } 234 235 /* 236 * Skip columns according to specs 237 */ 238 static size_t 239 skip_cols_to_start(const struct bwstring *s, size_t cols, size_t start, 240 bool skip_blanks, bool *empty_key) 241 { 242 if (cols < 1) 243 return (BWSLEN(s) + 1); 244 245 if (skip_blanks) 246 while (start < BWSLEN(s) && iswblank(BWS_GET(s,start))) 247 ++start; 248 249 while (start < BWSLEN(s) && cols > 1) { 250 --cols; 251 ++start; 252 } 253 254 if (start >= BWSLEN(s)) 255 *empty_key = true; 256 257 return (start); 258 } 259 260 /* 261 * Skip fields according to specs 262 */ 263 static size_t 264 skip_fields_to_start(const struct bwstring *s, size_t fields, bool *empty_field) 265 { 266 267 if (fields < 2) { 268 if (BWSLEN(s) == 0) 269 *empty_field = true; 270 return (0); 271 } else if (!(sort_opts_vals.tflag)) { 272 size_t cpos = 0; 273 bool pb = true; 274 275 while (cpos < BWSLEN(s)) { 276 bool isblank; 277 278 isblank = iswblank(BWS_GET(s, cpos)); 279 280 if (isblank && !pb) { 281 --fields; 282 if (fields <= 1) 283 return (cpos); 284 } 285 pb = isblank; 286 ++cpos; 287 } 288 if (fields > 1) 289 *empty_field = true; 290 return (cpos); 291 } else { 292 size_t cpos = 0; 293 294 while (cpos < BWSLEN(s)) { 295 if (BWS_GET(s,cpos) == (wchar_t)sort_opts_vals.field_sep) { 296 --fields; 297 if (fields <= 1) 298 return (cpos + 1); 299 } 300 ++cpos; 301 } 302 if (fields > 1) 303 *empty_field = true; 304 return (cpos); 305 } 306 } 307 308 /* 309 * Find fields start 310 */ 311 static void 312 find_field_start(const struct bwstring *s, struct key_specs *ks, 313 size_t *field_start, size_t *key_start, bool *empty_field, bool *empty_key) 314 { 315 316 *field_start = skip_fields_to_start(s, ks->f1, empty_field); 317 if (!*empty_field) 318 *key_start = skip_cols_to_start(s, ks->c1, *field_start, 319 ks->pos1b, empty_key); 320 else 321 *empty_key = true; 322 } 323 324 /* 325 * Find end key position 326 */ 327 static size_t 328 find_field_end(const struct bwstring *s, struct key_specs *ks) 329 { 330 size_t f2, next_field_start, pos_end; 331 bool empty_field, empty_key; 332 333 empty_field = false; 334 empty_key = false; 335 f2 = ks->f2; 336 337 if (f2 == 0) 338 return (BWSLEN(s) + 1); 339 else { 340 if (ks->c2 == 0) { 341 next_field_start = skip_fields_to_start(s, f2 + 1, 342 &empty_field); 343 if ((next_field_start > 0) && sort_opts_vals.tflag && 344 ((wchar_t)sort_opts_vals.field_sep == BWS_GET(s, 345 next_field_start - 1))) 346 --next_field_start; 347 } else 348 next_field_start = skip_fields_to_start(s, f2, 349 &empty_field); 350 } 351 352 if (empty_field || (next_field_start >= BWSLEN(s))) 353 return (BWSLEN(s) + 1); 354 355 if (ks->c2) { 356 pos_end = skip_cols_to_start(s, ks->c2, next_field_start, 357 ks->pos2b, &empty_key); 358 if (pos_end < BWSLEN(s)) 359 ++pos_end; 360 } else 361 pos_end = next_field_start; 362 363 return (pos_end); 364 } 365 366 /* 367 * Cut a field according to the key specs 368 */ 369 static struct bwstring * 370 cut_field(const struct bwstring *s, struct key_specs *ks) 371 { 372 struct bwstring *ret = NULL; 373 374 if (s && ks) { 375 size_t field_start, key_end, key_start, sz; 376 bool empty_field, empty_key; 377 378 field_start = 0; 379 key_start = 0; 380 empty_field = false; 381 empty_key = false; 382 383 find_field_start(s, ks, &field_start, &key_start, 384 &empty_field, &empty_key); 385 386 if (empty_key) 387 sz = 0; 388 else { 389 key_end = find_field_end(s, ks); 390 sz = (key_end < key_start) ? 0 : (key_end - key_start); 391 } 392 393 ret = bwsalloc(sz); 394 if (sz) 395 bwsnocpy(ret, s, key_start, sz); 396 } else 397 ret = bwsalloc(0); 398 399 return (ret); 400 } 401 402 /* 403 * Preprocesses a line applying the necessary transformations 404 * specified by command line options and returns the preprocessed 405 * string, which can be used to compare. 406 */ 407 int 408 preproc(struct bwstring *s, struct keys_array *ka) 409 { 410 411 if (sort_opts_vals.kflag) 412 for (size_t i = 0; i < keys_num; i++) { 413 struct bwstring *key; 414 struct key_specs *kspecs; 415 struct sort_mods *sm; 416 417 kspecs = &(keys[i]); 418 key = cut_field(s, kspecs); 419 420 sm = &(kspecs->sm); 421 if (sm->dflag) 422 key = dictionary_order(key); 423 else if (sm->iflag) 424 key = ignore_nonprinting(key); 425 if (sm->fflag || sm->Mflag) 426 key = ignore_case(key); 427 428 set_key_on_keys_array(ka, key, i); 429 } 430 else { 431 struct bwstring *ret = NULL; 432 struct sort_mods *sm = default_sort_mods; 433 434 if (sm->bflag) { 435 if (ret == NULL) 436 ret = bwsdup(s); 437 ret = ignore_leading_blanks(ret); 438 } 439 if (sm->dflag) { 440 if (ret == NULL) 441 ret = bwsdup(s); 442 ret = dictionary_order(ret); 443 } else if (sm->iflag) { 444 if (ret == NULL) 445 ret = bwsdup(s); 446 ret = ignore_nonprinting(ret); 447 } 448 if (sm->fflag || sm->Mflag) { 449 if (ret == NULL) 450 ret = bwsdup(s); 451 ret = ignore_case(ret); 452 } 453 if (ret == NULL) 454 set_key_on_keys_array(ka, s, 0); 455 else 456 set_key_on_keys_array(ka, ret, 0); 457 } 458 459 return 0; 460 } 461 462 cmpcoll_t 463 get_sort_func(struct sort_mods *sm) 464 { 465 466 if (sm->nflag) 467 return (numcoll); 468 else if (sm->hflag) 469 return (hnumcoll); 470 else if (sm->gflag) 471 return (gnumcoll); 472 else if (sm->Mflag) 473 return (monthcoll); 474 else if (sm->Rflag) 475 return (randomcoll); 476 else if (sm->Vflag) 477 return (versioncoll); 478 else 479 return (wstrcoll); 480 } 481 482 /* 483 * Compares the given strings. Returns a positive number if 484 * the first precedes the second, a negative number if the second is 485 * the preceding one, and zero if they are equal. This function calls 486 * the underlying collate functions, which done the actual comparison. 487 */ 488 int 489 key_coll(struct keys_array *ps1, struct keys_array *ps2, size_t offset) 490 { 491 struct key_value *kv1, *kv2; 492 struct sort_mods *sm; 493 int res = 0; 494 495 for (size_t i = 0; i < keys_num; ++i) { 496 kv1 = get_key_from_keys_array(ps1, i); 497 kv2 = get_key_from_keys_array(ps2, i); 498 sm = &(keys[i].sm); 499 500 if (sm->rflag) 501 res = sm->func(kv2, kv1, offset); 502 else 503 res = sm->func(kv1, kv2, offset); 504 505 if (res) 506 break; 507 508 /* offset applies to only the first key */ 509 offset = 0; 510 } 511 return (res); 512 } 513 514 /* 515 * Compare two strings. 516 * Plain symbol-by-symbol comparison. 517 */ 518 int 519 top_level_str_coll(const struct bwstring *s1, const struct bwstring *s2) 520 { 521 522 if (default_sort_mods->rflag) { 523 const struct bwstring *tmp; 524 525 tmp = s1; 526 s1 = s2; 527 s2 = tmp; 528 } 529 530 return (bwscoll(s1, s2, 0)); 531 } 532 533 /* 534 * Compare a string and a sort list item, according to the sort specs. 535 */ 536 int 537 str_list_coll(struct bwstring *str1, struct sort_list_item **ss2) 538 { 539 struct keys_array *ka1; 540 int ret = 0; 541 542 ka1 = keys_array_alloc(); 543 544 preproc(str1, ka1); 545 546 sort_list_item_make_key(*ss2); 547 548 if (debug_sort) { 549 bwsprintf(stdout, str1, "; s1=<", ">"); 550 bwsprintf(stdout, (*ss2)->str, ", s2=<", ">"); 551 } 552 553 ret = key_coll(ka1, &((*ss2)->ka), 0); 554 555 if (debug_sort) 556 printf("; cmp1=%d", ret); 557 558 clean_keys_array(str1, ka1); 559 sort_free(ka1); 560 561 if ((ret == 0) && !(sort_opts_vals.sflag) && sort_opts_vals.complex_sort) { 562 ret = top_level_str_coll(str1, ((*ss2)->str)); 563 if (debug_sort) 564 printf("; cmp2=%d", ret); 565 } 566 567 if (debug_sort) 568 printf("\n"); 569 570 return (ret); 571 } 572 573 /* 574 * Compare two sort list items, according to the sort specs. 575 */ 576 int 577 list_coll_offset(struct sort_list_item **ss1, struct sort_list_item **ss2, 578 size_t offset) 579 { 580 int ret; 581 582 ret = key_coll(&((*ss1)->ka), &((*ss2)->ka), offset); 583 584 if (debug_sort) { 585 if (offset) 586 printf("; offset=%d", (int) offset); 587 bwsprintf(stdout, ((*ss1)->str), "; s1=<", ">"); 588 bwsprintf(stdout, ((*ss2)->str), ", s2=<", ">"); 589 printf("; cmp1=%d\n", ret); 590 } 591 592 if (ret) 593 return (ret); 594 595 if (!(sort_opts_vals.sflag) && sort_opts_vals.complex_sort) { 596 ret = top_level_str_coll(((*ss1)->str), ((*ss2)->str)); 597 if (debug_sort) 598 printf("; cmp2=%d\n", ret); 599 } 600 601 return (ret); 602 } 603 604 /* 605 * Compare two sort list items, according to the sort specs. 606 */ 607 int 608 list_coll(struct sort_list_item **ss1, struct sort_list_item **ss2) 609 { 610 611 return (list_coll_offset(ss1, ss2, 0)); 612 } 613 614 #define LSCDEF(N) \ 615 static int \ 616 list_coll_##N(struct sort_list_item **ss1, struct sort_list_item **ss2) \ 617 { \ 618 \ 619 return (list_coll_offset(ss1, ss2, N)); \ 620 } 621 622 LSCDEF(1) 623 LSCDEF(2) 624 LSCDEF(3) 625 LSCDEF(4) 626 LSCDEF(5) 627 LSCDEF(6) 628 LSCDEF(7) 629 LSCDEF(8) 630 LSCDEF(9) 631 LSCDEF(10) 632 LSCDEF(11) 633 LSCDEF(12) 634 LSCDEF(13) 635 LSCDEF(14) 636 LSCDEF(15) 637 LSCDEF(16) 638 LSCDEF(17) 639 LSCDEF(18) 640 LSCDEF(19) 641 LSCDEF(20) 642 643 listcoll_t 644 get_list_call_func(size_t offset) 645 { 646 static const listcoll_t lsarray[] = { list_coll, list_coll_1, 647 list_coll_2, list_coll_3, list_coll_4, list_coll_5, 648 list_coll_6, list_coll_7, list_coll_8, list_coll_9, 649 list_coll_10, list_coll_11, list_coll_12, list_coll_13, 650 list_coll_14, list_coll_15, list_coll_16, list_coll_17, 651 list_coll_18, list_coll_19, list_coll_20 }; 652 653 if (offset <= 20) 654 return (lsarray[offset]); 655 656 return (list_coll); 657 } 658 659 /* 660 * Compare two sort list items, only by their original string. 661 */ 662 int 663 list_coll_by_str_only(struct sort_list_item **ss1, struct sort_list_item **ss2) 664 { 665 666 return (top_level_str_coll(((*ss1)->str), ((*ss2)->str))); 667 } 668 669 /* 670 * Maximum size of a number in the string (before or after decimal point) 671 */ 672 #define MAX_NUM_SIZE (128) 673 674 /* 675 * Set suffix value 676 */ 677 static void setsuffix(wchar_t c, unsigned char *si) 678 { 679 switch (c){ 680 case L'k': 681 case L'K': 682 *si = 1; 683 break; 684 case L'M': 685 *si = 2; 686 break; 687 case L'G': 688 *si = 3; 689 break; 690 case L'T': 691 *si = 4; 692 break; 693 case L'P': 694 *si = 5; 695 break; 696 case L'E': 697 *si = 6; 698 break; 699 case L'Z': 700 *si = 7; 701 break; 702 case L'Y': 703 *si = 8; 704 break; 705 default: 706 *si = 0; 707 } 708 } 709 710 /* 711 * Read string s and parse the string into a fixed-decimal-point number. 712 * sign equals -1 if the number is negative (explicit plus is not allowed, 713 * according to GNU sort's "info sort". 714 * The number part before decimal point is in the smain, after the decimal 715 * point is in sfrac, tail is the pointer to the remainder of the string. 716 */ 717 static int 718 read_number(struct bwstring *s0, int *sign, wchar_t *smain, size_t *main_len, wchar_t *sfrac, size_t *frac_len, unsigned char *si) 719 { 720 bwstring_iterator s; 721 722 s = bws_begin(s0); 723 724 /* always end the fraction with zero, even if we have no fraction */ 725 sfrac[0] = 0; 726 727 while (iswblank(bws_get_iter_value(s))) 728 s = bws_iterator_inc(s, 1); 729 730 if (bws_get_iter_value(s) == (wchar_t)symbol_negative_sign) { 731 *sign = -1; 732 s = bws_iterator_inc(s, 1); 733 } 734 735 // This is '0', not '\0', do not change this 736 while (iswdigit(bws_get_iter_value(s)) && 737 (bws_get_iter_value(s) == L'0')) 738 s = bws_iterator_inc(s, 1); 739 740 while (bws_get_iter_value(s) && *main_len < MAX_NUM_SIZE) { 741 if (iswdigit(bws_get_iter_value(s))) { 742 smain[*main_len] = bws_get_iter_value(s); 743 s = bws_iterator_inc(s, 1); 744 *main_len += 1; 745 } else if (symbol_thousands_sep && 746 (bws_get_iter_value(s) == (wchar_t)symbol_thousands_sep)) 747 s = bws_iterator_inc(s, 1); 748 else 749 break; 750 } 751 752 smain[*main_len] = 0; 753 754 if (bws_get_iter_value(s) == (wchar_t)symbol_decimal_point) { 755 s = bws_iterator_inc(s, 1); 756 while (iswdigit(bws_get_iter_value(s)) && 757 *frac_len < MAX_NUM_SIZE) { 758 sfrac[*frac_len] = bws_get_iter_value(s); 759 s = bws_iterator_inc(s, 1); 760 *frac_len += 1; 761 } 762 sfrac[*frac_len] = 0; 763 764 while (*frac_len > 0 && sfrac[*frac_len - 1] == L'0') { 765 --(*frac_len); 766 sfrac[*frac_len] = L'\0'; 767 } 768 } 769 770 setsuffix(bws_get_iter_value(s),si); 771 772 if ((*main_len + *frac_len) == 0) 773 *sign = 0; 774 775 return (0); 776 } 777 778 /* 779 * Implements string sort. 780 */ 781 static int 782 wstrcoll(struct key_value *kv1, struct key_value *kv2, size_t offset) 783 { 784 785 if (debug_sort) { 786 if (offset) 787 printf("; offset=%d\n", (int) offset); 788 bwsprintf(stdout, kv1->k, "; k1=<", ">"); 789 printf("(%zu)", BWSLEN(kv1->k)); 790 bwsprintf(stdout, kv2->k, ", k2=<", ">"); 791 printf("(%zu)", BWSLEN(kv2->k)); 792 } 793 794 return (bwscoll(kv1->k, kv2->k, offset)); 795 } 796 797 /* 798 * Compare two suffixes 799 */ 800 static inline int 801 cmpsuffix(unsigned char si1, unsigned char si2) 802 { 803 804 return ((char)si1 - (char)si2); 805 } 806 807 /* 808 * Implements numeric sort for -n and -h. 809 */ 810 static int 811 numcoll_impl(struct key_value *kv1, struct key_value *kv2, 812 size_t offset __unused, bool use_suffix) 813 { 814 struct bwstring *s1, *s2; 815 wchar_t sfrac1[MAX_NUM_SIZE + 1], sfrac2[MAX_NUM_SIZE + 1]; 816 wchar_t smain1[MAX_NUM_SIZE + 1], smain2[MAX_NUM_SIZE + 1]; 817 int cmp_res, sign1, sign2; 818 size_t frac1, frac2, main1, main2; 819 unsigned char SI1, SI2; 820 bool e1, e2, key1_read, key2_read; 821 822 s1 = kv1->k; 823 s2 = kv2->k; 824 sign1 = sign2 = 0; 825 main1 = main2 = 0; 826 frac1 = frac2 = 0; 827 828 key1_read = key2_read = false; 829 830 if (debug_sort) { 831 bwsprintf(stdout, s1, "; k1=<", ">"); 832 bwsprintf(stdout, s2, ", k2=<", ">"); 833 } 834 835 if (s1 == s2) 836 return (0); 837 838 if (kv1->hint->status == HS_UNINITIALIZED) { 839 /* read the number from the string */ 840 read_number(s1, &sign1, smain1, &main1, sfrac1, &frac1, &SI1); 841 key1_read = true; 842 kv1->hint->v.nh.n1 = wcstoull(smain1, NULL, 10); 843 if(main1 < 1 && frac1 < 1) 844 kv1->hint->v.nh.empty=true; 845 kv1->hint->v.nh.si = SI1; 846 kv1->hint->status = (kv1->hint->v.nh.n1 != ULLONG_MAX) ? 847 HS_INITIALIZED : HS_ERROR; 848 kv1->hint->v.nh.neg = (sign1 < 0) ? true : false; 849 } 850 851 if (kv2->hint->status == HS_UNINITIALIZED) { 852 /* read the number from the string */ 853 read_number(s2, &sign2, smain2, &main2, sfrac2, &frac2,&SI2); 854 key2_read = true; 855 kv2->hint->v.nh.n1 = wcstoull(smain2, NULL, 10); 856 if(main2 < 1 && frac2 < 1) 857 kv2->hint->v.nh.empty=true; 858 kv2->hint->v.nh.si = SI2; 859 kv2->hint->status = (kv2->hint->v.nh.n1 != ULLONG_MAX) ? 860 HS_INITIALIZED : HS_ERROR; 861 kv2->hint->v.nh.neg = (sign2 < 0) ? true : false; 862 } 863 864 if (kv1->hint->status == HS_INITIALIZED && kv2->hint->status == 865 HS_INITIALIZED) { 866 unsigned long long n1, n2; 867 bool neg1, neg2; 868 869 e1 = kv1->hint->v.nh.empty; 870 e2 = kv2->hint->v.nh.empty; 871 872 if (e1 && e2) 873 return (0); 874 875 neg1 = kv1->hint->v.nh.neg; 876 neg2 = kv2->hint->v.nh.neg; 877 878 if (neg1 && !neg2) 879 return (-1); 880 if (neg2 && !neg1) 881 return (+1); 882 883 if (e1) 884 return (neg2 ? +1 : -1); 885 else if (e2) 886 return (neg1 ? -1 : +1); 887 888 889 if (use_suffix) { 890 cmp_res = cmpsuffix(kv1->hint->v.nh.si, kv2->hint->v.nh.si); 891 if (cmp_res) 892 return (neg1 ? -cmp_res : cmp_res); 893 } 894 895 n1 = kv1->hint->v.nh.n1; 896 n2 = kv2->hint->v.nh.n1; 897 if (n1 < n2) 898 return (neg1 ? +1 : -1); 899 else if (n1 > n2) 900 return (neg1 ? -1 : +1); 901 } 902 903 /* read the numbers from the strings */ 904 if (!key1_read) 905 read_number(s1, &sign1, smain1, &main1, sfrac1, &frac1, &SI1); 906 if (!key2_read) 907 read_number(s2, &sign2, smain2, &main2, sfrac2, &frac2, &SI2); 908 909 e1 = ((main1 + frac1) == 0); 910 e2 = ((main2 + frac2) == 0); 911 912 if (e1 && e2) 913 return (0); 914 915 /* we know the result if the signs are different */ 916 if (sign1 < 0 && sign2 >= 0) 917 return (-1); 918 if (sign1 >= 0 && sign2 < 0) 919 return (+1); 920 921 if (e1) 922 return ((sign2 < 0) ? +1 : -1); 923 else if (e2) 924 return ((sign1 < 0) ? -1 : +1); 925 926 if (use_suffix) { 927 cmp_res = cmpsuffix(SI1, SI2); 928 if (cmp_res) 929 return ((sign1 < 0) ? -cmp_res : cmp_res); 930 } 931 932 /* if both numbers are empty assume that the strings are equal */ 933 if (main1 < 1 && main2 < 1 && frac1 < 1 && frac2 < 1) 934 return (0); 935 936 /* 937 * if the main part is of different size, we know the result 938 * (because the leading zeros are removed) 939 */ 940 if (main1 < main2) 941 cmp_res = -1; 942 else if (main1 > main2) 943 cmp_res = +1; 944 /* if the sizes are equal then simple non-collate string compare gives the correct result */ 945 else 946 cmp_res = wcscmp(smain1, smain2); 947 948 /* check fraction */ 949 if (!cmp_res) 950 cmp_res = wcscmp(sfrac1, sfrac2); 951 952 if (!cmp_res) 953 return (0); 954 955 /* reverse result if the signs are negative */ 956 if (sign1 < 0 && sign2 < 0) 957 cmp_res = -cmp_res; 958 959 return (cmp_res); 960 } 961 962 /* 963 * Implements numeric sort (-n). 964 */ 965 static int 966 numcoll(struct key_value *kv1, struct key_value *kv2, size_t offset) 967 { 968 969 return (numcoll_impl(kv1, kv2, offset, false)); 970 } 971 972 /* 973 * Implements 'human' numeric sort (-h). 974 */ 975 static int 976 hnumcoll(struct key_value *kv1, struct key_value *kv2, size_t offset) 977 { 978 979 return (numcoll_impl(kv1, kv2, offset, true)); 980 } 981 982 /* Use hint space to memoize md5 computations, at least. */ 983 static void 984 randomcoll_init_hint(struct key_value *kv, void *hash) 985 { 986 987 memcpy(kv->hint->v.Rh.cached, hash, sizeof(kv->hint->v.Rh.cached)); 988 kv->hint->status = HS_INITIALIZED; 989 } 990 991 /* 992 * Implements random sort (-R). 993 */ 994 static int 995 randomcoll(struct key_value *kv1, struct key_value *kv2, 996 size_t offset __unused) 997 { 998 struct bwstring *s1, *s2; 999 MD5_CTX ctx1, ctx2; 1000 unsigned char hash1[MD5_DIGEST_LENGTH], hash2[MD5_DIGEST_LENGTH]; 1001 int cmp; 1002 1003 s1 = kv1->k; 1004 s2 = kv2->k; 1005 1006 if (debug_sort) { 1007 bwsprintf(stdout, s1, "; k1=<", ">"); 1008 bwsprintf(stdout, s2, ", k2=<", ">"); 1009 } 1010 1011 if (s1 == s2) 1012 return (0); 1013 1014 if (kv1->hint->status == HS_INITIALIZED && 1015 kv2->hint->status == HS_INITIALIZED) { 1016 cmp = memcmp(kv1->hint->v.Rh.cached, 1017 kv2->hint->v.Rh.cached, sizeof(kv1->hint->v.Rh.cached)); 1018 if (cmp != 0) 1019 return (cmp); 1020 } 1021 1022 memcpy(&ctx1, &md5_ctx, sizeof(MD5_CTX)); 1023 memcpy(&ctx2, &md5_ctx, sizeof(MD5_CTX)); 1024 1025 MD5Update(&ctx1, bwsrawdata(s1), bwsrawlen(s1)); 1026 MD5Update(&ctx2, bwsrawdata(s2), bwsrawlen(s2)); 1027 1028 MD5Final(hash1, &ctx1); 1029 MD5Final(hash2, &ctx2); 1030 1031 if (kv1->hint->status == HS_UNINITIALIZED) 1032 randomcoll_init_hint(kv1, hash1); 1033 if (kv2->hint->status == HS_UNINITIALIZED) 1034 randomcoll_init_hint(kv2, hash2); 1035 1036 return (memcmp(hash1, hash2, sizeof(hash1))); 1037 } 1038 1039 /* 1040 * Implements version sort (-V). 1041 */ 1042 static int 1043 versioncoll(struct key_value *kv1, struct key_value *kv2, 1044 size_t offset __unused) 1045 { 1046 struct bwstring *s1, *s2; 1047 1048 s1 = kv1->k; 1049 s2 = kv2->k; 1050 1051 if (debug_sort) { 1052 bwsprintf(stdout, s1, "; k1=<", ">"); 1053 bwsprintf(stdout, s2, ", k2=<", ">"); 1054 } 1055 1056 if (s1 == s2) 1057 return (0); 1058 1059 return (vcmp(s1, s2)); 1060 } 1061 1062 /* 1063 * Check for minus infinity 1064 */ 1065 static inline bool 1066 huge_minus(double d, int err1) 1067 { 1068 1069 if (err1 == ERANGE) 1070 if (d == -HUGE_VAL || d == -HUGE_VALF || d == -HUGE_VALL) 1071 return (+1); 1072 1073 return (0); 1074 } 1075 1076 /* 1077 * Check for plus infinity 1078 */ 1079 static inline bool 1080 huge_plus(double d, int err1) 1081 { 1082 1083 if (err1 == ERANGE) 1084 if (d == HUGE_VAL || d == HUGE_VALF || d == HUGE_VALL) 1085 return (+1); 1086 1087 return (0); 1088 } 1089 1090 /* 1091 * Check whether a function is a NAN 1092 */ 1093 static bool 1094 is_nan(double d) 1095 { 1096 1097 return ((d == NAN) || (isnan(d))); 1098 } 1099 1100 /* 1101 * Compare two NANs 1102 */ 1103 static int 1104 cmp_nans(double d1, double d2) 1105 { 1106 1107 if (d1 < d2) 1108 return (-1); 1109 if (d1 > d2) 1110 return (+1); 1111 return (0); 1112 } 1113 1114 /* 1115 * Implements general numeric sort (-g). 1116 */ 1117 static int 1118 gnumcoll(struct key_value *kv1, struct key_value *kv2, 1119 size_t offset __unused) 1120 { 1121 double d1, d2; 1122 int err1, err2; 1123 bool empty1, empty2, key1_read, key2_read; 1124 1125 d1 = d2 = 0; 1126 err1 = err2 = 0; 1127 key1_read = key2_read = false; 1128 1129 if (debug_sort) { 1130 bwsprintf(stdout, kv1->k, "; k1=<", ">"); 1131 bwsprintf(stdout, kv2->k, "; k2=<", ">"); 1132 } 1133 1134 if (kv1->hint->status == HS_UNINITIALIZED) { 1135 errno = 0; 1136 d1 = bwstod(kv1->k, &empty1); 1137 err1 = errno; 1138 1139 if (empty1) 1140 kv1->hint->v.gh.notnum = true; 1141 else if (err1 == 0) { 1142 kv1->hint->v.gh.d = d1; 1143 kv1->hint->v.gh.nan = is_nan(d1); 1144 kv1->hint->status = HS_INITIALIZED; 1145 } else 1146 kv1->hint->status = HS_ERROR; 1147 1148 key1_read = true; 1149 } 1150 1151 if (kv2->hint->status == HS_UNINITIALIZED) { 1152 errno = 0; 1153 d2 = bwstod(kv2->k, &empty2); 1154 err2 = errno; 1155 1156 if (empty2) 1157 kv2->hint->v.gh.notnum = true; 1158 else if (err2 == 0) { 1159 kv2->hint->v.gh.d = d2; 1160 kv2->hint->v.gh.nan = is_nan(d2); 1161 kv2->hint->status = HS_INITIALIZED; 1162 } else 1163 kv2->hint->status = HS_ERROR; 1164 1165 key2_read = true; 1166 } 1167 1168 if (kv1->hint->status == HS_INITIALIZED && 1169 kv2->hint->status == HS_INITIALIZED) { 1170 if (kv1->hint->v.gh.notnum) 1171 return ((kv2->hint->v.gh.notnum) ? 0 : -1); 1172 else if (kv2->hint->v.gh.notnum) 1173 return (+1); 1174 1175 if (kv1->hint->v.gh.nan) 1176 return ((kv2->hint->v.gh.nan) ? 1177 cmp_nans(kv1->hint->v.gh.d, kv2->hint->v.gh.d) : 1178 -1); 1179 else if (kv2->hint->v.gh.nan) 1180 return (+1); 1181 1182 d1 = kv1->hint->v.gh.d; 1183 d2 = kv2->hint->v.gh.d; 1184 1185 if (d1 < d2) 1186 return (-1); 1187 else if (d1 > d2) 1188 return (+1); 1189 else 1190 return (0); 1191 } 1192 1193 if (!key1_read) { 1194 errno = 0; 1195 d1 = bwstod(kv1->k, &empty1); 1196 err1 = errno; 1197 } 1198 1199 if (!key2_read) { 1200 errno = 0; 1201 d2 = bwstod(kv2->k, &empty2); 1202 err2 = errno; 1203 } 1204 1205 /* Non-value case: */ 1206 if (empty1) 1207 return (empty2 ? 0 : -1); 1208 else if (empty2) 1209 return (+1); 1210 1211 /* NAN case */ 1212 if (is_nan(d1)) 1213 return (is_nan(d2) ? cmp_nans(d1, d2) : -1); 1214 else if (is_nan(d2)) 1215 return (+1); 1216 1217 /* Infinities */ 1218 if (err1 == ERANGE || err2 == ERANGE) { 1219 /* Minus infinity case */ 1220 if (huge_minus(d1, err1)) { 1221 if (huge_minus(d2, err2)) { 1222 if (d1 < d2) 1223 return (-1); 1224 if (d1 > d2) 1225 return (+1); 1226 return (0); 1227 } else 1228 return (-1); 1229 1230 } else if (huge_minus(d2, err2)) { 1231 if (huge_minus(d1, err1)) { 1232 if (d1 < d2) 1233 return (-1); 1234 if (d1 > d2) 1235 return (+1); 1236 return (0); 1237 } else 1238 return (+1); 1239 } 1240 1241 /* Plus infinity case */ 1242 if (huge_plus(d1, err1)) { 1243 if (huge_plus(d2, err2)) { 1244 if (d1 < d2) 1245 return (-1); 1246 if (d1 > d2) 1247 return (+1); 1248 return (0); 1249 } else 1250 return (+1); 1251 } else if (huge_plus(d2, err2)) { 1252 if (huge_plus(d1, err1)) { 1253 if (d1 < d2) 1254 return (-1); 1255 if (d1 > d2) 1256 return (+1); 1257 return (0); 1258 } else 1259 return (-1); 1260 } 1261 } 1262 1263 if (d1 < d2) 1264 return (-1); 1265 if (d1 > d2) 1266 return (+1); 1267 1268 return (0); 1269 } 1270 1271 /* 1272 * Implements month sort (-M). 1273 */ 1274 static int 1275 monthcoll(struct key_value *kv1, struct key_value *kv2, size_t offset __unused) 1276 { 1277 int val1, val2; 1278 bool key1_read, key2_read; 1279 1280 val1 = val2 = 0; 1281 key1_read = key2_read = false; 1282 1283 if (debug_sort) { 1284 bwsprintf(stdout, kv1->k, "; k1=<", ">"); 1285 bwsprintf(stdout, kv2->k, "; k2=<", ">"); 1286 } 1287 1288 if (kv1->hint->status == HS_UNINITIALIZED) { 1289 kv1->hint->v.Mh.m = bws_month_score(kv1->k); 1290 key1_read = true; 1291 kv1->hint->status = HS_INITIALIZED; 1292 } 1293 1294 if (kv2->hint->status == HS_UNINITIALIZED) { 1295 kv2->hint->v.Mh.m = bws_month_score(kv2->k); 1296 key2_read = true; 1297 kv2->hint->status = HS_INITIALIZED; 1298 } 1299 1300 if (kv1->hint->status == HS_INITIALIZED) { 1301 val1 = kv1->hint->v.Mh.m; 1302 key1_read = true; 1303 } 1304 1305 if (kv2->hint->status == HS_INITIALIZED) { 1306 val2 = kv2->hint->v.Mh.m; 1307 key2_read = true; 1308 } 1309 1310 if (!key1_read) 1311 val1 = bws_month_score(kv1->k); 1312 if (!key2_read) 1313 val2 = bws_month_score(kv2->k); 1314 1315 if (val1 == val2) { 1316 return (0); 1317 } 1318 if (val1 < val2) 1319 return (-1); 1320 return (+1); 1321 } 1322