2 * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
3 * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: head/usr.bin/sort/coll.c 281132 2015-04-06 02:35:55Z pfg $
31 #include <sys/types.h>
38 #if defined(SORT_RANDOM)
49 struct key_specs *keys;
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'+';
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 #if defined(SORT_RANDOM)
64 static int randomcoll(struct key_value*, struct key_value *, size_t offset);
66 static int versioncoll(struct key_value*, struct key_value *, size_t offset);
72 keys_array_alloc(void)
74 struct keys_array *ka;
77 sz = keys_array_size();
85 * Calculate whether we need key hint space
91 return (need_hint ? sizeof(struct key_hint) : 0);
95 * Calculate keys array size
101 return (keys_num * (sizeof(struct key_value) + key_hint_size()));
105 * Clean data of keys array
108 clean_keys_array(const struct bwstring *s, struct keys_array *ka)
112 for (size_t i = 0; i < keys_num; ++i)
113 if (ka->key[i].k && ka->key[i].k != s)
114 bwsfree(ka->key[i].k);
115 memset(ka, 0, keys_array_size());
120 * Set value of a key in the keys set
123 set_key_on_keys_array(struct keys_array *ka, struct bwstring *s, size_t ind)
126 if (ka && keys_num > ind) {
127 struct key_value *kv;
129 kv = &(ka->key[ind]);
131 if (kv->k && kv->k != s)
138 * Initialize a sort list item
140 struct sort_list_item *
141 sort_list_item_alloc(void)
143 struct sort_list_item *si;
146 sz = sizeof(struct sort_list_item) + keys_array_size();
147 si = sort_malloc(sz);
154 sort_list_item_size(struct sort_list_item *si)
159 ret = sizeof(struct sort_list_item) + keys_array_size();
161 ret += bws_memsize(si->str);
162 for (size_t i = 0; i < keys_num; ++i) {
163 struct key_value *kv;
165 kv = &(si->ka.key[i]);
167 if (kv->k != si->str)
168 ret += bws_memsize(kv->k);
175 * Calculate key for a sort list item
178 sort_list_item_make_key(struct sort_list_item *si)
181 preproc(si->str, &(si->ka));
185 * Set value of a sort list item.
186 * Return combined string and keys memory size.
189 sort_list_item_set(struct sort_list_item *si, struct bwstring *str)
193 clean_keys_array(si->str, &(si->ka));
195 if (si->str == str) {
196 /* we are trying to reset the same string */
204 sort_list_item_make_key(si);
209 * De-allocate a sort list item object memory
212 sort_list_item_clean(struct sort_list_item *si)
216 clean_keys_array(si->str, &(si->ka));
225 * Skip columns according to specs
228 skip_cols_to_start(const struct bwstring *s, size_t cols, size_t start,
229 bool skip_blanks, bool *empty_key)
232 return (BWSLEN(s) + 1);
235 while (start < BWSLEN(s) && iswblank(BWS_GET(s,start)))
238 while (start < BWSLEN(s) && cols > 1) {
243 if (start >= BWSLEN(s))
250 * Skip fields according to specs
253 skip_fields_to_start(const struct bwstring *s, size_t fields, bool *empty_field)
260 } else if (!(sort_opts_vals.tflag)) {
264 while (cpos < BWSLEN(s)) {
267 isblank = iswblank(BWS_GET(s, cpos));
269 if (isblank && !pb) {
283 while (cpos < BWSLEN(s)) {
284 if (BWS_GET(s,cpos) == (wchar_t)sort_opts_vals.field_sep) {
301 find_field_start(const struct bwstring *s, struct key_specs *ks,
302 size_t *field_start, size_t *key_start, bool *empty_field, bool *empty_key)
305 *field_start = skip_fields_to_start(s, ks->f1, empty_field);
307 *key_start = skip_cols_to_start(s, ks->c1, *field_start,
308 ks->pos1b, empty_key);
314 * Find end key position
317 find_field_end(const struct bwstring *s, struct key_specs *ks)
319 size_t f2, next_field_start, pos_end;
320 bool empty_field, empty_key;
323 next_field_start = 0;
329 return (BWSLEN(s) + 1);
332 next_field_start = skip_fields_to_start(s, f2 + 1,
334 if ((next_field_start > 0) && sort_opts_vals.tflag &&
335 ((wchar_t)sort_opts_vals.field_sep == BWS_GET(s,
336 next_field_start - 1)))
339 next_field_start = skip_fields_to_start(s, f2,
343 if (empty_field || (next_field_start >= BWSLEN(s)))
344 return (BWSLEN(s) + 1);
347 pos_end = skip_cols_to_start(s, ks->c2, next_field_start,
348 ks->pos2b, &empty_key);
349 if (pos_end < BWSLEN(s))
352 pos_end = next_field_start;
358 * Cut a field according to the key specs
360 static struct bwstring *
361 cut_field(const struct bwstring *s, struct key_specs *ks)
363 struct bwstring *ret = NULL;
366 size_t field_start, key_end, key_start, sz;
367 bool empty_field, empty_key;
374 find_field_start(s, ks, &field_start, &key_start,
375 &empty_field, &empty_key);
380 key_end = find_field_end(s, ks);
381 sz = (key_end < key_start) ? 0 : (key_end - key_start);
386 bwsnocpy(ret, s, key_start, sz);
394 * Preprocesses a line applying the necessary transformations
395 * specified by command line options and returns the preprocessed
396 * string, which can be used to compare.
399 preproc(struct bwstring *s, struct keys_array *ka)
402 if (sort_opts_vals.kflag)
403 for (size_t i = 0; i < keys_num; i++) {
404 struct bwstring *key;
405 struct key_specs *kspecs;
406 struct sort_mods *sm;
409 key = cut_field(s, kspecs);
413 key = dictionary_order(key);
415 key = ignore_nonprinting(key);
416 if (sm->fflag || sm->Mflag)
417 key = ignore_case(key);
419 set_key_on_keys_array(ka, key, i);
422 struct bwstring *ret = NULL;
423 struct sort_mods *sm = default_sort_mods;
428 ret = ignore_leading_blanks(ret);
433 ret = dictionary_order(ret);
434 } else if (sm->iflag) {
437 ret = ignore_nonprinting(ret);
439 if (sm->fflag || sm->Mflag) {
442 ret = ignore_case(ret);
445 set_key_on_keys_array(ka, s, 0);
447 set_key_on_keys_array(ka, ret, 0);
454 get_sort_func(struct sort_mods *sm)
465 #if defined(SORT_RANDOM)
470 return (versioncoll);
476 * Compares the given strings. Returns a positive number if
477 * the first precedes the second, a negative number if the second is
478 * the preceding one, and zero if they are equal. This function calls
479 * the underlying collate functions, which done the actual comparison.
482 key_coll(struct keys_array *ps1, struct keys_array *ps2, size_t offset)
484 struct sort_mods *sm;
487 for (size_t i = 0; i < keys_num; ++i) {
491 res = sm->func(&(ps2->key[i]), &(ps1->key[i]), offset);
493 res = sm->func(&(ps1->key[i]), &(ps2->key[i]), offset);
498 /* offset applies to only the first key */
505 * Compare two strings.
506 * Plain symbol-by-symbol comparison.
509 top_level_str_coll(const struct bwstring *s1, const struct bwstring *s2)
512 if (default_sort_mods->rflag) {
513 const struct bwstring *tmp;
520 return (bwscoll(s1, s2, 0));
524 * Compare a string and a sort list item, according to the sort specs.
527 str_list_coll(struct bwstring *str1, struct sort_list_item **ss2)
529 struct keys_array *ka1;
532 ka1 = keys_array_alloc();
536 sort_list_item_make_key(*ss2);
539 bwsprintf(stdout, str1, "; s1=<", ">");
540 bwsprintf(stdout, (*ss2)->str, ", s2=<", ">");
543 ret = key_coll(ka1, &((*ss2)->ka), 0);
546 printf("; cmp1=%d", ret);
548 clean_keys_array(str1, ka1);
551 if ((ret == 0) && !(sort_opts_vals.sflag) && sort_opts_vals.complex_sort) {
552 ret = top_level_str_coll(str1, ((*ss2)->str));
554 printf("; cmp2=%d", ret);
564 * Compare two sort list items, according to the sort specs.
567 list_coll_offset(struct sort_list_item **ss1, struct sort_list_item **ss2,
572 ret = key_coll(&((*ss1)->ka), &((*ss2)->ka), offset);
576 printf("; offset=%d", (int) offset);
577 bwsprintf(stdout, ((*ss1)->str), "; s1=<", ">");
578 bwsprintf(stdout, ((*ss2)->str), ", s2=<", ">");
579 printf("; cmp1=%d\n", ret);
585 if (!(sort_opts_vals.sflag) && sort_opts_vals.complex_sort) {
586 ret = top_level_str_coll(((*ss1)->str), ((*ss2)->str));
588 printf("; cmp2=%d\n", ret);
595 * Compare two sort list items, according to the sort specs.
598 list_coll(struct sort_list_item **ss1, struct sort_list_item **ss2)
601 return (list_coll_offset(ss1, ss2, 0));
606 list_coll_##N(struct sort_list_item **ss1, struct sort_list_item **ss2) \
609 return (list_coll_offset(ss1, ss2, N)); \
634 get_list_call_func(size_t offset)
636 static const listcoll_t lsarray[] = { list_coll, list_coll_1,
637 list_coll_2, list_coll_3, list_coll_4, list_coll_5,
638 list_coll_6, list_coll_7, list_coll_8, list_coll_9,
639 list_coll_10, list_coll_11, list_coll_12, list_coll_13,
640 list_coll_14, list_coll_15, list_coll_16, list_coll_17,
641 list_coll_18, list_coll_19, list_coll_20 };
644 return (lsarray[offset]);
650 * Compare two sort list items, only by their original string.
653 list_coll_by_str_only(struct sort_list_item **ss1, struct sort_list_item **ss2)
656 return (top_level_str_coll(((*ss1)->str), ((*ss2)->str)));
660 * Maximum size of a number in the string (before or after decimal point)
662 #define MAX_NUM_SIZE (128)
667 static void setsuffix(wchar_t c, unsigned char *si)
701 * Read string s and parse the string into a fixed-decimal-point number.
702 * sign equals -1 if the number is negative (explicit plus is not allowed,
703 * according to GNU sort's "info sort".
704 * The number part before decimal point is in the smain, after the decimal
705 * point is in sfrac, tail is the pointer to the remainder of the string.
708 read_number(struct bwstring *s0, int *sign, wchar_t *smain, size_t *main_len, wchar_t *sfrac, size_t *frac_len, unsigned char *si)
714 /* always end the fraction with zero, even if we have no fraction */
717 while (iswblank(bws_get_iter_value(s)))
718 s = bws_iterator_inc(s, 1);
720 if (bws_get_iter_value(s) == (wchar_t)symbol_negative_sign) {
722 s = bws_iterator_inc(s, 1);
725 // This is '0', not '\0', do not change this
726 while (iswdigit(bws_get_iter_value(s)) &&
727 (bws_get_iter_value(s) == L'0'))
728 s = bws_iterator_inc(s, 1);
730 while (bws_get_iter_value(s) && *main_len < MAX_NUM_SIZE) {
731 if (iswdigit(bws_get_iter_value(s))) {
732 smain[*main_len] = bws_get_iter_value(s);
733 s = bws_iterator_inc(s, 1);
735 } else if (symbol_thousands_sep &&
736 (bws_get_iter_value(s) == (wchar_t)symbol_thousands_sep))
737 s = bws_iterator_inc(s, 1);
742 smain[*main_len] = 0;
744 if (bws_get_iter_value(s) == (wchar_t)symbol_decimal_point) {
745 s = bws_iterator_inc(s, 1);
746 while (iswdigit(bws_get_iter_value(s)) &&
747 *frac_len < MAX_NUM_SIZE) {
748 sfrac[*frac_len] = bws_get_iter_value(s);
749 s = bws_iterator_inc(s, 1);
752 sfrac[*frac_len] = 0;
754 while (*frac_len > 0 && sfrac[*frac_len - 1] == L'0') {
756 sfrac[*frac_len] = L'\0';
760 setsuffix(bws_get_iter_value(s),si);
762 if ((*main_len + *frac_len) == 0)
769 * Implements string sort.
772 wstrcoll(struct key_value *kv1, struct key_value *kv2, size_t offset)
777 printf("; offset=%d\n", (int) offset);
778 bwsprintf(stdout, kv1->k, "; k1=<", ">");
779 printf("(%zu)", BWSLEN(kv1->k));
780 bwsprintf(stdout, kv2->k, ", k2=<", ">");
781 printf("(%zu)", BWSLEN(kv2->k));
784 return (bwscoll(kv1->k, kv2->k, offset));
788 * Compare two suffixes
791 cmpsuffix(unsigned char si1, unsigned char si2)
794 return ((char)si1 - (char)si2);
798 * Implements numeric sort for -n and -h.
801 numcoll_impl(struct key_value *kv1, struct key_value *kv2,
802 size_t offset __unused, bool use_suffix)
804 struct bwstring *s1, *s2;
805 wchar_t sfrac1[MAX_NUM_SIZE + 1], sfrac2[MAX_NUM_SIZE + 1];
806 wchar_t smain1[MAX_NUM_SIZE + 1], smain2[MAX_NUM_SIZE + 1];
807 int cmp_res, sign1, sign2;
808 size_t frac1, frac2, main1, main2;
809 unsigned char SI1, SI2;
810 bool e1, e2, key1_read, key2_read;
819 key1_read = key2_read = false;
822 bwsprintf(stdout, s1, "; k1=<", ">");
823 bwsprintf(stdout, s2, ", k2=<", ">");
829 if (kv1->hint->status == HS_UNINITIALIZED) {
830 /* read the number from the string */
831 read_number(s1, &sign1, smain1, &main1, sfrac1, &frac1, &SI1);
833 kv1->hint->v.nh.n1 = wcstoull(smain1, NULL, 10);
834 if(main1 < 1 && frac1 < 1)
835 kv1->hint->v.nh.empty=true;
836 kv1->hint->v.nh.si = SI1;
837 kv1->hint->status = (kv1->hint->v.nh.n1 != ULLONG_MAX) ?
838 HS_INITIALIZED : HS_ERROR;
839 kv1->hint->v.nh.neg = (sign1 < 0) ? true : false;
842 if (kv2->hint->status == HS_UNINITIALIZED) {
843 /* read the number from the string */
844 read_number(s2, &sign2, smain2, &main2, sfrac2, &frac2,&SI2);
846 kv2->hint->v.nh.n1 = wcstoull(smain2, NULL, 10);
847 if(main2 < 1 && frac2 < 1)
848 kv2->hint->v.nh.empty=true;
849 kv2->hint->v.nh.si = SI2;
850 kv2->hint->status = (kv2->hint->v.nh.n1 != ULLONG_MAX) ?
851 HS_INITIALIZED : HS_ERROR;
852 kv2->hint->v.nh.neg = (sign2 < 0) ? true : false;
855 if (kv1->hint->status == HS_INITIALIZED && kv2->hint->status ==
857 unsigned long long n1, n2;
860 e1 = kv1->hint->v.nh.empty;
861 e2 = kv2->hint->v.nh.empty;
866 neg1 = kv1->hint->v.nh.neg;
867 neg2 = kv2->hint->v.nh.neg;
875 return (neg2 ? +1 : -1);
877 return (neg1 ? -1 : +1);
881 cmp_res = cmpsuffix(kv1->hint->v.nh.si, kv2->hint->v.nh.si);
883 return (neg1 ? -cmp_res : cmp_res);
886 n1 = kv1->hint->v.nh.n1;
887 n2 = kv2->hint->v.nh.n1;
889 return (neg1 ? +1 : -1);
891 return (neg1 ? -1 : +1);
894 /* read the numbers from the strings */
896 read_number(s1, &sign1, smain1, &main1, sfrac1, &frac1, &SI1);
898 read_number(s2, &sign2, smain2, &main2, sfrac2, &frac2, &SI2);
900 e1 = ((main1 + frac1) == 0);
901 e2 = ((main2 + frac2) == 0);
906 /* we know the result if the signs are different */
907 if (sign1 < 0 && sign2 >= 0)
909 if (sign1 >= 0 && sign2 < 0)
913 return ((sign2 < 0) ? +1 : -1);
915 return ((sign1 < 0) ? -1 : +1);
918 cmp_res = cmpsuffix(SI1, SI2);
920 return ((sign1 < 0) ? -cmp_res : cmp_res);
923 /* if both numbers are empty assume that the strings are equal */
924 if (main1 < 1 && main2 < 1 && frac1 < 1 && frac2 < 1)
928 * if the main part is of different size, we know the result
929 * (because the leading zeros are removed)
933 else if (main1 > main2)
935 /* if the sizes are equal then simple non-collate string compare gives the correct result */
937 cmp_res = wcscmp(smain1, smain2);
941 cmp_res = wcscmp(sfrac1, sfrac2);
946 /* reverse result if the signs are negative */
947 if (sign1 < 0 && sign2 < 0)
954 * Implements numeric sort (-n).
957 numcoll(struct key_value *kv1, struct key_value *kv2, size_t offset)
960 return (numcoll_impl(kv1, kv2, offset, false));
964 * Implements 'human' numeric sort (-h).
967 hnumcoll(struct key_value *kv1, struct key_value *kv2, size_t offset)
970 return (numcoll_impl(kv1, kv2, offset, true));
974 * Implements random sort (-R).
976 #if defined(SORT_RANDOM)
978 randomcoll(struct key_value *kv1, struct key_value *kv2,
979 size_t offset __unused)
981 struct bwstring *s1, *s2;
989 bwsprintf(stdout, s1, "; k1=<", ">");
990 bwsprintf(stdout, s2, ", k2=<", ">");
996 memcpy(&ctx1,&md5_ctx,sizeof(MD5_CTX));
997 memcpy(&ctx2,&md5_ctx,sizeof(MD5_CTX));
999 MD5Update(&ctx1, bwsrawdata(s1), bwsrawlen(s1));
1000 MD5Update(&ctx2, bwsrawdata(s2), bwsrawlen(s2));
1001 b1 = MD5End(&ctx1, NULL);
1002 b2 = MD5End(&ctx2, NULL);
1010 } else if (b2 == NULL) {
1016 cmp_res = strcmp(b1,b2);
1021 cmp_res = bwscoll(s1, s2, 0);
1029 * Implements version sort (-V).
1032 versioncoll(struct key_value *kv1, struct key_value *kv2,
1033 size_t offset __unused)
1035 struct bwstring *s1, *s2;
1041 bwsprintf(stdout, s1, "; k1=<", ">");
1042 bwsprintf(stdout, s2, ", k2=<", ">");
1048 return (vcmp(s1, s2));
1052 * Check for minus infinity
1055 huge_minus(double d, int err1)
1059 if (d == -HUGE_VAL || d == -HUGE_VALF || d == -HUGE_VALL)
1066 * Check for plus infinity
1069 huge_plus(double d, int err1)
1073 if (d == HUGE_VAL || d == HUGE_VALF || d == HUGE_VALL)
1080 * Check whether a function is a NAN
1085 return ((d == NAN) || (isnan(d)));
1092 cmp_nans(double d1, double d2)
1103 * Implements general numeric sort (-g).
1106 gnumcoll(struct key_value *kv1, struct key_value *kv2,
1107 size_t offset __unused)
1111 bool empty1, empty2, key1_read, key2_read;
1115 key1_read = key2_read = false;
1118 bwsprintf(stdout, kv1->k, "; k1=<", ">");
1119 bwsprintf(stdout, kv2->k, "; k2=<", ">");
1122 if (kv1->hint->status == HS_UNINITIALIZED) {
1124 d1 = bwstod(kv1->k, &empty1);
1128 kv1->hint->v.gh.notnum = true;
1129 else if (err1 == 0) {
1130 kv1->hint->v.gh.d = d1;
1131 kv1->hint->v.gh.nan = is_nan(d1);
1132 kv1->hint->status = HS_INITIALIZED;
1134 kv1->hint->status = HS_ERROR;
1139 if (kv2->hint->status == HS_UNINITIALIZED) {
1141 d2 = bwstod(kv2->k, &empty2);
1145 kv2->hint->v.gh.notnum = true;
1146 else if (err2 == 0) {
1147 kv2->hint->v.gh.d = d2;
1148 kv2->hint->v.gh.nan = is_nan(d2);
1149 kv2->hint->status = HS_INITIALIZED;
1151 kv2->hint->status = HS_ERROR;
1156 if (kv1->hint->status == HS_INITIALIZED &&
1157 kv2->hint->status == HS_INITIALIZED) {
1158 if (kv1->hint->v.gh.notnum)
1159 return ((kv2->hint->v.gh.notnum) ? 0 : -1);
1160 else if (kv2->hint->v.gh.notnum)
1163 if (kv1->hint->v.gh.nan)
1164 return ((kv2->hint->v.gh.nan) ?
1165 cmp_nans(kv1->hint->v.gh.d, kv2->hint->v.gh.d) :
1167 else if (kv2->hint->v.gh.nan)
1170 d1 = kv1->hint->v.gh.d;
1171 d2 = kv2->hint->v.gh.d;
1183 d1 = bwstod(kv1->k, &empty1);
1189 d2 = bwstod(kv2->k, &empty2);
1193 /* Non-value case: */
1195 return (empty2 ? 0 : -1);
1201 return (is_nan(d2) ? cmp_nans(d1, d2) : -1);
1202 else if (is_nan(d2))
1206 if (err1 == ERANGE || err2 == ERANGE) {
1207 /* Minus infinity case */
1208 if (huge_minus(d1, err1)) {
1209 if (huge_minus(d2, err2)) {
1218 } else if (huge_minus(d2, err2)) {
1219 if (huge_minus(d1, err1)) {
1229 /* Plus infinity case */
1230 if (huge_plus(d1, err1)) {
1231 if (huge_plus(d2, err2)) {
1239 } else if (huge_plus(d2, err2)) {
1240 if (huge_plus(d1, err1)) {
1260 * Implements month sort (-M).
1263 monthcoll(struct key_value *kv1, struct key_value *kv2, size_t offset __unused)
1266 bool key1_read, key2_read;
1269 key1_read = key2_read = false;
1272 bwsprintf(stdout, kv1->k, "; k1=<", ">");
1273 bwsprintf(stdout, kv2->k, "; k2=<", ">");
1276 if (kv1->hint->status == HS_UNINITIALIZED) {
1277 kv1->hint->v.Mh.m = bws_month_score(kv1->k);
1279 kv1->hint->status = HS_INITIALIZED;
1282 if (kv2->hint->status == HS_UNINITIALIZED) {
1283 kv2->hint->v.Mh.m = bws_month_score(kv2->k);
1285 kv2->hint->status = HS_INITIALIZED;
1288 if (kv1->hint->status == HS_INITIALIZED) {
1289 val1 = kv1->hint->v.Mh.m;
1293 if (kv2->hint->status == HS_INITIALIZED) {
1294 val2 = kv2->hint->v.Mh.m;
1299 val1 = bws_month_score(kv1->k);
1301 val2 = bws_month_score(kv2->k);