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: