Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

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 #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 }

Generated on Tue Dec 27 22:20:13 2016 for rpm by  doxygen 1.4.4