Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions es.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,9 @@ extern Binding *reversebindings(Binding *binding);
/* eval.c */

extern Binding *bindargs(Tree *params, List *args, Binding *binding);
extern List *forkexec(char *file, List *list, Boolean inchild);
extern List *walk(Tree *tree, Binding *binding, int flags);
extern List *eval(List *list, Binding *binding, int flags);
extern List *eval1(Term *term, int flags);
extern List *pathsearch(Term *term);

extern unsigned long evaldepth, maxevaldepth;
#define MINmaxevaldepth 100
Expand Down
82 changes: 11 additions & 71 deletions eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,6 @@

unsigned long evaldepth = 0, maxevaldepth = MAXmaxevaldepth;

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));
esexit(1);
}

/* forkexec -- fork (if necessary) and exec */
extern List *forkexec(char *file, List *list, Boolean inchild) {
int pid, status;
Vector *env;
gcdisable();
env = mkenv();
pid = efork(!inchild, FALSE);
if (pid == 0) {
execve(file, vectorize(list)->vector, env->vector);
failexec(file, list);
}
gcenable();
status = ewaitfor(pid);
if ((status & 0xff) == 0) {
sigint_newline = FALSE;
SIGCHK();
sigint_newline = TRUE;
} else
SIGCHK();
printstatus(0, status);
return mklist(mkterm(mkstatus(status), NULL), NULL);
}

/* assign -- bind a list of values to a list of variables */
static List *assign(Tree *varform, Tree *valueform0, Binding *binding0) {
Ref(List *, result, NULL);
Expand Down Expand Up @@ -345,17 +304,19 @@ extern Binding *bindargs(Tree *params, List *args, Binding *binding) {
RefReturn(result);
}

/* pathsearch -- evaluate fn %pathsearch + some argument */
extern List *pathsearch(Term *term) {
List *list;
Ref(List *, search, NULL);
search = varlookup("fn-%pathsearch", NULL);
/* whatis -- evaluate fn %whatis + some argument */
static List *whatis(Term *term, char *name) {
Ref(List *, list, NULL);
Ref(List *, search, varlookup("fn-%whatis", NULL));
if (search == NULL)
fail("es:pathsearch", "%E: fn %%pathsearch undefined", term);
list = mklist(term, NULL);
fail("es:whatis", "%E: fn %%whatis undefined", term);
gcdisable();
list = mklist(term, name == NULL ? NULL : mklist(mkstr(name), NULL));
list = append(search, list);
RefEnd(search);
return eval(list, NULL, 0);
gcenable();
list = eval(list, NULL, 0);
RefReturn(list);
}

/* eval -- evaluate a list, producing a list */
Expand Down Expand Up @@ -439,8 +400,6 @@ extern List *eval(List *list0, Binding *binding0, int flags) {
goto done;
}

/* the logic here is duplicated in $&whatis */

Ref(char *, name, getstr(list->term));
fn = varlookup2("fn-", name, binding);
if (fn != NULL) {
Expand All @@ -449,28 +408,9 @@ extern List *eval(List *list0, Binding *binding0, int flags) {
RefPop(name);
goto restart;
}
if (isabsolute(name)) {
char *error = checkexecutable(name);
if (error != NULL)
fail("$&whatis", "%s: %s", name, error);
if (funcname != NULL) {
Term *fn = mkstr(funcname);
list = mklist(fn, list->next);
}
list = forkexec(name, list, flags & eval_inchild);
RefPop(name);
goto done;
}
RefEnd(name);

fn = pathsearch(list->term);
if (fn != NULL && fn->next == NULL
&& (cp = getclosure(fn->term)) == NULL) {
char *name = getstr(fn->term);
list = forkexec(name, list, flags & eval_inchild);
goto done;
}

fn = whatis(list->term, funcname);
if (fn != NULL)
funcname = getstr(list->term);
list = append(fn, list->next);
Expand Down
31 changes: 29 additions & 2 deletions initial.es
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,27 @@ fn-%newfd = $&newfd
fn-%run = $&run
fn-%split = $&split
fn-%var = $&var
fn-%whatis = $&whatis

# The %whatis function is called by the shell to convert anything that
# isn't a function into a function that it can call. The shell performs
# its own function lookup, but %whatis does too for user convenience.
#
# $name is the optional name used to refer to the current term being
# looked up, which comes up in cases like `fn-name = /path/to/bin`.

fn %whatis term name {
if {~ $#name 0} {
name = $term
}
if {!~ $#(fn-$term) 0} {
result $(fn-$term)
} {~ $term /* ./* ../*} {
result %run $term $name
} {
let (searched = <={%pathsearch $term})
result %run $searched(1) $name $searched(2 ...)
}
}

# These builtins are only around as a matter of convenience, so
# users don't have to type the infamous <= (nee <>) operator.
Expand All @@ -165,7 +185,14 @@ fn whatis {
echo >[1=2] $message
result = $result 1
} {
echo <={%whatis $i}
# Hide the %run call in this "sugary" case.
let (r = <={%whatis $i}) {
if {~ $r(1) %run} {
echo $r(2) $r(4 ...)
} {
echo $r
}
}
result = $result 0
}
}
Expand Down
27 changes: 0 additions & 27 deletions prim-etc.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,32 +88,6 @@ PRIM(flatten) {
RefReturn(lp);
}

PRIM(whatis) {
/* the logic in here is duplicated in eval() */
if (list == NULL || list->next != NULL)
fail("$&whatis", "usage: $&whatis program");
Ref(Term *, term, list->term);
if (getclosure(term) == NULL) {
List *fn;
Ref(char *, prog, getstr(term));
assert(prog != NULL);
fn = varlookup2("fn-", prog, NULL);
if (fn != NULL)
list = fn;
else {
if (isabsolute(prog)) {
char *error = checkexecutable(prog);
if (error != NULL)
fail("$&whatis", "%s: %s", prog, error);
} else
list = pathsearch(term);
}
RefEnd(prog);
}
RefEnd(term);
return list;
}

PRIM(split) {
char *sep;
if (list == NULL)
Expand Down Expand Up @@ -355,7 +329,6 @@ extern Dict *initprims_etc(Dict *primdict) {
X(exec);
X(dot);
X(flatten);
X(whatis);
X(split);
X(fsplit);
X(var);
Expand Down
41 changes: 41 additions & 0 deletions prim-sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,47 @@ PRIM(fork) {
return mklist(mkstr(mkstatus(status)), NULL);
}

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));
esexit(1);
}

/* forkexec -- fork (if necessary) and exec */
static List *forkexec(char *file, List *list, Boolean inchild) {
int pid, status;
Vector *env;
gcdisable();
env = mkenv();
pid = efork(!inchild, FALSE);
if (pid == 0) {
execve(file, vectorize(list)->vector, env->vector);
failexec(file, list);
}
gcenable();
status = ewaitfor(pid);
if ((status & 0xff) == 0) {
sigint_newline = FALSE;
SIGCHK();
sigint_newline = TRUE;
} else
SIGCHK();
printstatus(0, status);
return mklist(mkterm(mkstatus(status), NULL), NULL);
}

PRIM(run) {
char *file;
if (list == NULL)
Expand Down