This repository has been archived by the owner on Oct 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathframe.c
110 lines (81 loc) · 2.33 KB
/
frame.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "frame.h"
#define G_VALUE_UPDATE(source, dest) {\
GValue *src = source, *dst = dest;\
g_value_unset (src);\
g_value_init (src, G_VALUE_TYPE(src));\
g_value_copy (src, dest);\
}
struct _Frame {
Frame *parent;
GHashTable *symbols;
};
Frame *frame_new (Frame *parent)
{
Frame *ret;
ret = g_new0 (Frame, 1);
ret->parent = parent;
ret->symbols = g_hash_table_new (g_str_hash, g_str_equal);
return ret;
}
/* creates a local instance of value */
void frame_set_local(Frame *frame, gchar *name, GValue *value)
{
GValue *stored;
/* check whether the key exists, if so overwrite previous GValue */
/* TODO: freelists? */
if ((stored = g_hash_table_lookup (frame->symbols, name))) {
g_value_unset (stored);
} else {
stored = g_new0 (GValue, 1);
g_hash_table_insert (frame->symbols, name, stored);
}
g_value_init (stored, G_VALUE_TYPE (value));
g_value_copy (value, stored);
}
/* updates the symbol in the inner-most frame in which it is defined. If the
* symbol is defined in the current scope, the effect is the same as calling
* frame_set_local. Has no effect if the frame is undefined. */
gboolean frame_update (Frame *frame, gchar *name, GValue *value)
{
GValue *stored;
if (!frame)
return FALSE;
if ((stored = frame_get_local (frame, name))) {
G_VALUE_UPDATE (stored, value);
return TRUE;
}
return frame_update (frame->parent, name, value);
}
/* recursive search of parent frames for value */
GValue *frame_get_value(Frame *frame, gchar *name)
{
GValue *stored = NULL;
if (!frame) {
return NULL;
}
if ((stored = frame_get_local(frame, name)))
return stored;
return frame_get_value (frame->parent, name);
}
/* returns local copy of value or NULL */
GValue *frame_get_local (Frame *frame, gchar *name)
{
GValue *stored = NULL;
return g_hash_table_lookup (frame->symbols, name);
}
static void print_entry (gchar *key, GValue *value, void *unused) {
GValue v = { 0 };
g_value_init (&v, G_TYPE_STRING);
g_value_transform (value, &v);
g_printf (" %s = %s\n", key, g_value_get_string (&v));
g_value_unset (&v);
}
void frame_dump_stack (Frame *frame)
{
if (frame->parent) {
frame_dump_stack (frame->parent);
g_printf ("\n");
}
g_printf ("<frame at %p>\n", frame);
g_hash_table_foreach (frame->symbols, (GHFunc) print_entry, NULL);
}