4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=ISO-8859-1
7 Content-Transfer-Encoding: 8bit
11 Problem: resolve() only handles one symbolic link, need to repeat it to
12 resolve all of them. Then need to simplify the file name.
13 Solution: Make resolve() resolve all symbolic links and simplify the result.
14 Add simplify() to just simplify a file name. Fix that test49
15 doesn't work if /tmp is a symbolic link. (Servatius Brandt)
16 Files: runtime/doc/eval.txt, src/eval.c, src/tag.c,
17 src/testdir/test49.vim
20 *** ../vim-6.2.063/runtime/doc/eval.txt Sun Jun 1 14:45:23 2003
21 --- runtime/doc/eval.txt Thu Aug 7 19:31:16 2003
24 ! *eval.txt* For Vim version 6.2. Last change: 2003 Jun 01
27 VIM REFERENCE MANUAL by Bram Moolenaar
29 ! *eval.txt* For Vim version 6.2. Last change: 2003 Aug 07
32 VIM REFERENCE MANUAL by Bram Moolenaar
36 setline( {lnum}, {line}) Number set line {lnum} to {line}
37 setreg( {n}, {v}[, {opt}]) Number set register to value and type
38 setwinvar( {nr}, {varname}, {val}) set {varname} in window {nr} to {val}
39 + simplify( {filename}) String simplify filename as much as possible
40 strftime( {format}[, {time}]) String time in specified format
41 stridx( {haystack}, {needle}) Number first index of {needle} in {haystack}
42 strlen( {expr}) Number length of the String {expr}
45 successfully, and non-zero when the renaming failed.
46 This function is not available in the |sandbox|.
48 ! resolve({filename}) *resolve()*
49 On MS-Windows, when {filename} is a shortcut (a .lnk file),
50 ! returns the path the shortcut points to.
51 ! On Unix, when {filename} is a symbolic link, returns the path
52 ! the symlink points to. This only happens once, the returned
53 ! path could be a symlink again.
54 ! Otherwise {filename} is returned.
56 search({pattern} [, {flags}]) *search()*
57 Search for regexp pattern {pattern}. The search starts at the
59 successfully, and non-zero when the renaming failed.
60 This function is not available in the |sandbox|.
62 ! resolve({filename}) *resolve()* *E655*
63 On MS-Windows, when {filename} is a shortcut (a .lnk file),
64 ! returns the path the shortcut points to in a simplified form.
65 ! On Unix, repeat resolving symbolic links in all path
66 ! components of {filename} and return the simplified result.
67 ! To cope with link cycles, resolving of symbolic links is
68 ! stopped after 100 iterations.
69 ! On other systems, return the simplified {filename}.
70 ! The simplification step is done as by |simplify()|.
71 ! resolve() keeps a leading path component specifying the
72 ! current directory (provided the result is still a relative
73 ! path name) and also keeps a trailing path separator.
75 search({pattern} [, {flags}]) *search()*
76 Search for regexp pattern {pattern}. The search starts at the
80 :call setwinvar(2, "myvar", "foobar")
81 < This function is not available in the |sandbox|.
83 + simplify({filename}) *simplify()*
84 + Simplify the file name as much as possible without changing
85 + the meaning. Shortcuts (on MS-Windows) or symbolic links (on
86 + Unix) are not resolved. If the first path component in
87 + {filename} designates the current directory, this will be
88 + valid for the result as well. A trailing path separator is
91 + simplify("./dir/.././/file/") == "./file/"
92 + < Note: The combination "dir/.." is only removed if "dir" is
93 + a searchable directory or does not exist. On Unix, it is also
94 + removed when "dir" is a symbolic link within the same
95 + directory. In order to resolve all the involved symbolic
96 + links before simplifying the path name, use |resolve()|.
98 strftime({format} [, {time}]) *strftime()*
99 The result is a String, which is a formatted date and time, as
100 specified by the {format} string. The given {time} is used,
101 *** ../vim-6.2.063/src/eval.c Sun Aug 10 22:24:37 2003
102 --- src/eval.c Thu Jul 31 19:47:34 2003
106 static void f_serverlist __ARGS((VAR argvars, VAR retvar));
107 static void f_setline __ARGS((VAR argvars, VAR retvar));
108 static void f_setreg __ARGS((VAR argvars, VAR retvar));
109 + static void f_simplify __ARGS((VAR argvars, VAR retvar));
110 static void find_some_match __ARGS((VAR argvars, VAR retvar, int start));
111 static void f_strftime __ARGS((VAR argvars, VAR retvar));
112 static void f_stridx __ARGS((VAR argvars, VAR retvar));
116 {"setline", 2, 2, f_setline},
117 {"setreg", 2, 3, f_setreg},
118 {"setwinvar", 3, 3, f_setwinvar},
119 + {"simplify", 1, 1, f_simplify},
121 {"strftime", 1, 2, f_strftime},
131 p = get_var_string(&argvars[0]);
135 char_u buf[MAXPATHL + 1];
139 ! len = readlink((char *)p, (char *)buf, MAXPATHL);
143 ! if (gettail(p) > p && !mch_isFullName(buf))
145 ! /* symlink is relative to directory of argument */
146 ! cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
150 ! STRCPY(gettail(cpy), buf);
151 ! retvar->var_val.var_string = cpy;
159 ! retvar->var_val.var_string = vim_strsave(p);
162 retvar->var_val.var_string = vim_strsave(p);
165 retvar->var_type = VAR_STRING;
169 char_u buf[MAXPATHL + 1];
172 + char_u *remain = NULL;
174 + int is_relative_to_current = FALSE;
175 + int has_trailing_pathsep = FALSE;
177 ! p = vim_strsave(p);
179 ! if (p[0] == '.' && (vim_ispathsep(p[1])
180 ! || (p[1] == '.' && (vim_ispathsep(p[2])))))
181 ! is_relative_to_current = TRUE;
184 ! if (len > 0 && vim_ispathsep(p[len-1]))
185 ! has_trailing_pathsep = TRUE;
187 ! q = getnextcomp(p);
190 ! /* Separate the first path component in "p", and keep the
191 ! * remainder (beginning with the path separator). */
192 ! remain = vim_strsave(q - 1);
200 ! len = readlink((char *)p, (char *)buf, MAXPATHL);
209 ! EMSG(_("E655: Too much symbolic links (cycle?)"));
210 ! retvar->var_val.var_string = NULL;
214 ! /* Ensure that the result will have a trailing path separator
215 ! * if the argument has one. */
216 ! if (remain == NULL && has_trailing_pathsep)
219 ! /* Separate the first path component in the link value and
220 ! * concatenate the remainders. */
221 ! q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
224 ! if (remain == NULL)
225 ! remain = vim_strsave(q - 1);
228 ! cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
231 ! STRCAT(cpy, remain);
240 ! if (q > p && *q == NUL)
242 ! /* Ignore trailing path separator. */
246 ! if (q > p && !mch_isFullName(buf))
248 ! /* symlink is relative to directory of argument */
249 ! cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
253 ! STRCPY(gettail(cpy), buf);
261 ! p = vim_strsave(buf);
265 + if (remain == NULL)
268 + /* Append the first path component of "remain" to "p". */
269 + q = getnextcomp(remain + 1);
270 + len = q - remain - (*q != NUL);
271 + cpy = vim_strnsave(p, STRLEN(p) + len);
274 + STRNCAT(cpy, remain, len);
278 + /* Shorten "remain". */
280 + STRCPY(remain, q - 1);
288 ! /* If the result is a relative path name, make it explicitly relative to
289 ! * the current directory if and only if the argument had this form. */
290 ! if (!vim_ispathsep(*p))
292 ! if (is_relative_to_current
296 ! || vim_ispathsep(p[1])
299 ! || vim_ispathsep(p[2]))))))
301 ! /* Prepend "./". */
302 ! cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
310 ! else if (!is_relative_to_current)
312 ! /* Strip leading "./". */
314 ! while (q[0] == '.' && vim_ispathsep(q[1]))
317 ! mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
321 ! /* Ensure that the result will have no trailing path separator
322 ! * if the argument had none. But keep "/" or "//". */
323 ! if (!has_trailing_pathsep)
326 ! while ((q > p + 2 || (q == p + 2 && !vim_ispathsep(*p)))
327 ! && vim_ispathsep(q[-1]))
332 ! retvar->var_val.var_string = p;
335 retvar->var_val.var_string = vim_strsave(p);
339 + simplify_filename(retvar->var_val.var_string);
342 + retvar->var_type = VAR_STRING;
346 + * "simplify()" function
349 + f_simplify(argvars, retvar)
355 + p = get_var_string(&argvars[0]);
356 + retvar->var_val.var_string = vim_strsave(p);
357 + simplify_filename(retvar->var_val.var_string); /* simplify in place */
358 retvar->var_type = VAR_STRING;
361 *** ../vim-6.2.063/src/tag.c Sun Aug 10 22:24:37 2003
362 --- src/tag.c Thu Jul 31 18:27:34 2003
365 #ifndef AMIGA /* Amiga doesn't have "..", it uses "/" */
367 char_u *p, *tail, *start;
369 ! char_u *orig = vim_strsave(filename);
376 #ifdef BACKSLASH_IN_FILENAME
378 #ifndef AMIGA /* Amiga doesn't have "..", it uses "/" */
380 char_u *p, *tail, *start;
381 ! int stripping_disabled = FALSE;
382 ! int relative = TRUE;
385 #ifdef BACKSLASH_IN_FILENAME
391 ! while (vim_ispathsep(*p))
393 ! start = p; /* remember start after "c:/" or "/" or "//" */
397 ! /* At this point "p" is pointing to the char following a "/". */
399 /* VMS allows device:[path] - don't strip the [ in directory */
400 if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':')
405 ! if (vim_ispathsep(*p))
410 ! while (vim_ispathsep(*p));
412 ! start = p; /* remember start after "c:/" or "/" or "///" */
416 ! /* At this point "p" is pointing to the char following a single "/"
417 ! * or "p" is at the "start" of the (absolute or relative) path name. */
419 /* VMS allows device:[path] - don't strip the [ in directory */
420 if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':')
423 /* ":: composition: vms host/passwd component */
425 p = getnextcomp(p + 2);
430 if (vim_ispathsep(*p))
431 movetail(p, p + 1); /* remove duplicate "/" */
432 ! else if (p[0] == '.' && vim_ispathsep(p[1]))
433 ! movetail(p, p + 2); /* strip "./" */
434 ! else if (p[0] == '.' && p[1] == '.' && vim_ispathsep(p[2]))
436 if (components > 0) /* strip one preceding component */
438 ! tail = p + 3; /* skip to after "../" or "..///" */
439 ! while (vim_ispathsep(*tail))
442 ! /* skip back to after previous '/' */
443 ! while (p > start && !vim_ispathsep(p[-1]))
445 ! /* skip back to after first '/' in a row */
446 ! while (p - 1 > start && vim_ispathsep(p[-2]))
448 ! movetail(p, tail); /* strip previous component */
451 - else /* leading "../" */
452 - p += 3; /* skip to char after "/" */
456 ++components; /* simple path component */
459 ! } while (p != NULL && *p != NUL);
462 ! /* Check that the new file name is really the same file. This will not be
463 ! * the case when using symbolic links: "dir/link/../name" != "dir/name". */
465 ! struct stat orig_st, new_st;
467 ! if ( mch_stat((char *)orig, &orig_st) < 0
468 ! || mch_stat((char *)filename, &new_st) < 0
469 ! || orig_st.st_ino != new_st.st_ino
470 ! || orig_st.st_dev != new_st.st_dev)
471 ! STRCPY(filename, orig);
479 /* ":: composition: vms host/passwd component */
481 p = getnextcomp(p + 2);
485 if (vim_ispathsep(*p))
486 movetail(p, p + 1); /* remove duplicate "/" */
487 ! else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL))
489 ! if (p == start && relative)
490 ! p += 1 + (p[1] != NUL); /* keep single "." or leading "./" */
493 ! /* Strip "./" or ".///". If we are at the end of the file name
494 ! * and there is no trailing path separator, either strip "/." if
495 ! * we are after "start", or strip "." if we are at the beginning
496 ! * of an absolute path name . */
499 ! while (vim_ispathsep(*tail))
501 ! else if (p > start)
502 ! --p; /* strip preceding path separator */
506 ! else if (p[0] == '.' && p[1] == '.' &&
507 ! (vim_ispathsep(p[2]) || p[2] == NUL))
509 + /* Skip to after ".." or "../" or "..///". */
511 + while (vim_ispathsep(*tail))
514 if (components > 0) /* strip one preceding component */
516 ! int do_strip = FALSE;
518 ! struct stat st, new_st;
520 ! /* Don't strip for an erroneous file name. */
521 ! if (!stripping_disabled)
523 ! /* If the preceding component does not exist in the file
524 ! * system, we strip it. On Unix, we don't accept a symbolic
525 ! * link that refers to a non-existent file. */
526 ! saved_char = p[-1];
529 ! if (mch_lstat((char *)filename, &st) < 0)
531 ! if (mch_stat((char *)filename, &st) < 0)
534 ! p[-1] = saved_char;
537 ! /* Skip back to after previous '/'. */
538 ! while (p > start && !vim_ispathsep(p[-1]))
543 ! /* If the component exists in the file system, check
544 ! * that stripping it won't change the meaning of the
545 ! * file name. First get information about the
546 ! * unstripped file name. This may fail if the component
547 ! * to strip is not a searchable directory (but a regular
548 ! * file, for instance), since the trailing "/.." cannot
549 ! * be applied then. We don't strip it then since we
550 ! * don't want to replace an erroneous file name by
551 ! * a valid one, and we disable stripping of later
553 ! saved_char = *tail;
555 ! if (mch_stat((char *)filename, &st) >= 0)
558 ! stripping_disabled = TRUE;
559 ! *tail = saved_char;
563 ! /* On Unix, the check for the unstripped file name
564 ! * above works also for a symbolic link pointing to
565 ! * a searchable directory. But then the parent of
566 ! * the directory pointed to by the link must be the
567 ! * same as the stripped file name. (The latter
568 ! * exists in the file system since it is the
569 ! * component's parent directory.) */
570 ! if (p == start && relative)
571 ! (void)mch_stat(".", &new_st);
576 ! (void)mch_stat((char *)filename, &new_st);
580 ! if (new_st.st_ino != st.st_ino ||
581 ! new_st.st_dev != st.st_dev)
584 ! /* We don't disable stripping of later
585 ! * components since the unstripped path name is
595 ! /* Skip the ".." or "../" and reset the counter for the
596 ! * components that might be stripped later on. */
602 ! /* Strip previous component. If the result would get empty
603 ! * and there is no trailing path separator, leave a single
604 ! * "." instead. If we are at the end of the file name and
605 ! * there is no trailing path separator and a preceding
606 ! * component is left after stripping, strip its trailing
607 ! * path separator as well. */
608 ! if (p == start && relative && tail[-1] == '.')
615 ! if (p > start && tail[-1] == '.')
617 ! movetail(p, tail); /* strip previous component */
623 ! else if (p == start && !relative) /* leading "/.." or "/../" */
624 ! movetail(p, tail); /* strip ".." or "../" */
627 ! if (p == start + 2 && p[-2] == '.') /* leading "./../" */
629 ! movetail(p - 2, p); /* strip leading "./" */
632 ! p = tail; /* skip to char after ".." or "../" */
637 ++components; /* simple path component */
640 ! } while (*p != NUL);
644 *** ../vim-6.2.063/src/testdir/test49.vim Fri May 30 21:45:31 2003
645 --- src/testdir/test49.vim Thu Jul 31 18:25:02 2003
648 " Vim script language tests
649 " Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
650 ! " Last Change: 2003 May 30
652 "-------------------------------------------------------------------------------
653 " Test environment {{{1
655 " Vim script language tests
656 " Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
657 ! " Last Change: 2003 Jul 30
659 "-------------------------------------------------------------------------------
660 " Test environment {{{1
663 Xpath 1048576 " X: 1048576
664 let exception = v:exception
665 let throwpoint = v:throwpoint
666 ! call CHECK(7, "autsch", scriptT, '\<6\>')
668 Xpath 2097152 " X: 2097152
669 let exception = v:exception
671 Xpath 1048576 " X: 1048576
672 let exception = v:exception
673 let throwpoint = v:throwpoint
674 ! " Symbolic links in tempname()s are not resolved, whereas resolving
675 ! " is done for v:throwpoint. Resolve the temporary file name for
676 ! " scriptT, so that it can be matched against v:throwpoint.
677 ! call CHECK(7, "autsch", resolve(scriptT), '\<6\>')
679 Xpath 2097152 " X: 2097152
680 let exception = v:exception
683 Xpath 8388608 " X: 8388608
684 let exception = v:exception
685 let throwpoint = v:throwpoint
686 ! call CHECK(9, "brrrr", scriptT, '\<8\>')
688 Xpath 16777216 " X: 16777216
689 let exception = v:exception
691 Xpath 8388608 " X: 8388608
692 let exception = v:exception
693 let throwpoint = v:throwpoint
694 ! " Resolve scriptT for matching it against v:throwpoint.
695 ! call CHECK(9, "brrrr", resolve(scriptT), '\<8\>')
697 Xpath 16777216 " X: 16777216
698 let exception = v:exception
699 *** ../vim-6.2.063/src/version.c Sun Aug 10 22:24:37 2003
700 --- src/version.c Sun Aug 10 22:26:34 2003
704 { /* Add new patch number below this line */
710 From "know your smileys":
711 :-{} Too much lipstick
713 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
714 /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
715 \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
716 \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///