LCOV - code coverage report
Current view: top level - libpkg - pkg_deps.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 249 300 83.0 %
Date: 2015-08-15 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2015, Vsevolod Stakhov
       3             :  * All rights reserved.
       4             :  *
       5             :  * Redistribution and use in source and binary forms, with or without
       6             :  * modification, are permitted provided that the following conditions are met:
       7             :  *       * Redistributions of source code must retain the above copyright
       8             :  *         notice, this list of conditions and the following disclaimer.
       9             :  *       * Redistributions in binary form must reproduce the above copyright
      10             :  *         notice, this list of conditions and the following disclaimer in the
      11             :  *         documentation and/or other materials provided with the distribution.
      12             :  *
      13             :  * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
      14             :  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      15             :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      16             :  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
      17             :  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      18             :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      19             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      20             :  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      21             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      22             :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      23             :  */
      24             : 
      25             : #ifdef HAVE_CONFIG_H
      26             : #include "pkg_config.h"
      27             : #endif
      28             : 
      29             : #include "bsd_compat.h"
      30             : 
      31             : #include <stddef.h>
      32             : #include <ctype.h>
      33             : #include <assert.h>
      34             : #include <string.h>
      35             : 
      36             : #include "pkg.h"
      37             : #include "private/event.h"
      38             : #include "private/pkg_deps.h"
      39             : #include "utlist.h"
      40             : 
      41             : struct pkg_dep_formula *
      42          12 : pkg_deps_parse_formula(const char *in)
      43             : {
      44          12 :         struct pkg_dep_formula *res = NULL, *cur = NULL;
      45          12 :         struct pkg_dep_formula_item *cur_item = NULL;
      46          12 :         struct pkg_dep_version_item *cur_ver = NULL;
      47          12 :         struct pkg_dep_option_item *cur_opt = NULL;
      48             :         const char *p, *c, *end;
      49          12 :         enum pkg_dep_version_op cur_op = VERSION_ANY;
      50             :         enum {
      51             :                 st_parse_dep_name = 0,
      52             :                 st_parse_after_name,
      53             :                 st_parse_ver_op,
      54             :                 st_parse_after_op,
      55             :                 st_parse_version_number,
      56             :                 st_parse_after_version,
      57             :                 st_parse_option_start,
      58             :                 st_parse_option,
      59             :                 st_parse_after_option,
      60             :                 st_parse_comma,
      61             :                 st_parse_or,
      62             :                 st_skip_spaces,
      63             :                 st_error
      64          12 :         } state = 0, next_state = 0;
      65             : 
      66          12 :         c = in;
      67          12 :         p = in;
      68             : 
      69          12 :         end = p + strlen(p);
      70             : 
      71         448 :         while (p <= end) {
      72         424 :                 switch (state) {
      73             :                 case st_parse_dep_name:
      74         126 :                         if (isspace(*p) || *p == '\0') {
      75          20 :                                 state = st_skip_spaces;
      76             : 
      77          40 :                                 if (p == c) {
      78             :                                         /* Spaces at the beginning */
      79           0 :                                         next_state = st_parse_dep_name;
      80             :                                 }
      81             :                                 else {
      82             :                                         /* Spaces after the name */
      83          20 :                                         cur_item = calloc(1, sizeof(*cur_item));
      84             : 
      85          20 :                                         if (cur_item == NULL) {
      86           0 :                                                 pkg_emit_errno("malloc", "struct pkg_dep_formula_item");
      87             : 
      88           0 :                                                 return (NULL);
      89             :                                         }
      90          20 :                                         cur_item->name = malloc(p - c + 1);
      91             : 
      92          20 :                                         if (cur_item->name == NULL) {
      93           0 :                                                 pkg_emit_errno("malloc", "cur->name");
      94             : 
      95           0 :                                                 return (NULL);
      96             :                                         }
      97             : 
      98          20 :                                         strlcpy(cur_item->name, c, p - c + 1);
      99          20 :                                         next_state = st_parse_after_name;
     100             :                                 }
     101             :                         }
     102         106 :                         else if (*p == ',') {
     103           2 :                                 if (p == c) {
     104           0 :                                         state = st_error;
     105             :                                 }
     106             :                                 else {
     107           2 :                                         cur_item = calloc(1, sizeof(*cur_item));
     108             : 
     109           2 :                                         if (cur_item == NULL) {
     110           0 :                                                 pkg_emit_errno("malloc", "struct pkg_dep_formula_item");
     111             : 
     112           0 :                                                 return (NULL);
     113             :                                         }
     114           2 :                                         cur_item->name = malloc(p - c + 1);
     115             : 
     116           2 :                                         if (cur_item->name == NULL) {
     117           0 :                                                 pkg_emit_errno("malloc", "cur->name");
     118             : 
     119           0 :                                                 return (NULL);
     120             :                                         }
     121             : 
     122           2 :                                         strlcpy(cur_item->name, c, p - c + 1);
     123           2 :                                         state = st_parse_after_name;
     124             :                                 }
     125             :                         }
     126         104 :                         else if (!isprint(*p)) {
     127           0 :                                 state = st_error;
     128             :                         }
     129             :                         else {
     130         104 :                                 p++;
     131             :                         }
     132         126 :                         break;
     133             : 
     134             :                 case st_parse_after_name:
     135             :                 case st_parse_after_version:
     136             :                 case st_parse_after_option: {
     137          28 :                         switch (*p) {
     138             :                         case ',':
     139             :                         case '\0':
     140           5 :                                 state = st_parse_comma;
     141           5 :                                 break;
     142             :                         case '|':
     143           5 :                                 state = st_parse_or;
     144           5 :                                 break;
     145             :                         case '+':
     146             :                         case '-':
     147           2 :                                 c = p;
     148           2 :                                 state = st_parse_option_start;
     149           2 :                                 break;
     150             :                         case '>':
     151             :                         case '<':
     152             :                         case '=':
     153             :                         case '!':
     154          16 :                                 c = p;
     155          16 :                                 cur_op = VERSION_ANY;
     156          16 :                                 state = st_parse_ver_op;
     157          16 :                                 break;
     158             :                         default:
     159           0 :                                 state = st_error;
     160           0 :                                 break;
     161             :                         }
     162          28 :                         break;
     163             :                 }
     164             : 
     165             :                 case st_parse_ver_op: {
     166          39 :                         switch (*p) {
     167             :                         case '>':
     168             :                         case '<':
     169             :                         case '=':
     170             :                         case '!':
     171          23 :                                 p ++;
     172          23 :                                 break;
     173             :                         default:
     174          16 :                                 if (p - c == 2) {
     175           7 :                                         if (memcmp(c, ">=", 2) == 0) {
     176           2 :                                                 cur_op = VERSION_GE;
     177             :                                         }
     178           5 :                                         else if (memcmp(c, "<=", 2) == 0) {
     179           0 :                                                 cur_op = VERSION_LE;
     180             :                                         }
     181           5 :                                         else if (memcmp(c, "!=", 2) == 0) {
     182           5 :                                                 cur_op = VERSION_NOT;
     183             :                                         }
     184           0 :                                         else if (memcmp(c, "==", 2) == 0) {
     185           0 :                                                 cur_op = VERSION_EQ;
     186             :                                         }
     187             :                                         else {
     188           0 :                                                 state = st_error;
     189             :                                         }
     190             :                                 }
     191           9 :                                 else if (p - c == 1) {
     192           9 :                                         if (*c == '>') {
     193           2 :                                                 cur_op = VERSION_GT;
     194             :                                         }
     195           7 :                                         else if (*c == '<') {
     196           2 :                                                 cur_op = VERSION_LT;
     197             :                                         }
     198           5 :                                         else if (*c == '!') {
     199           0 :                                                 cur_op = VERSION_NOT;
     200             :                                         }
     201           5 :                                         else if (*c == '=') {
     202           5 :                                                 cur_op = VERSION_EQ;
     203             :                                         }
     204             :                                         else {
     205           0 :                                                 state = st_error;
     206             :                                         }
     207             :                                 }
     208             :                                 else {
     209           0 :                                         state = st_error;
     210             :                                 }
     211             : 
     212          16 :                                 if (state != st_error) {
     213          16 :                                         state = st_skip_spaces;
     214          16 :                                         next_state = st_parse_after_op;
     215             :                                 }
     216          16 :                                 break;
     217             :                         }
     218          39 :                         break;
     219             :                 }
     220             : 
     221             :                 case st_parse_after_op:
     222          16 :                         if (cur_op == VERSION_ANY) {
     223           0 :                                 state = st_error;
     224             :                         }
     225             :                         else {
     226          16 :                                 state = st_parse_version_number;
     227             :                         }
     228          16 :                         break;
     229             : 
     230             :                 case st_parse_version_number:
     231          86 :                         if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' ||
     232          23 :                                         (*p == ',' && isdigit(*(p + 1)))) {
     233          52 :                                 p ++;
     234             :                         }
     235             :                         else {
     236          16 :                                 if (p - c > 0) {
     237          16 :                                         cur_ver = calloc(1, sizeof(*cur_ver));
     238             : 
     239          16 :                                         if (cur_ver == NULL) {
     240           0 :                                                 pkg_emit_errno("malloc", "struct pkg_dep_version");
     241             : 
     242           0 :                                                 return (NULL);
     243             :                                         }
     244          16 :                                         cur_ver->ver = malloc(p - c + 1);
     245             : 
     246          16 :                                         if (cur_ver->ver == NULL) {
     247           0 :                                                 pkg_emit_errno("malloc", "cur_ver->ver");
     248             : 
     249           0 :                                                 return (NULL);
     250             :                                         }
     251             : 
     252          16 :                                         strlcpy(cur_ver->ver, c, p - c + 1);
     253          16 :                                         cur_ver->op = cur_op;
     254          16 :                                         assert(cur_item != NULL);
     255          16 :                                         DL_APPEND(cur_item->versions, cur_ver);
     256          16 :                                         state = st_skip_spaces;
     257          16 :                                         next_state = st_parse_after_version;
     258             :                                 }
     259             :                                 else {
     260           0 :                                         state = st_error;
     261             :                                 }
     262             :                         }
     263          68 :                         break;
     264             : 
     265             :                 case st_parse_option_start:
     266           2 :                         cur_opt = calloc(1, sizeof(*cur_opt));
     267           2 :                         if (cur_ver == NULL) {
     268           0 :                                 pkg_emit_errno("malloc", "struct pkg_dep_option");
     269             : 
     270           0 :                                 return (NULL);
     271             :                         }
     272             : 
     273           2 :                         if (*p == '+') {
     274           1 :                                 cur_opt->on = true;
     275             :                         }
     276             :                         else {
     277           1 :                                 cur_opt->on = false;
     278             :                         }
     279             : 
     280           2 :                         p ++;
     281           2 :                         c = p;
     282           2 :                         state = st_parse_option;
     283           2 :                         break;
     284             : 
     285             :                 case st_parse_option:
     286          10 :                         if (isalnum(*p) || *p == '-' || *p == '_') {
     287           8 :                                 p ++;
     288             :                         }
     289             :                         else {
     290           2 :                                 if (p - c > 0) {
     291           2 :                                         cur_opt->opt = malloc(p - c + 1);
     292             : 
     293           2 :                                         if (cur_opt->opt == NULL) {
     294           0 :                                                 pkg_emit_errno("malloc", "cur_opt->opt");
     295             : 
     296           0 :                                                 return (NULL);
     297             :                                         }
     298             : 
     299           2 :                                         strlcpy(cur_opt->opt, c, p - c + 1);
     300           2 :                                         assert(cur_item != NULL);
     301           2 :                                         DL_APPEND(cur_item->options, cur_opt);
     302           2 :                                         state = st_skip_spaces;
     303           2 :                                         next_state = st_parse_after_option;
     304             :                                 }
     305             :                                 else {
     306           0 :                                         state = st_error;
     307             :                                 }
     308             :                         }
     309          10 :                         break;
     310             : 
     311             :                 case st_parse_comma:
     312          17 :                         assert(cur_item != NULL);
     313             : 
     314          17 :                         if (cur == NULL) {
     315          12 :                                 cur = calloc(1, sizeof(*cur));
     316             : 
     317          12 :                                 if (cur == NULL) {
     318           0 :                                         pkg_emit_errno("malloc", "struct pkg_dep_formula");
     319             : 
     320           0 :                                         return (NULL);
     321             :                                 }
     322             :                         }
     323             : 
     324          17 :                         DL_APPEND(cur->items, cur_item);
     325          17 :                         DL_APPEND(res, cur);
     326          17 :                         cur_item = NULL;
     327          17 :                         cur = NULL;
     328          17 :                         p ++;
     329          17 :                         state = st_skip_spaces;
     330          17 :                         next_state = st_parse_dep_name;
     331          17 :                         break;
     332             : 
     333             :                 case st_parse_or:
     334           5 :                         assert(cur_item != NULL);
     335             : 
     336           5 :                         if (cur == NULL) {
     337           5 :                                 cur = calloc(1, sizeof(*cur));
     338             : 
     339           5 :                                 if (cur == NULL) {
     340           0 :                                         pkg_emit_errno("malloc", "struct pkg_dep_formula");
     341             : 
     342           0 :                                         return (NULL);
     343             :                                 }
     344             :                         }
     345             : 
     346           5 :                         DL_APPEND(cur->items, cur_item);
     347           5 :                         cur_item = NULL;
     348           5 :                         p ++;
     349           5 :                         state = st_skip_spaces;
     350           5 :                         next_state = st_parse_dep_name;
     351           5 :                         break;
     352             : 
     353             :                 case st_skip_spaces:
     354         113 :                         if (isspace(*p)) {
     355          49 :                                 p ++;
     356             :                         }
     357          64 :                         else if (*p == '\0') {
     358          12 :                                 state = st_parse_comma;
     359             :                         }
     360             :                         else {
     361          52 :                                 c = p;
     362          52 :                                 state = next_state;
     363             :                         }
     364         113 :                         break;
     365             : 
     366             :                 case st_error:
     367             :                 default:
     368           0 :                         pkg_emit_error("cannot parse pkg formula: %s", in);
     369           0 :                         pkg_deps_formula_free(res);
     370             : 
     371           0 :                         return (NULL);
     372             : 
     373             :                         break;
     374             :                 }
     375             :         }
     376             : 
     377          12 :         if (state != st_skip_spaces && state != st_parse_comma) {
     378           0 :                 pkg_emit_error("cannot parse pkg formula: %s", in);
     379           0 :                 pkg_deps_formula_free(res);
     380             : 
     381           0 :                 return (NULL);
     382             :         }
     383             : 
     384          12 :         return (res);
     385             : }
     386             : 
     387             : void
     388          12 : pkg_deps_formula_free(struct pkg_dep_formula *f)
     389             : {
     390             :         struct pkg_dep_formula *cf, *cftmp;
     391             :         struct pkg_dep_formula_item *cit, *cittmp;
     392             :         struct pkg_dep_version_item *cver, *cvertmp;
     393             :         struct pkg_dep_option_item *copt, *copttmp;
     394             : 
     395          29 :         DL_FOREACH_SAFE(f, cf, cftmp) {
     396          39 :                 DL_FOREACH_SAFE(cf->items, cit, cittmp) {
     397          22 :                         free(cit->name);
     398             : 
     399          38 :                         DL_FOREACH_SAFE(cit->versions, cver, cvertmp) {
     400          16 :                                 free(cver->ver);
     401          16 :                                 free(cver);
     402             :                         }
     403             : 
     404          24 :                         DL_FOREACH_SAFE(cit->options, copt, copttmp) {
     405           2 :                                 free(copt->opt);
     406           2 :                                 free(copt);
     407             :                         }
     408             : 
     409          22 :                         free(cit);
     410             :                 }
     411             : 
     412          17 :                 free(cf);
     413             :         }
     414          12 : }
     415             : 
     416             : static const char*
     417          16 : pkg_deps_op_tostring(enum pkg_dep_version_op op)
     418             : {
     419             :         const char *op_str;
     420             : 
     421          16 :         switch (op) {
     422             :         case VERSION_ANY:
     423             :         default:
     424           0 :                 op_str = "?";
     425           0 :                 break;
     426             :         case VERSION_EQ:
     427           5 :                 op_str = "=";
     428           5 :                 break;
     429             :         case VERSION_LE:
     430           0 :                 op_str = "<=";
     431           0 :                 break;
     432             :         case VERSION_GE:
     433           2 :                 op_str = ">=";
     434           2 :                 break;
     435             :         case VERSION_LT:
     436           2 :                 op_str = "<";
     437           2 :                 break;
     438             :         case VERSION_GT:
     439           2 :                 op_str = ">";
     440           2 :                 break;
     441             :         case VERSION_NOT:
     442           5 :                 op_str = "!=";
     443           5 :                 break;
     444             :         }
     445             : 
     446          16 :         return (op_str);
     447             : }
     448             : 
     449             : char*
     450           7 : pkg_deps_formula_tostring(struct pkg_dep_formula *f)
     451             : {
     452             :         struct pkg_dep_formula *cf, *cftmp;
     453             :         struct pkg_dep_formula_item *cit, *cittmp;
     454             :         struct pkg_dep_version_item *cver, *cvertmp;
     455             :         struct pkg_dep_option_item *copt, *copttmp;
     456           7 :         char *res = NULL, *p;
     457             : 
     458           7 :         int rlen = 0, r;
     459             : 
     460          19 :         DL_FOREACH_SAFE(f, cf, cftmp) {
     461          27 :                 DL_FOREACH_SAFE(cf->items, cit, cittmp) {
     462          15 :                         rlen += strlen(cit->name);
     463             : 
     464          27 :                         DL_FOREACH_SAFE(cit->versions, cver, cvertmp) {
     465          12 :                                 rlen += strlen(cver->ver);
     466          12 :                                 rlen += 4; /* <OP><SP><VER><SP> */
     467             :                         }
     468             : 
     469          17 :                         DL_FOREACH_SAFE(cit->options, copt, copttmp) {
     470           2 :                                 rlen += strlen(copt->opt);
     471           2 :                                 rlen += 2; /* <+-><OPT><SP> */
     472             :                         }
     473             : 
     474          15 :                         rlen += 2; /* |<SP> */
     475             :                 }
     476             : 
     477          12 :                 rlen += 2; /* <,><SP> */
     478             :         }
     479             : 
     480           7 :         if (rlen == 0) {
     481           0 :                 return (NULL);
     482             :         }
     483             : 
     484           7 :         res = malloc(rlen + 1);
     485             : 
     486           7 :         if (res == NULL) {
     487           0 :                 pkg_emit_errno("malloc", "string");
     488             : 
     489           0 :                 return (NULL);
     490             :         }
     491             : 
     492           7 :         p = res;
     493             : 
     494          19 :         DL_FOREACH_SAFE(f, cf, cftmp) {
     495          27 :                 DL_FOREACH_SAFE(cf->items, cit, cittmp) {
     496          15 :                         r = snprintf(p, rlen, "%s", cit->name);
     497          15 :                         p += r;
     498          15 :                         rlen -= r;
     499             : 
     500          27 :                         DL_FOREACH_SAFE(cit->versions, cver, cvertmp) {
     501          12 :                                 r = snprintf(p, rlen, " %s %s", pkg_deps_op_tostring(cver->op),
     502             :                                                 cver->ver);
     503          12 :                                 p += r;
     504          12 :                                 rlen -= r;
     505             :                         }
     506             : 
     507          17 :                         DL_FOREACH_SAFE(cit->options, copt, copttmp) {
     508           2 :                                 r = snprintf(p, rlen, " %c%s", copt->on ? '+' : '-', copt->opt);
     509           2 :                                 p += r;
     510           2 :                                 rlen -= r;
     511             :                         }
     512             : 
     513          15 :                         r = snprintf(p, rlen, "%s", cit->next ? " | " : "");
     514          15 :                         p += r;
     515          15 :                         rlen -= r;
     516             :                 }
     517             : 
     518          12 :                 r = snprintf(p, rlen, "%s", cf->next ? ", " : "");
     519          12 :                 p += r;
     520          12 :                 rlen -= r;
     521             :         }
     522             : 
     523           7 :         return (res);
     524             : }
     525             : 
     526             : char*
     527           5 : pkg_deps_formula_tosql(struct pkg_dep_formula_item *f)
     528             : {
     529             :         struct pkg_dep_formula_item *cit, *cittmp;
     530             :         struct pkg_dep_version_item *cver, *cvertmp;
     531           5 :         char *res = NULL, *p;
     532             : 
     533           5 :         int rlen = 0, r;
     534             : 
     535          12 :         DL_FOREACH_SAFE(f, cit, cittmp) {
     536           7 :                 rlen += sizeof("AND (name='' )");
     537           7 :                 rlen += strlen(cit->name);
     538             : 
     539          11 :                 DL_FOREACH_SAFE(cit->versions, cver, cvertmp) {
     540           4 :                         rlen += sizeof(" AND vercmp(>=, version,'') ");
     541           4 :                         rlen += strlen(cver->ver);
     542             :                 }
     543             : 
     544           7 :                 rlen += sizeof(" OR ");
     545             :         }
     546             : 
     547           5 :         if (rlen == 0) {
     548           0 :                 return (NULL);
     549             :         }
     550             : 
     551           5 :         res = malloc(rlen + 1);
     552             : 
     553           5 :         if (res == NULL) {
     554           0 :                 pkg_emit_errno("malloc", "string");
     555             : 
     556           0 :                 return (NULL);
     557             :         }
     558             : 
     559           5 :         p = res;
     560             : 
     561          12 :         DL_FOREACH_SAFE(f, cit, cittmp) {
     562           7 :                 r = snprintf(p, rlen, "(name='%s'", cit->name);
     563           7 :                 p += r;
     564           7 :                 rlen -= r;
     565             : 
     566          11 :                 DL_FOREACH_SAFE(cit->versions, cver, cvertmp) {
     567           4 :                         r = snprintf(p, rlen, " AND vercmp('%s',version,'%s')",
     568             :                                         pkg_deps_op_tostring(cver->op),
     569             :                                         cver->ver);
     570           4 :                         p += r;
     571           4 :                         rlen -= r;
     572             :                 }
     573           7 :                 r = snprintf(p, rlen, ")%s", cit->next ? " OR " : "");
     574           7 :                 p += r;
     575           7 :                 rlen -= r;
     576             :         }
     577             : 
     578           5 :         return (res);
     579             : }
     580             : 
     581             : enum pkg_dep_version_op
     582          11 : pkg_deps_string_toop(const char *in)
     583             : {
     584          11 :         enum pkg_dep_version_op ret = VERSION_ANY;
     585             :         int len;
     586             : 
     587          11 :         if (in != NULL) {
     588          10 :                 len = strlen(in);
     589             : 
     590          10 :                 if (len == 2) {
     591           5 :                         if (memcmp(in, ">=", 2) == 0) {
     592           1 :                                 ret = VERSION_GE;
     593             :                         }
     594           4 :                         else if (memcmp(in, "<=", 2) == 0) {
     595           1 :                                 ret = VERSION_LE;
     596             :                         }
     597           3 :                         else if (memcmp(in, "!=", 2) == 0) {
     598           1 :                                 ret = VERSION_NOT;
     599             :                         }
     600           2 :                         else if (memcmp(in, "==", 2) == 0) {
     601           1 :                                 ret = VERSION_EQ;
     602             :                         }
     603             :                 }
     604           5 :                 else if (len == 1) {
     605           5 :                         if (*in == '>') {
     606           1 :                                 ret = VERSION_GT;
     607             :                         }
     608           4 :                         else if (*in == '<') {
     609           1 :                                 ret = VERSION_LT;
     610             :                         }
     611           3 :                         else if (*in == '!') {
     612           1 :                                 ret = VERSION_NOT;
     613             :                         }
     614           2 :                         else if (*in == '=') {
     615           1 :                                 ret = VERSION_EQ;
     616             :                         }
     617             :                 }
     618             :         }
     619             : 
     620          11 :         return (ret);
     621             : }

Generated by: LCOV version 1.10