Multiple Ordering Criteria
Multiple Ordering Criteria
Order records using a sequence of field descriptions.
- Define keycompare()
-
Function definition
- Segment Source
-
984: /* Compare two lines A and B trying every key in sequence until there
985: are no more keys or a difference is found. */
986:
987: static int
988: keycompare (const struct line *a, const struct line *b)
989: {
990: register char *texta, *textb, *lima, *limb;
991: register unsigned char *translate;
992: register int *ignore;
993: struct keyfield *key;
994: int diff = 0, iter = 0, lena, lenb;
995:
996: for (key = keyhead.next; key; key = key->next, ++iter)
997: {
998: ignore = key->ignore;
999: translate = (unsigned char *) key->translate;
1000:
1001: /* Find the beginning and limit of each field. */
1002: if (iter || a->keybeg == NULL || b->keybeg == NULL)
1003: {
1004: if (key->eword >= 0)
1005: lima = limfield (a, key), limb = limfield (b, key);
1006: else
1007: lima = a->text + a->length, limb = b->text + b->length;
1008:
1009: if (key->sword >= 0)
1010: texta = begfield (a, key), textb = begfield (b, key);
1011: else
1012: {
1013: texta = a->text, textb = b->text;
1014: if (key->skipsblanks)
1015: {
1016: while (texta < lima && blanks[UCHAR (*texta)])
1017: ++texta;
1018: while (textb < limb && blanks[UCHAR (*textb)])
1019: ++textb;
1020: }
1021: }
1022: }
1023: else
1024: {
1025: /* For the first iteration only, the key positions have
1026: been precomputed for us. */
1027: texta = a->keybeg, lima = a->keylim;
1028: textb = b->keybeg, limb = b->keylim;
1029: }
1030:
1031: /* Find the lengths. */
1032: lena = lima - texta, lenb = limb - textb;
1033: if (lena < 0)
1034: lena = 0;
1035: if (lenb < 0)
1036: lenb = 0;
1037:
1038: if (key->skipeblanks)
1039: {
1040: char *a_end = texta + lena;
1041: char *b_end = textb + lenb;
1042: trim_trailing_blanks (texta, &a_end);
1043: trim_trailing_blanks (textb, &b_end);
1044: lena = a_end - texta;
1045: lenb = b_end - textb;
1046: }
1047:
1048: /* Actually compare the fields. */
1049: if (key->numeric)
1050: {
1051: if (*lima || *limb)
1052: {
1053: char savea = *lima, saveb = *limb;
1054:
1055: *lima = *limb = '\0';
1056: diff = numcompare (texta, textb);
1057: *lima = savea, *limb = saveb;
1058: }
1059: else
1060: diff = numcompare (texta, textb);
1061:
1062: if (diff)
1063: return key->reverse ? -diff : diff;
1064: continue;
1065: }
1066: else if (key->general_numeric)
1067: {
1068: if (*lima || *limb)
1069: {
1070: char savea = *lima, saveb = *limb;
1071:
1072: *lima = *limb = '\0';
1073: diff = general_numcompare (texta, textb);
1074: *lima = savea, *limb = saveb;
1075: }
1076: else
1077: diff = general_numcompare (texta, textb);
1078:
1079: if (diff)
1080: return key->reverse ? -diff : diff;
1081: continue;
1082: }
1083: else if (key->month)
1084: {
1085: diff = getmonth (texta, lena) - getmonth (textb, lenb);
1086: if (diff)
1087: return key->reverse ? -diff : diff;
1088: continue;
1089: }
1090: else if (ignore && translate)
1091:
1092: #define CMP_WITH_IGNORE(A, B) \
1093: do \
1094: { \
1095: while (texta < lima && textb < limb) \
1096: { \
1097: while (texta < lima && ignore[UCHAR (*texta)]) \
1098: ++texta; \
1099: while (textb < limb && ignore[UCHAR (*textb)]) \
1100: ++textb; \
1101: if (texta < lima && textb < limb) \
1102: { \
1103: if ((A) != (B)) \
1104: { \
1105: diff = (A) - (B); \
1106: break; \
1107: } \
1108: ++texta; \
1109: ++textb; \
1110: } \
1111: \
1112: if (texta == lima && textb < limb && !ignore[UCHAR (*textb)]) \
1113: diff = -1; \
1114: else if (texta < lima && textb == limb \
1115: && !ignore[UCHAR (*texta)]) \
1116: diff = 1; \
1117: } \
1118: \
1119: if (diff == 0) \
1120: { \
1121: while (texta < lima && ignore[UCHAR (*texta)]) \
1122: ++texta; \
1123: while (textb < limb && ignore[UCHAR (*textb)]) \
1124: ++textb; \
1125: \
1126: if (texta == lima && textb < limb) \
1127: diff = -1; \
1128: else if (texta < lima && textb == limb) \
1129: diff = 1; \
1130: } \
1131: /* Relative lengths are meaningless if characters were ignored. \
1132: Handling this case here avoids what might be an invalid length \
1133: comparison below. */ \
1134: if (diff == 0 && texta == lima && textb == limb) \
1135: return 0; \
1136: } \
1137: while (0)
1138:
1139: CMP_WITH_IGNORE (translate[UCHAR (*texta)], translate[UCHAR (*textb)]);
1140: else if (ignore)
1141: CMP_WITH_IGNORE (UCHAR (*texta), UCHAR (*textb));
1142: else if (translate)
1143: while (texta < lima && textb < limb)
1144: {
1145: if (translate[UCHAR (*texta++)] != translate[UCHAR (*textb++)])
1146: {
1147: diff = (translate[UCHAR (*--texta)]
1148: - translate[UCHAR (*--textb)]);
1149: break;
1150: }
1151: }
1152: else
1153: diff = memcmp (texta, textb, min (lena, lenb));
1154:
1155: if (diff)
1156: return key->reverse ? -diff : diff;
1157: if ((diff = lena - lenb) != 0)
1158: return key->reverse ? -diff : diff;
1159: }
1160:
1161: return 0;
1162: }
1163:
- Dispatch key compare
-
Code insertion
- Segment Source
-
1172: /* First try to compare on the specified keys (if any).
1173: The only two cases with no key at all are unadorned sort,
1174: and unadorned sort -r. */
1175: if (keyhead.next)
1176: {
1177: diff = keycompare (a, b);
1178: if (diff != 0)
1179: return diff;
1180: if (unique || stable)
1181: return 0;
1182: }
1183: