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/regsubexec.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/regex/regsubexec.c')
-rw-r--r-- | src/lib/libast/regex/regsubexec.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/lib/libast/regex/regsubexec.c b/src/lib/libast/regex/regsubexec.c new file mode 100644 index 0000000..78caeba --- /dev/null +++ b/src/lib/libast/regex/regsubexec.c @@ -0,0 +1,196 @@ +/*********************************************************************** +* * +* 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 + +/* + * posix regex ed(1) style substitute execute + */ + +#include "reglib.h" + +#define NEED(p,b,n,r) \ + do \ + { \ + if (((b)->re_end - (b)->re_cur) < (n)) \ + { \ + size_t o = (b)->re_cur - (b)->re_buf; \ + size_t a = ((b)->re_end - (b)->re_buf); \ + if (a < n) \ + a = roundof(n, 128); \ + a *= 2; \ + if (!((b)->re_buf = alloc(p->env->disc, (b)->re_buf, a))) \ + { \ + (b)->re_buf = (b)->re_cur = (b)->re_end = 0; \ + c = REG_ESPACE; \ + r; \ + } \ + (b)->re_cur = (b)->re_buf + o; \ + (b)->re_end = (b)->re_buf + a; \ + } \ + } while (0) + +#define PUTC(p,b,x,r) \ + do \ + { \ + NEED(p, b, 1, r); \ + *(b)->re_cur++ = (x); \ + } while (0) + +#define PUTS(p,b,x,z,r) \ + do if (z) \ + { \ + NEED(p, b, z, r); \ + memcpy((b)->re_cur, x, z); \ + (b)->re_cur += (z); \ + } while (0) + +/* + * do a single substitution + */ + +static int +sub(const regex_t* p, register regsub_t* b, const char* ss, register regsubop_t* op, size_t nmatch, register regmatch_t* match) +{ + register char* s; + register char* e; + register int c; + + for (;; op++) + { + switch (op->len) + { + case -1: + break; + case 0: + if (op->off >= nmatch) + return REG_ESUBREG; + if ((c = match[op->off].rm_so) < 0) + continue; + s = (char*)ss + c; + if ((c = match[op->off].rm_eo) < 0) + continue; + e = (char*)ss + c; + NEED(p, b, e - s, return c); + switch (op->op) + { + case REG_SUB_UPPER: + while (s < e) + { + c = *s++; + if (islower(c)) + c = toupper(c); + *b->re_cur++ = c; + } + break; + case REG_SUB_LOWER: + while (s < e) + { + c = *s++; + if (isupper(c)) + c = tolower(c); + *b->re_cur++ = c; + } + break; + case REG_SUB_UPPER|REG_SUB_LOWER: + while (s < e) + { + c = *s++; + if (isupper(c)) + c = tolower(c); + else if (islower(c)) + c = toupper(c); + *b->re_cur++ = c; + } + break; + default: + while (s < e) + *b->re_cur++ = *s++; + break; + } + continue; + default: + NEED(p, b, op->len, return c); + s = b->re_rhs + op->off; + e = s + op->len; + while (s < e) + *b->re_cur++ = *s++; + continue; + } + break; + } + return 0; +} + +/* + * ed(1) style substitute using matches from last regexec() + */ + +int +regsubexec(const regex_t* p, const char* s, size_t nmatch, regmatch_t* match) +{ + register int c; + register regsub_t* b; + const char* e; + int m; + + if (!p->env->sub || (p->env->flags & REG_NOSUB) || !nmatch) + return fatal(p->env->disc, REG_BADPAT, NiL); + b = p->re_sub; + m = b->re_min; + b->re_cur = b->re_buf; + e = (const char*)p->env->end; + c = 0; + for (;;) + { + if (--m > 0) + PUTS(p, b, s, match->rm_eo, return fatal(p->env->disc, c, NiL)); + else + { + PUTS(p, b, s, match->rm_so, return fatal(p->env->disc, c, NiL)); + if (!c && (c = sub(p, b, s, b->re_ops, nmatch, match))) + return fatal(p->env->disc, c, NiL); + } + s += match->rm_eo; + if (m <= 0 && !(b->re_flags & REG_SUB_ALL) || !*s) + break; + if (c = regnexec(p, s, e - s, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0))) + { + if (c != REG_NOMATCH) + return fatal(p->env->disc, c, NiL); + break; + } + if (!match->rm_so && !match->rm_eo && *s && m <= 1) + { + match->rm_so = match->rm_eo = 1; + c = 1; + } + } + while (s < e) + { + c = *s++; + PUTC(p, b, c, return fatal(p->env->disc, c, NiL)); + } + NEED(p, b, 1, return fatal(p->env->disc, c, NiL)); + *b->re_cur = 0; + b->re_len = b->re_cur - b->re_buf; + return 0; +} |