Skip to content

Up for discussion: User-provided commands for reading shell input #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
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: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
name: Test
command: |
mkdir -p ./test/results
./es -s < ./test/test.es --junit ./test/tests/* > ./test/results/results.xml
./es -ps < ./test/test.es --junit ./test/tests/* > ./test/results/results.xml

- store_artifacts:
path: ./test/results/
Expand Down
13 changes: 7 additions & 6 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ VPATH = $(srcdir)
HFILES = config.h es.h gc.h input.h prim.h print.h sigmsgs.h \
stdenv.h syntax.h term.h var.h
CFILES = access.c closure.c conv.c dict.c eval.c except.c fd.c gc.c glob.c \
glom.c input.c heredoc.c history.c list.c main.c match.c open.c opt.c \
glom.c input.c heredoc.c list.c main.c match.c open.c opt.c \
prim-ctl.c prim-etc.c prim-io.c prim-sys.c prim.c print.c proc.c \
sigmsgs.c signal.c split.c status.c str.c syntax.c term.c token.c \
tree.c util.c var.c vec.c version.c y.tab.c dump.c
readline.c sigmsgs.c signal.c split.c status.c str.c syntax.c term.c \
token.c tree.c util.c var.c vec.c version.c y.tab.c dump.c
OFILES = access.o closure.o conv.o dict.o eval.o except.o fd.o gc.o glob.o \
glom.o input.o heredoc.o history.o list.o main.o match.o open.o opt.o \
glom.o input.o heredoc.o list.o main.o match.o open.o opt.o \
prim-ctl.o prim-etc.o prim-io.o prim-sys.o prim.o print.o proc.o \
sigmsgs.o signal.o split.o status.o str.o syntax.o term.o token.o \
tree.o util.o var.o vec.o version.o y.tab.o
readline.o sigmsgs.o signal.o split.o status.o str.o syntax.o term.o \
token.o tree.o util.o var.o vec.o version.o y.tab.o
OTHER = Makefile parse.y mksignal
GEN = esdump y.tab.c y.tab.h y.output token.h sigmsgs.c initial.c

Expand Down Expand Up @@ -145,6 +145,7 @@ prim.o : prim.c es.h config.h stdenv.h prim.h
prim-ctl.o : prim-ctl.c es.h config.h stdenv.h prim.h
prim-etc.o : prim-etc.c es.h config.h stdenv.h prim.h
prim-io.o : prim-io.c es.h config.h stdenv.h gc.h prim.h
readline.o : readline.c es.h config.h stdenv.h prim.h
prim-sys.o : prim-sys.c es.h config.h stdenv.h prim.h
print.o : print.c es.h config.h stdenv.h print.h
proc.o : proc.c es.h config.h stdenv.h prim.h
Expand Down
20 changes: 17 additions & 3 deletions es.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ extern List *sortlist(List *list);

/* tree.c */

extern Tree *mk(NodeKind VARARGS);
extern Tree *gcmk(NodeKind VARARGS);


/* closure.c */
Expand Down Expand Up @@ -188,6 +188,7 @@ extern List *extractmatches(List *subjects, List *patterns, StrList *quotes);

extern void initvars(void);
extern void initenv(char **envp, Boolean protected);
extern void initgetenv(void);
extern void hidevariables(void);
extern void validatevar(const char *var);
extern List *varlookup(const char *name, Binding *binding);
Expand Down Expand Up @@ -290,7 +291,7 @@ extern Boolean streq2(const char *s, const char *t1, const char *t2);
/* input.c */

extern char *prompt, *prompt2;
extern Tree *parse(char *esprompt1, char *esprompt2);
extern Tree *parse(List *);
extern Tree *parsestring(const char *str);
extern Boolean isinteractive(void);
extern Boolean isfromfd(void);
Expand All @@ -307,8 +308,16 @@ extern List *runstring(const char *str, const char *name, int flags);
#define run_printcmds 32 /* -x */
#define run_lisptrees 64 /* -L and defined(LISPTREES) */


/* readline.c */

#if HAVE_READLINE
extern Boolean resetterminal;
extern void inithistory(void);

extern void sethistory(char *file);
extern void loghistory(char *cmd);
extern void setmaxhistorylength(int length);
extern void rlsetup(void);
#endif


Expand Down Expand Up @@ -404,6 +413,11 @@ extern void gcenable(void); /* enable collections */
extern void gcdisable(void); /* disable collections */
extern Boolean gcisblocked(void); /* is collection disabled? */

extern void *palloc(size_t n, Tag *t); /* allocate like gcalloc but in pspace */
extern void *pseal(void *p); /* collect pspace into gcspace with one root */
extern char *pdup(const char *s); /* copy a 0-terminated string into pspace */
extern char *pndup(const char *s, size_t n); /* copy a counted string into pspace */


