1 /*** stack.c ******************************************************************
2 **
3 ** This file is part of BibTool.
4 ** It is distributed under the GNU General Public License.
5 ** See the file COPYING for details.
6 **
7 ** (c) 1996-2020 Gerd Neugebauer
8 **
9 ** Net: gene@gerd-neugebauer.de
10 **
11 ** This program is free software; you can redistribute it and/or modify
12 ** it under the terms of the GNU General Public License as published by
13 ** the Free Software Foundation; either version 2, or (at your option)
14 ** any later version.
15 **
16 ** This program is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ** GNU General Public License for more details.
20 **
21 ** You should have received a copy of the GNU General Public License
22 ** along with this program; if not, write to the Free Software
23 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 **
25 **-----------------------------------------------------------------------------
26 ** Description:
27 ** This module provides a single stack of strings. There are two
28 ** operations on this stack, namely to push a string onto the
29 ** stack and a pop operation to get the topmost element from the
30 ** stack and remove it or to get a signal that the stack is
31 ** empty.
32 **
33 ** The stack is implemented as an array which grows on demand.
34 ** Currently the memory of the stack is not returned to the
35 ** operating system. This seems to be not problemeatic since this
36 ** memory is not assumed to be really large. Normally just a few
37 ** strings are pushed to the stack at any time.
38 **
39 ******************************************************************************/
40
41 #include <bibtool/general.h>
42 #include <bibtool/error.h>
43 #include <bibtool/stack.h>
44
45 /*****************************************************************************/
46 /* Internal Programs */
47 /*===========================================================================*/
48
49 #ifdef __STDC__
50 #define _ARG(A) A
51 #else
52 #define _ARG(A) ()
53 #endif
54 Symbol pop_string _ARG((void)); /* stack.c */
55 void push_string _ARG((Symbol s)); /* stack.c */
56
57 /*****************************************************************************/
58 /* External Programs */
59 /*===========================================================================*/
60
61 /*---------------------------------------------------------------------------*/
62
63 static Symbol *stack;
64 static size_t stack_size = 0;
65 static size_t stack_ptr = 0;
66
67 /*-----------------------------------------------------------------------------
68 ** Function: push_string()
69 ** Purpose: Push a string onto the stack. Only the memory for the
70 ** stack is allocated. The string is stored as pointer to
71 ** existing memory. No copy of the string is made.
72 **
73 ** If no memory is left then an error is raised and the program
74 ** is terminated.
75 ** Arguments:
76 ** s String to push to the stack.
77 ** Returns: nothing
78 **___________________________________________________ */
push_string(s)79 void push_string(s) /* */
80 register Symbol s; /* */
81 { /* */
82 if ( stack_ptr >= stack_size ) /* */
83 { stack_size += 16; /* */
84 stack = (stack_ptr == 0 /* */
85 ?(Symbol*)malloc((size_t)(stack_size*sizeof(Symbol)))/* */
86 :(Symbol*)realloc((char*)stack, /* */
87 (size_t)(stack_size*sizeof(Symbol))));/* */
88 if ( stack == NULL ) /* */
89 { OUT_OF_MEMORY("stack"); } /* */
90 } /* */
91 DebugPrint2("pushing ", SymbolValue(s)); /* */
92 stack[stack_ptr++] = s; /* */
93 } /*------------------------*/
94
95 /*-----------------------------------------------------------------------------
96 ** Function: pop_string()
97 ** Purpose: Pop a string from the stack. It the stack is empty
98 ** then |NULL| is returned. Thus the |NULL| value should
99 ** not be pushed to the stack since this can be confused
100 ** with the end of the stack.
101 ** Arguments: none
102 ** Returns: The old top element or |NULL| if the stack is empty.
103 **___________________________________________________ */
pop_string()104 Symbol pop_string() /* */
105 { /* */
106 if ( stack_ptr <= 0 ) return NO_SYMBOL; /* */
107 /* */
108 DebugPrint2("poping ", /* */
109 SymbolValue(stack[stack_ptr-1])); /* */
110 return stack[--stack_ptr]; /* */
111 } /*------------------------*/
112