#include #include "ctl-stack.h" #include #include #include "error.h" #include "xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) struct ctl_struct { struct ctl_class *class; /* Class of control structure. */ struct ctl_struct *down; /* Points toward the bottom of ctl_stack. */ void *private; /* Private data. */ }; 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 (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 (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 (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 UNUSED) { 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; }