Logo Search packages:      
Sourcecode: ksh version File versions  Download package

regsubexec.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*                  Copyright (c) 1985-2006 AT&T Corp.                  *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                            by AT&T Corp.                             *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              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;
      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 = 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))
                  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;
            }
      }
      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;
}

Generated by  Doxygen 1.6.0   Back to index