/*
* garbage collector tags
Expand Down
129 changes: 123 additions & 6 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct Space {
#define INSPACE(p, sp) ((sp)->bot <= (char *) (p) && (char *) (p) < (sp)->top)

#define MIN_minspace 10000
#define MIN_minpspace 5000

#if GCPROTECT
#define NSPACES 10
Expand All @@ -38,13 +39,15 @@ int gcblocked = 0;
Tag StringTag;

/* own variables */
static Space *new, *old;
static Space *new, *old, *pspace;
#if GCPROTECT
static Space *spaces;
#endif
static Root *globalrootlist, *exceptionrootlist;
static size_t minspace = MIN_minspace; /* minimum number of bytes in a new space */

static size_t minpspace = MIN_minpspace; /* minimum number of bytes in a new pspace */


/*
* debugging
Expand Down Expand Up @@ -192,6 +195,18 @@ static Space *newspace(Space *next) {

#endif /* !GCPROTECT */

/* newpspace -- create a new ``half'' space for use while parsing
* only exists to avoid gcprotect which I don't understand */
static Space *newpspace(Space *next) {
size_t n = ALIGN(minpspace);
Space *space = ealloc(sizeof (Space) + n);
space->bot = (void *) &space[1];
space->top = (void *) (((char *) space->bot) + n);
space->current = space->bot;
space->next = next;
return space;
}

