home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis184.zip / src / regsub.c < prev    next >
C/C++ Source or Header  |  1993-10-24  |  5KB  |  250 lines

  1. /* regsub.c */
  2.  
  3. /* This file contains the regsub() function, which performs substitutions
  4.  * after a regexp match has been found.
  5.  */
  6.  
  7. #include "config.h"
  8. #include "ctype.h"
  9. #include "vi.h"
  10. #include "regexp.h"
  11.  
  12.  
  13. /* perform substitutions after a regexp match */
  14. void regsub(re, src, dst)
  15.     regexp        *re;    /* the regexp with pointers into matched text */
  16.     REG char    *src;    /* the replacement string */
  17.     REG char    *dst;    /* where to put the result of the subst */
  18. {
  19.     REG char    *cpy;    /* pointer to start of text to copy */
  20.     REG char    *end;    /* pointer to end of text to copy */
  21.     REG char    c;
  22.     char        *start;
  23. #ifndef CRUNCH
  24.     int        mod = 0;/* used to track \U, \L, \u, \l, and \E */
  25.     int        len;    /* used to calculate length of subst string */
  26.     static char    *prev;    /* a copy of the text from the previous subst */
  27.  
  28.     /* replace \~ (or maybe ~) by previous substitution text */
  29.  
  30.     /* step 1: calculate the length of the new substitution text */
  31.     for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
  32.     {
  33. # ifdef NO_MAGIC
  34.         if (c == '\\' && *cpy == '~')
  35. # else
  36.         if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
  37. # endif
  38.         {
  39.             if (!prev)
  40.             {
  41.                 regerror("No prev text to substitute for ~");
  42.                 return;
  43.             }
  44.             len += strlen(prev) - 1;
  45. # ifndef NO_MAGIC
  46.             if (!*o_magic)
  47. # endif
  48.                 len -= 1; /* because we lose the \ too */
  49.         }
  50.  
  51.         /* watch backslash quoting */
  52.         if (c != '\\' && *cpy == '\\')
  53.             c = '\\';
  54.         else
  55.             c = '\0';
  56.     }
  57.  
  58.     /* allocate memory for the ~ed version of src */
  59.     checkmem();
  60.     start = cpy = (char *)malloc((unsigned)(len + 1));
  61.     if (!cpy)
  62.     {
  63.         regerror("Not enough memory for ~ expansion");
  64.         return;
  65.     }
  66.  
  67.     /* copy src into start, replacing the ~s by the previous text */
  68.     while (*src)
  69.     {
  70. # ifndef NO_MAGIC
  71.         if (*o_magic && *src == '~')
  72.         {
  73.             strcpy(cpy, prev);
  74.             cpy += strlen(prev);
  75.             src++;
  76.         }
  77.         else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
  78. # else /* NO_MAGIC */
  79.         if (*src == '\\' && *(src + 1) == '~')
  80. # endif /* NO_MAGIC */
  81.         {
  82.             strcpy(cpy, prev);
  83.             cpy += strlen(prev);
  84.             src += 2;
  85.         }
  86.         else
  87.         {
  88.             if (*src == '\\')
  89.             {
  90.                 *cpy++ = *src++;
  91.             }
  92.             *cpy++ = *src++;
  93.         }
  94.     }
  95.     *cpy = '\0';
  96. #ifdef DEBUG
  97.     if ((int)(cpy - start) != len)
  98.     {
  99.         msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
  100.     }
  101. #endif
  102.     checkmem();
  103.  
  104.     /* remember this as the "previous" for next time */
  105.     if (prev)
  106.         _free_(prev);
  107.     prev = src = start;
  108.  
  109. #endif /* undef CRUNCH */
  110.  
  111.     start = src;
  112.     while ((c = *src++) != '\0')
  113.     {
  114. #ifndef NO_MAGIC
  115.         /* recognize any meta characters */
  116.         if (c == '&' && *o_magic)
  117.         {
  118.             cpy = re->startp[0];
  119.             end = re->endp[0];
  120.         }
  121.         else
  122. #endif /* not NO_MAGIC */
  123.         if (c == '\\')
  124.         {
  125.             c = *src++;
  126.             switch (c)
  127.             {
  128. #ifndef NO_MAGIC
  129.               case '0':
  130.               case '1':
  131.               case '2':
  132.               case '3':
  133.               case '4':
  134.               case '5':
  135.               case '6':
  136.               case '7':
  137.               case '8':
  138.               case '9':
  139.                 /* \0 thru \9 mean "copy subexpression" */
  140.                 c -= '0';
  141.                 cpy = re->startp[c];
  142.                 end = re->endp[c];
  143.                 break;
  144. # ifndef CRUNCH
  145.               case 'U':
  146.               case 'u':
  147.               case 'L':
  148.               case 'l':
  149.                 /* \U and \L mean "convert to upper/lowercase" */
  150.                 mod = c;
  151.                 continue;
  152.  
  153.               case 'E':
  154.               case 'e':
  155.                 /* \E ends the \U or \L */
  156.                 mod = 0;
  157.                 continue;
  158. # endif /* not CRUNCH */
  159.               case '&':
  160.                 /* "\&" means "original text" */
  161.                 if (*o_magic)
  162.                 {
  163.                     *dst++ = c;
  164.                     continue;
  165.                 }
  166.                 cpy = re->startp[0];
  167.                 end = re->endp[0];
  168.                 break;
  169.  
  170. #else /* NO_MAGIC */
  171.               case '&':
  172.                 /* "\&" means "original text" */
  173.                 cpy = re->startp[0];
  174.                 end = re->endp[0];
  175.                 break;
  176. #endif /* NO_MAGIC */
  177.               default:
  178.                 /* ordinary char preceded by backslash */
  179.                 *dst++ = c;
  180.                 continue;
  181.             }
  182.         }
  183. #ifndef CRUNCH
  184. # if OSK
  185.         else if (c == '\l')
  186. # else
  187.         else if (c == '\r')
  188. # endif
  189.         {
  190.             /* transliterate ^M into newline */
  191.             *dst++ = '\n';
  192.             continue;
  193.         }
  194. #endif /* !CRUNCH */
  195.         else
  196.         {
  197.             /* ordinary character, so just copy it */
  198.             *dst++ = c;
  199.             continue;
  200.         }
  201.  
  202.         /* Note: to reach this point in the code, we must have evaded
  203.          * all "continue" statements.  To do that, we must have hit
  204.          * a metacharacter that involves copying.
  205.          */
  206.  
  207.         /* if there is nothing to copy, loop */
  208.         if (!cpy)
  209.             continue;
  210.  
  211.         /* copy over a portion of the original */
  212.         while (cpy < end)
  213.         {
  214. #ifndef NO_MAGIC
  215. # ifndef CRUNCH
  216.             switch (mod)
  217.             {
  218.               case 'U':
  219.               case 'u':
  220.                 /* convert to uppercase */
  221.                 *dst++ = toupper(*cpy++);
  222.                 break;
  223.  
  224.               case 'L':
  225.               case 'l':
  226.                 /* convert to lowercase */
  227.                 *dst++ = tolower(*cpy++);
  228.                 break;
  229.  
  230.               default:
  231.                 /* copy without any conversion */
  232.                 *dst++ = *cpy++;
  233.             }
  234.  
  235.             /* \u and \l end automatically after the first char */
  236.             if (mod && (mod == 'u' || mod == 'l'))
  237.             {
  238.                 mod = 0;
  239.             }
  240. # else /* CRUNCH */
  241.             *dst++ = *cpy++;
  242. # endif /* CRUNCH */
  243. #else /* NO_MAGIC */
  244.             *dst++ = *cpy++;
  245. #endif /* NO_MAGIC */
  246.         }
  247.     }
  248.     *dst = '\0';
  249. }
  250.