Logo Search packages:      
Sourcecode: ksh version File versions

regsub.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*                  Copyright (c) 1985-2005 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

/*
 * 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);
      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;
}

Generated by  Doxygen 1.6.0   Back to index