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