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