Commit | Line | Data |
---|---|---|
9bf86ebb PR |
1 | /* Input handling for G++. |
2 | Copyright (C) 1992, 1993 Free Software Foundation, Inc. | |
3 | Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing. | |
4 | ||
5 | This file is part of GNU CC. | |
6 | ||
7 | GNU CC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU CC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU CC; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
21 | /* G++ needs to do enough saving and re-parsing of text that it is | |
22 | necessary to abandon the simple FILE* model and use a mechanism where | |
23 | we can pre-empt one input stream with another derived from saved text; | |
24 | we may need to do this arbitrarily often, and cannot depend on having | |
25 | the GNU library available, so FILE objects just don't cut it. | |
26 | ||
27 | This file is written as a separate module, but can be included by | |
28 | cp-lex.c for very minor efficiency gains (primarily in function | |
29 | inlining). */ | |
30 | ||
31 | #include <stdio.h> | |
32 | #include "obstack.h" | |
33 | ||
34 | extern FILE *finput; | |
35 | ||
36 | struct pending_input *save_pending_input (); | |
37 | void restore_pending_input (); | |
38 | ||
39 | struct input_source { | |
40 | /* saved string */ | |
41 | char *str; | |
42 | int length; | |
43 | /* current position, when reading as input */ | |
44 | int offset; | |
45 | /* obstack to free this input string from when finished, if any */ | |
46 | struct obstack *obstack; | |
47 | /* linked list maintenance */ | |
48 | struct input_source *next; | |
49 | /* values to restore after reading all of current string */ | |
50 | char *filename; | |
51 | int lineno; | |
52 | struct pending_input *input; | |
53 | int putback_char; | |
54 | }; | |
55 | ||
56 | static struct input_source *input, *free_inputs; | |
57 | ||
58 | extern char *input_filename; | |
59 | extern int lineno; | |
60 | ||
61 | #ifdef __GNUC__ | |
62 | #define inline __inline__ | |
63 | #else | |
64 | #define inline | |
65 | #endif | |
66 | ||
67 | static inline struct input_source * | |
68 | allocate_input () | |
69 | { | |
70 | struct input_source *inp; | |
71 | if (free_inputs) | |
72 | { | |
73 | inp = free_inputs; | |
74 | free_inputs = inp->next; | |
75 | inp->next = 0; | |
76 | return inp; | |
77 | } | |
78 | inp = (struct input_source *) xmalloc (sizeof (struct input_source)); | |
79 | inp->next = 0; | |
80 | inp->obstack = 0; | |
81 | return inp; | |
82 | } | |
83 | ||
84 | static inline void | |
85 | free_input (inp) | |
86 | struct input_source *inp; | |
87 | { | |
88 | if (inp->obstack) | |
89 | obstack_free (inp->obstack, inp->str); | |
90 | inp->obstack = 0; | |
91 | inp->str = 0; | |
92 | inp->length = 0; | |
93 | inp->next = free_inputs; | |
94 | free_inputs = inp; | |
95 | } | |
96 | ||
97 | static int putback_char = -1; | |
98 | ||
99 | /* Some of these external functions are declared inline in case this file | |
100 | is included in cp-lex.c. */ | |
101 | ||
102 | inline | |
103 | void | |
104 | feed_input (str, len, delete) | |
105 | char *str; | |
106 | int len; | |
107 | struct obstack *delete; | |
108 | { | |
109 | struct input_source *inp = allocate_input (); | |
110 | ||
111 | /* This shouldn't be necessary. */ | |
112 | while (len && !str[len-1]) | |
113 | len--; | |
114 | ||
115 | inp->str = str; | |
116 | inp->length = len; | |
117 | inp->obstack = delete; | |
118 | inp->offset = 0; | |
119 | inp->next = input; | |
120 | inp->filename = input_filename; | |
121 | inp->lineno = lineno; | |
122 | inp->input = save_pending_input (); | |
123 | inp->putback_char = putback_char; | |
124 | putback_char = -1; | |
125 | input = inp; | |
126 | } | |
127 | ||
128 | struct pending_input *to_be_restored; /* XXX */ | |
129 | extern int end_of_file; | |
130 | ||
131 | int | |
132 | getch () | |
133 | { | |
134 | if (putback_char != -1) | |
135 | { | |
136 | int ch = putback_char; | |
137 | putback_char = -1; | |
138 | return ch; | |
139 | } | |
140 | if (input) | |
141 | { | |
142 | if (input->offset == input->length) | |
143 | { | |
144 | struct input_source *inp = input; | |
145 | my_friendly_assert (putback_char == -1, 223); | |
146 | to_be_restored = inp->input; | |
147 | input->offset++; | |
148 | return EOF; | |
149 | } | |
150 | else if (input->offset > input->length) | |
151 | { | |
152 | struct input_source *inp = input; | |
153 | ||
154 | end_of_file = 0; | |
155 | input = inp->next; | |
156 | input_filename = inp->filename; | |
157 | lineno = inp->lineno; | |
158 | /* Get interface/implementation back in sync. */ | |
159 | extract_interface_info (); | |
160 | putback_char = inp->putback_char; | |
161 | free_input (inp); | |
162 | return getch (); | |
163 | } | |
164 | if (input) | |
165 | return input->str[input->offset++]; | |
166 | } | |
167 | return getc (finput); | |
168 | } | |
169 | ||
170 | inline | |
171 | void | |
172 | put_back (ch) | |
173 | int ch; | |
174 | { | |
175 | my_friendly_assert (putback_char == -1, 224); | |
176 | putback_char = ch; | |
177 | } | |
178 | ||
179 | inline | |
180 | int | |
181 | input_redirected () | |
182 | { | |
183 | return input != 0; | |
184 | } |