X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcontrol-stack.c;fp=src%2Fdata%2Fcontrol-stack.c;h=d8228f896c807d8ecd3ce3fe0de9c2cf1442ef08;hb=cfe28ef151771c04be56d459c58d818f6c43f5e1;hp=0000000000000000000000000000000000000000;hpb=cbda9ae91c77f34e9591d980d5202fd7d376ac12;p=pspp diff --git a/src/data/control-stack.c b/src/data/control-stack.c new file mode 100644 index 0000000000..d8228f896c --- /dev/null +++ b/src/data/control-stack.c @@ -0,0 +1,98 @@ +#include + +#include "data/control-stack.h" + +#include +#include + +#include "libpspp/compiler.h" +#include "libpspp/message.h" + +#include "gl/xalloc.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +struct ctl_struct + { + const struct ctl_class *class; /* Class of control structure. */ + struct ctl_struct *down; /* Points toward the bottom of ctl_stack. */ + void *private; /* Private data. */ + }; + +static struct ctl_struct *ctl_stack; + +void +ctl_stack_clear (void) +{ + while (ctl_stack != NULL) + { + struct ctl_struct *top = ctl_stack; + msg (SE, _("%s without %s."), + top->class->start_name, top->class->end_name); + ctl_stack_pop (top->private); + } +} + +void +ctl_stack_push (const struct ctl_class *class, void *private) +{ + struct ctl_struct *ctl; + + assert (private != NULL); + ctl = xmalloc (sizeof *ctl); + ctl->class = class; + ctl->down = ctl_stack; + ctl->private = private; + ctl_stack = ctl; +} + +void * +ctl_stack_top (const struct ctl_class *class) +{ + struct ctl_struct *top = ctl_stack; + if (top != NULL && top->class == class) + return top->private; + else + { + if (ctl_stack_search (class) != NULL) + msg (SE, _("This command must appear inside %s...%s, " + "without intermediate %s...%s."), + class->start_name, class->end_name, + top->class->start_name, top->class->end_name); + return NULL; + } +} + +void * +ctl_stack_search (const struct ctl_class *class) +{ + struct ctl_struct *ctl; + + for (ctl = ctl_stack; ctl != NULL; ctl = ctl->down) + if (ctl->class == class) + return ctl->private; + + msg (SE, _("This command cannot appear outside %s...%s."), + class->start_name, class->end_name); + return NULL; +} + +void +ctl_stack_pop (void *private) +{ + struct ctl_struct *top = ctl_stack; + + assert (top != NULL); + assert (top->private == private); + + top->class->close (top->private); + ctl_stack = top->down; + free (top); +} + +bool +ctl_stack_is_empty (void) +{ + return ctl_stack == NULL; +}