Implemented multiline macro support.
CVS patchset: 7231 CVS date: 2004/04/08 20:27:53
This commit is contained in:
parent
66f860d94f
commit
70905ee4c6
|
@ -145,15 +145,50 @@ static int copyNextLine(Spec spec, OFI_t *ofi, int strip)
|
|||
}
|
||||
/* Expand next line from file into line buffer */
|
||||
if (!(spec->nextline && *spec->nextline)) {
|
||||
char *from, *to;
|
||||
to = last = spec->lbuf;
|
||||
int pc = 0, bc = 0, nc = 0;
|
||||
char *from, *to, *p;
|
||||
to = spec->lbufPtr ? spec->lbufPtr : spec->lbuf;
|
||||
from = ofi->readPtr;
|
||||
ch = ' ';
|
||||
while (*from && ch != '\n')
|
||||
ch = *to++ = *from++;
|
||||
spec->lbufPtr = to;
|
||||
*to++ = '\0';
|
||||
ofi->readPtr = from;
|
||||
|
||||
/* Check if we need another line before expanding the buffer. */
|
||||
for (p = spec->lbuf; *p; p++) {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
switch (*(p+1)) {
|
||||
case '\n': p++, nc = 1; break;
|
||||
case '\0': break;
|
||||
default: p++; break;
|
||||
}
|
||||
break;
|
||||
case '\n': nc = 0; break;
|
||||
case '%':
|
||||
switch (*(p+1)) {
|
||||
case '{': p++, bc++; break;
|
||||
case '(': p++, pc++; break;
|
||||
case '%': p++; break;
|
||||
}
|
||||
break;
|
||||
case '{': if (bc > 0) bc++; break;
|
||||
case '}': if (bc > 0) bc--; break;
|
||||
case '(': if (pc > 0) pc++; break;
|
||||
case ')': if (pc > 0) pc--; break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it doesn't, ask for one more line. We need a better
|
||||
* error code for this. */
|
||||
if (pc || bc || nc ) {
|
||||
spec->nextline = "";
|
||||
return RPMERR_UNMATCHEDIF;
|
||||
}
|
||||
spec->lbufPtr = spec->lbuf;
|
||||
|
||||
/* Don't expand macros (eg. %define) in false branch of %if clause */
|
||||
if (spec->readStack->reading &&
|
||||
expandMacros(spec, spec->macros, spec->lbuf, sizeof(spec->lbuf))) {
|
||||
|
@ -265,8 +300,11 @@ retry:
|
|||
#endif
|
||||
|
||||
/* Copy next file line into the spec line buffer */
|
||||
if ((rc = copyNextLine(spec, ofi, strip)) != 0)
|
||||
if ((rc = copyNextLine(spec, ofi, strip)) != 0) {
|
||||
if (rc == RPMERR_UNMATCHEDIF)
|
||||
goto retry;
|
||||
return rc;
|
||||
}
|
||||
|
||||
s = spec->line;
|
||||
SKIPSPACE(s);
|
||||
|
|
|
@ -106,7 +106,8 @@ struct Spec_s {
|
|||
|
||||
/*@owned@*/
|
||||
struct OpenFileInfo * fileStack;
|
||||
char lbuf[4*BUFSIZ];
|
||||
char lbuf[10*BUFSIZ];
|
||||
char *lbufPtr;
|
||||
char nextpeekc;
|
||||
/*@dependent@*/
|
||||
char * nextline;
|
||||
|
|
|
@ -291,7 +291,7 @@ findEntry(MacroContext mc, const char * name, size_t namelen)
|
|||
/*@-boundswrite@*/
|
||||
/*@null@*/
|
||||
static char *
|
||||
rdcl(/*@returned@*/ char * buf, size_t size, FD_t fd, int escapes)
|
||||
rdcl(/*@returned@*/ char * buf, size_t size, FD_t fd)
|
||||
/*@globals fileSystem @*/
|
||||
/*@modifies buf, fileSystem @*/
|
||||
{
|
||||
|
@ -299,6 +299,8 @@ rdcl(/*@returned@*/ char * buf, size_t size, FD_t fd, int escapes)
|
|||
size_t nb = 0;
|
||||
size_t nread = 0;
|
||||
FILE * f = fdGetFILE(fd);
|
||||
int pc = 0, bc = 0;
|
||||
char *p = buf;
|
||||
|
||||
if (f != NULL)
|
||||
do {
|
||||
|
@ -309,14 +311,32 @@ rdcl(/*@returned@*/ char * buf, size_t size, FD_t fd, int escapes)
|
|||
nread += nb; /* trim trailing \r and \n */
|
||||
for (q += nb - 1; nb > 0 && iseol(*q); q--)
|
||||
nb--;
|
||||
if (!(nb > 0 && *q == '\\')) { /* continue? */
|
||||
for (; p <= q; p++) {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
switch (*(p+1)) {
|
||||
case '\0': break;
|
||||
default: p++; break;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
switch (*(p+1)) {
|
||||
case '{': p++, bc++; break;
|
||||
case '(': p++, pc++; break;
|
||||
case '%': p++; break;
|
||||
}
|
||||
break;
|
||||
case '{': if (bc > 0) bc++; break;
|
||||
case '}': if (bc > 0) bc--; break;
|
||||
case '(': if (pc > 0) pc++; break;
|
||||
case ')': if (pc > 0) pc--; break;
|
||||
}
|
||||
}
|
||||
if (nb <= 0 || (*q != '\\' && !bc && !pc) || *(q+1) == '\0') {
|
||||
*(++q) = '\0'; /* trim trailing \r, \n */
|
||||
break;
|
||||
}
|
||||
if (escapes) { /* copy escape too */
|
||||
q++;
|
||||
nb++;
|
||||
}
|
||||
q++; p++; nb++; /* copy newline too */
|
||||
size -= nb;
|
||||
if (*q == '\r') /* XXX avoid \r madness */
|
||||
*q = '\n';
|
||||
|
@ -470,17 +490,6 @@ printExpansion(MacroBuf mb, const char * t, const char * te)
|
|||
/*@=boundswrite@*/ \
|
||||
}
|
||||
|
||||
#define COPYBODY(_be, _s, _c) \
|
||||
{ /*@-boundswrite@*/ \
|
||||
while(((_c) = *(_s)) && !iseol(_c)) { \
|
||||
if ((_c) == '\\') \
|
||||
(_s)++; \
|
||||
*(_be)++ = *(_s)++; \
|
||||
} \
|
||||
*(_be) = '\0'; \
|
||||
/*@=boundswrite@*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* Save source and expand field into target.
|
||||
* @param mb macro expansion state
|
||||
|
@ -663,9 +672,39 @@ doDefine(MacroBuf mb, /*@returned@*/ const char * se, int level, int expandbody)
|
|||
se++; /* XXX skip } */
|
||||
s = se; /* move scan forward */
|
||||
} else { /* otherwise free-field */
|
||||
COPYBODY(be, s, c);
|
||||
|
||||
/*@-boundswrite@*/
|
||||
int bc = 0, pc = 0;
|
||||
while (*s && (bc || pc || !iseol(*s))) {
|
||||
switch (*s) {
|
||||
case '\\':
|
||||
switch (*(s+1)) {
|
||||
case '\0': break;
|
||||
default: s++; break;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
switch (*(s+1)) {
|
||||
case '{': *be++ = *s++; bc++; break;
|
||||
case '(': *be++ = *s++; pc++; break;
|
||||
case '%': *be++ = *s++; break;
|
||||
}
|
||||
break;
|
||||
case '{': if (bc > 0) bc++; break;
|
||||
case '}': if (bc > 0) bc--; break;
|
||||
case '(': if (pc > 0) pc++; break;
|
||||
case ')': if (pc > 0) pc--; break;
|
||||
}
|
||||
*be++ = *s++;
|
||||
}
|
||||
*be = '\0';
|
||||
|
||||
if (bc || pc) {
|
||||
rpmError(RPMERR_BADSPEC,
|
||||
_("Macro %%%s has unterminated body\n"), n);
|
||||
se = s; /* XXX W2DO? */
|
||||
return se;
|
||||
}
|
||||
|
||||
/* Trim trailing blanks/newlines */
|
||||
/*@-globs@*/
|
||||
while (--be >= b && (c = *be) && (isblank(c) || iseol(c)))
|
||||
|
@ -1899,7 +1938,7 @@ rpmLoadMacroFile(MacroContext mc, const char * fn)
|
|||
/*@=mods@*/
|
||||
|
||||
buf[0] = '\0';
|
||||
while(rdcl(buf, sizeof(buf), fd, 1) != NULL) {
|
||||
while(rdcl(buf, sizeof(buf), fd) != NULL) {
|
||||
char c, *n;
|
||||
|
||||
n = buf;
|
||||
|
@ -2340,7 +2379,7 @@ main(int argc, char *argv[])
|
|||
rpmDumpMacroTable(NULL, NULL);
|
||||
|
||||
if ((fp = fopen(testfile, "r")) != NULL) {
|
||||
while(rdcl(buf, sizeof(buf), fp, 1)) {
|
||||
while(rdcl(buf, sizeof(buf), fp)) {
|
||||
x = expandMacros(NULL, NULL, buf, sizeof(buf));
|
||||
fprintf(stderr, "%d->%s\n", x, buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
@ -2348,7 +2387,7 @@ main(int argc, char *argv[])
|
|||
fclose(fp);
|
||||
}
|
||||
|
||||
while(rdcl(buf, sizeof(buf), stdin, 1)) {
|
||||
while(rdcl(buf, sizeof(buf), stdin)) {
|
||||
x = expandMacros(NULL, NULL, buf, sizeof(buf));
|
||||
fprintf(stderr, "%d->%s\n <-\n", x, buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
|
Loading…
Reference in New Issue