📄 tclglob.c
字号:
if (d == NULL) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "couldn't read directory \"",
dirName, "\": ", Tcl_UnixError(interp), (char *) NULL);
return TCL_ERROR;
}
l1 = strlen(dir);
l2 = (p - rem);
if (l2 < STATIC_SIZE) {
pattern = static2;
} else {
pattern = (char *) ckalloc((unsigned) (l2+1));
}
strncpy(pattern, rem, l2);
pattern[l2] = '\0';
result = TCL_OK;
while (1) {
entryPtr = readdir(d);
if (entryPtr == NULL) {
break;
}
/*
* Don't match names starting with "." unless the "." is
* present in the pattern.
*/
if ((*entryPtr->d_name == '.') && (*pattern != '.')) {
continue;
}
if (Tcl_StringMatch(entryPtr->d_name, pattern)) {
int nameLength = strlen(entryPtr->d_name);
if (*p == 0) {
AppendResult(interp, dir, separator, entryPtr->d_name,
nameLength);
} else {
if ((l1+nameLength+2) <= STATIC_SIZE) {
newDir = static1;
} else {
newDir = (char *) ckalloc((unsigned) (l1+nameLength+2));
}
sprintf(newDir, "%s%s%s", dir, separator, entryPtr->d_name);
result = DoGlob(interp, newDir, p+1);
if (newDir != static1) {
ckfree(newDir);
}
if (result != TCL_OK) {
break;
}
}
}
}
closedir(d);
if (pattern != static2) {
ckfree(pattern);
}
return result;
}
/*
* This is the simplest case: just another path element. Move
* it to the dir side and recurse (or just add the name to the
* list, if we're at the end of the path).
*/
if (*p == 0) {
AppendResult(interp, dir, separator, rem, p-rem);
} else {
int l1, l2;
char *newDir;
char static1[STATIC_SIZE];
l1 = strlen(dir);
l2 = l1 + (p - rem) + 2;
if (l2 <= STATIC_SIZE) {
newDir = static1;
} else {
newDir = (char *) ckalloc((unsigned) l2);
}
sprintf(newDir, "%s%s%.*s", dir, separator, (int)(p-rem), rem);
result = DoGlob(interp, newDir, p+1);
if (newDir != static1) {
ckfree(newDir);
}
if (result != TCL_OK) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_TildeSubst --
*
* Given a name starting with a tilde, 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. This name will only persist until the next
* call to Tcl_TildeSubst; save it if you care about it for
* the long term. If there was an error in processing the
* tilde, then an error message is left in interp->result
* and the return value is NULL.
*
* Side effects:
* None that the caller needs to worry about.
*
*----------------------------------------------------------------------
*/
char *
Tcl_TildeSubst(interp, name)
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). */
{
#define STATIC_BUF_SIZE 50
static char staticBuf[STATIC_BUF_SIZE];
static int curSize = STATIC_BUF_SIZE;
static char *curBuf = staticBuf;
char *dir;
int length;
int fromPw = 0;
register char *p;
if (name[0] != '~') {
return name;
}
/*
* First, find the directory name corresponding to the tilde entry.
*/
if ((name[1] == '/') || (name[1] == '\0')) {
dir = getenv("HOME");
if (dir == NULL) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "couldn't find HOME environment ",
"variable to expand \"", name, "\"", (char *) NULL);
return NULL;
}
p = name+1;
} else {
struct passwd *pwPtr;
for (p = &name[1]; (*p != 0) && (*p != '/'); p++) {
/* Null body; just find end of name. */
}
length = p-&name[1];
if (length >= curSize) {
length = curSize-1;
}
memcpy((VOID *) curBuf, (VOID *) (name+1), length);
curBuf[length] = '\0';
//pwPtr = getpwnam(curBuf);
pwPtr = NULL;
if (pwPtr == NULL) {
//endpwent();
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "user \"", curBuf,
"\" doesn't exist", (char *) NULL);
return NULL;
}
dir = pwPtr->pw_dir;
fromPw = 1;
}
/*
* Grow the buffer if necessary to make enough space for the
* full file name.
*/
length = strlen(dir) + strlen(p);
if (length >= curSize) {
if (curBuf != staticBuf) {
ckfree(curBuf);
}
curSize = length + 1;
curBuf = (char *) ckalloc((unsigned) curSize);
}
/*
* Finally, concatenate the directory name with the remainder
* of the path in the buffer.
*/
strcpy(curBuf, dir);
strcat(curBuf, p);
if (fromPw) {
//endpwent();
}
return curBuf;
}
/*
*----------------------------------------------------------------------
*
* Tcl_GlobCmd --
*
* This procedure is invoked to process the "glob" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
Tcl_GlobCmd(dummy, interp, argc, argv)
ClientData dummy; /* Not used. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int i, result, noComplain;
if (argc < 2) {
notEnoughArgs:
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ?-nocomplain? name ?name ...?\"", (char *) NULL);
return TCL_ERROR;
}
noComplain = 0;
if ((argv[1][0] == '-') && (strcmp(argv[1], "-nocomplain") == 0)) {
if (argc < 3) {
goto notEnoughArgs;
}
noComplain = 1;
}
for (i = 1 + noComplain; i < argc; i++) {
char *thisName;
/*
* Do special checks for names starting at the root and for
* names beginning with ~. Then let DoGlob do the rest.
*/
thisName = argv[i];
if (*thisName == '~') {
thisName = Tcl_TildeSubst(interp, thisName);
if (thisName == NULL) {
return TCL_ERROR;
}
}
if (*thisName == '/') {
result = DoGlob(interp, "/", thisName+1);
} else {
result = DoGlob(interp, "", thisName);
}
if (result != TCL_OK) {
return result;
}
}
if ((*interp->result == 0) && !noComplain) {
char *sep = "";
Tcl_AppendResult(interp, "no files matched glob pattern",
(argc == 2) ? " \"" : "s \"", (char *) NULL);
for (i = 1; i < argc; i++) {
Tcl_AppendResult(interp, sep, argv[i], (char *) NULL);
sep = " ";
}
Tcl_AppendResult(interp, "\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -