forked from parrot/parrot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rxstacks.c
124 lines (104 loc) · 3.16 KB
/
rxstacks.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* rxstacks.c
* Copyright: (When this is determined...it will go here)
* CVS Info
* $Id$
* Overview:
* Regex stack handling routines for Parrot
* Data Structure and Algorithms:
* Same as regular stacks, except they store only INTVALs and don't have
* cleanup routines.
* History:
* Notes:
* References: */
#include "parrot/parrot.h"
#include "parrot/rxstacks.h"
IntStack
intstack_new(struct Parrot_Interp *interpreter)
{
IntStack stack = mem_sys_allocate(sizeof(struct IntStack_chunk_t));
stack->used = 0;
stack->next = stack;
stack->prev = stack;
return stack;
}
INTVAL
intstack_depth(struct Parrot_Interp *interpreter, IntStack stack)
{
IntStack_Chunk chunk;
INTVAL depth = stack->used;
for (chunk = stack->next; chunk != stack; chunk = chunk->next)
depth += chunk->used;
return depth;
}
void
intstack_push(struct Parrot_Interp *interpreter, IntStack stack, INTVAL data)
{
IntStack_Chunk chunk = stack->prev;
IntStack_Entry entry = &chunk->entry[chunk->used];
entry->value = data;
/* Register the new entry */
if (++chunk->used == STACK_CHUNK_DEPTH) {
if (chunk->next == stack) {
/* Need to add a new chunk */
IntStack_Chunk new_chunk = mem_sys_allocate(sizeof(*new_chunk));
new_chunk->used = 0;
new_chunk->next = stack;
new_chunk->prev = chunk;
chunk->next = new_chunk;
stack->prev = new_chunk;
}
else {
/* Reuse the spare chunk we kept */
chunk = chunk->next;
stack->prev = chunk;
}
}
}
INTVAL
intstack_pop(struct Parrot_Interp *interpreter, IntStack stack)
{
IntStack_Chunk chunk = stack->prev;
IntStack_Entry entry;
/* We may have an empty chunk at the end of the list */
if (chunk->used == 0 && chunk != stack) {
/* That chunk != stack check is just to allow the empty stack case
* to fall through to the following exception throwing code. */
/* If the chunk that has just become empty is not the last chunk
* on the stack then we make it the last chunk - the GC will clean
* up any chunks that are discarded by this operation. */
if (chunk->next != stack) {
chunk->next = stack;
}
/* Now back to the previous chunk - we'll keep the one we have
* just emptied around for now in case we need it again. */
chunk = chunk->prev;
stack->prev = chunk;
}
/* Quick sanity check */
if (chunk->used == 0) {
internal_exception(ERROR_STACK_EMPTY, "No entries on stack!\n");
}
entry = &chunk->entry[chunk->used - 1];
/* Now decrement the SP */
chunk->used--;
/* Snag the value */
return entry->value;
}
void intstack_free (struct Parrot_Interp *interpreter, IntStack stack)
{
IntStack chunk, temp;
for (chunk = stack->next; chunk != stack; chunk = temp) {
temp = chunk->next;
mem_sys_free(chunk);
}
mem_sys_free(stack);
}
/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/