Add xscale-elf and xscale-coff targets. (Only supported in binutils at the
[official-gcc.git] / libio / parsestream.cc
blob711733221b5e67024d6a8a374a4afe283fbf1f3d
1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
2 Copyright (C) 1993 Free Software Foundation
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License.
25 Written by Per Bothner (bothner@cygnus.com). */
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30 #include "libioP.h"
31 #include "parsestream.h"
32 #include <stdlib.h>
33 #include <string.h>
35 streambuf* parsebuf::setbuf(char*, int)
37 return NULL;
40 int parsebuf::tell_in_line()
42 return 0;
45 int parsebuf::pbackfail(int c)
47 if (c == EOF)
48 return 0;
49 if (seekoff(-1, ios::cur) == EOF)
50 return EOF;
51 return (unsigned char)c;
54 char* parsebuf::current_line() { return NULL; }
56 streampos parsebuf::seekoff(streamoff offset, _seek_dir dir, int)
58 // Make offset relative to line start.
59 switch (dir) {
60 case ios::beg:
61 offset -= pos_at_line_start;
62 break;
63 case ios::cur:
64 offset += tell_in_line();
65 break;
66 default:
67 return EOF;
69 if (offset < -1)
70 return EOF;
71 if (offset > _line_length + 1)
72 return EOF;
73 return seek_in_line(offset) + pos_at_line_start;
76 // string_parsebuf invariants:
77 // The reserve ares (base() .. ebuf()) is always the entire string.
78 // The get area (eback() .. egptr()) is the extended current line
79 // (i.e. with the '\n' at either end, if these exist).
81 string_parsebuf::string_parsebuf(char *buf, int len,
82 int delete_at_close /* = 0*/)
83 : parsebuf()
85 setb(buf, buf+len, delete_at_close);
86 register char *ptr = buf;
87 while (ptr < ebuf() && *ptr != '\n') ptr++;
88 _line_length = ptr - buf;
89 setg(buf, buf, ptr);
92 int string_parsebuf::underflow()
94 register char* ptr = egptr(); // Point to end of current_line
95 do {
96 int i = right() - ptr;
97 if (i <= 0)
98 return EOF;
99 ptr++; i--; // Skip '\n'.
100 char *line_start = ptr;
101 while (ptr < right() && *ptr == '\n') ptr++;
102 setg(line_start-1, line_start, ptr + (ptr < right()));
103 pos_at_line_start = line_start - left();
104 _line_length = ptr - line_start;
105 __line_number++;
106 } while (gptr() == ptr);
107 return *gptr();
110 char* string_parsebuf::current_line()
112 char *ptr = eback();
113 if (__line_number > 0)
114 ptr++; // Skip '\n' at end of previous line.
115 return ptr;
118 int string_parsebuf::tell_in_line()
120 int offset = gptr() - eback();
121 if (__line_number > 0)
122 offset--;
123 return offset;
126 int string_parsebuf::seek_in_line(int i)
128 int delta = i - tell_in_line();
129 gbump(delta); // FIXME: Needs error (bounds) checking!
130 return i;
133 static const char NewLine[1] = { '\n' };
135 general_parsebuf::general_parsebuf(streambuf *buf, int delete_arg_buf)
136 : parsebuf()
138 delete_buf = delete_arg_buf;
139 sbuf = buf;
140 int buf_size = 128;
141 char* buffer = (char*)malloc(buf_size);
142 setb(buffer, buffer+buf_size, 1);
143 // setg(buffer, buffer, buffer);
146 general_parsebuf::~general_parsebuf()
148 if (delete_buf)
149 delete sbuf;
152 int general_parsebuf::underflow()
154 register char *ptr = base();
155 int has_newline = eback() < gptr() && gptr()[-1] == '\n';
156 if (has_newline)
157 *ptr++ = '\n';
158 register streambuf *sb = sbuf;
159 register int ch;
160 for (;;) {
161 ch = sb->sbumpc();
162 if (ch == EOF)
163 break;
164 if (ptr == ebuf()) {
165 int old_size = ebuf() - base();
166 char *new_buffer = new char[old_size * 2];
167 memcpy(new_buffer, base(), old_size);
168 setb(new_buffer, new_buffer + 2 * old_size, 1);
169 ptr = new_buffer + old_size;
171 *ptr++ = ch;
172 if (ch == '\n')
173 break;
175 char *cur_pos = base() + has_newline;
176 pos_at_line_start += _line_length + 1;
177 _line_length = ptr - cur_pos;
178 if (ch != EOF || _line_length > 0)
179 __line_number++;
180 setg(base(), cur_pos, ptr);
181 return ptr == cur_pos ? EOF : cur_pos[0];
184 char* general_parsebuf::current_line()
186 char* ret = base();
187 if (__line_number > 1)
188 ret++; // Move past '\n' from end of previous line.
189 return ret;
192 int general_parsebuf::tell_in_line()
194 int off = gptr() - base();
195 if (__line_number > 1)
196 off--; // Subtract 1 for '\n' from end of previous line.
197 return off;
200 int general_parsebuf::seek_in_line(int i)
202 if (__line_number == 0)
203 (void)general_parsebuf::underflow();
204 if (__line_number > 1)
205 i++; // Add 1 for '\n' from end of previous line.
206 if (i < 0) i = 0;
207 int len = egptr() - eback();
208 if (i > len) i = len;
209 setg(base(), base() + i, egptr());
210 return i;
213 func_parsebuf::func_parsebuf(CharReader func, void *argm) : parsebuf()
215 read_func = func;
216 arg = argm;
217 buf_start = NULL;
218 buf_end = NULL;
219 setb((char*)NewLine, (char*)NewLine+1, 0);
220 setg((char*)NewLine, (char*)NewLine+1, (char*)NewLine+1);
221 backed_up_to_newline = 0;
224 int func_parsebuf::tell_in_line()
226 if (buf_start == NULL)
227 return 0;
228 if (egptr() != (char*)NewLine+1)
229 // Get buffer was line buffer.
230 return gptr() - buf_start;
231 if (backed_up_to_newline)
232 return -1; // Get buffer is '\n' preceding current line.
233 // Get buffer is '\n' following current line.
234 return (buf_end - buf_start) + (gptr() - (char*)NewLine);
237 char* func_parsebuf::current_line()
239 return buf_start;
242 int func_parsebuf::seek_in_line(int i)
244 if (i < 0) {
245 // Back up to preceding '\n'.
246 if (i < -1) i = -1;
247 backed_up_to_newline = 1;
248 setg((char*)NewLine, (char*)NewLine+(i+1), (char*)NewLine+1);
249 return i;
251 backed_up_to_newline = 0;
252 int line_length = buf_end-buf_start;
253 if (i <= line_length) {
254 setg(buf_start, buf_start+i, buf_end);
255 return i;
257 i -= line_length;
258 if (i > 0) i = 1;
259 setg((char*)NewLine, (char*)NewLine+i, (char*)NewLine+1);
260 return line_length + i;
263 int func_parsebuf::underflow()
265 retry:
266 if (gptr() < egptr())
267 return *gptr();
268 if (gptr() != (char*)NewLine+1) {
269 // Get buffer was line buffer. Move to following '\n'.
270 setg((char*)NewLine, (char*)NewLine, (char*)NewLine+1);
271 return *gptr();
273 if (backed_up_to_newline)
274 // Get buffer was '\n' preceding current line. Move to current line.
275 backed_up_to_newline = 0;
276 else {
277 // Get buffer was '\n' following current line. Read new line.
278 if (buf_start) free(buf_start);
279 char *str = (*read_func)(arg);
280 buf_start = str;
281 if (str == NULL)
282 return EOF;
283 // Initially, _line_length == -1, so pos_at_line_start becomes 0.
284 pos_at_line_start += _line_length + 1;
285 _line_length = strlen(str);
286 buf_end = str + _line_length;
287 __line_number++;
289 setg(buf_start, buf_start, buf_end);
290 goto retry;
293 #if 0
294 size_t parsebuf::line_length()
296 if (current_line_length == (size_t)(-1)) // Initial value;
297 (void)sgetc();
298 return current_line_length;
300 #endif
302 int parsebuf::seek_in_line(int i)
304 #if 1
305 abort();
306 return i; // Suppress warnings.
307 #else
308 if (i > 0) {
309 size_t len = line_length();
310 if ((unsigned)i > len) i = len;
312 else if (i < -1) i = -1;
313 int new_pos = seekoff(pos_at_line_start + i, ios::beg);
314 if (new_pos == EOF)
315 return tell_in_line();
316 else return new_pos - pos_at_line_start;
317 #endif