📄 tclfilename.c
字号:
} if (macRootPatternPtr->startp[5] != NULL) { /* * Unix-style tilde prefixed paths. */ isMac = 0; i = 5; } else if (macRootPatternPtr->startp[7] != NULL) { /* * Mac-style tilde prefixed paths. */ isMac = 1; i = 7; } else if (macRootPatternPtr->startp[10] != NULL) { /* * Normal Unix style paths. */ isMac = 0; i = 10; } else if (macRootPatternPtr->startp[12] != NULL) { /* * Normal Mac style paths. */ isMac = 1; i = 12; } length = macRootPatternPtr->endp[i] - macRootPatternPtr->startp[i]; /* * Append the element and terminate it with a : and a null. Note that * we are forcing the DString to contain an extra null at the end. */ Tcl_DStringAppend(bufPtr, macRootPatternPtr->startp[i], length); Tcl_DStringAppend(bufPtr, ":", 2); p = macRootPatternPtr->endp[i]; } else { isMac = (strchr(path, ':') != NULL); p = path; } if (isMac) { /* * p is pointing at the first colon in the path. There * will always be one, since this is a Mac-style path. */ elementStart = p++; while ((p = strchr(p, ':')) != NULL) { length = p - elementStart; if (length == 1) { while (*p == ':') { Tcl_DStringAppend(bufPtr, "::", 3); elementStart = p++; } } else { /* * If this is a simple component, drop the leading colon. */ if ((elementStart[1] != '~') && (strchr(elementStart+1, '/') == NULL)) { elementStart++; length--; } Tcl_DStringAppend(bufPtr, elementStart, length); Tcl_DStringAppend(bufPtr, "", 1); elementStart = p++; } } if (elementStart[1] != '\0' || elementStart == path) { if ((elementStart[1] != '~') && (elementStart[1] != '\0') && (strchr(elementStart+1, '/') == NULL)) { elementStart++; } Tcl_DStringAppend(bufPtr, elementStart, -1); Tcl_DStringAppend(bufPtr, "", 1); } } else { /* * Split on slashes, suppress extra /'s, and convert .. to ::. */ for (;;) { elementStart = p; while ((*p != '\0') && (*p != '/')) { p++; } length = p - elementStart; if (length > 0) { if ((length == 1) && (elementStart[0] == '.')) { Tcl_DStringAppend(bufPtr, ":", 2); } else if ((length == 2) && (elementStart[0] == '.') && (elementStart[1] == '.')) { Tcl_DStringAppend(bufPtr, "::", 3); } else { if (*elementStart == '~') { Tcl_DStringAppend(bufPtr, ":", 1); } Tcl_DStringAppend(bufPtr, elementStart, length); Tcl_DStringAppend(bufPtr, "", 1); } } if (*p++ == '\0') { break; } } } return Tcl_DStringValue(bufPtr);}/* *---------------------------------------------------------------------- * * Tcl_JoinPath -- * * Combine a list of paths in a platform specific manner. * * Results: * Appends the joined path to the end of the specified * returning a pointer to the resulting string. Note that * the Tcl_DString must already be initialized. * * Side effects: * Modifies the Tcl_DString. * *---------------------------------------------------------------------- */char *Tcl_JoinPath(argc, argv, resultPtr) int argc; char **argv; Tcl_DString *resultPtr; /* Pointer to previously initialized DString. */{ int oldLength, length, i, needsSep; Tcl_DString buffer; char *p, c, *dest; Tcl_DStringInit(&buffer); oldLength = Tcl_DStringLength(resultPtr); switch (tclPlatform) { case TCL_PLATFORM_UNIX: for (i = 0; i < argc; i++) { p = argv[i]; /* * If the path is absolute, reset the result buffer. * Consume any duplicate leading slashes or a ./ in * front of a tilde prefixed path that isn't at the * beginning of the path. */ if (*p == '/') { Tcl_DStringSetLength(resultPtr, oldLength); Tcl_DStringAppend(resultPtr, "/", 1); while (*p == '/') { p++; } } else if (*p == '~') { Tcl_DStringSetLength(resultPtr, oldLength); } else if ((Tcl_DStringLength(resultPtr) != oldLength) && (p[0] == '.') && (p[1] == '/') && (p[2] == '~')) { p += 2; } if (*p == '\0') { continue; } /* * Append a separator if needed. */ length = Tcl_DStringLength(resultPtr); if ((length != oldLength) && (Tcl_DStringValue(resultPtr)[length-1] != '/')) { Tcl_DStringAppend(resultPtr, "/", 1); length++; } /* * Append the element, eliminating duplicate and trailing * slashes. */ Tcl_DStringSetLength(resultPtr, (int) (length + strlen(p))); dest = Tcl_DStringValue(resultPtr) + length; for (; *p != '\0'; p++) { if (*p == '/') { while (p[1] == '/') { p++; } if (p[1] != '\0') { *dest++ = '/'; } } else { *dest++ = *p; } } length = dest - Tcl_DStringValue(resultPtr); Tcl_DStringSetLength(resultPtr, length); } break; case TCL_PLATFORM_WINDOWS: /* * Iterate over all of the components. If a component is * absolute, then reset the result and start building the * path from the current component on. */ for (i = 0; i < argc; i++) { p = ExtractWinRoot(argv[i], resultPtr, oldLength); length = Tcl_DStringLength(resultPtr); /* * If the pointer didn't move, then this is a relative path * or a tilde prefixed path. */ if (p == argv[i]) { /* * Remove the ./ from tilde prefixed elements unless * it is the first component. */ if ((length != oldLength) && (p[0] == '.') && ((p[1] == '/') || (p[1] == '\\')) && (p[2] == '~')) { p += 2; } else if (*p == '~') { Tcl_DStringSetLength(resultPtr, oldLength); length = oldLength; } } if (*p != '\0') { /* * Check to see if we need to append a separator. */ if (length != oldLength) { c = Tcl_DStringValue(resultPtr)[length-1]; if ((c != '/') && (c != ':')) { Tcl_DStringAppend(resultPtr, "/", 1); } } /* * Append the element, eliminating duplicate and * trailing slashes. */ length = Tcl_DStringLength(resultPtr); Tcl_DStringSetLength(resultPtr, (int) (length + strlen(p))); dest = Tcl_DStringValue(resultPtr) + length; for (; *p != '\0'; p++) { if ((*p == '/') || (*p == '\\')) { while ((p[1] == '/') || (p[1] == '\\')) { p++; } if (p[1] != '\0') { *dest++ = '/'; } } else { *dest++ = *p; } } length = dest - Tcl_DStringValue(resultPtr); Tcl_DStringSetLength(resultPtr, length); } } break; case TCL_PLATFORM_MAC: needsSep = 1; for (i = 0; i < argc; i++) { Tcl_DStringSetLength(&buffer, 0); p = SplitMacPath(argv[i], &buffer); if ((*p != ':') && (*p != '\0') && (strchr(p, ':') != NULL)) { Tcl_DStringSetLength(resultPtr, oldLength); length = strlen(p); Tcl_DStringAppend(resultPtr, p, length); needsSep = 0; p += length+1; } /* * Now append the rest of the path elements, skipping * : unless it is the first element of the path, and * watching out for :: et al. so we don't end up with * too many colons in the result. */ for (; *p != '\0'; p += length+1) { if (p[0] == ':' && p[1] == '\0') { if (Tcl_DStringLength(resultPtr) != oldLength) { p++; } else { needsSep = 0; } } else { c = p[1]; if (*p == ':') { if (!needsSep) { p++; } } else { if (needsSep) { Tcl_DStringAppend(resultPtr, ":", 1); } } needsSep = (c == ':') ? 0 : 1; } length = strlen(p); Tcl_DStringAppend(resultPtr, p, length); } } break; } Tcl_DStringFree(&buffer); return Tcl_DStringValue(resultPtr);}/* *---------------------------------------------------------------------- * * Tcl_TranslateFileName -- * * Converts a file name into a form usable by the native system * interfaces. If the name starts with a tilde, it will produce * a name where the tilde and following characters have been * replaced by the home directory location for the named user. * * Results: * The result is a pointer to a static string containing * the new name. If there was an error in processing the * name, then an error message is left in interp->result * and the return value is NULL. The result will be stored * in bufferPtr; the caller must call Tcl_DStringFree(bufferPtr) * to free the name if the return value was not NULL. * * Side effects: * Information may be left in bufferPtr. * *---------------------------------------------------------------------- */char *Tcl_TranslateFileName(interp, name, bufferPtr) Tcl_Interp *interp; /* Interpreter in which to store error * message (if necessary). */ char *name; /* File name, which may begin with "~" * (to indicate current user's home directory) * or "~<user>" (to indicate any user's * home directory). */ Tcl_DString *bufferPtr; /* May be used to hold result. Must not hold * anything at the time of the call, and need * not even be initialized. */{ register char *p; /* * Handle tilde substitutions, if needed. */ if (name[0] == '~') { int argc, length; char **argv; Tcl_DString temp; Tcl_SplitPath(name, &argc, &argv); /* * Strip the trailing ':' off of a Mac path * before passing the user name to DoTildeSubst. */ if (tclPlatform == TCL_PLATFORM_MAC) { length = strlen(argv[0]); argv[0][length-1] = '\0'; } Tcl_DStringInit(&temp); argv[0] = DoTildeSubst(interp, argv[0]+1, &temp); if (argv[0] == NULL) { Tcl_DStringFree(&temp); ckfree((char *)argv); return NULL; } Tcl_DStringInit(bufferPtr); Tcl_JoinPath(argc, argv, bufferPtr); Tcl_DStringFree(&temp); ckfree((char*)argv); } else { Tcl_DStringInit(bufferPtr); Tcl_JoinPath(1, &name, bufferPtr); } /* * Convert forward slashes to backslashes in Windows paths because * some system interfaces don't accept forward slashes. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) { if (*p == '/') { *p = '\\'; } } } return Tcl_DStringValue(bufferPtr);}/* *---------------------------------------------------------------------- * * TclGetExtension -- * * This function returns a pointer to the beginning of the * extension part of a file name. * * Results: * Returns a pointer into name which indicates where the extension * starts. If there is no extension, returns NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */char *TclGetExtension(name) char *name; /* File name to parse. */{ char *p, *lastSep; /* * First find the last directory separator. */ lastSep = NULL; /* Needed only to prevent gcc warnings. */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: lastSep = strrchr(name, '/'); break; case TCL_PLATFORM_MAC: if (strchr(name, ':') == NULL) { lastSep = strrchr(name, '/'); } else { lastSep = strrchr(name, ':'); } break; case TCL_PLATFORM_WINDOWS: lastSep = NULL; for (p = name; *p != '\0'; p++) { if (strchr("/\\:", *p) != NULL) { lastSep = p; } } break; } p = strrchr(name, '.'); if ((p != NULL) && (lastSep != NULL) && (lastSep > p)) { p = NULL; } /* * Back up to the first period in a series of contiguous dots. * This is needed so foo..o will be split on the first dot. */ if (p != NULL) { while ((p > name) && *(p-1) == '.') { p--; } } return p;}/* *---------------------------------------------------------------------- * * DoTildeSubst -- * * Given a string following a tilde, this routine returns the * corresponding home directory. * * Results: * The result is a pointer to a static string containing the home * directory in native format. If there was an error in processing * the substitution, then an error message is left in interp->result * and the return value is NULL. On success, the results are appended * to resultPtr, and the contents of resultPtr are returned. * * Side effects: * Information may be left in resultPtr. * *---------------------------------------------------------------------- */static char *DoTildeSubst(interp, user, resultPtr) Tcl_Interp *interp; /* Interpreter in which to store error * message (if necessary). */ char *user; /* Name of user whose home directory should be * substituted, or "" for current user. */ Tcl_DString *resultPtr; /* May be used to hold result. Must not hold * anything at the time of the call, and need * not even be initialized. */{ char *dir, *home_var; if (*user == '\0') { #ifdef WIN32 home_var = "HOMEDIR";#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -