[24079] trunk/base/src/pextlib1.0/find.c
source_changes at macosforge.org
source_changes at macosforge.org
Sun Apr 15 22:44:31 PDT 2007
Revision: 24079
http://trac.macosforge.org/projects/macports/changeset/24079
Author: eridius at macports.org
Date: 2007-04-15 22:44:31 -0700 (Sun, 15 Apr 2007)
Log Message:
-----------
Rewrite Pextlib find command. Now actually has useful API. Usage is find ?-depth? ?-ignoreErrors? target ?target ...? varname body. -depth identical to -d switch to find. -ignoreErrors causes it to ignore permission/read errors. Does not follow symlinks.
Modified Paths:
--------------
trunk/base/src/pextlib1.0/find.c
Modified: trunk/base/src/pextlib1.0/find.c
===================================================================
--- trunk/base/src/pextlib1.0/find.c 2007-04-16 05:44:26 UTC (rev 24078)
+++ trunk/base/src/pextlib1.0/find.c 2007-04-16 05:44:31 UTC (rev 24079)
@@ -59,104 +59,132 @@
#include <tcl.h>
-static int do_find(Tcl_Interp *interp, int depth, char *dir, char *match, char *action);
+static int do_find(Tcl_Interp *interp, int flags, char *target, char *varname, char *body);
+#define F_DEPTH 0x1
+#define F_IGNORE_ERRORS 0x2
+
+/* find ?-depth? ?-ignoreErrors? varname target ?target ...? body */
int
FindCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
- char *startdir;
- char *match, *action;
- char *def_match = "1";
- char *def_action = "puts \"$_filename\"";
- int depth = 0;
+ char *varname;
+ char *body;
+ int flags = 0;
+ int rval = TCL_OK;
+ Tcl_Obj *CONST *objv_orig = objv;
- /* Adjust arguments */
- ++objv, --objc;
+ /* Adjust arguments to remove initial `find' */
+ ++objv, --objc;
- if (objc && !strcmp(Tcl_GetString(*objv), "-depth")) {
- depth = 1;
- ++objv, --objc;
- }
- if (!objc)
- startdir = ".";
- else {
- startdir = Tcl_GetString(*objv);
- ++objv, --objc;
- }
- if (!objc)
- match = def_match;
- else {
- match = Tcl_GetString(*objv);
- ++objv, --objc;
- }
- if (!objc)
- action = def_action;
- else {
- action = Tcl_GetString(*objv);
- ++objv, --objc;
- }
- if (objc) {
- Tcl_WrongNumArgs(interp, 1, objv, "[dir] [match] [action]");
- return TCL_ERROR;
- }
- return do_find(interp, depth, startdir, match, action);
+ /* Parse flags */
+ while (objc) {
+ if (!strcmp(Tcl_GetString(*objv), "-depth")) {
+ flags |= F_DEPTH;
+ ++objv, --objc;
+ continue;
+ }
+ if (!strcmp(Tcl_GetString(*objv), "-ignoreErrors")) {
+ flags |= F_IGNORE_ERRORS;
+ ++objv, --objc;
+ continue;
+ }
+ break;
+ }
+
+ /* Parse remaining args */
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv_orig, "?-depth? ?-ignoreErrors? varname target ?target target ...? body");
+ return TCL_ERROR;
+ }
+
+ varname = Tcl_GetString(*objv);
+ ++objv, --objc;
+
+ body = Tcl_GetString(objv[objc-1]);
+ --objc;
+
+ while (objc) {
+ char *target = Tcl_GetString(*objv);
+ ++objv, --objc;
+
+ if ((rval = do_find(interp, flags, target, varname, body)) == TCL_CONTINUE) {
+ rval = TCL_OK;
+ continue;
+ } else if (rval == TCL_BREAK) {
+ rval = TCL_OK;
+ break;
+ } else if (rval != TCL_OK) {
+ break;
+ }
+ }
+ return rval;
}
static int
-do_find(Tcl_Interp *interp, int depth, char *dir, char *match, char *action)
+do_find(Tcl_Interp *interp, int flags, char *target, char *varname, char *body)
{
- DIR *dirp;
- struct dirent *dp;
- int rval, alen;
- struct stat sb;
-
- if ((dirp = opendir(dir)) == NULL)
- return TCL_ERROR;
- /* be optimistic */
- rval = TCL_OK;
+ DIR *dirp;
+ struct dirent *dp;
+ int rval = TCL_OK;
+ struct stat sb;
+
+ /* No permission? */
+ if (lstat(target, &sb) != 0) {
+ if (flags & F_IGNORE_ERRORS) {
+ return TCL_OK;
+ } else {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "Error: no permission to access file/folder `", target, "'");
+ return TCL_ERROR;
+ }
+ }
+
+ /* Handle files now, or directories if !depth */
+ if (!(flags & F_DEPTH) || !(sb.st_mode & S_IFDIR)) {
+ Tcl_SetVar(interp, varname, target, 0);
+ if ((rval = Tcl_EvalEx(interp, body, -1, 0)) != TCL_OK) {
+ return rval;
+ }
+ }
+
+ /* Handle directories */
+ if (sb.st_mode & S_IFDIR) {
+ if ((dirp = opendir(target)) == NULL) {
+ if (flags & F_IGNORE_ERRORS) {
+ return TCL_OK;
+ } else {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "Error: Could not open directory `", target, "'");
+ return TCL_ERROR;
+ }
+ }
+
+ while ((dp = readdir(dirp)) != NULL) {
+ char tmp_path[PATH_MAX];
- alen = strlen(action);
+ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+ continue;
+ strcpy(tmp_path, target);
+ strcat(tmp_path, "/");
+ strcat(tmp_path, dp->d_name);
- while ((dp = readdir(dirp)) != NULL) {
- char tmp_path[PATH_MAX];
- int res;
-
- if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
- continue;
- strcpy(tmp_path, dir);
- strcat(tmp_path, "/");
- strcat(tmp_path, dp->d_name);
-
- /* No permission? */
- if (stat(tmp_path, &sb) != 0)
- continue;
- /* Handle directories specially. If depth, do it now */
- if (depth && sb.st_mode & S_IFDIR) {
- if (do_find(interp, depth, tmp_path, match, action) != TCL_OK)
- return TCL_ERROR;
- }
- Tcl_SetVar(interp, "_filename", tmp_path, TCL_GLOBAL_ONLY);
- if (Tcl_ExprBoolean(interp, match, &res) == TCL_OK) {
- if (res == 1) {
- /* match */
- if (Tcl_EvalEx(interp, action, alen, TCL_EVAL_GLOBAL) != TCL_OK) {
- rval = TCL_ERROR;
- break;
- }
- }
- else
- continue;
- }
- else {
- rval = TCL_ERROR;
- break;
- }
- /* Handle directories specially. If !depth, do it now */
- if (!depth && sb.st_mode & S_IFDIR) {
- if (do_find(interp, depth, tmp_path, match, action) != TCL_OK)
- return TCL_ERROR;
- }
- }
- (void)closedir(dirp);
- return rval;
+ if ((rval = do_find(interp, flags, tmp_path, varname, body)) == TCL_CONTINUE) {
+ rval = TCL_OK;
+ continue;
+ } else if (rval != TCL_OK) {
+ break;
+ }
+ }
+ (void)closedir(dirp);
+
+ /* Handle directory now if depth */
+ if (flags & F_DEPTH) {
+ Tcl_SetVar(interp, varname, target, 0);
+ if ((rval = Tcl_EvalEx(interp, body, -1, 0)) != TCL_OK) {
+ return rval;
+ }
+ }
+ }
+ return rval;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070415/76ff854e/attachment.html
More information about the macports-changes
mailing list