/* deprecate -- take a space and invalidate it */
static void deprecate(Space *space) {
#if GCPROTECT
Expand Down Expand Up @@ -222,7 +237,8 @@ static void deprecate(Space *space) {
}

/* isinspace -- does an object lie inside a given Space? */
extern Boolean isinspace(Space *space, void *p) {
extern Boolean isinspace(Space *space0, void *p) {
Space *space = space0;
for (; space != NULL; space = space->next)
if (INSPACE(p, space)) {
assert((char *) p < space->current);
Expand Down Expand Up @@ -273,12 +289,17 @@ extern void exceptionunroot(void) {
#define FOLLOWTO(p) ((Tag *) (((char *) p) + 1))
#define FOLLOW(tagp) ((void *) (((char *) tagp) - 1))

static Boolean pmode = FALSE;

/* forward -- forward an individual pointer from old space */
extern void *forward(void *p) {
Tag *tag;
void *np;

if (!isinspace(old, p)) {
if (pmode && !isinspace(pspace, p)) {
VERBOSE(("GC %8ux : <<not in pspace>>\n", p));
return p;
} else if (!pmode && !isinspace(old, p)) {
VERBOSE(("GC %8ux : <<not in old space>>\n", p));
return p;
}
Expand All @@ -287,6 +308,7 @@ extern void *forward(void *p) {

tag = TAG(p);
assert(tag != NULL);

if (FORWARDED(tag)) {
np = FOLLOW(tag);
assert(TAG(np)->magic == TAGMAGIC);
Expand All @@ -297,6 +319,13 @@ extern void *forward(void *p) {
VERBOSE(("%s -> %8ux (forwarded)\n", tag->typename, np));
TAG(p) = FOLLOWTO(np);
}

/* hack of the decade: recurse, sometimes */
if (pmode) {
tag = TAG(np);
(*tag->scan)(np);
}

return np;
}

Expand All @@ -315,9 +344,7 @@ static void scanspace(void) {
for (scanned = NULL;;) {
Space *front = new;
for (sp = new; sp != scanned; sp = sp->next) {
char *scan;
assert(sp != NULL);
scan = sp->bot;
char *scan = sp->bot;
while (scan < sp->current) {
Tag *tag = *(Tag **) scan;
assert(tag->magic == TAGMAGIC);
Expand Down Expand Up @@ -439,6 +466,49 @@ extern void gc(void) {
} while (new->next != NULL);
}

/* pseal -- collect pspace to new, and translate p to its new location */
extern void *pseal(void *p) {
size_t psize = 0;
Space *sp;

for (sp = pspace; sp != NULL; sp = sp->next)
psize += SPACEUSED(sp);

if (psize == 0)
return p;

/* TODO: this is an overestimate since it includes garbage */
gcreserve(psize);
pmode = TRUE;
VERBOSE(("Reserved %d for pspace copy\n", psize));

assert (gcblocked >= 0);
++gcblocked;

#if GCVERBOSE
for (sp = pspace; sp != NULL; sp = sp->next)
VERBOSE(("GC pspace = %ux ... %ux\n", sp->bot, sp->current));
#endif
if (p != NULL) {
VERBOSE(("GC new space = %ux ... %ux\n", new->bot, new->top));

p = forward(p);
(*(TAG(p))->scan)(p);
}

/* TODO: possible performance win: save+reuse the first pspace */
for (sp = pspace; sp != NULL;) {
Space *old = sp;
sp = sp->next;
efree(old);
}
pspace = newpspace(NULL);

--gcblocked;
pmode = FALSE;
return p;
}

/* initgc -- initialize the garbage collector */
extern void initgc(void) {
#if GCPROTECT
Expand All @@ -449,6 +519,7 @@ extern void initgc(void) {
#else
new = newspace(NULL);
#endif
pspace = newpspace(NULL);
old = NULL;
}

Expand Down Expand Up @@ -481,6 +552,24 @@ extern void *gcalloc(size_t nbytes, Tag *tag) {
}
}

/* palloc -- allocate an object in pspace during parse */
extern void *palloc(size_t nbytes, Tag *tag) {
size_t n = ALIGN(nbytes + sizeof (Tag *));
assert(tag == NULL || tag->magic == TAGMAGIC);
for (;;) {
Tag **p = (void *) pspace->current;
char *q = ((char *) p) + n;
if (q <= pspace->top) {
pspace->current = q;
*p++ = tag;
return p;
}
if (minpspace < nbytes)
minpspace = nbytes + sizeof (Tag *);
pspace = newpspace(pspace);
}
}


/*
* strings
Expand Down Expand Up @@ -519,6 +608,22 @@ static size_t StringScan(void *p) {
}


extern char *pndup(const char *s, size_t n) {
char *ns;

ns = palloc((n + 1) * sizeof (char), &StringTag);
memcpy(ns, s, n);
ns[n] = '\0';
assert(strlen(ns) == n);

return ns;
}

extern char *pdup(const char *s) {
return pndup(s, strlen(s));
}


/*
* allocation of large, contiguous buffers for large object creation
* see the use of this in str(). note that this region may not
Expand Down Expand Up @@ -547,12 +652,24 @@ extern char *sealbuffer(Buffer *buf) {
return s;
}

extern char *psealbuffer(Buffer *buf) {
char *s = pdup(buf->str);
efree(buf);
return s;
}

extern char *sealcountedbuffer(Buffer *buf) {
char *s = gcndup(buf->str, buf->current);
efree(buf);
return s;
}

extern char *psealcountedbuffer(Buffer *buf) {
char *s = pndup(buf->str, buf->current);
efree(buf);
return s;
}

extern Buffer *bufncat(Buffer *buf, const char *s, size_t len) {
while (buf->current + len >= buf->len)
buf = expandbuffer(buf, buf->current + len - buf->len);
Expand Down
2 changes: 2 additions & 0 deletions gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ extern Buffer *bufcat(Buffer *buf, const char *s);
extern Buffer *bufputc(Buffer *buf, char c);
extern char *sealbuffer(Buffer *buf);
extern char *sealcountedbuffer(Buffer *buf);
extern char *psealbuffer(Buffer *buf);
extern char *psealcountedbuffer(Buffer *buf);
extern void freebuffer(Buffer *buf);

extern void *forward(void *p);
10 changes: 5 additions & 5 deletions heredoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extern Tree *getherevar(void) {
while ((c = GETC()) != EOF && !dnw[c])
buf = bufputc(buf, c);
len = buf->len;
s = sealcountedbuffer(buf);
s = psealcountedbuffer(buf);
if (len == 0) {
yyerror("null variable name in here document");
return NULL;
Expand All @@ -47,14 +47,14 @@ extern Tree *snarfheredoc(const char *eof, Boolean quoted) {

for (tree = NULL, tailp = &tree, buf = openbuffer(0);;) {
int c;
print_prompt2();
increment_line();
for (s = (unsigned char *) eof; (c = GETC()) == *s; s++)
;
if (*s == '\0' && (c == '\n' || c == EOF)) {
if (buf->current == 0 && tree != NULL)
freebuffer(buf);
else
*tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL);
*tailp = treecons(mk(nQword, psealcountedbuffer(buf)), NULL);
break;
}
if (s != (unsigned char *) eof)
Expand All @@ -72,7 +72,7 @@ extern Tree *snarfheredoc(const char *eof, Boolean quoted) {
if (buf->current == 0)
freebuffer(buf);
else {
*tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL);
*tailp = treecons(mk(nQword, psealcountedbuffer(buf)), NULL);
tailp = &(*tailp)->CDR;
}
var = getherevar();
Expand Down Expand Up @@ -133,7 +133,7 @@ extern Boolean queueheredoc(Tree *t) {
return FALSE;
}

here = gcalloc(sizeof (Here), NULL);
here = palloc(sizeof (Here), NULL);
here->next = hereq;
here->marker = eof;
hereq = here;
Expand Down
Loading