Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Supported operators: %elif, %elifarch, %elifos.
There may be several %elifs within the same %if statement.
They must be placed after %if and before %endif and %else
(if %else is contained). The first %elif expression (if any)
that evaluates to TRUE would be executed.

In scope of %if you can use any of the new operators - %elif, %elifarch,
%elifos. Similarly for %ifos, %ifnos, %ifarch and %ifnarch.

The expression after %elif (resp. %elifos or %elifarch) is expandedd iff
the expression can influence the execution of the %elif branch.
E.g.: an %elif expression after the first %elif expression that
evaluates to TRUE is not expanded.
  • Loading branch information
pavlinamv authored and ffesti committed May 27, 2019
1 parent 5c3f332 commit 1c4b238
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
35 changes: 26 additions & 9 deletions build/parseSpec.c
Expand Up @@ -230,9 +230,15 @@ static int expandMacrosInSpecBuf(rpmSpec spec, int strip)
condition->text, spec->lineNum, lbuf);
}

/* Don't expand macros after %elif (resp. %elifarch, %elifos) in a false branch */
if (condition && (condition->id & LINE_ELIFANY)) {
if (!spec->readStack->readable)
return 0;
/* Don't expand macros (eg. %define) in false branch of %if clause */
if (!spec->readStack->reading)
return 0;
} else {
if (!spec->readStack->reading)
return 0;
}

if (specExpand(spec, ofi->lineNum, spec->lbuf, &lbuf))
return 1;
Expand Down Expand Up @@ -412,6 +418,7 @@ int readLine(rpmSpec spec, int strip)
int startLine = 0;
parsedSpecLine lineType;
int prevType = spec->readStack->lastConditional->id;
int checkCondition;

if (!restoreFirstChar(spec)) {
retry:
Expand Down Expand Up @@ -463,19 +470,23 @@ int readLine(rpmSpec spec, int strip)
return PART_ERROR;
}

if (lineType->id == LINE_IFARCH) {
if (lineType->id & (LINE_IFARCH | LINE_ELIFARCH)) {
ARGMATCH(s, "%{_target_cpu}", match);
} else if (lineType->id == LINE_IFNARCH) {
ARGMATCH(s, "%{_target_cpu}", match);
match = !match;
} else if (lineType->id == LINE_IFOS) {
} else if (lineType->id & (LINE_IFOS | LINE_ELIFOS)) {
ARGMATCH(s, "%{_target_os}", match);
} else if (lineType->id == LINE_IFNOS) {
ARGMATCH(s, "%{_target_os}", match);
match = !match;
} else if (lineType->id == LINE_IF) {
s += 3;
if (spec->readStack->reading) {
} else if (lineType->id & (LINE_IF | LINE_ELIF)) {
s += lineType->textLen;
if (lineType->id == LINE_IF)
checkCondition = spec->readStack->reading;
else
checkCondition = spec->readStack->readable;
if (checkCondition) {
match = parseExpressionBoolean(s);
if (match < 0) {
rpmlog(RPMLOG_ERR,
Expand All @@ -487,7 +498,7 @@ int readLine(rpmSpec spec, int strip)
} else if (lineType->id == LINE_ELSE) {
spec->readStack->lastConditional = lineType;
spec->readStack->reading =
spec->readStack->next->reading && ! spec->readStack->reading;
spec->readStack->next->reading && spec->readStack->readable;
spec->line[0] = '\0';
} else if (lineType->id == LINE_ENDIF) {
rl = spec->readStack;
Expand Down Expand Up @@ -517,14 +528,20 @@ int readLine(rpmSpec spec, int strip)
goto retry;
}

if (lineType->id & (LINE_IFANY)) {
if (lineType->id & LINE_IFANY) {
rl = xmalloc(sizeof(*rl));
rl->reading = spec->readStack->reading && match;
rl->next = spec->readStack;
rl->lineNum = ofi->lineNum;
rl->readable = (!rl->reading) && (spec->readStack->reading);
rl->lastConditional = lineType;
spec->readStack = rl;
spec->line[0] = '\0';
} else if (lineType->id & LINE_ELIFANY) {
spec->readStack->reading = spec->readStack->readable && match;
if (spec->readStack->reading)
spec->readStack->readable = 0;
spec->line[0] = '\0';
}

after_classification:
Expand Down
8 changes: 8 additions & 0 deletions build/rpmbuild_internal.h
Expand Up @@ -42,6 +42,9 @@ typedef enum rpmParseLineType_e {
LINE_ELSE = (1 << 5),
LINE_ENDIF = (1 << 6),
LINE_INCLUDE = (1 << 7),
LINE_ELIF = (1 << 8),
LINE_ELIFARCH = (1 << 9),
LINE_ELIFOS = (1 << 10),
} rpmParseLineType;

typedef const struct parsedSpecLine_s {
Expand All @@ -62,14 +65,19 @@ static struct parsedSpecLine_s const lineTypes[] = {
{ LINE_IFOS, LEN_AND_STR("%ifos") , 1, 1, 0},
{ LINE_IFNOS, LEN_AND_STR("%ifnos") , 1, 1, 0},
{ LINE_INCLUDE, LEN_AND_STR("%include"), 1, 0, 0},
{ LINE_ELIFARCH, LEN_AND_STR("%elifarch"), 1, 1, LINE_ENDIF | LINE_ELSE},
{ LINE_ELIFOS, LEN_AND_STR("%elifos"), 1, 1, LINE_ENDIF | LINE_ELSE},
{ LINE_ELIF, LEN_AND_STR("%elif") ,1, 1, LINE_ENDIF | LINE_ELSE},
{ 0, 0, 0, 0, 0, 0 }
};

#define LINE_IFANY (LINE_IF | LINE_IFARCH | LINE_IFNARCH | LINE_IFOS | LINE_IFNOS)
#define LINE_ELIFANY (LINE_ELIF | LINE_ELIFOS | LINE_ELIFARCH)

typedef struct ReadLevelEntry {
int reading;
int lineNum;
int readable;
parsedSpecLine lastConditional;
struct ReadLevelEntry * next;
} RLE_t;
Expand Down
1 change: 1 addition & 0 deletions build/spec.c
Expand Up @@ -271,6 +271,7 @@ rpmSpec newSpec(void)
spec->readStack->next = NULL;
spec->readStack->reading = 1;
spec->readStack->lastConditional = lineTypes;
spec->readStack->readable = 1;

spec->rootDir = NULL;
spec->prep = NULL;
Expand Down

0 comments on commit 1c4b238

Please sign in to comment.