- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# 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         if (*evr->E == '\0') evr->E = "0";
    00110         evr->Elong = strtoul(evr->E, NULL, 10);
    00111     } else {
    00112         evr->E = NULL;  /* XXX disable epoch compare if missing */
    00113         evr->V = s;
    00114         evr->Elong = 0;
    00115     }
    00116     se = strrchr(se, '-');              /* se points to version terminator */
    00117     if (se) {
    00118         *se++ = '\0';
    00119         evr->R = se;
    00120     } else {
    00121         evr->R = NULL;
    00122     }
    00123     return 0;
    00124 }
    00125
    00132 static int compare_values(const char *a, const char *b)
    00133         /*@*/
    00134 {
    00135     return rpmvercmp(a, b);
    00136 }
    00137
    00138 int rpmEVRcompare(const EVR_t a, const EVR_t b)
    00139 {
    00140     int rc = 0;
    00141
    00142     if (!rc)
    00143         rc = compare_values(a->E, b->E);
    00144     if (!rc)
    00145         rc = compare_values(a->V, b->V);
    00146     if (!rc)
    00147         rc = compare_values(a->R, b->R);
    00148     return rc;
    00149 }
    00150
    00151 int (*rpmvercmp) (const char *a, const char *b) = rpmEVRcmp;
    00152
    00155 /*@unchecked@*/ /*@observer@*/
    00156 static struct EVRop_s {
    00157 /*@observer@*/ /*@null@*/
    00158     const char * operator;
    00159     rpmsenseFlags sense;
    00160 } cops[] = {
    00161     { "<=", RPMSENSE_LESS ^ RPMSENSE_EQUAL},
    00162     { "=<", RPMSENSE_LESS ^ RPMSENSE_EQUAL},
    00163
    00164     { "==", RPMSENSE_EQUAL},
    00165     { "!=", RPMSENSE_NOTEQUAL},
    00166
    00167     { ">=", RPMSENSE_GREATER ^ RPMSENSE_EQUAL},
    00168     { "=>", RPMSENSE_GREATER ^ RPMSENSE_EQUAL},
    00169
    00170     { "<", RPMSENSE_LESS},
    00171     { "=", RPMSENSE_EQUAL},
    00172     { ">", RPMSENSE_GREATER},
    00173
    00174     { NULL, 0 },
    00175 };
    00176
    00177 rpmsenseFlags rpmEVRflags(const char *op, const char **end)
    00178 {
    00179     rpmsenseFlags Flags = 0;
    00180     struct EVRop_s *cop;
    00181
    00182     if (op == NULL || *op == '\0')
    00183         Flags = RPMSENSE_EQUAL;
    00184     else
    00185     for (cop = cops; cop->operator != NULL; cop++) {
    00186         if (strncmp(op, cop->operator, strlen(cop->operator)))
    00187             continue;
    00188         Flags = cop->sense;
    00189         if (end)
    00190             *end = op + strlen(cop->operator);
    00191         break;
    00192     }
    00193     return Flags;
    00194 }