• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 }

Generated on Mon Nov 29 2010 05:18:44 for rpm by  doxygen 1.7.2