summaryrefslogtreecommitdiff
path: root/src/lib/libast/regex/regsub.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/regex/regsub.c
downloadksh-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.c269
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;
+}