lib/rpmevr.c

Go to the documentation of this file.
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 /*@unchecked@*/
00022 static int _invert_digits_alphas_comparison = -1;
00023 
00024 /* XXX Punctuation characters that are not treated as alphas */
00025 /*@unchecked@*/ /*@observer@*/
00026 static const char * _rpmnotalpha = ".:-";
00027 
00033 static inline int xisrpmalpha(int c)
00034         /*@*/
00035 {
00036     int rc = xisalpha(c);
00037     if (!rc)
00038         rc = xispunct(c);
00039     if (rc && _rpmnotalpha && *_rpmnotalpha)
00040         rc = (strchr(_rpmnotalpha, c) == NULL);
00041     return rc;
00042 }
00043 
00044 int rpmEVRcmp(const char * a, const char * b)
00045         /*@*/
00046 {
00047     const char * ae, * be;
00048     int rc = 0;
00049 
00050     /* Compare version strings segment by segment. */
00051     for (; *a && *b && rc == 0; a = ae, b = be) {
00052 
00053         /* Skip leading non-alpha, non-digit characters. */
00054         while (*a && !(xisdigit(*a) || xisrpmalpha(*a))) a++;
00055         while (*b && !(xisdigit(*b) || xisrpmalpha(*b))) b++;
00056 
00057         /* Digit string comparison? */
00058         if (xisdigit(*a) || xisdigit(*b)) {
00059             /* Discard leading zeroes. */
00060             while (a[0] == '0' && xisdigit(a[1])) a++;
00061             while (b[0] == '0' && xisdigit(b[1])) b++;
00062 
00063             /* Find end of digit strings. */
00064             ae = a; while (xisdigit(*ae)) ae++;
00065             be = b; while (xisdigit(*be)) be++;
00066 
00067             /* Calculate digit comparison return code. */
00068             if (a == ae || b == be)
00069                 rc = (*b - *a) * _invert_digits_alphas_comparison;
00070             else {
00071                 rc = (ae - a) - (be - b);
00072                 if (!rc)
00073                     rc = strncmp(a, b, (ae - a));
00074             }
00075         } else {
00076             /* Find end of alpha strings. */
00077             ae = a; while (xisrpmalpha(*ae)) ae++;
00078             be = b; while (xisrpmalpha(*be)) be++;
00079 
00080             /* Calculate alpha comparison return code. */
00081             rc = strncmp(a, b, MAX((ae - a), (be - b)));
00082         }
00083     }
00084 
00085     /* Longer string wins. */
00086     if (!rc)
00087         rc = (*a - *b);
00088 
00089     /* Force strict -1, 0, 1 return. */
00090     rc = (rc > 0 ? 1
00091         : rc < 0 ? -1
00092         : 0);
00093     return rc;
00094 }
00095 
00096 int rpmEVRparse(const char * evrstr, EVR_t evr)
00097         /*@modifies evrstr, evr @*/
00098 {
00099     char *s = xstrdup(evrstr);
00100     char *se;
00101 
00102     evr->str = se = s;
00103     while (*se && xisdigit(*se)) se++;  /* se points to epoch terminator */
00104 
00105     if (*se == ':') {
00106         evr->E = s;
00107         *se++ = '\0';
00108         evr->V = se;
00109 /*@-branchstate@*/
00110         if (*evr->E == '\0') evr->E = "0";
00111 /*@=branchstate@*/
00112         evr->Elong = strtoul(evr->E, NULL, 10);
00113     } else {
00114         evr->E = NULL;  /* XXX disable epoch compare if missing */
00115         evr->V = s;
00116         evr->Elong = 0;
00117     }
00118     se = strrchr(se, '-');              /* se points to version terminator */
00119     if (se) {
00120         *se++ = '\0';
00121         evr->R = se;
00122     } else {
00123         evr->R = NULL;
00124     }
00125     return 0;
00126 }
00127 
00134 static int compare_values(const char *a, const char *b)
00135         /*@*/
00136 {
00137     return rpmvercmp(a, b);
00138 }
00139 
00140 int rpmEVRcompare(const EVR_t a, const EVR_t b)
00141 {
00142     int rc = 0;
00143 
00144     if (!rc)
00145         rc = compare_values(a->E, b->E);
00146     if (!rc)
00147         rc = compare_values(a->V, b->V);
00148     if (!rc)
00149         rc = compare_values(a->R, b->R);
00150     return rc;
00151 }
00152 
00153 int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp;
00154 
00157 /*@unchecked@*/ /*@observer@*/
00158 static struct EVRop_s {
00159 /*@observer@*/ /*@null@*/
00160     const char * operator;
00161     rpmsenseFlags sense;
00162 } cops[] = {
00163     { "<=", RPMSENSE_LESS ^ RPMSENSE_EQUAL},
00164     { "=<", RPMSENSE_LESS ^ RPMSENSE_EQUAL},
00165 
00166     { "==", RPMSENSE_EQUAL},
00167     { "!=", RPMSENSE_NOTEQUAL},
00168     
00169     { ">=", RPMSENSE_GREATER ^ RPMSENSE_EQUAL},
00170     { "=>", RPMSENSE_GREATER ^ RPMSENSE_EQUAL},
00171 
00172     { "<", RPMSENSE_LESS},
00173     { "=", RPMSENSE_EQUAL},
00174     { ">", RPMSENSE_GREATER},
00175 
00176     { NULL, 0 },
00177 };
00178 
00179 rpmsenseFlags rpmEVRflags(const char *op, const char **end)
00180 {
00181     rpmsenseFlags Flags = 0;
00182     struct EVRop_s *cop;
00183 
00184     if (op == NULL || *op == '\0')
00185         Flags = RPMSENSE_EQUAL;
00186     else
00187     for (cop = cops; cop->operator != NULL; cop++) {
00188         if (strncmp(op, cop->operator, strlen(cop->operator)))
00189             continue;
00190         Flags = cop->sense;
00191         if (end)
00192             *end = op + strlen(cop->operator);
00193         break;
00194     }
00195     return Flags;
00196 }

Generated on Fri May 25 21:18:12 2007 for rpm by  doxygen 1.5.2