+- /*
+- * Out of memory or illegal wide chars; fall back to wcscmp()
+- * but leave errno indicating the error. Callers that don't
+- * check for error will get a reasonable but often slightly
+- * incorrect result.
+- */
+- sverrno = errno;
+- free(mbs1);
+- errno = sverrno;
+- return (wcscmp(ws1, ws2));
++ info = &loc->__lc_collate->__info;
++ len = len2 = 1;
++ ret = ret2 = 0;
++
++ if ((info->directive[0] & NOTFORWARD) ||
++ (info->directive[1] & NOTFORWARD) ||
++ (!(info->flags && COLLATE_SUBST_DUP) &&
++ (info->subst_count[0] > 0 || info->subst_count[1] > 0))) {
++ int direc, pass;
++ for(pass = 0; pass < info->directive_count; pass++) {
++ direc = info->directive[pass];
++ if (pass == 0 || !(info->flags & COLLATE_SUBST_DUP)) {
++ free(tt);
++ tt = __collate_substitute(ws1, pass, loc);
++ free(tt2);
++ tt2 = tt ? __collate_substitute(ws2, pass, loc) : NULL;
++ }
++ if (direc & DIRECTIVE_BACKWARD) {
++ wchar_t *bp, *fp, c;
++ tr = __collate_wcsdup(tt ? tt : ws1);
++ bp = tr;
++ fp = tr + wcslen(tr) - 1;
++ while(bp < fp) {
++ c = *bp;
++ *bp++ = *fp;
++ *fp-- = c;
++ }
++ tr2 = __collate_wcsdup(tt2 ? tt2 : ws2);
++ bp = tr2;
++ fp = tr2 + wcslen(tr2) - 1;
++ while(bp < fp) {
++ c = *bp;
++ *bp++ = *fp;
++ *fp-- = c;
++ }
++ t = (const wchar_t *)tr;
++ t2 = (const wchar_t *)tr2;
++ } else if (tt) {
++ t = (const wchar_t *)tt;
++ t2 = (const wchar_t *)tt2;
++ } else {
++ t = (const wchar_t *)ws1;
++ t2 = (const wchar_t *)ws2;
++ }
++ if(direc & DIRECTIVE_POSITION) {
++ while(*t && *t2) {
++ prim = prim2 = 0;
++ __collate_lookup_which(t, &len, &prim, pass, loc);
++ if (prim <= 0) {
++ if (prim < 0) {
++ errno = EINVAL;
++ ret = -1;
++ goto end;
++ }
++ prim = COLLATE_MAX_PRIORITY;
++ }
++ __collate_lookup_which(t2, &len2, &prim2, pass, loc);
++ if (prim2 <= 0) {
++ if (prim2 < 0) {
++ errno = EINVAL;
++ ret = -1;
++ goto end;
++ }
++ prim2 = COLLATE_MAX_PRIORITY;
++ }
++ if(prim != prim2) {
++ ret = prim - prim2;
++ goto end;
++ }
++ t += len;
++ t2 += len2;
++ }
++ } else {
++ while(*t && *t2) {
++ prim = prim2 = 0;
++ while(*t) {
++ __collate_lookup_which(t, &len, &prim, pass, loc);
++ if(prim > 0)
++ break;
++ if (prim < 0) {
++ errno = EINVAL;
++ ret = -1;
++ goto end;
++ }
++ t += len;
++ }
++ while(*t2) {
++ __collate_lookup_which(t2, &len2, &prim2, pass, loc);
++ if(prim2 > 0)
++ break;
++ if (prim2 < 0) {
++ errno = EINVAL;
++ ret = -1;
++ goto end;
++ }
++ t2 += len2;
++ }
++ if(!prim || !prim2)
++ break;
++ if(prim != prim2) {
++ ret = prim - prim2;
++ goto end;
++ }
++ t += len;
++ t2 += len2;
++ }
++ }
++ if(!*t) {
++ if(*t2) {
++ ret = -(int)*t2;
++ goto end;
++ }
++ } else {
++ ret = *t;
++ goto end;
++ }
++ }
++ ret = 0;
++ goto end;