rpm
4.5
|
00001 00004 #include "system.h" 00005 00006 #include <rpmio.h> 00007 00008 #define _RPMEVR_INTERNAL 00009 #include <rpmevr.h> 00010 00011 #include "debug.h" 00012 00013 /*@unchecked@*/ 00014 int _rpmevr_debug = 0; 00015 00016 #if !defined(MAX) 00017 #define MAX(x, y) ( ((x)>(y))?(x):(y) ) 00018 #endif 00019 00020 /* XXX Force digits to beat alphas. See bugzilla #50977. */ 00021 #if defined(RPM_VENDOR_MANDRIVA) 00022 /*@unchecked@*/ 00023 static int _invert_digits_alphas_comparison = 1; 00024 #else 00025 /*@unchecked@*/ 00026 static int _invert_digits_alphas_comparison = -1; 00027 #endif 00028 00029 /* XXX Punctuation characters that are not treated as alphas */ 00030 /*@unchecked@*/ /*@observer@*/ 00031 static const char * _rpmnotalpha = ".:-"; 00032 00038 static inline int xisrpmalpha(int c) 00039 /*@*/ 00040 { 00041 int rc = xisalpha(c); 00042 if (!rc) 00043 rc = xispunct(c); 00044 if (rc && _rpmnotalpha && *_rpmnotalpha) 00045 rc = (strchr(_rpmnotalpha, c) == NULL); 00046 return rc; 00047 } 00048 00049 int rpmEVRcmp(const char * a, const char * b) 00050 /*@*/ 00051 { 00052 const char * ae, * be; 00053 int rc = 0; 00054 00055 /* Compare version strings segment by segment. */ 00056 for (; *a && *b && rc == 0; a = ae, b = be) { 00057 00058 /* Skip leading non-alpha, non-digit characters. */ 00059 while (*a && !(xisdigit(*a) || xisrpmalpha(*a))) a++; 00060 while (*b && !(xisdigit(*b) || xisrpmalpha(*b))) b++; 00061 00062 /* Digit string comparison? */ 00063 if (xisdigit(*a) || xisdigit(*b)) { 00064 /* Discard leading zeroes. */ 00065 while (a[0] == '0' && xisdigit(a[1])) a++; 00066 while (b[0] == '0' && xisdigit(b[1])) b++; 00067 00068 /* Find end of digit strings. */ 00069 ae = a; while (xisdigit(*ae)) ae++; 00070 be = b; while (xisdigit(*be)) be++; 00071 00072 /* Calculate digit comparison return code. */ 00073 if (a == ae || b == be) 00074 rc = (*b - *a) * _invert_digits_alphas_comparison; 00075 else { 00076 rc = (ae - a) - (be - b); 00077 if (!rc) 00078 rc = strncmp(a, b, (ae - a)); 00079 } 00080 } else { 00081 /* Find end of alpha strings. */ 00082 ae = a; while (xisrpmalpha(*ae)) ae++; 00083 be = b; while (xisrpmalpha(*be)) be++; 00084 00085 /* Calculate alpha comparison return code. */ 00086 rc = strncmp(a, b, MAX((ae - a), (be - b))); 00087 } 00088 } 00089 00090 /* Longer string wins. */ 00091 if (!rc) 00092 rc = (*a - *b); 00093 00094 /* Force strict -1, 0, 1 return. */ 00095 rc = (rc > 0 ? 1 00096 : rc < 0 ? -1 00097 : 0); 00098 return rc; 00099 } 00100 00101 int rpmEVRparse(const char * evrstr, EVR_t evr) 00102 /*@modifies evrstr, evr @*/ 00103 { 00104 char *s = xstrdup(evrstr); 00105 char *se; 00106 00107 evr->str = se = s; 00108 while (*se && xisdigit(*se)) se++; /* se points to epoch terminator */ 00109 00110 if (*se == ':') { 00111 evr->E = s; 00112 *se++ = '\0'; 00113 evr->V = se; 00114 /*@-branchstate@*/ 00115 if (*evr->E == '\0') evr->E = "0"; 00116 /*@=branchstate@*/ 00117 evr->Elong = strtoul(evr->E, NULL, 10); 00118 } else { 00119 evr->E = NULL; /* XXX disable epoch compare if missing */ 00120 evr->V = s; 00121 evr->Elong = 0; 00122 } 00123 se = strrchr(se, '-'); /* se points to version terminator */ 00124 if (se) { 00125 *se++ = '\0'; 00126 evr->R = se; 00127 } else { 00128 evr->R = NULL; 00129 } 00130 return 0; 00131 } 00132 00139 static int compare_values(const char *a, const char *b) 00140 /*@*/ 00141 { 00142 return rpmvercmp(a, b); 00143 } 00144 00145 int rpmEVRcompare(const EVR_t a, const EVR_t b) 00146 { 00147 int rc = 0; 00148 00149 if (!rc) 00150 rc = compare_values(a->E, b->E); 00151 if (!rc) 00152 rc = compare_values(a->V, b->V); 00153 if (!rc) 00154 rc = compare_values(a->R, b->R); 00155 return rc; 00156 } 00157 00158 int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp; 00159 00162 /*@unchecked@*/ /*@observer@*/ 00163 static struct EVRop_s { 00164 /*@observer@*/ /*@null@*/ 00165 const char * operator; 00166 rpmsenseFlags sense; 00167 } cops[] = { 00168 { "<=", RPMSENSE_LESS ^ RPMSENSE_EQUAL}, 00169 { "=<", RPMSENSE_LESS ^ RPMSENSE_EQUAL}, 00170 00171 { "==", RPMSENSE_EQUAL}, 00172 { "!=", RPMSENSE_NOTEQUAL}, 00173 00174 { ">=", RPMSENSE_GREATER ^ RPMSENSE_EQUAL}, 00175 { "=>", RPMSENSE_GREATER ^ RPMSENSE_EQUAL}, 00176 00177 { "<", RPMSENSE_LESS}, 00178 { "=", RPMSENSE_EQUAL}, 00179 { ">", RPMSENSE_GREATER}, 00180 00181 { NULL, 0 }, 00182 }; 00183 00184 rpmsenseFlags rpmEVRflags(const char *op, const char **end) 00185 { 00186 rpmsenseFlags Flags = 0; 00187 struct EVRop_s *cop; 00188 00189 if (op == NULL || *op == '\0') 00190 Flags = RPMSENSE_EQUAL; 00191 else 00192 for (cop = cops; cop->operator != NULL; cop++) { 00193 if (strncmp(op, cop->operator, strlen(cop->operator))) 00194 continue; 00195 Flags = cop->sense; 00196 if (end) 00197 *end = op + strlen(cop->operator); 00198 break; 00199 } 00200 return Flags; 00201 }