diff src/eval.c @ 15:631143ac4a01 v7.0007

updated for version 7.0007
author vimboss
date Sat, 10 Jul 2004 09:47:34 +0000
parents 946da5994c01
children 3ba373b54370
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -370,6 +370,7 @@ static void f_substitute __ARGS((VAR arg
 static void f_tempname __ARGS((VAR argvars, VAR retvar));
 static void f_tolower __ARGS((VAR argvars, VAR retvar));
 static void f_toupper __ARGS((VAR argvars, VAR retvar));
+static void f_tr __ARGS((VAR argvars, VAR retvar));
 static void f_type __ARGS((VAR argvars, VAR retvar));
 static void f_virtcol __ARGS((VAR argvars, VAR retvar));
 static void f_visualmode __ARGS((VAR argvars, VAR retvar));
@@ -2923,6 +2924,7 @@ static struct fst
     {"tempname",	0, 0, f_tempname},
     {"tolower",		1, 1, f_tolower},
     {"toupper",		1, 1, f_toupper},
+    {"tr",		3, 3, f_tr},
     {"type",		1, 1, f_type},
     {"virtcol",		1, 1, f_virtcol},
     {"visualmode",	0, 1, f_visualmode},
@@ -7438,6 +7440,122 @@ f_toupper(argvars, retvar)
 }
 
 /*
+ * "tr(string, fromstr, tostr)" function
+ */
+    static void
+f_tr(argvars, retvar)
+    VAR		argvars;
+    VAR		retvar;
+{
+    char_u	*instr;
+    char_u	*fromstr;
+    char_u	*tostr;
+    char_u	*p;
+#ifdef FEAT_MBYTE
+    int	        inlen;
+    int	        fromlen;
+    int	        tolen;
+    int		idx;
+    char_u	*cpstr;
+    int		cplen;
+    int		first = TRUE;
+#endif
+    char_u	buf[NUMBUFLEN];
+    char_u	buf2[NUMBUFLEN];
+    garray_T	ga;
+
+    instr = get_var_string(&argvars[0]);
+    fromstr = get_var_string_buf(&argvars[1], buf);
+    tostr = get_var_string_buf(&argvars[2], buf2);
+
+    /* Default return value: empty string. */
+    retvar->var_type = VAR_STRING;
+    retvar->var_val.var_string = NULL;
+    ga_init2(&ga, (int)sizeof(char), 80);
+
+#ifdef FEAT_MBYTE
+    if (!has_mbyte)
+#endif
+	/* not multi-byte: fromstr and tostr must be the same length */
+	if (STRLEN(fromstr) != STRLEN(tostr))
+	{
+error:
+	    EMSG2(_(e_invarg2), fromstr);
+	    ga_clear(&ga);
+	    return;
+	}
+
+    /* fromstr and tostr have to contain the same number of chars */
+    while (*instr != NUL)
+    {
+#ifdef FEAT_MBYTE
+	if (has_mbyte)
+	{
+	    inlen = mb_ptr2len_check(instr);
+	    cpstr = instr;
+	    cplen = inlen;
+	    idx = 0;
+	    for (p = fromstr; *p != NUL; p += fromlen)
+	    {
+		fromlen = mb_ptr2len_check(p);
+		if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
+		{
+		    for (p = tostr; *p != NUL; p += tolen)
+		    {
+			tolen = mb_ptr2len_check(p);
+			if (idx-- == 0)
+			{
+			    cplen = tolen;
+			    cpstr = p;
+			    break;
+			}
+		    }
+		    if (*p == NUL)	/* tostr is shorter than fromstr */
+			goto error;
+		    break;
+		}
+		++idx;
+	    }
+
+	    if (first && cpstr == instr)
+	    {
+		/* Check that fromstr and tostr have the same number of
+		 * (multi-byte) characters.  Done only once when a character
+		 * of instr doesn't appear in fromstr. */
+		first = FALSE;
+		for (p = tostr; *p != NUL; p += tolen)
+		{
+		    tolen = mb_ptr2len_check(p);
+		    --idx;
+		}
+		if (idx != 0)
+		    goto error;
+	    }
+
+	    ga_grow(&ga, cplen);
+	    mch_memmove(ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
+	    ga.ga_len += cplen;
+	    ga.ga_room -= cplen;
+
+	    instr += inlen;
+	}
+	else
+#endif
+	{
+	    /* When not using multi-byte chars we can do it faster. */
+	    p = vim_strchr(fromstr, *instr);
+	    if (p != NULL)
+		ga_append(&ga, tostr[p - fromstr]);
+	    else
+		ga_append(&ga, *instr);
+	    ++instr;
+	}
+    }
+
+    retvar->var_val.var_string = ga.ga_data;
+}
+
+/*
  * "type(expr)" function
  */
     static void