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