tree_ptr tree_new_binary(fun_ptr fun, tree_ptr x, tree_ptr y) { tree_ptr t = tree_new_funcall(); tree_append(t, x); tree_append(t, y); tree_set_fun(t, tree_new_fun(fun)); return t; }
static void url_add (char *urltext, int len) { char *data; int size; if (!prefs.url_grabber) return; data = malloc (len + 1); if (!data) return; memcpy (data, urltext, len); data[len] = 0; if (data[len - 1] == '.') /* chop trailing dot */ { len--; data[len] = 0; } if (data[len - 1] == ')') /* chop trailing ) */ data[len - 1] = 0; if (url_find (data)) { free (data); return; } if (!url_tree) url_tree = tree_new ((tree_cmp_func *)g_ascii_strcasecmp, NULL); size = tree_size (url_tree); /* 0 is unlimited */ if (prefs.url_grabber_limit > 0 && size >= prefs.url_grabber_limit) { /* the loop is necessary to handle having the limit lowered while xchat is running */ size -= prefs.url_grabber_limit; for(; size > 0; size--) tree_remove_at_pos (url_tree, 0); } tree_append (url_tree, data); fe_url_add (data); }
/* * Open a directory tree for traversal. */ struct tree * tree_open(const char *path) { struct tree *t; t = malloc(sizeof(*t)); memset(t, 0, sizeof(*t)); tree_append(t, path, strlen(path)); t->initialDirFd = open(".", O_RDONLY); /* * During most of the traversal, items are set up and then * returned immediately from tree_next(). That doesn't work * for the very first entry, so we set a flag for this special * case. */ t->flags = needsReturn; return (t); }
/* * Open a directory tree for traversal. */ struct tree * tree_open(const char *path) { struct tree *t; t = malloc(sizeof(*t)); if (t == NULL) abort(); memset(t, 0, sizeof(*t)); tree_append(t, path, strlen(path)); #ifdef HAVE_FCHDIR t->initialDirFd = open(".", O_RDONLY); #elif defined(_WIN32) && !defined(__CYGWIN__) t->initialDir = getcwd(NULL, 0); #endif /* * During most of the traversal, items are set up and then * returned immediately from tree_next(). That doesn't work * for the very first entry, so we set a flag for this special * case. */ t->flags = needsReturn; return (t); }
static void url_add (char *urltext, int len) { char *data; int size; /* we don't need any URLs if we have neither URL grabbing nor URL logging enabled */ if (!prefs.hex_url_grabber && !prefs.hex_url_logging) { return; } data = malloc (len + 1); if (!data) { return; } memcpy (data, urltext, len); data[len] = 0; if (data[len - 1] == '.') /* chop trailing dot */ { len--; data[len] = 0; } /* chop trailing ) but only if there's no counterpart */ if (data[len - 1] == ')' && strchr (data, '(') == NULL) { data[len - 1] = 0; } if (prefs.hex_url_logging) { url_save_node (data); } /* the URL is saved already, only continue if we need the URL grabber too */ if (!prefs.hex_url_grabber) { free (data); return; } if (!url_tree) { url_tree = tree_new ((tree_cmp_func *)strcasecmp, NULL); url_btree = g_tree_new ((GCompareFunc)strcasecmp); } if (url_find (data)) { free (data); return; } size = tree_size (url_tree); /* 0 is unlimited */ if (prefs.hex_url_grabber_limit > 0 && size >= prefs.hex_url_grabber_limit) { /* the loop is necessary to handle having the limit lowered while HexChat is running */ size -= prefs.hex_url_grabber_limit; for(; size > 0; size--) { char *pos; pos = tree_remove_at_pos (url_tree, 0); g_tree_remove (url_btree, pos); free (pos); } } tree_append (url_tree, data); g_tree_insert (url_btree, data, GINT_TO_POINTER (tree_size (url_tree) - 1)); fe_url_add (data); }
/* * Get the next item in the tree traversal. */ int tree_next(struct tree *t) { struct dirent *de = NULL; int r; /* If we're called again after a fatal error, that's an API * violation. Just crash now. */ if (t->visit_type == TREE_ERROR_FATAL) { const char *msg = "Unable to continue traversing" " directory hierarchy after a fatal error.\n"; errmsg(msg); *(volatile int *)0 = 1; /* Deliberate SEGV; NULL pointer dereference. */ exit(1); /* In case the SEGV didn't work. */ } /* Handle the startup case by returning the initial entry. */ if (t->flags & needsReturn) { t->flags &= ~needsReturn; return (t->visit_type = TREE_REGULAR); } while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ while (t->d != NULL) { errno = 0; de = readdir(t->d); if (de == NULL) { if (errno) { /* If readdir fails, we're screwed. */ closedir(t->d); t->d = NULL; t->visit_type = TREE_ERROR_FATAL; return (t->visit_type); } /* Reached end of directory. */ closedir(t->d); t->d = NULL; } else if (de->d_name[0] == '.' && de->d_name[1] == '\0') { /* Skip '.' */ } else if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { /* Skip '..' */ } else { /* * Append the path to the current path * and return it. */ tree_append(t, de->d_name, D_NAMELEN(de)); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (t->visit_type = TREE_REGULAR); } } /* If the current dir needs to be visited, set it up. */ if (t->stack->flags & needsPreVisit) { t->current = t->stack; tree_append(t, t->stack->name, strlen(t->stack->name)); t->stack->flags &= ~needsPreVisit; /* If it is a link, set up fd for the ascent. */ if (t->stack->flags & isDirLink) { #ifdef HAVE_FCHDIR t->stack->fd = open(".", O_RDONLY); #elif defined(_WIN32) && !defined(__CYGWIN__) t->stack->fullpath = getcwd(NULL, 0); #endif t->openCount++; if (t->openCount > t->maxOpenCount) t->maxOpenCount = t->openCount; } t->dirname_length = t->path_length; if (chdir(t->stack->name) != 0) { /* chdir() failed; return error */ tree_pop(t); t->tree_errno = errno; return (t->visit_type = TREE_ERROR_DIR); } t->depth++; t->d = opendir("."); if (t->d == NULL) { r = tree_ascend(t); /* Undo "chdir" */ tree_pop(t); t->tree_errno = errno; t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } t->flags &= ~hasLstat; t->flags &= ~hasStat; t->basename = "."; /* Figure out where we are. */ if (getcwd(t->realpath, PATH_MAX) != NULL) { t->realpath_dirname_length = strlen(t->realpath); if (t->realpath[0] == '/' && t->realpath[1] == '\0') t->realpath_dirname_length = 0; t->realpath_valid = 1; } else { t->realpath_valid = 0; } return (t->visit_type = TREE_POSTDESCENT); } /* We've done everything necessary for the top stack entry. */ if (t->stack->flags & needsPostVisit) { r = tree_ascend(t); tree_pop(t); t->flags &= ~hasLstat; t->flags &= ~hasStat; t->visit_type = r != 0 ? r : TREE_POSTASCENT; return (t->visit_type); } } return (t->visit_type = 0); }
static tree_ptr tree_new_unary(fun_ptr fun, tree_ptr x) { tree_ptr t = tree_new_funcall(); tree_append(t, x); tree_set_fun(t, tree_new_fun(fun)); return t; }
/* * Get the next item in the tree traversal. */ int tree_next(struct tree *t) { struct dirent *de = NULL; /* Handle the startup case by returning the initial entry. */ if (t->flags & needsReturn) { t->flags &= ~needsReturn; return (1); } while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ while (t->d != NULL) { de = readdir(t->d); if (de == NULL) { closedir(t->d); t->d = NULL; } else if (de->d_name[0] == '.' && de->d_name[1] == '\0') { /* Skip '.' */ } else if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { /* Skip '..' */ } else { /* * Append the path to the current path * and return it. */ tree_append(t, de->d_name, D_NAMELEN(de)); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (1); } } /* If the current dir needs to be traversed, set it up. */ if (t->stack->flags & needsTraversal) { tree_append(t, t->stack->name, strlen(t->stack->name)); t->stack->flags &= ~needsTraversal; /* If it is a link, set up fd for the ascent. */ if (t->stack->flags & isDirLink) { t->stack->fd = open(".", O_RDONLY); t->openCount++; if (t->openCount > t->maxOpenCount) t->maxOpenCount = t->openCount; } if (chdir(t->stack->name) == 0) { t->depth++; t->dirname_length = t->path_length; t->d = opendir("."); } else tree_pop(t); continue; } /* We've done everything necessary for the top stack entry. */ tree_ascend(t); tree_pop(t); } return (0); }
/* * Get the next item in the tree traversal. */ int tree_next(struct tree *t) { struct dirent *de = NULL; /* Handle the startup case by returning the initial entry. */ if (t->flags & needsReturn) { t->flags &= ~needsReturn; return (t->visit_type = TREE_REGULAR); } while (t->stack != NULL) { /* If there's an open dir, get the next entry from there. */ while (t->d != NULL) { de = readdir(t->d); if (de == NULL) { closedir(t->d); t->d = NULL; } else if (de->d_name[0] == '.' && de->d_name[1] == '\0') { /* Skip '.' */ } else if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') { /* Skip '..' */ } else { /* * Append the path to the current path * and return it. */ tree_append(t, de->d_name, D_NAMELEN(de)); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (t->visit_type = TREE_REGULAR); } } /* If the current dir needs to be visited, set it up. */ if (t->stack->flags & needsPreVisit) { t->current = t->stack; tree_append(t, t->stack->name, strlen(t->stack->name)); t->stack->flags &= ~needsPreVisit; /* If it is a link, set up fd for the ascent. */ if (t->stack->flags & isDirLink) { t->stack->fd = open(".", O_RDONLY); t->openCount++; if (t->openCount > t->maxOpenCount) t->maxOpenCount = t->openCount; } t->dirname_length = t->path_length; if (chdir(t->stack->name) != 0) { /* chdir() failed; return error */ tree_pop(t); t->tree_errno = errno; return (t->visit_type = TREE_ERROR_DIR); } t->depth++; t->d = opendir("."); if (t->d == NULL) { tree_ascend(t); /* Undo "chdir" */ tree_pop(t); t->tree_errno = errno; return (t->visit_type = TREE_ERROR_DIR); } t->flags &= ~hasLstat; t->flags &= ~hasStat; t->basename = "."; return (t->visit_type = TREE_POSTDESCENT); } /* We've done everything necessary for the top stack entry. */ if (t->stack->flags & needsPostVisit) { tree_ascend(t); tree_pop(t); t->flags &= ~hasLstat; t->flags &= ~hasStat; return (t->visit_type = TREE_POSTASCENT); } } return (t->visit_type = 0); }