diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/regex/regsub.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/regex/regsub.c')
-rw-r--r-- | src/lib/libast/regex/regsub.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/src/lib/libast/regex/regsub.c b/src/lib/libast/regex/regsub.c new file mode 100644 index 0000000..8e89bea --- /dev/null +++ b/src/lib/libast/regex/regsub.c @@ -0,0 +1,269 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped + +/* + * OBSOLETE Sfio_t buffer interface -- use regsubcomp(),regsubexec() + */ + +#include "reglib.h" + +/* + * do a single substitution + */ + +static int +subold(register Sfio_t* dp, const char* op, register const char* sp, size_t nmatch, register regmatch_t* match, register regflags_t flags, int sre) +{ + register int c; + char* s; + char* e; + const char* b; + regflags_t f; + + f = flags &= (REG_SUB_LOWER|REG_SUB_UPPER); + for (;;) + { + switch (c = *sp++) + { + case 0: + return 0; + case '~': + if (!sre || *sp != '(') + { + sfputc(dp, c); + continue; + } + b = sp - 1; + sp++; + break; + case '\\': + if (sre) + { + sfputc(dp, chresc(sp - 1, &s)); + sp = (const char*)s; + continue; + } + if (*sp == '&') + { + c = *sp++; + sfputc(dp, c); + continue; + } + break; + case '&': + if (sre) + { + sfputc(dp, c); + continue; + } + sp--; + break; + default: + switch (flags) + { + case REG_SUB_UPPER: + if (islower(c)) + c = toupper(c); + break; + case REG_SUB_LOWER: + if (isupper(c)) + c = tolower(c); + break; + case REG_SUB_UPPER|REG_SUB_LOWER: + if (isupper(c)) + c = tolower(c); + else if (islower(c)) + c = toupper(c); + break; + } + sfputc(dp, c); + continue; + } + switch (c = *sp++) + { + case 0: + sp--; + continue; + case '&': + c = 0; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + c -= '0'; + if (sre) + while (isdigit(*sp)) + c = c * 10 + *sp++ - '0'; + break; + case 'l': + if (sre && *sp != ')') + { + c = -1; + break; + } + if (c = *sp) + { + sp++; + if (isupper(c)) + c = tolower(c); + sfputc(dp, c); + } + continue; + case 'u': + if (sre) + { + if (*sp != ')') + { + c = -1; + break; + } + sp++; + } + if (c = *sp) + { + sp++; + if (islower(c)) + c = toupper(c); + sfputc(dp, c); + } + continue; + case 'E': + if (sre) + { + if (*sp != ')') + { + c = -1; + break; + } + sp++; + } + flags = f; + continue; + case 'L': + if (sre) + { + if (*sp != ')') + { + c = -1; + break; + } + sp++; + } + f = flags; + flags = REG_SUB_LOWER; + continue; + case 'U': + if (sre) + { + if (*sp != ')') + { + c = -1; + break; + } + sp++; + } + f = flags; + flags = REG_SUB_UPPER; + continue; + default: + if (!sre) + { + sfputc(dp, chresc(sp - 2, &s)); + sp = (const char*)s; + continue; + } + sp--; + c = -1; + break; + } + if (sre) + { + if (c < 0 || *sp != ')') + { + for (; b < sp; b++) + sfputc(dp, *b); + continue; + } + sp++; + } + if (c >= nmatch) + return REG_ESUBREG; + s = (char*)op + match[c].rm_so; + e = (char*)op + match[c].rm_eo; + while (s < e) + { + c = *s++; + switch (flags) + { + case REG_SUB_UPPER: + if (islower(c)) + c = toupper(c); + break; + case REG_SUB_LOWER: + if (isupper(c)) + c = tolower(c); + break; + case REG_SUB_UPPER|REG_SUB_LOWER: + if (isupper(c)) + c = tolower(c); + else if (islower(c)) + c = toupper(c); + break; + } + sfputc(dp, c); + } + } +} + +/* + * ed(1) style substitute using matches from last regexec() + */ + +int +regsub(const regex_t* p, Sfio_t* dp, const char* op, const char* sp, size_t nmatch, regmatch_t* match, regflags_t flags) +{ + int m; + int r; + int sre; + + if ((p->env->flags & REG_NOSUB) || !nmatch) + return fatal(p->env->disc, REG_BADPAT, NiL); + m = (flags >> 16) & 0x3fff; + sre = !!(p->env->flags & REG_SHELL); + r = 0; + do + { + if (--m > 0) + sfwrite(dp, op, match->rm_eo); + else + { + sfwrite(dp, op, match->rm_so); + if (r = subold(dp, op, sp, nmatch, match, flags, sre)) + return fatal(p->env->disc, r, NiL); + } + op += match->rm_eo; + } while ((m > 0 || (flags & REG_SUB_ALL)) && !(r = regexec(p, op, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0)))); + if (r && r != REG_NOMATCH) + return fatal(p->env->disc, r, NiL); + sfputr(dp, op, -1); + return 0; +} |