1 /*
2 Copyright (c) 1997-2021, John M. Boyer
3 All rights reserved.
4 See the LICENSE.TXT file for licensing information.
5 */
6
7 #include "appconst.h"
8 #include "stack.h"
9 #include <stdlib.h>
10
sp_New(int capacity)11 stackP sp_New(int capacity)
12 {
13 stackP theStack;
14
15 theStack = (stackP) malloc(sizeof(stack));
16
17 if (theStack != NULL)
18 {
19 theStack->S = (int *) malloc(capacity*sizeof(int));
20 if (theStack->S == NULL)
21 {
22 free(theStack);
23 theStack = NULL;
24 }
25 }
26
27 if (theStack != NULL)
28 {
29 theStack->capacity = capacity;
30 sp_ClearStack(theStack);
31 }
32
33 return theStack;
34 }
35
sp_Free(stackP * pStack)36 void sp_Free(stackP *pStack)
37 {
38 if (pStack == NULL || *pStack == NULL) return;
39
40 (*pStack)->capacity = (*pStack)->size = 0;
41
42 if ((*pStack)->S != NULL)
43 free((*pStack)->S);
44 (*pStack)->S = NULL;
45 free(*pStack);
46
47 *pStack = NULL;
48 }
49
sp_CopyContent(stackP stackDst,stackP stackSrc)50 int sp_CopyContent(stackP stackDst, stackP stackSrc)
51 {
52 if (stackDst->capacity < stackSrc->size)
53 return NOTOK;
54
55 if (stackSrc->size > 0)
56 memcpy(stackDst->S, stackSrc->S, stackSrc->size*sizeof(int));
57
58 stackDst->size = stackSrc->size;
59 return OK;
60 }
61
sp_Duplicate(stackP theStack)62 stackP sp_Duplicate(stackP theStack)
63 {
64 stackP newStack = sp_New(theStack->capacity);
65
66 if (newStack == NULL)
67 return NULL;
68
69 if (theStack->size > 0)
70 {
71 memcpy(newStack->S, theStack->S, theStack->size*sizeof(int));
72 newStack->size = theStack->size;
73 }
74
75 return newStack;
76 }
77
sp_Copy(stackP stackDst,stackP stackSrc)78 int sp_Copy(stackP stackDst, stackP stackSrc)
79 {
80 if (sp_CopyContent(stackDst, stackSrc) != OK)
81 {
82 stackP newStack = sp_Duplicate(stackSrc);
83 int *p;
84
85 if (newStack == NULL)
86 return NOTOK;
87
88 p = stackDst->S;
89 stackDst->S = newStack->S;
90 newStack->S = p;
91 newStack->capacity = stackDst->capacity;
92 sp_Free(&newStack);
93
94 stackDst->size = stackSrc->size;
95 stackDst->capacity = stackSrc->capacity;
96 }
97
98 return OK;
99 }
100
101 #ifndef SPEED_MACROS
102
sp_ClearStack(stackP theStack)103 int sp_ClearStack(stackP theStack)
104 {
105 theStack->size = 0;
106 return OK;
107 }
108
sp_GetCurrentSize(stackP theStack)109 int sp_GetCurrentSize(stackP theStack)
110 {
111 return theStack->size;
112 }
113
sp_SetCurrentSize(stackP theStack,int size)114 int sp_SetCurrentSize(stackP theStack, int size)
115 {
116 return size > theStack->capacity ? NOTOK : (theStack->size = size, OK);
117 }
118
sp_IsEmpty(stackP theStack)119 int sp_IsEmpty(stackP theStack)
120 {
121 return !theStack->size;
122 }
123
sp_NonEmpty(stackP theStack)124 int sp_NonEmpty(stackP theStack)
125 {
126 return theStack->size;
127 }
128
sp__Push(stackP theStack,int a)129 int sp__Push(stackP theStack, int a)
130 {
131 if (theStack->size >= theStack->capacity)
132 return NOTOK;
133
134 theStack->S[theStack->size++] = a;
135 return OK;
136 }
137
sp__Push2(stackP theStack,int a,int b)138 int sp__Push2(stackP theStack, int a, int b)
139 {
140 if (theStack->size + 1 >= theStack->capacity)
141 return NOTOK;
142
143 theStack->S[theStack->size++] = a;
144 theStack->S[theStack->size++] = b;
145 return OK;
146 }
147
sp__Pop(stackP theStack,int * pA)148 int sp__Pop(stackP theStack, int *pA)
149 {
150 if (theStack->size <= 0)
151 return NOTOK;
152
153 *pA = theStack->S[--theStack->size];
154 return OK;
155 }
156
sp__Pop_Discard(stackP theStack)157 int sp__Pop_Discard(stackP theStack)
158 {
159 if (theStack->size <= 0)
160 return NOTOK;
161
162 --theStack->size;
163 return OK;
164 }
165
sp__Pop2(stackP theStack,int * pA,int * pB)166 int sp__Pop2(stackP theStack, int *pA, int *pB)
167 {
168 if (theStack->size <= 1)
169 return NOTOK;
170
171 *pB = theStack->S[--theStack->size];
172 *pA = theStack->S[--theStack->size];
173
174 return OK;
175 }
176
sp__Pop2_Discard1(stackP theStack,int * pA)177 int sp__Pop2_Discard1(stackP theStack, int *pA)
178 {
179 if (theStack->size <= 1)
180 return NOTOK;
181
182 // When a pair of the form (main, secondary) are pushed in order,
183 // it is sometimes necessary to pop the secondary and discard,
184 // then pop and store the main datum.
185 --theStack->size;
186 *pA = theStack->S[--theStack->size];
187
188 return OK;
189 }
190
sp__Pop2_Discard(stackP theStack)191 int sp__Pop2_Discard(stackP theStack)
192 {
193 if (theStack->size <= 1)
194 return NOTOK;
195
196 --theStack->size;
197 --theStack->size;
198
199 return OK;
200 }
201
sp_Top(stackP theStack)202 int sp_Top(stackP theStack)
203 {
204 return theStack->size ? theStack->S[theStack->size-1] : NIL;
205 }
206
sp_Get(stackP theStack,int pos)207 int sp_Get(stackP theStack, int pos)
208 {
209 if (theStack == NULL || pos < 0 || pos >= theStack->size)
210 return NOTOK;
211
212 return (theStack->S[pos]);
213 }
214
sp_Set(stackP theStack,int pos,int val)215 int sp_Set(stackP theStack, int pos, int val)
216 {
217 if (theStack == NULL || pos < 0 || pos >= theStack->size)
218 return NOTOK;
219
220 return (theStack->S[pos] = val);
221 }
222
223 #endif // not defined SPEED_MACROS
224