c82fc8f417d7ec539b2a3ba46a50ec989ee3accc
[gcc.git] / gcc / cp / input.c
1 /* Input handling for G++.
2 Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000
3 Free Software Foundation, Inc.
4 Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
5 Enhanced by Michael Tiemann (tiemann@cygnus.com) to better support USE_CPPLIB
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 /* G++ needs to do enough saving and re-parsing of text that it is
25 necessary to abandon the simple FILE* model and use a mechanism where
26 we can pre-empt one input stream with another derived from saved text;
27 we may need to do this arbitrarily often, and cannot depend on having
28 the GNU library available, so FILE objects just don't cut it.
29
30 This file is written as a separate module, but can be included by
31 lex.c for very minor efficiency gains (primarily in function
32 inlining). */
33
34 #include "system.h"
35
36 #if !USE_CPPLIB
37 struct putback_buffer {
38 char *buffer;
39 int buffer_size;
40 int index;
41 };
42
43 static struct putback_buffer putback = {NULL, 0, -1};
44 #endif
45
46 struct input_source {
47 /* saved string */
48 char *str;
49 int length;
50 /* current position, when reading as input */
51 int offset;
52 /* linked list maintenance */
53 struct input_source *next;
54 /* values to restore after reading all of current string */
55 struct pending_input *input;
56 #if !USE_CPPLIB
57 char *filename;
58 int lineno;
59 struct putback_buffer putback;
60 #endif
61 };
62
63 static struct input_source *input, *free_inputs;
64
65 extern char *input_filename;
66 extern int lineno;
67
68 #if USE_CPPLIB
69 extern unsigned char *yy_cur, *yy_lim;
70 extern int yy_get_token ();
71 #endif
72
73 extern void feed_input PARAMS ((char *, int, char *, int));
74 extern void put_input PARAMS ((int));
75 extern void put_back PARAMS ((int));
76 extern int getch PARAMS ((void));
77 extern int input_redirected PARAMS ((void));
78
79 static inline struct input_source * allocate_input PARAMS ((void));
80 static inline void free_input PARAMS ((struct input_source *));
81 static inline void end_input PARAMS ((void));
82
83 static inline struct input_source *
84 allocate_input ()
85 {
86 struct input_source *inp;
87 if (free_inputs)
88 {
89 inp = free_inputs;
90 free_inputs = inp->next;
91 inp->next = 0;
92 return inp;
93 }
94 inp = (struct input_source *) xmalloc (sizeof (struct input_source));
95 inp->next = 0;
96 return inp;
97 }
98
99 static inline void
100 free_input (inp)
101 struct input_source *inp;
102 {
103 inp->str = 0;
104 inp->length = 0;
105 inp->next = free_inputs;
106 free_inputs = inp;
107 }
108
109 /* Some of these external functions are declared inline in case this file
110 is included in lex.c. */
111
112 inline
113 void
114 feed_input (str, len, file, line)
115 char *str;
116 int len;
117 char *file;
118 int line;
119 {
120 struct input_source *inp = allocate_input ();
121
122 /* This shouldn't be necessary. */
123 while (len && !str[len-1])
124 len--;
125
126 #if USE_CPPLIB
127 if (yy_lim > yy_cur)
128 /* If we've started reading the next token, we're hosed. The
129 token_getch stuff is supposed to prevent this from happening. */
130 my_friendly_abort (990710);
131 cpp_push_buffer (&parse_in, str, len);
132 CPP_BUFFER (&parse_in)->manual_pop = 1;
133 CPP_BUFFER (&parse_in)->nominal_fname
134 = CPP_BUFFER (&parse_in)->fname = file;
135 CPP_BUFFER (&parse_in)->lineno = parse_in.lineno = line;
136 #else
137 inp->str = str;
138 inp->length = len;
139 inp->offset = 0;
140 inp->putback = putback;
141 inp->filename = input_filename;
142 inp->lineno = lineno;
143 putback.buffer = NULL;
144 putback.buffer_size = 0;
145 putback.index = -1;
146 #endif
147 inp->next = input;
148 inp->input = save_pending_input ();
149 input = inp;
150 lineno = line;
151 input_filename = file;
152 }
153
154 extern int end_of_file;
155
156 static inline void
157 end_input ()
158 {
159 struct input_source *inp = input;
160
161 #if USE_CPPLIB
162 cpp_pop_buffer (&parse_in);
163 #else
164 putback = inp->putback;
165 input_filename = inp->filename;
166 lineno = inp->lineno;
167 #endif
168
169 end_of_file = 0;
170 input = inp->next;
171 /* Get interface/implementation back in sync. */
172 extract_interface_info ();
173 restore_pending_input (inp->input);
174 free_input (inp);
175 }
176
177 inline int
178 getch ()
179 {
180 #if USE_CPPLIB
181 return (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ());
182 #else
183 if (putback.index != -1)
184 {
185 int ch = putback.buffer[putback.index];
186 --putback.index;
187 return ch;
188 }
189 if (input)
190 {
191 if (input->offset >= input->length)
192 {
193 my_friendly_assert (putback.index == -1, 223);
194 ++(input->offset);
195 if (input->offset - input->length < 64)
196 return EOF;
197
198 /* We must be stuck in an error-handling rule; give up. */
199 end_input ();
200 return getch ();
201 }
202 return (unsigned char)input->str[input->offset++];
203 }
204 return getc (finput);
205 #endif
206 }
207
208 inline
209 void
210 put_back (ch)
211 int ch;
212 {
213 #if USE_CPPLIB
214 if (ch == EOF)
215 ;
216 else if (yy_cur[-1] != ch)
217 my_friendly_abort (990709);
218 else
219 yy_cur--;
220 #else
221 if (ch != EOF)
222 {
223 if (putback.index == putback.buffer_size - 1)
224 {
225 putback.buffer_size += 16;
226 putback.buffer = xrealloc (putback.buffer, putback.buffer_size);
227 }
228 my_friendly_assert (putback.buffer != NULL, 224);
229 putback.buffer[++putback.index] = ch;
230 }
231 #endif
232 }
233
234 inline
235 int
236 input_redirected ()
237 {
238 #ifdef USE_CPPLIB
239 return CPP_BUFFER(&parse_in)->manual_pop;
240 #else
241 return input != 0;
242 #endif
243 }