1570af302Sopenharmony_ci#define _GNU_SOURCE 2570af302Sopenharmony_ci#include <ctype.h> 3570af302Sopenharmony_ci#include <string.h> 4570af302Sopenharmony_ci 5570af302Sopenharmony_ciint strverscmp(const char *l0, const char *r0) 6570af302Sopenharmony_ci{ 7570af302Sopenharmony_ci const unsigned char *l = (const void *)l0; 8570af302Sopenharmony_ci const unsigned char *r = (const void *)r0; 9570af302Sopenharmony_ci size_t i, dp, j; 10570af302Sopenharmony_ci int z = 1; 11570af302Sopenharmony_ci 12570af302Sopenharmony_ci /* Find maximal matching prefix and track its maximal digit 13570af302Sopenharmony_ci * suffix and whether those digits are all zeros. */ 14570af302Sopenharmony_ci for (dp=i=0; l[i]==r[i]; i++) { 15570af302Sopenharmony_ci int c = l[i]; 16570af302Sopenharmony_ci if (!c) return 0; 17570af302Sopenharmony_ci if (!isdigit(c)) dp=i+1, z=1; 18570af302Sopenharmony_ci else if (c!='0') z=0; 19570af302Sopenharmony_ci } 20570af302Sopenharmony_ci 21570af302Sopenharmony_ci if (l[dp]-'1'<9U && r[dp]-'1'<9U) { 22570af302Sopenharmony_ci /* If we're looking at non-degenerate digit sequences starting 23570af302Sopenharmony_ci * with nonzero digits, longest digit string is greater. */ 24570af302Sopenharmony_ci for (j=i; isdigit(l[j]); j++) 25570af302Sopenharmony_ci if (!isdigit(r[j])) return 1; 26570af302Sopenharmony_ci if (isdigit(r[j])) return -1; 27570af302Sopenharmony_ci } else if (z && dp<i && (isdigit(l[i]) || isdigit(r[i]))) { 28570af302Sopenharmony_ci /* Otherwise, if common prefix of digit sequence is 29570af302Sopenharmony_ci * all zeros, digits order less than non-digits. */ 30570af302Sopenharmony_ci return (unsigned char)(l[i]-'0') - (unsigned char)(r[i]-'0'); 31570af302Sopenharmony_ci } 32570af302Sopenharmony_ci 33570af302Sopenharmony_ci return l[i] - r[i]; 34570af302Sopenharmony_ci} 35