8456f819f53eaa13e0d77bda090883527aad3d03
[pspp-builds.git] / src / language / control / control-stack.c
1 #include <config.h>
2 #include "control-stack.h"
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <libpspp/compiler.h>
6 #include <libpspp/message.h>
7 #include "xalloc.h"
8
9 #include "gettext.h"
10 #define _(msgid) gettext (msgid)
11
12 struct ctl_struct
13   {
14     const struct ctl_class *class;    /* Class of control structure. */
15     struct ctl_struct *down;    /* Points toward the bottom of ctl_stack. */
16     void *private;              /* Private data. */
17   };
18
19 static struct ctl_struct *ctl_stack;
20
21 void
22 ctl_stack_clear (void)
23 {
24   while (ctl_stack != NULL)
25     {
26       struct ctl_struct *top = ctl_stack;
27       msg (SE, _("%s without %s."),
28            top->class->start_name, top->class->end_name);
29       ctl_stack_pop (top->private);
30     }
31 }
32
33 void
34 ctl_stack_push (const struct ctl_class *class, void *private)
35 {
36   struct ctl_struct *ctl;
37
38   assert (private != NULL);
39   ctl = xmalloc (sizeof *ctl);
40   ctl->class = class;
41   ctl->down = ctl_stack;
42   ctl->private = private;
43   ctl_stack = ctl;
44 }
45
46 void *
47 ctl_stack_top (const struct ctl_class *class)
48 {
49   struct ctl_struct *top = ctl_stack;
50   if (top != NULL && top->class == class)
51     return top->private;
52   else
53     {
54       if (ctl_stack_search (class) != NULL)
55         msg (SE, _("This command must appear inside %s...%s, "
56                    "without intermediate %s...%s."),
57              class->start_name, class->end_name,
58              top->class->start_name, top->class->end_name);
59       return NULL;
60     }
61 }
62
63 void *
64 ctl_stack_search (const struct ctl_class *class)
65 {
66   struct ctl_struct *ctl;
67
68   for (ctl = ctl_stack; ctl != NULL; ctl = ctl->down)
69     if (ctl->class == class)
70       return ctl->private;
71
72   msg (SE, _("This command cannot appear outside %s...%s."),
73        class->start_name, class->end_name);
74   return NULL;
75 }
76
77 void
78 ctl_stack_pop (void *private)
79 {
80   struct ctl_struct *top = ctl_stack;
81
82   assert (top != NULL);
83   assert (top->private == private);
84
85   top->class->close (top->private);
86   ctl_stack = top->down;
87   free (top);
88 }
89
90 bool
91 ctl_stack_is_empty (void)
92 {
93   return ctl_stack == NULL;
94 }