home *** CD-ROM | disk | FTP | other *** search
- /* regsub.c */
-
- /* This file contains the regsub() function, which performs substitutions
- * after a regexp match has been found.
- */
-
- #include "config.h"
- #include "ctype.h"
- #include "vi.h"
- #include "regexp.h"
-
-
- /* perform substitutions after a regexp match */
- void regsub(re, src, dst)
- regexp *re; /* the regexp with pointers into matched text */
- REG char *src; /* the replacement string */
- REG char *dst; /* where to put the result of the subst */
- {
- REG char *cpy; /* pointer to start of text to copy */
- REG char *end; /* pointer to end of text to copy */
- REG char c;
- char *start;
- #ifndef CRUNCH
- int mod = 0;/* used to track \U, \L, \u, \l, and \E */
- int len; /* used to calculate length of subst string */
- static char *prev; /* a copy of the text from the previous subst */
-
- /* replace \~ (or maybe ~) by previous substitution text */
-
- /* step 1: calculate the length of the new substitution text */
- for (len = strlen(src), c = '\0', cpy = src; *cpy; cpy++)
- {
- # ifdef NO_MAGIC
- if (c == '\\' && *cpy == '~')
- # else
- if (c == (*o_magic ? '\0' : '\\') && *cpy == '~')
- # endif
- {
- if (!prev)
- {
- regerror("No prev text to substitute for ~");
- return;
- }
- len += strlen(prev) - 1;
- # ifndef NO_MAGIC
- if (!*o_magic)
- # endif
- len -= 1; /* because we lose the \ too */
- }
-
- /* watch backslash quoting */
- if (c != '\\' && *cpy == '\\')
- c = '\\';
- else
- c = '\0';
- }
-
- /* allocate memory for the ~ed version of src */
- start = cpy = (char *)malloc((unsigned)(len + 1));
- if (!cpy)
- {
- regerror("Not enough memory for ~ expansion");
- return;
- }
-
- /* copy src into start, replacing the ~s by the previous text */
- while (*src)
- {
- # ifndef NO_MAGIC
- if (*o_magic && *src == '~')
- {
- strcpy(cpy, prev);
- cpy += strlen(prev);
- src++;
- }
- else if (!*o_magic && *src == '\\' && *(src + 1) == '~')
- # else /* NO_MAGIC */
- if (*src == '\\' && *(src + 1) == '~')
- # endif /* NO_MAGIC */
- {
- strcpy(cpy, prev);
- cpy += strlen(prev);
- src += 2;
- }
- else
- {
- *cpy++ = *src++;
- }
- }
- *cpy = '\0';
- #ifdef DEBUG
- if ((int)(cpy - start) != len)
- {
- msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
- }
- #endif
-
- /* remember this as the "previous" for next time */
- if (prev)
- free(prev);
- prev = src = start;
-
- #endif /* undef CRUNCH */
-
- start = src;
- while ((c = *src++) != '\0')
- {
- #ifndef NO_MAGIC
- /* recognize any meta characters */
- if (c == '&' && *o_magic)
- {
- cpy = re->startp[0];
- end = re->endp[0];
- }
- else
- #endif /* not NO_MAGIC */
- if (c == '\\')
- {
- c = *src++;
- switch (c)
- {
- #ifndef NO_MAGIC
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- /* \0 thru \9 mean "copy subexpression" */
- c -= '0';
- cpy = re->startp[c];
- end = re->endp[c];
- break;
- # ifndef CRUNCH
- case 'U':
- case 'u':
- case 'L':
- case 'l':
- /* \U and \L mean "convert to upper/lowercase" */
- mod = c;
- continue;
-
- case 'E':
- case 'e':
- /* \E ends the \U or \L */
- mod = 0;
- continue;
- # endif /* not CRUNCH */
- case '&':
- /* "\&" means "original text" */
- if (*o_magic)
- {
- *dst++ = c;
- continue;
- }
- cpy = re->startp[0];
- end = re->endp[0];
- break;
-
- #else /* NO_MAGIC */
- case '&':
- /* "\&" means "original text" */
- cpy = re->startp[0];
- end = re->endp[0];
- break;
- #endif /* NO_MAGIC */
- default:
- /* ordinary char preceded by backslash */
- *dst++ = c;
- continue;
- }
- }
- #ifndef CRUNCH
- # if OSK
- else if (c == '\l')
- # else
- else if (c == '\r')
- # endif
- {
- /* transliterate ^M into newline */
- *dst++ = '\n';
- continue;
- }
- #endif /* !CRUNCH */
- else
- {
- /* ordinary character, so just copy it */
- *dst++ = c;
- continue;
- }
-
- /* Note: to reach this point in the code, we must have evaded
- * all "continue" statements. To do that, we must have hit
- * a metacharacter that involves copying.
- */
-
- /* if there is nothing to copy, loop */
- if (!cpy)
- continue;
-
- /* copy over a portion of the original */
- while (cpy < end)
- {
- #ifndef NO_MAGIC
- # ifndef CRUNCH
- switch (mod)
- {
- case 'U':
- case 'u':
- /* convert to uppercase */
- *dst++ = toupper(*cpy++);
- break;
-
- case 'L':
- case 'l':
- /* convert to lowercase */
- *dst++ = tolower(*cpy++);
- break;
-
- default:
- /* copy without any conversion */
- *dst++ = *cpy++;
- }
-
- /* \u and \l end automatically after the first char */
- if (mod && (mod == 'u' || mod == 'l'))
- {
- mod = 0;
- }
- # else /* CRUNCH */
- *dst++ = *cpy++;
- # endif /* CRUNCH */
- #else /* NO_MAGIC */
- *dst++ = *cpy++;
- #endif /* NO_MAGIC */
- }
- }
- *dst = '\0';
- }
-