static noreturn failexec(char *file, List *args) { List *fn; assert(gcisblocked()); fn = varlookup("fn-%exec-failure", NULL); if (fn != NULL) { int olderror = errno; Ref(List *, list, append(fn, mklist(mkstr(file), args))); RefAdd(file); gcenable(); RefRemove(file); eval(list, NULL, 0); RefEnd(list); errno = olderror; } eprint("%s: %s\n", file, esstrerror(errno)); exit(1); }
/* dirmatch -- match a pattern against the contents of directory */ static List *dirmatch(const char *prefix, const char *dirname, const char *pattern, const char *quote) { List *list, **prevp; static DIR *dirp; static Dirent *dp; static struct stat s; /* * opendir succeeds on regular files on some systems, so the stat call * is necessary (sigh); the check is done here instead of with the * opendir to handle a trailing slash. */ if (stat(dirname, &s) == -1 || (s.st_mode & S_IFMT) != S_IFDIR) return NULL; if (!haswild(pattern, quote)) { char *name = str("%s%s", prefix, pattern); if (lstat(name, &s) == -1) return NULL; return mklist(mkstr(name), NULL); } assert(gcisblocked()); dirp = opendir(dirname); if (dirp == NULL) return NULL; for (list = NULL, prevp = &list; (dp = readdir(dirp)) != NULL;) if (match(dp->d_name, pattern, quote) && (!ishiddenfile(dp->d_name) || *pattern == '.')) { List *lp = mklist(mkstr(str("%s%s", prefix, dp->d_name)), NULL); *prevp = lp; prevp = &lp->next; } closedir(dirp); return list; }
static void mkenv0(void *dummy, char *key, void *value) { Var *var = value; assert(gcisblocked()); if ( var == NULL || var->defn == NULL || (var->flags & var_isinternal) || !isexported(key) ) return; if (var->env == NULL || (rebound && (var->flags & var_hasbindings))) { char *envstr = str(ENV_FORMAT, key, var->defn); var->env = envstr; } assert(env->count < env->alloclen); env->vector[env->count++] = var->env; if (env->count == env->alloclen) { Vector *newenv = mkvector(env->alloclen * 2); newenv->count = env->count; memcpy(newenv->vector, env->vector, env->count * sizeof *env->vector); env = newenv; } }
Handler *roothandler = NULL; List *exception = NULL; Push *pushlist = NULL; /* pophandler -- remove a handler */ extern void pophandler(Handler *handler) { assert(tophandler == handler); assert(handler->rootlist == rootlist); tophandler = handler->up; } /* throw -- raise an exception */ extern noreturn throw(List *e) { Handler *handler = tophandler; assert(!gcisblocked()); assert(e != NULL); assert(handler != NULL); tophandler = handler->up; while (pushlist != handler->pushlist) { rootlist = &pushlist->defnroot; varpop(pushlist); } #if ASSERTIONS for (; rootlist != handler->rootlist; rootlist = rootlist->next) assert(rootlist != NULL); #else rootlist = handler->rootlist; #endif