Implementation of triggerprein scriptlets.
[platform/upstream/rpm.git] / build / parseReqs.c
1 /** \ingroup rpmbuild
2  * \file build/parseReqs.c
3  *  Parse dependency tag from spec file or from auto-dependency generator.
4  */
5
6 #include "system.h"
7
8 #include <rpm/rpmbuild.h>
9 #include <rpm/rpmlog.h>
10 #include "debug.h"
11
12 /**
13  */
14 static struct ReqComp {
15 const char * token;
16     rpmsenseFlags sense;
17 } ReqComparisons[] = {
18     { "<=", RPMSENSE_LESS | RPMSENSE_EQUAL},
19     { "=<", RPMSENSE_LESS | RPMSENSE_EQUAL},
20     { "<", RPMSENSE_LESS},
21
22     { "==", RPMSENSE_EQUAL},
23     { "=", RPMSENSE_EQUAL},
24     
25     { ">=", RPMSENSE_GREATER | RPMSENSE_EQUAL},
26     { "=>", RPMSENSE_GREATER | RPMSENSE_EQUAL},
27     { ">", RPMSENSE_GREATER},
28
29     { NULL, 0 },
30 };
31
32 #define SKIPWHITE(_x)   {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
33 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
34
35 rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpm_tag_t tagN,
36                int index, rpmsenseFlags tagflags)
37 {
38     const char *r, *re, *v, *ve;
39     char * N, * EVR;
40     rpmsenseFlags Flags;
41     Header h;
42
43     switch (tagN) {
44     case RPMTAG_PROVIDEFLAGS:
45         tagflags |= RPMSENSE_PROVIDES;
46         h = pkg->header;
47         break;
48     case RPMTAG_OBSOLETEFLAGS:
49         tagflags |= RPMSENSE_OBSOLETES;
50         h = pkg->header;
51         break;
52     case RPMTAG_CONFLICTFLAGS:
53         tagflags |= RPMSENSE_CONFLICTS;
54         h = pkg->header;
55         break;
56     case RPMTAG_BUILDCONFLICTS:
57         tagflags |= RPMSENSE_CONFLICTS;
58         h = spec->buildRestrictions;
59         break;
60     case RPMTAG_PREREQ:
61         tagflags |= RPMSENSE_PREREQ;
62         h = pkg->header;
63         break;
64     case RPMTAG_BUILDPREREQ:
65         tagflags |= RPMSENSE_PREREQ;
66         h = spec->buildRestrictions;
67         break;
68     case RPMTAG_TRIGGERPREIN:
69         tagflags |= RPMSENSE_TRIGGERPREIN;
70         h = pkg->header;
71         break;
72     case RPMTAG_TRIGGERIN:
73         tagflags |= RPMSENSE_TRIGGERIN;
74         h = pkg->header;
75         break;
76     case RPMTAG_TRIGGERPOSTUN:
77         tagflags |= RPMSENSE_TRIGGERPOSTUN;
78         h = pkg->header;
79         break;
80     case RPMTAG_TRIGGERUN:
81         tagflags |= RPMSENSE_TRIGGERUN;
82         h = pkg->header;
83         break;
84     case RPMTAG_BUILDREQUIRES:
85         tagflags |= RPMSENSE_ANY;
86         h = spec->buildRestrictions;
87         break;
88     default:
89     case RPMTAG_REQUIREFLAGS:
90         tagflags |= RPMSENSE_ANY;
91         h = pkg->header;
92         break;
93     }
94
95     for (r = field; *r != '\0'; r = re) {
96         SKIPWHITE(r);
97         if (*r == '\0')
98             break;
99
100         Flags = (tagflags & ~RPMSENSE_SENSEMASK);
101
102         /* Tokens must begin with alphanumeric, _, or / */
103         if (!(xisalnum(r[0]) || r[0] == '_' || r[0] == '/')) {
104             rpmlog(RPMLOG_ERR,
105                      _("line %d: Dependency tokens must begin with alpha-numeric, '_' or '/': %s\n"),
106                      spec->lineNum, spec->line);
107             return RPMRC_FAIL;
108         }
109
110         re = r;
111         SKIPNONWHITE(re);
112         N = xmalloc((re-r) + 1);
113         strncpy(N, r, (re-r));
114         N[re-r] = '\0';
115
116         /* Parse EVR */
117         v = re;
118         SKIPWHITE(v);
119         ve = v;
120         SKIPNONWHITE(ve);
121
122         re = v; /* ==> next token (if no EVR found) starts here */
123
124         /* Check for possible logical operator */
125         if (ve > v) {
126           struct ReqComp *rc;
127           for (rc = ReqComparisons; rc->token != NULL; rc++) {
128             if ((ve-v) != strlen(rc->token) || strncmp(v, rc->token, (ve-v)))
129                 continue;
130
131             if (r[0] == '/') {
132                 rpmlog(RPMLOG_ERR,
133                          _("line %d: Versioned file name not permitted: %s\n"),
134                          spec->lineNum, spec->line);
135                 return RPMRC_FAIL;
136             }
137
138             switch(tagN) {
139             case RPMTAG_BUILDPREREQ:
140             case RPMTAG_PREREQ:
141             case RPMTAG_PROVIDEFLAGS:
142             case RPMTAG_OBSOLETEFLAGS:
143                 /* Add prereq on rpmlib that has versioned dependencies. */
144                 if (!rpmExpandNumeric("%{?_noVersionedDependencies}"))
145                     (void) rpmlibNeedsFeature(h, "VersionedDependencies", "3.0.3-1");
146                 break;
147             default:
148                 break;
149             }
150             Flags |= rc->sense;
151
152             /* now parse EVR */
153             v = ve;
154             SKIPWHITE(v);
155             ve = v;
156             SKIPNONWHITE(ve);
157             break;
158           }
159         }
160
161         if (Flags & RPMSENSE_SENSEMASK) {
162             if (*v == '\0' || ve == v) {
163                 rpmlog(RPMLOG_ERR, _("line %d: Version required: %s\n"),
164                         spec->lineNum, spec->line);
165                 return RPMRC_FAIL;
166             }
167             EVR = xmalloc((ve-v) + 1);
168             strncpy(EVR, v, (ve-v));
169             EVR[ve-v] = '\0';
170             re = ve;    /* ==> next token after EVR string starts here */
171         } else
172             EVR = NULL;
173
174         (void) addReqProv(spec, h, tagN, N, EVR, Flags, index);
175
176         N = _free(N);
177         EVR = _free(EVR);
178
179     }
180
181     return RPMRC_OK;
182 }