1 /*
2  * context.c - context save and restore
3  *
4  * This file is part of zsh, the Z shell.
5  *
6  * Copyright (c) 2015 Peter Stephenson
7  * All rights reserved.
8  *
9  * Permission is hereby granted, without written agreement and without
10  * license or royalty fees, to use, copy, modify, and distribute this
11  * software and to distribute modified versions of this software for any
12  * purpose, provided that the above copyright notice and the following
13  * two paragraphs appear in all copies of this software.
14  *
15  * In no event shall Peter Stephenson or the Zsh Development Group be liable
16  * to any party for direct, indirect, special, incidental, or consequential
17  * damages arising out of the use of this software and its documentation,
18  * even if Peter Stephenson and the Zsh Development Group have been advised of
19  * the possibility of such damage.
20  *
21  * Peter Stephenson and the Zsh Development Group specifically disclaim any
22  * warranties, including, but not limited to, the implied warranties of
23  * merchantability and fitness for a particular purpose.  The software
24  * provided hereunder is on an "as is" basis, and Peter Stephenson and the
25  * Zsh Development Group have no obligation to provide maintenance,
26  * support, updates, enhancements, or modifications.
27  *
28  */
29 /*
30  * This short file provides a home for the stack of saved contexts.
31  * The actions for saving and restoring are encapsulated within
32  * individual modules.
33  */
34 
35 #include "zsh.mdh"
36 #include "context.pro"
37 
38 struct context_stack {
39     struct context_stack *next;
40 
41     struct hist_stack hist_stack;
42     struct lex_stack lex_stack;
43     struct parse_stack parse_stack;
44 };
45 
46 static struct context_stack *cstack;
47 
48 /* save some or all of current context */
49 
50 /**/
51 mod_export void
zcontext_save_partial(int parts)52 zcontext_save_partial(int parts)
53 {
54     struct context_stack *cs;
55 
56     queue_signals();
57 
58     cs = (struct context_stack *)malloc(sizeof(struct context_stack));
59 
60     if (parts & ZCONTEXT_HIST) {
61 	hist_context_save(&cs->hist_stack, !cstack);
62     }
63     if (parts & ZCONTEXT_LEX) {
64 	lex_context_save(&cs->lex_stack, !cstack);
65     }
66     if (parts & ZCONTEXT_PARSE) {
67 	parse_context_save(&cs->parse_stack, !cstack);
68     }
69 
70     cs->next = cstack;
71     cstack = cs;
72 
73     unqueue_signals();
74 }
75 
76 /* save context in full */
77 
78 /**/
79 mod_export void
zcontext_save(void)80 zcontext_save(void)
81 {
82     zcontext_save_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
83 }
84 
85 /* restore context or part thereof */
86 
87 /**/
88 mod_export void
zcontext_restore_partial(int parts)89 zcontext_restore_partial(int parts)
90 {
91     struct context_stack *cs = cstack;
92 
93     DPUTS(!cstack, "BUG: zcontext_restore() without zcontext_save()");
94 
95     queue_signals();
96     cstack = cstack->next;
97 
98     if (parts & ZCONTEXT_HIST) {
99 	hist_context_restore(&cs->hist_stack, !cstack);
100     }
101     if (parts & ZCONTEXT_LEX) {
102 	lex_context_restore(&cs->lex_stack, !cstack);
103     }
104     if (parts & ZCONTEXT_PARSE) {
105 	parse_context_restore(&cs->parse_stack, !cstack);
106     }
107 
108     free(cs);
109 
110     unqueue_signals();
111 }
112 
113 /* restore full context */
114 
115 /**/
116 mod_export void
zcontext_restore(void)117 zcontext_restore(void)
118 {
119     zcontext_restore_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
120 }
121