summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2002-10-28 23:33:57 +0000
committerjmallett <jmallett@FreeBSD.org>2002-10-28 23:33:57 +0000
commit1d4b44fe4a5179218b67807b2f8a72b1ea5e30da (patch)
treee236724d2a28f3e60d37eeb142b7049cd93427bb /usr.bin
parent46972a1cd987b2dea0a141dde525fdc000ab59d2 (diff)
downloadFreeBSD-src-1d4b44fe4a5179218b67807b2f8a72b1ea5e30da.zip
FreeBSD-src-1d4b44fe4a5179218b67807b2f8a72b1ea5e30da.tar.gz
Split var.c into var.c and var_modify.c and move all the modification funcs
to var_modify.c, for readability. constify some low hanging fruit (string manipulation functions) and the upper layers appropriately. No longer use the private strstr(3) implementation, while changing string code. Tested by: lots of successful make buildworld.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/make/Makefile2
-rw-r--r--usr.bin/make/job.c4
-rw-r--r--usr.bin/make/nonints.h7
-rw-r--r--usr.bin/make/str.c55
-rw-r--r--usr.bin/make/var.c652
-rw-r--r--usr.bin/make/var.h97
-rw-r--r--usr.bin/make/var_modify.c583
7 files changed, 731 insertions, 669 deletions
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile
index 6c135c3..1163282 100644
--- a/usr.bin/make/Makefile
+++ b/usr.bin/make/Makefile
@@ -5,7 +5,7 @@
PROG= make
CFLAGS+=-I${.CURDIR}
SRCS= arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c main.c \
- make.c parse.c str.c suff.c targ.c util.c var.c
+ make.c parse.c str.c suff.c targ.c util.c var.c var_modify.c
SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \
lstDatum.c lstDeQueue.c lstDestroy.c lstDupl.c lstEnQueue.c \
lstFind.c lstFindFrom.c lstFirst.c lstForEach.c lstForEachFrom.c \
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index b25edd8..e7d0450 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -1877,7 +1877,7 @@ JobOutput(Job *job, char *cp, char *endp, int msg)
char *ecp;
if (commandShell->noPrint) {
- ecp = Str_FindSubstring(cp, commandShell->noPrint);
+ ecp = strstr(cp, commandShell->noPrint);
while (ecp != NULL) {
if (cp != ecp) {
*ecp = '\0';
@@ -1905,7 +1905,7 @@ JobOutput(Job *job, char *cp, char *endp, int msg)
while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
cp++;
}
- ecp = Str_FindSubstring(cp, commandShell->noPrint);
+ ecp = strstr(cp, commandShell->noPrint);
} else {
return cp;
}
diff --git a/usr.bin/make/nonints.h b/usr.bin/make/nonints.h
index a9720c5..d7047e4 100644
--- a/usr.bin/make/nonints.h
+++ b/usr.bin/make/nonints.h
@@ -94,10 +94,9 @@ void str_init(void);
void str_end(void);
char *str_concat(char *, char *, int);
char **brk_string(char *, int *, Boolean);
-char *Str_FindSubstring(char *, char *);
-int Str_Match(char *, char *);
-char *Str_SYSVMatch(char *, char *, int *len);
-void Str_SYSVSubst(Buffer, char *, char *, int);
+int Str_Match(const char *, const char *);
+const char *Str_SYSVMatch(const char *, const char *, int *);
+void Str_SYSVSubst(Buffer, const char *, const char *, int);
/* suff.c */
void Suff_ClearSuffixes(void);
diff --git a/usr.bin/make/str.c b/usr.bin/make/str.c
index 56cb71f..a6fdb63 100644
--- a/usr.bin/make/str.c
+++ b/usr.bin/make/str.c
@@ -253,44 +253,6 @@ done: argv[argc] = (char *)NULL;
}
/*
- * Str_FindSubstring -- See if a string contains a particular substring.
- *
- * Results: If string contains substring, the return value is the location of
- * the first matching instance of substring in string. If string doesn't
- * contain substring, the return value is NULL. Matching is done on an exact
- * character-for-character basis with no wildcards or special characters.
- *
- * Side effects: None.
- *
- * XXX should be strstr(3).
- */
-char *
-Str_FindSubstring(char *string, char *substring)
-{
- char *a, *b;
-
- /*
- * First scan quickly through the two strings looking for a single-
- * character match. When it's found, then compare the rest of the
- * substring.
- */
-
- for (b = substring; *string != 0; string += 1) {
- if (*string != *b)
- continue;
- a = string;
- for (;;) {
- if (*b == 0)
- return(string);
- if (*a++ != *b++)
- break;
- }
- b = substring;
- }
- return((char *) NULL);
-}
-
-/*
* Str_Match --
*
* See if a particular string matches a particular pattern.
@@ -302,7 +264,7 @@ Str_FindSubstring(char *string, char *substring)
* Side effects: None.
*/
int
-Str_Match(char *string, char *pattern)
+Str_Match(const char *string, const char *pattern)
{
char c2;
@@ -404,12 +366,13 @@ thisCharOK: ++pattern;
*
*-----------------------------------------------------------------------
*/
-char *
-Str_SYSVMatch(char *word, char *pattern, int *len)
+const char *
+Str_SYSVMatch(const char *word, const char *pattern, int *len)
{
- char *p = pattern;
- char *w = word;
- char *m;
+ const char *m, *p, *w;
+
+ p = pattern;
+ w = word;
if (*w == '\0') {
/* Zero-length word cannot be matched against */
@@ -468,9 +431,9 @@ Str_SYSVMatch(char *word, char *pattern, int *len)
*-----------------------------------------------------------------------
*/
void
-Str_SYSVSubst(Buffer buf, char *pat, char *src, int len)
+Str_SYSVSubst(Buffer buf, const char *pat, const char *src, int len)
{
- char *m;
+ const char *m;
if ((m = strchr(pat, '%')) != NULL) {
/* Copy the prefix */
diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c
index a1462bc..6d3093a 100644
--- a/usr.bin/make/var.c
+++ b/usr.bin/make/var.c
@@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include "make.h"
#include "buf.h"
+#include "var.h"
/*
* This is a harmless return value for Var_Parse that can be used by Var_Subst
@@ -129,64 +130,16 @@ static Lst allVars; /* List of all variables */
#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
#define FIND_ENV 0x4 /* look in the environment also */
-typedef struct Var {
- char *name; /* the variable's name */
- Buffer val; /* its value */
- int flags; /* miscellaneous status flags */
-#define VAR_IN_USE 1 /* Variable's value currently being used.
- * Used to avoid recursion */
-#define VAR_FROM_ENV 2 /* Variable comes from the environment */
-#define VAR_JUNK 4 /* Variable is a junk variable that
- * should be destroyed when done with
- * it. Used by Var_Parse for undefined,
- * modified variables */
-} Var;
-
-/* Var*Pattern flags */
-#define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
-#define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
-#define VAR_SUB_MATCHED 0x04 /* There was a match */
-#define VAR_MATCH_START 0x08 /* Match at start of word */
-#define VAR_MATCH_END 0x10 /* Match at end of word */
-#define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */
-
-typedef struct {
- char *lhs; /* String to match */
- int leftLen; /* Length of string */
- char *rhs; /* Replacement string (w/ &'s removed) */
- int rightLen; /* Length of replacement */
- int flags;
-} VarPattern;
-
-typedef struct {
- regex_t re;
- int nsub;
- regmatch_t *matches;
- char *replace;
- int flags;
-} VarREPattern;
-
static int VarCmp(void *, void *);
static void VarPossiblyExpand(char **, GNode *);
static Var *VarFind(char *, GNode *, int);
static void VarAdd(char *, char *, GNode *);
static void VarDelete(void *);
-static Boolean VarHead(char *, Boolean, Buffer, void *);
-static Boolean VarTail(char *, Boolean, Buffer, void *);
-static Boolean VarSuffix(char *, Boolean, Buffer, void *);
-static Boolean VarRoot(char *, Boolean, Buffer, void *);
-static Boolean VarMatch(char *, Boolean, Buffer, void *);
-#ifdef SYSVVARSUB
-static Boolean VarSYSVMatch(char *, Boolean, Buffer, void *);
-#endif
-static Boolean VarNoMatch(char *, Boolean, Buffer, void *);
-static void VarREError(int, regex_t *, const char *);
-static Boolean VarRESubstitute(char *, Boolean, Buffer, void *);
-static Boolean VarSubstitute(char *, Boolean, Buffer, void *);
static char *VarGetPattern(GNode *, int, char **, int, int *, int *,
VarPattern *);
-static char *VarQuote(char *);
-static char *VarModify(char *, Boolean (*)(char *, Boolean, Buffer, void *),
+static char *VarQuote(const char *);
+static char *VarModify(char *,
+ Boolean (*)(const char *, Boolean, Buffer, void *),
void *);
static int VarPrintVar(void *, void *);
@@ -616,567 +569,6 @@ Var_Value (char *name, GNode *ctxt, char **frp)
/*-
*-----------------------------------------------------------------------
- * VarHead --
- * Remove the tail of the given word and place the result in the given
- * buffer.
- *
- * Results:
- * TRUE if characters were added to the buffer (a space needs to be
- * added to the buffer before the next word).
- *
- * Side Effects:
- * The trimmed word is added to the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarHead (char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
-{
- char *slash;
-
- slash = strrchr (word, '/');
- if (slash != (char *)NULL) {
- if (addSpace) {
- Buf_AddByte (buf, (Byte)' ');
- }
- *slash = '\0';
- Buf_AddBytes (buf, strlen (word), (Byte *)word);
- *slash = '/';
- return (TRUE);
- } else {
- /*
- * If no directory part, give . (q.v. the POSIX standard)
- */
- if (addSpace) {
- Buf_AddBytes(buf, 2, (Byte *)" .");
- } else {
- Buf_AddByte(buf, (Byte)'.');
- }
- }
- return (TRUE);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * VarTail --
- * Remove the head of the given word and place the result in the given
- * buffer.
- *
- * Results:
- * TRUE if characters were added to the buffer (a space needs to be
- * added to the buffer before the next word).
- *
- * Side Effects:
- * The trimmed word is added to the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarTail (char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
-{
- char *slash;
-
- if (addSpace) {
- Buf_AddByte (buf, (Byte)' ');
- }
-
- slash = strrchr (word, '/');
- if (slash != (char *)NULL) {
- *slash++ = '\0';
- Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
- slash[-1] = '/';
- } else {
- Buf_AddBytes (buf, strlen(word), (Byte *)word);
- }
- return (TRUE);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * VarSuffix --
- * Place the suffix of the given word in the given buffer.
- *
- * Results:
- * TRUE if characters were added to the buffer (a space needs to be
- * added to the buffer before the next word).
- *
- * Side Effects:
- * The suffix from the word is placed in the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarSuffix (char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
-{
- char *dot;
-
- dot = strrchr (word, '.');
- if (dot != (char *)NULL) {
- if (addSpace) {
- Buf_AddByte (buf, (Byte)' ');
- }
- *dot++ = '\0';
- Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
- dot[-1] = '.';
- addSpace = TRUE;
- }
- return (addSpace);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * VarRoot --
- * Remove the suffix of the given word and place the result in the
- * buffer.
- *
- * Results:
- * TRUE if characters were added to the buffer (a space needs to be
- * added to the buffer before the next word).
- *
- * Side Effects:
- * The trimmed word is added to the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarRoot (char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
-{
- char *dot;
-
- if (addSpace) {
- Buf_AddByte (buf, (Byte)' ');
- }
-
- dot = strrchr (word, '.');
- if (dot != (char *)NULL) {
- *dot = '\0';
- Buf_AddBytes (buf, strlen (word), (Byte *)word);
- *dot = '.';
- } else {
- Buf_AddBytes (buf, strlen(word), (Byte *)word);
- }
- return (TRUE);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * VarMatch --
- * Place the word in the buffer if it matches the given pattern.
- * Callback function for VarModify to implement the :M modifier.
- * A space will be added if requested. A pattern is supplied
- * which the word must match.
- *
- * Results:
- * TRUE if a space should be placed in the buffer before the next
- * word.
- *
- * Side Effects:
- * The word may be copied to the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarMatch (char *word, Boolean addSpace, Buffer buf, void *pattern)
-{
- if (Str_Match(word, (char *) pattern)) {
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- addSpace = TRUE;
- Buf_AddBytes(buf, strlen(word), (Byte *)word);
- }
- return(addSpace);
-}
-
-#ifdef SYSVVARSUB
-/*-
- *-----------------------------------------------------------------------
- * VarSYSVMatch --
- * Place the word in the buffer if it matches the given pattern.
- * Callback function for VarModify to implement the System V %
- * modifiers. A space is added if requested.
- *
- * Results:
- * TRUE if a space should be placed in the buffer before the next
- * word.
- *
- * Side Effects:
- * The word may be copied to the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarSYSVMatch (char *word, Boolean addSpace, Buffer buf, void *patp)
-{
- int len;
- char *ptr;
- VarPattern *pat = (VarPattern *) patp;
-
- if (addSpace)
- Buf_AddByte(buf, (Byte)' ');
-
- addSpace = TRUE;
-
- if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL)
- Str_SYSVSubst(buf, pat->rhs, ptr, len);
- else
- Buf_AddBytes(buf, strlen(word), (Byte *) word);
-
- return(addSpace);
-}
-#endif
-
-
-/*-
- *-----------------------------------------------------------------------
- * VarNoMatch --
- * Place the word in the buffer if it doesn't match the given pattern.
- * Callback function for VarModify to implement the :N modifier. A
- * space is added if requested.
- *
- * Results:
- * TRUE if a space should be placed in the buffer before the next
- * word.
- *
- * Side Effects:
- * The word may be copied to the buffer.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarNoMatch (char *word, Boolean addSpace, Buffer buf, void *pattern)
-{
- if (!Str_Match(word, (char *) pattern)) {
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- addSpace = TRUE;
- Buf_AddBytes(buf, strlen(word), (Byte *)word);
- }
- return(addSpace);
-}
-
-
-/*-
- *-----------------------------------------------------------------------
- * VarSubstitute --
- * Perform a string-substitution on the given word, placing the
- * result in the passed buffer. A space is added if requested.
- *
- * Results:
- * TRUE if a space is needed before more characters are added.
- *
- * Side Effects:
- * None.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarSubstitute (char *word, Boolean addSpace, Buffer buf, void *patternp)
-{
- int wordLen; /* Length of word */
- char *cp; /* General pointer */
- VarPattern *pattern = (VarPattern *) patternp;
-
- wordLen = strlen(word);
- if (1) { /* substitute in each word of the variable */
- /*
- * Break substitution down into simple anchored cases
- * and if none of them fits, perform the general substitution case.
- */
- if ((pattern->flags & VAR_MATCH_START) &&
- (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
- /*
- * Anchored at start and beginning of word matches pattern
- */
- if ((pattern->flags & VAR_MATCH_END) &&
- (wordLen == pattern->leftLen)) {
- /*
- * Also anchored at end and matches to the end (word
- * is same length as pattern) add space and rhs only
- * if rhs is non-null.
- */
- if (pattern->rightLen != 0) {
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- addSpace = TRUE;
- Buf_AddBytes(buf, pattern->rightLen,
- (Byte *)pattern->rhs);
- }
- } else if (pattern->flags & VAR_MATCH_END) {
- /*
- * Doesn't match to end -- copy word wholesale
- */
- goto nosub;
- } else {
- /*
- * Matches at start but need to copy in trailing characters
- */
- if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- addSpace = TRUE;
- }
- Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
- Buf_AddBytes(buf, wordLen - pattern->leftLen,
- (Byte *)(word + pattern->leftLen));
- }
- } else if (pattern->flags & VAR_MATCH_START) {
- /*
- * Had to match at start of word and didn't -- copy whole word.
- */
- goto nosub;
- } else if (pattern->flags & VAR_MATCH_END) {
- /*
- * Anchored at end, Find only place match could occur (leftLen
- * characters from the end of the word) and see if it does. Note
- * that because the $ will be left at the end of the lhs, we have
- * to use strncmp.
- */
- cp = word + (wordLen - pattern->leftLen);
- if ((cp >= word) &&
- (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
- /*
- * Match found. If we will place characters in the buffer,
- * add a space before hand as indicated by addSpace, then
- * stuff in the initial, unmatched part of the word followed
- * by the right-hand-side.
- */
- if (((cp - word) + pattern->rightLen) != 0) {
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- addSpace = TRUE;
- }
- Buf_AddBytes(buf, cp - word, (Byte *)word);
- Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
- } else {
- /*
- * Had to match at end and didn't. Copy entire word.
- */
- goto nosub;
- }
- } else {
- /*
- * Pattern is unanchored: search for the pattern in the word using
- * String_FindSubstring, copying unmatched portions and the
- * right-hand-side for each match found, handling non-global
- * substitutions correctly, etc. When the loop is done, any
- * remaining part of the word (word and wordLen are adjusted
- * accordingly through the loop) is copied straight into the
- * buffer.
- * addSpace is set FALSE as soon as a space is added to the
- * buffer.
- */
- Boolean done;
- int origSize;
-
- done = FALSE;
- origSize = Buf_Size(buf);
- while (!done) {
- cp = Str_FindSubstring(word, pattern->lhs);
- if (cp != (char *)NULL) {
- if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
- Buf_AddByte(buf, (Byte)' ');
- addSpace = FALSE;
- }
- Buf_AddBytes(buf, cp-word, (Byte *)word);
- Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
- wordLen -= (cp - word) + pattern->leftLen;
- word = cp + pattern->leftLen;
- if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){
- done = TRUE;
- }
- } else {
- done = TRUE;
- }
- }
- if (wordLen != 0) {
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- Buf_AddBytes(buf, wordLen, (Byte *)word);
- }
- /*
- * If added characters to the buffer, need to add a space
- * before we add any more. If we didn't add any, just return
- * the previous value of addSpace.
- */
- return ((Buf_Size(buf) != origSize) || addSpace);
- }
- /*
- * Common code for anchored substitutions:
- * addSpace was set TRUE if characters were added to the buffer.
- */
- return (addSpace);
- }
- nosub:
- if (addSpace) {
- Buf_AddByte(buf, (Byte)' ');
- }
- Buf_AddBytes(buf, wordLen, (Byte *)word);
- return(TRUE);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * VarREError --
- * Print the error caused by a regcomp or regexec call.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * An error gets printed.
- *
- *-----------------------------------------------------------------------
- */
-static void
-VarREError(int err, regex_t *pat, const char *str)
-{
- char *errbuf;
- int errlen;
-
- errlen = regerror(err, pat, 0, 0);
- errbuf = emalloc(errlen);
- regerror(err, pat, errbuf, errlen);
- Error("%s: %s", str, errbuf);
- free(errbuf);
-}
-
-
-/*-
- *-----------------------------------------------------------------------
- * VarRESubstitute --
- * Perform a regex substitution on the given word, placing the
- * result in the passed buffer. A space is added if requested.
- *
- * Results:
- * TRUE if a space is needed before more characters are added.
- *
- * Side Effects:
- * None.
- *
- *-----------------------------------------------------------------------
- */
-static Boolean
-VarRESubstitute(char *word, Boolean addSpace, Buffer buf, void *patternp)
-{
- VarREPattern *pat;
- int xrv;
- char *wp;
- char *rp;
- int added;
- int flags = 0;
-
-#define MAYBE_ADD_SPACE() \
- if (addSpace && !added) \
- Buf_AddByte(buf, ' '); \
- added = 1
-
- added = 0;
- wp = word;
- pat = patternp;
-
- if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
- (VAR_SUB_ONE|VAR_SUB_MATCHED))
- xrv = REG_NOMATCH;
- else {
- tryagain:
- xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
- }
-
- switch (xrv) {
- case 0:
- pat->flags |= VAR_SUB_MATCHED;
- if (pat->matches[0].rm_so > 0) {
- MAYBE_ADD_SPACE();
- Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
- }
-
- for (rp = pat->replace; *rp; rp++) {
- if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
- MAYBE_ADD_SPACE();
- Buf_AddByte(buf,rp[1]);
- rp++;
- }
- else if ((*rp == '&') ||
- ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
- int n;
- char *subbuf;
- int sublen;
- char errstr[3];
-
- if (*rp == '&') {
- n = 0;
- errstr[0] = '&';
- errstr[1] = '\0';
- } else {
- n = rp[1] - '0';
- errstr[0] = '\\';
- errstr[1] = rp[1];
- errstr[2] = '\0';
- rp++;
- }
-
- if (n > pat->nsub) {
- Error("No subexpression %s", &errstr[0]);
- subbuf = "";
- sublen = 0;
- } else if ((pat->matches[n].rm_so == -1) &&
- (pat->matches[n].rm_eo == -1)) {
- Error("No match for subexpression %s", &errstr[0]);
- subbuf = "";
- sublen = 0;
- } else {
- subbuf = wp + pat->matches[n].rm_so;
- sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
- }
-
- if (sublen > 0) {
- MAYBE_ADD_SPACE();
- Buf_AddBytes(buf, sublen, subbuf);
- }
- } else {
- MAYBE_ADD_SPACE();
- Buf_AddByte(buf, *rp);
- }
- }
- wp += pat->matches[0].rm_eo;
- if (pat->flags & VAR_SUB_GLOBAL) {
- flags |= REG_NOTBOL;
- if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
- MAYBE_ADD_SPACE();
- Buf_AddByte(buf, *wp);
- wp++;
-
- }
- if (*wp)
- goto tryagain;
- }
- if (*wp) {
- MAYBE_ADD_SPACE();
- Buf_AddBytes(buf, strlen(wp), wp);
- }
- break;
- default:
- VarREError(xrv, &pat->re, "Unexpected regex error");
- /* fall through */
- case REG_NOMATCH:
- if (*wp) {
- MAYBE_ADD_SPACE();
- Buf_AddBytes(buf,strlen(wp),wp);
- }
- break;
- }
- return(addSpace||added);
-}
-
-
-/*-
- *-----------------------------------------------------------------------
* VarModify --
* Modify each of the words of the passed string using the given
* function. Used to implement all modifiers.
@@ -1190,7 +582,7 @@ VarRESubstitute(char *word, Boolean addSpace, Buffer buf, void *patternp)
*-----------------------------------------------------------------------
*/
static char *
-VarModify (char *str, Boolean (*modProc)(char *, Boolean, Buffer, void *),
+VarModify (char *str, Boolean (*modProc)(const char *, Boolean, Buffer, void *),
void *datum)
{
Buffer buf; /* Buffer for the new string */
@@ -1351,12 +743,13 @@ VarGetPattern(GNode *ctxt, int err, char **tstr, int delim, int *flags,
*-----------------------------------------------------------------------
*/
static char *
-VarQuote(char *str)
+VarQuote(const char *str)
{
Buffer buf;
/* This should cover most shells :-( */
static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
+ char *ret;
buf = Buf_Init (MAKE_BSIZE);
for (; *str; str++) {
@@ -1365,11 +758,38 @@ VarQuote(char *str)
Buf_AddByte(buf, (Byte)*str);
}
Buf_AddByte(buf, (Byte) '\0');
- str = (char *)Buf_GetAll (buf, (int *)NULL);
+ ret = Buf_GetAll (buf, NULL);
Buf_Destroy (buf, FALSE);
- return str;
+ return ret;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarREError --
+ * Print the error caused by a regcomp or regexec call.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * An error gets printed.
+ *
+ *-----------------------------------------------------------------------
+ */
+void
+VarREError(int err, regex_t *pat, const char *str)
+{
+ char *errbuf;
+ int errlen;
+
+ errlen = regerror(err, pat, 0, 0);
+ errbuf = emalloc(errlen);
+ regerror(err, pat, errbuf, errlen);
+ Error("%s: %s", str, errbuf);
+ free(errbuf);
}
+
/*-
*-----------------------------------------------------------------------
* Var_Parse --
diff --git a/usr.bin/make/var.h b/usr.bin/make/var.h
new file mode 100644
index 0000000..7a94f06
--- /dev/null
+++ b/usr.bin/make/var.h
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2002 Juli Mallett.
+ * Copyright (c) 1988, 1989, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+typedef struct Var {
+ char *name; /* the variable's name */
+ Buffer val; /* its value */
+ int flags; /* miscellaneous status flags */
+#define VAR_IN_USE 1 /* Variable's value currently being used.
+ * Used to avoid recursion */
+#define VAR_FROM_ENV 2 /* Variable comes from the environment */
+#define VAR_JUNK 4 /* Variable is a junk variable that
+ * should be destroyed when done with
+ * it. Used by Var_Parse for undefined,
+ * modified variables */
+} Var;
+
+/* Var*Pattern flags */
+#define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
+#define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
+#define VAR_SUB_MATCHED 0x04 /* There was a match */
+#define VAR_MATCH_START 0x08 /* Match at start of word */
+#define VAR_MATCH_END 0x10 /* Match at end of word */
+#define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */
+
+typedef struct {
+ char *lhs; /* String to match */
+ int leftLen; /* Length of string */
+ char *rhs; /* Replacement string (w/ &'s removed) */
+ int rightLen; /* Length of replacement */
+ int flags;
+} VarPattern;
+
+typedef struct {
+ regex_t re;
+ int nsub;
+ regmatch_t *matches;
+ char *replace;
+ int flags;
+} VarREPattern;
+
+/*
+ * var.c
+ */
+void VarREError(int, regex_t *, const char *);
+
+/*
+ * var_modify.c
+ */
+Boolean VarHead(const char *, Boolean, Buffer, void *);
+Boolean VarTail(const char *, Boolean, Buffer, void *);
+Boolean VarSuffix(const char *, Boolean, Buffer, void *);
+Boolean VarRoot(const char *, Boolean, Buffer, void *);
+Boolean VarMatch(const char *, Boolean, Buffer, void *);
+#ifdef SYSVVARSUB
+Boolean VarSYSVMatch(const char *, Boolean, Buffer, void *);
+#endif
+Boolean VarNoMatch(const char *, Boolean, Buffer, void *);
+Boolean VarRESubstitute(const char *, Boolean, Buffer, void *);
+Boolean VarSubstitute(const char *, Boolean, Buffer, void *);
diff --git a/usr.bin/make/var_modify.c b/usr.bin/make/var_modify.c
new file mode 100644
index 0000000..ef4257c
--- /dev/null
+++ b/usr.bin/make/var_modify.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2002 Juli Mallett.
+ * Copyright (c) 1988, 1989, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)var.c 8.3 (Berkeley) 3/19/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <stdlib.h>
+#include "make.h"
+#include "buf.h"
+#include "var.h"
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarHead --
+ * Remove the tail of the given word and place the result in the given
+ * buffer.
+ *
+ * Results:
+ * TRUE if characters were added to the buffer (a space needs to be
+ * added to the buffer before the next word).
+ *
+ * Side Effects:
+ * The trimmed word is added to the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarHead (const char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
+{
+ char *slash;
+ char *buffer;
+
+ buffer = estrdup(word);
+ slash = strrchr (buffer, '/');
+ if (slash != NULL) {
+ if (addSpace) {
+ Buf_AddByte (buf, (Byte)' ');
+ }
+ *slash = '\0';
+ Buf_AddBytes (buf, strlen (word), (Byte *)word);
+ free(buffer);
+ return (TRUE);
+ } else {
+ /*
+ * If no directory part, give . (q.v. the POSIX standard)
+ */
+ if (addSpace) {
+ Buf_AddBytes(buf, 2, (Byte *)" .");
+ } else {
+ Buf_AddByte(buf, (Byte)'.');
+ }
+ }
+ free(buffer);
+ return (TRUE);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarTail --
+ * Remove the head of the given word and place the result in the given
+ * buffer.
+ *
+ * Results:
+ * TRUE if characters were added to the buffer (a space needs to be
+ * added to the buffer before the next word).
+ *
+ * Side Effects:
+ * The trimmed word is added to the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarTail (const char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
+{
+ const char *slash;
+
+ if (addSpace) {
+ Buf_AddByte (buf, (Byte)' ');
+ }
+
+ slash = strrchr (word, '/');
+ if (slash++ != NULL) {
+ Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
+ } else {
+ Buf_AddBytes (buf, strlen(word), (Byte *)word);
+ }
+ return (TRUE);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarSuffix --
+ * Place the suffix of the given word in the given buffer.
+ *
+ * Results:
+ * TRUE if characters were added to the buffer (a space needs to be
+ * added to the buffer before the next word).
+ *
+ * Side Effects:
+ * The suffix from the word is placed in the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarSuffix (const char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
+{
+ const char *dot;
+
+ dot = strrchr (word, '.');
+ if (dot++ != (char *)NULL) {
+ if (addSpace) {
+ Buf_AddByte (buf, (Byte)' ');
+ }
+ Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
+ addSpace = TRUE;
+ }
+ return (addSpace);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarRoot --
+ * Remove the suffix of the given word and place the result in the
+ * buffer.
+ *
+ * Results:
+ * TRUE if characters were added to the buffer (a space needs to be
+ * added to the buffer before the next word).
+ *
+ * Side Effects:
+ * The trimmed word is added to the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarRoot (const char *word, Boolean addSpace, Buffer buf, void *dummy __unused)
+{
+ char *buffer;
+ char *dot;
+
+ if (addSpace) {
+ Buf_AddByte (buf, (Byte)' ');
+ }
+
+ buffer = estrdup(word);
+ dot = strrchr (buffer, '.');
+ if (dot != NULL) {
+ *dot = '\0';
+ }
+ Buf_AddBytes (buf, strlen(buffer), (Byte *)buffer);
+ free(buffer);
+ return (TRUE);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarMatch --
+ * Place the word in the buffer if it matches the given pattern.
+ * Callback function for VarModify to implement the :M modifier.
+ * A space will be added if requested. A pattern is supplied
+ * which the word must match.
+ *
+ * Results:
+ * TRUE if a space should be placed in the buffer before the next
+ * word.
+ *
+ * Side Effects:
+ * The word may be copied to the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarMatch (const char *word, Boolean addSpace, Buffer buf, void *pattern)
+{
+ if (Str_Match(word, pattern)) {
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ addSpace = TRUE;
+ Buf_AddBytes(buf, strlen(word), word);
+ }
+ return(addSpace);
+}
+
+#ifdef SYSVVARSUB
+/*-
+ *-----------------------------------------------------------------------
+ * VarSYSVMatch --
+ * Place the word in the buffer if it matches the given pattern.
+ * Callback function for VarModify to implement the System V %
+ * modifiers. A space is added if requested.
+ *
+ * Results:
+ * TRUE if a space should be placed in the buffer before the next
+ * word.
+ *
+ * Side Effects:
+ * The word may be copied to the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarSYSVMatch (const char *word, Boolean addSpace, Buffer buf, void *patp)
+{
+ int len;
+ const char *ptr;
+ VarPattern *pat = (VarPattern *) patp;
+
+ if (addSpace)
+ Buf_AddByte(buf, (Byte)' ');
+
+ addSpace = TRUE;
+
+ if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL)
+ Str_SYSVSubst(buf, pat->rhs, ptr, len);
+ else
+ Buf_AddBytes(buf, strlen(word), (Byte *) word);
+
+ return(addSpace);
+}
+#endif
+
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarNoMatch --
+ * Place the word in the buffer if it doesn't match the given pattern.
+ * Callback function for VarModify to implement the :N modifier. A
+ * space is added if requested.
+ *
+ * Results:
+ * TRUE if a space should be placed in the buffer before the next
+ * word.
+ *
+ * Side Effects:
+ * The word may be copied to the buffer.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarNoMatch (const char *word, Boolean addSpace, Buffer buf, void *pattern)
+{
+ if (!Str_Match(word, pattern)) {
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ addSpace = TRUE;
+ Buf_AddBytes(buf, strlen(word), (Byte *)word);
+ }
+ return(addSpace);
+}
+
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarSubstitute --
+ * Perform a string-substitution on the given word, placing the
+ * result in the passed buffer. A space is added if requested.
+ *
+ * Results:
+ * TRUE if a space is needed before more characters are added.
+ *
+ * Side Effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarSubstitute (const char *word, Boolean addSpace, Buffer buf, void *patternp)
+{
+ int wordLen; /* Length of word */
+ const char *cp; /* General pointer */
+ VarPattern *pattern = (VarPattern *) patternp;
+
+ wordLen = strlen(word);
+ if (1) { /* substitute in each word of the variable */
+ /*
+ * Break substitution down into simple anchored cases
+ * and if none of them fits, perform the general substitution case.
+ */
+ if ((pattern->flags & VAR_MATCH_START) &&
+ (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
+ /*
+ * Anchored at start and beginning of word matches pattern
+ */
+ if ((pattern->flags & VAR_MATCH_END) &&
+ (wordLen == pattern->leftLen)) {
+ /*
+ * Also anchored at end and matches to the end (word
+ * is same length as pattern) add space and rhs only
+ * if rhs is non-null.
+ */
+ if (pattern->rightLen != 0) {
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ addSpace = TRUE;
+ Buf_AddBytes(buf, pattern->rightLen,
+ (Byte *)pattern->rhs);
+ }
+ } else if (pattern->flags & VAR_MATCH_END) {
+ /*
+ * Doesn't match to end -- copy word wholesale
+ */
+ goto nosub;
+ } else {
+ /*
+ * Matches at start but need to copy in trailing characters
+ */
+ if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ addSpace = TRUE;
+ }
+ Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
+ Buf_AddBytes(buf, wordLen - pattern->leftLen,
+ (Byte *)(word + pattern->leftLen));
+ }
+ } else if (pattern->flags & VAR_MATCH_START) {
+ /*
+ * Had to match at start of word and didn't -- copy whole word.
+ */
+ goto nosub;
+ } else if (pattern->flags & VAR_MATCH_END) {
+ /*
+ * Anchored at end, Find only place match could occur (leftLen
+ * characters from the end of the word) and see if it does. Note
+ * that because the $ will be left at the end of the lhs, we have
+ * to use strncmp.
+ */
+ cp = word + (wordLen - pattern->leftLen);
+ if ((cp >= word) &&
+ (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
+ /*
+ * Match found. If we will place characters in the buffer,
+ * add a space before hand as indicated by addSpace, then
+ * stuff in the initial, unmatched part of the word followed
+ * by the right-hand-side.
+ */
+ if (((cp - word) + pattern->rightLen) != 0) {
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ addSpace = TRUE;
+ }
+ Buf_AddBytes(buf, cp - word, (Byte *)word);
+ Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
+ } else {
+ /*
+ * Had to match at end and didn't. Copy entire word.
+ */
+ goto nosub;
+ }
+ } else {
+ /*
+ * Pattern is unanchored: search for the pattern in the word using
+ * strstr(3), copying unmatched portions and the
+ * right-hand-side for each match found, handling non-global
+ * substitutions correctly, etc. When the loop is done, any
+ * remaining part of the word (word and wordLen are adjusted
+ * accordingly through the loop) is copied straight into the
+ * buffer.
+ * addSpace is set FALSE as soon as a space is added to the
+ * buffer.
+ */
+ Boolean done;
+ int origSize;
+
+ done = FALSE;
+ origSize = Buf_Size(buf);
+ while (!done) {
+ cp = strstr(word, pattern->lhs);
+ if (cp != (char *)NULL) {
+ if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
+ Buf_AddByte(buf, (Byte)' ');
+ addSpace = FALSE;
+ }
+ Buf_AddBytes(buf, cp-word, (Byte *)word);
+ Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
+ wordLen -= (cp - word) + pattern->leftLen;
+ word = cp + pattern->leftLen;
+ if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){
+ done = TRUE;
+ }
+ } else {
+ done = TRUE;
+ }
+ }
+ if (wordLen != 0) {
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ Buf_AddBytes(buf, wordLen, (Byte *)word);
+ }
+ /*
+ * If added characters to the buffer, need to add a space
+ * before we add any more. If we didn't add any, just return
+ * the previous value of addSpace.
+ */
+ return ((Buf_Size(buf) != origSize) || addSpace);
+ }
+ /*
+ * Common code for anchored substitutions:
+ * addSpace was set TRUE if characters were added to the buffer.
+ */
+ return (addSpace);
+ }
+ nosub:
+ if (addSpace) {
+ Buf_AddByte(buf, (Byte)' ');
+ }
+ Buf_AddBytes(buf, wordLen, (Byte *)word);
+ return(TRUE);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * VarRESubstitute --
+ * Perform a regex substitution on the given word, placing the
+ * result in the passed buffer. A space is added if requested.
+ *
+ * Results:
+ * TRUE if a space is needed before more characters are added.
+ *
+ * Side Effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+VarRESubstitute(const char *word, Boolean addSpace, Buffer buf, void *patternp)
+{
+ VarREPattern *pat;
+ int xrv;
+ const char *wp;
+ char *rp;
+ int added;
+ int flags = 0;
+
+#define MAYBE_ADD_SPACE() \
+ if (addSpace && !added) \
+ Buf_AddByte(buf, ' '); \
+ added = 1
+
+ added = 0;
+ wp = word;
+ pat = patternp;
+
+ if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
+ (VAR_SUB_ONE|VAR_SUB_MATCHED))
+ xrv = REG_NOMATCH;
+ else {
+ tryagain:
+ xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
+ }
+
+ switch (xrv) {
+ case 0:
+ pat->flags |= VAR_SUB_MATCHED;
+ if (pat->matches[0].rm_so > 0) {
+ MAYBE_ADD_SPACE();
+ Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
+ }
+
+ for (rp = pat->replace; *rp; rp++) {
+ if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
+ MAYBE_ADD_SPACE();
+ Buf_AddByte(buf,rp[1]);
+ rp++;
+ }
+ else if ((*rp == '&') ||
+ ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
+ int n;
+ const char *subbuf;
+ int sublen;
+ char errstr[3];
+
+ if (*rp == '&') {
+ n = 0;
+ errstr[0] = '&';
+ errstr[1] = '\0';
+ } else {
+ n = rp[1] - '0';
+ errstr[0] = '\\';
+ errstr[1] = rp[1];
+ errstr[2] = '\0';
+ rp++;
+ }
+
+ if (n > pat->nsub) {
+ Error("No subexpression %s", &errstr[0]);
+ subbuf = "";
+ sublen = 0;
+ } else if ((pat->matches[n].rm_so == -1) &&
+ (pat->matches[n].rm_eo == -1)) {
+ Error("No match for subexpression %s", &errstr[0]);
+ subbuf = "";
+ sublen = 0;
+ } else {
+ subbuf = wp + pat->matches[n].rm_so;
+ sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
+ }
+
+ if (sublen > 0) {
+ MAYBE_ADD_SPACE();
+ Buf_AddBytes(buf, sublen, subbuf);
+ }
+ } else {
+ MAYBE_ADD_SPACE();
+ Buf_AddByte(buf, *rp);
+ }
+ }
+ wp += pat->matches[0].rm_eo;
+ if (pat->flags & VAR_SUB_GLOBAL) {
+ flags |= REG_NOTBOL;
+ if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
+ MAYBE_ADD_SPACE();
+ Buf_AddByte(buf, *wp);
+ wp++;
+
+ }
+ if (*wp)
+ goto tryagain;
+ }
+ if (*wp) {
+ MAYBE_ADD_SPACE();
+ Buf_AddBytes(buf, strlen(wp), wp);
+ }
+ break;
+ default:
+ VarREError(xrv, &pat->re, "Unexpected regex error");
+ /* fall through */
+ case REG_NOMATCH:
+ if (*wp) {
+ MAYBE_ADD_SPACE();
+ Buf_AddBytes(buf,strlen(wp),wp);
+ }
+ break;
+ }
+ return(addSpace||added);
+}
OpenPOWER on IntegriCloud