1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* istack.c */ |
4 | /* */ |
5 | /* Input stack for the scanner */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2000-2003 Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | /* common */ |
37 | #include "check.h" |
38 | #include "xmalloc.h" |
39 | |
40 | /* ca65 */ |
41 | #include "error.h" |
42 | #include "istack.h" |
43 | |
44 | |
45 | |
46 | /*****************************************************************************/ |
47 | /* Data */ |
48 | /*****************************************************************************/ |
49 | |
50 | |
51 | |
52 | /* Size of the stack (== maximum nested macro or repeat count) */ |
53 | #define ISTACK_MAX 256 |
54 | |
55 | /* Structure holding a stack element */ |
56 | typedef struct IElement IElement; |
57 | struct IElement { |
58 | IElement* Next; /* Next stack element */ |
59 | int (*Func)(void*); /* Function called for input */ |
60 | void* Data; /* User data given as argument */ |
61 | const char* Desc; /* Description */ |
62 | }; |
63 | |
64 | /* The stack */ |
65 | static IElement* IStack = 0; /* Input stack pointer */ |
66 | static unsigned ICount = 0; /* Number of items on the stack */ |
67 | |
68 | |
69 | |
70 | /*****************************************************************************/ |
71 | /* Code */ |
72 | /*****************************************************************************/ |
73 | |
74 | |
75 | |
76 | void PushInput (int (*Func) (void*), void* Data, const char* Desc) |
77 | /* Push an input function onto the input stack */ |
78 | { |
79 | IElement* E; |
80 | |
81 | /* Check for a stack overflow */ |
82 | if (ICount > ISTACK_MAX) { |
83 | Fatal ("Maximum input stack nesting exceeded" ); |
84 | } |
85 | |
86 | /* Create a new stack element */ |
87 | E = xmalloc (sizeof (*E)); |
88 | |
89 | /* Initialize it */ |
90 | E->Func = Func; |
91 | E->Data = Data; |
92 | E->Desc = Desc; |
93 | |
94 | /* Push it */ |
95 | E->Next = IStack; |
96 | IStack = E; |
97 | } |
98 | |
99 | |
100 | |
101 | void PopInput (void) |
102 | /* Pop the current input function from the input stack */ |
103 | { |
104 | IElement* E; |
105 | |
106 | /* We cannot pop from an empty stack */ |
107 | PRECONDITION (IStack != 0); |
108 | |
109 | /* Remember the last element */ |
110 | E = IStack; |
111 | |
112 | /* Pop it */ |
113 | IStack = IStack->Next; |
114 | |
115 | /* And delete it */ |
116 | xfree (E); |
117 | } |
118 | |
119 | |
120 | |
121 | int InputFromStack (void) |
122 | /* Try to get input from the input stack. Return true if we had such input, |
123 | ** return false otherwise. |
124 | */ |
125 | { |
126 | /* Repeatedly call the TOS routine until we have a token or if run out of |
127 | ** routines. |
128 | */ |
129 | while (IStack) { |
130 | if (IStack->Func (IStack->Data) != 0) { |
131 | /* We have a token */ |
132 | return 1; |
133 | } |
134 | } |
135 | |
136 | /* Nothing is on the stack */ |
137 | return 0; |
138 | } |
139 | |
140 | |
141 | |
142 | int HavePushedInput (void) |
143 | /* Return true if we have stacked input available, return false if not */ |
144 | { |
145 | return (IStack != 0); |
146 | } |
147 | |
148 | |
149 | |
150 | void CheckInputStack (void) |
151 | /* Called from the scanner before closing an input file. Will check for any |
152 | ** stuff on the input stack. |
153 | */ |
154 | { |
155 | if (IStack) { |
156 | Error ("Open %s" , IStack->Desc); |
157 | } |
158 | } |
159 | |