diff options
Diffstat (limited to 'gnu/lib/libg++/iostream/editbuf.C')
-rw-r--r-- | gnu/lib/libg++/iostream/editbuf.C | 707 |
1 files changed, 0 insertions, 707 deletions
diff --git a/gnu/lib/libg++/iostream/editbuf.C b/gnu/lib/libg++/iostream/editbuf.C deleted file mode 100644 index 3d99e8442d1..00000000000 --- a/gnu/lib/libg++/iostream/editbuf.C +++ /dev/null @@ -1,707 +0,0 @@ -// This is part of the iostream library, providing input/output for C++. -// Copyright (C) 1991 Per Bothner. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Library General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Library General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the Free -// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -#ifdef __GNUG__ -#pragma implementation -#endif -#include "ioprivate.h" -#include "editbuf.h" -#include <stddef.h> - -/* NOTE: Some of the code here is taken from GNU emacs */ -/* Hence this file falls under the GNU License! */ - -// Invariants for edit_streambuf: -// An edit_streambuf is associated with a specific edit_string, -// which again is a sub-string of a specific edit_buffer. -// An edit_streambuf is always in either get mode or put mode, never both. -// In get mode, gptr() is the current position, -// and pbase(), pptr(), and epptr() are all NULL. -// In put mode, pptr() is the current position, -// and eback(), gptr(), and egptr() are all NULL. -// Any edit_streambuf that is actively doing insertion (as opposed to -// replacing) // must have its pptr() pointing to the start of the gap. -// Only one edit_streambuf can be actively inserting into a specific -// edit_buffer; the edit_buffer's _writer field points to that edit_streambuf. -// That edit_streambuf "owns" the gap, and the actual start of the -// gap is the pptr() of the edit_streambuf; the edit_buffer::_gap_start pointer -// will only be updated on an edit_streambuf::overflow(). - -int edit_streambuf::truncate() -{ - str->buffer->delete_range(str->buffer->tell((buf_char*)pptr()), - str->buffer->tell(str->end)); - return 0; -} - -#ifdef OLD_STDIO -inline void disconnect_gap_from_file(edit_buffer* buffer, FILE* fp) -{ - if (buffer->gap_start_ptr != &fp->__bufp) - return; - buffer->gap_start_normal = fp->__bufp; - buffer->gap_start_ptr = &buffer->gap_start_normal; -} -#endif - -void edit_streambuf::flush_to_buffer(edit_buffer* buffer) -{ - if (pptr() > buffer->_gap_start && pptr() < buffer->gap_end()) - buffer->_gap_start = pptr(); -} - -void edit_streambuf::disconnect_gap_from_file(edit_buffer* buffer) -{ - if (buffer->_writer != this) return; - flush_to_buffer(buffer); - setp(pptr(),pptr()); - buffer->_writer = NULL; -} - -buf_index edit_buffer::tell(buf_char *ptr) -{ - if (ptr <= gap_start()) - return ptr - data; - else - return ptr - gap_end() + size1(); -} - -#if 0 -buf_index buf_cookie::tell() -{ - return str->buffer->tell(file->__bufp); -} -#endif - -buf_index edit_buffer::tell(edit_mark*mark) -{ - return tell(data + mark->index_in_buffer(this)); -} - -// adjust the position of the gap - -void edit_buffer::move_gap(buf_offset pos) -{ - if (pos < size1()) - gap_left (pos); - else if (pos > size1()) - gap_right (pos); -} - -void edit_buffer::gap_left (int pos) -{ - register buf_char *to, *from; - register int i; - int new_s1; - - i = size1(); - from = gap_start(); - to = from + gap_size(); - new_s1 = size1(); - - /* Now copy the characters. To move the gap down, - copy characters up. */ - - for (;;) - { - /* I gets number of characters left to copy. */ - i = new_s1 - pos; - if (i == 0) - break; -#if 0 - /* If a quit is requested, stop copying now. - Change POS to be where we have actually moved the gap to. */ - if (QUITP) - { - pos = new_s1; - break; - } -#endif - /* Move at most 32000 chars before checking again for a quit. */ - if (i > 32000) - i = 32000; - new_s1 -= i; - while (--i >= 0) - *--to = *--from; - } - - /* Adjust markers, and buffer data structure, to put the gap at POS. - POS is where the loop above stopped, which may be what was specified - or may be where a quit was detected. */ - adjust_markers (pos << 1, size1() << 1, gap_size(), data); -#ifndef OLD_STDIO - _gap_start = data + pos; -#else - if (gap_start_ptr == &gap_start_normal) - gap_start_normal = data + pos; -#endif - __gap_end_pos = to - data; -/* QUIT;*/ -} - -void edit_buffer::gap_right (int pos) -{ - register buf_char *to, *from; - register int i; - int new_s1; - - i = size1(); - to = gap_start(); - from = i + gap_end(); - new_s1 = i; - - /* Now copy the characters. To move the gap up, - copy characters down. */ - - while (1) - { - /* I gets number of characters left to copy. */ - i = pos - new_s1; - if (i == 0) - break; -#if 0 - /* If a quit is requested, stop copying now. - Change POS to be where we have actually moved the gap to. */ - if (QUITP) - { - pos = new_s1; - break; - } -#endif - /* Move at most 32000 chars before checking again for a quit. */ - if (i > 32000) - i = 32000; - new_s1 += i; - while (--i >= 0) - *to++ = *from++; - } - - adjust_markers ((size1() + gap_size()) << 1, (pos + gap_size()) << 1, - - gap_size(), data); -#ifndef OLD_STDIO - _gap_start = data+pos; -#else - if (gap_start_ptr == &gap_start_normal) - gap_start_normal = data + pos; -#endif - __gap_end_pos = from - data; -/* QUIT;*/ -} - -/* make sure that the gap in the current buffer is at least k - characters wide */ - -void edit_buffer::make_gap(buf_offset k) -{ - register buf_char *p1, *p2, *lim; - buf_char *old_data = data; - int s1 = size1(); - - if (gap_size() >= k) - return; - - /* Get more than just enough */ - if (buf_size > 1000) k += 2000; - else k += /*200;*/ 20; // for testing! - - p1 = (buf_char *) realloc (data, s1 + size2() + k); - if (p1 == 0) - abort(); /*memory_full ();*/ - - k -= gap_size(); /* Amount of increase. */ - - /* Record new location of text */ - data = p1; - - /* Transfer the new free space from the end to the gap - by shifting the second segment upward */ - p2 = data + buf_size; - p1 = p2 + k; - lim = p2 - size2(); - while (lim < p2) - *--p1 = *--p2; - - /* Finish updating text location data */ - __gap_end_pos += k; - -#ifndef OLD_STDIO - _gap_start = data + s1; -#else - if (gap_start_ptr == &gap_start_normal) - gap_start_normal = data + s1; -#endif - - /* adjust markers */ - adjust_markers (s1 << 1, (buf_size << 1) + 1, k, old_data); - buf_size += k; -} - -/* Add `amount' to the position of every marker in the current buffer - whose current position is between `from' (exclusive) and `to' (inclusive). - Also, any markers past the outside of that interval, in the direction - of adjustment, are first moved back to the near end of the interval - and then adjusted by `amount'. */ - -void edit_buffer::adjust_markers(register mark_pointer low, - register mark_pointer high, - int amount, buf_char *old_data) -{ - register struct edit_mark *m; - register mark_pointer mpos; - /* convert to mark_pointer */ - amount <<= 1; - - if (_writer) - _writer->disconnect_gap_from_file(this); - - for (m = mark_list(); m != NULL; m = m->chain) - { - mpos = m->_pos; - if (amount > 0) - { - if (mpos > high && mpos < high + amount) - mpos = high + amount; - } - else - { - if (mpos > low + amount && mpos <= low) - mpos = low + amount; - } - if (mpos > low && mpos <= high) - mpos += amount; - m->_pos = mpos; - } - - // Now adjust files - edit_streambuf *file; - - for (file = files; file != NULL; file = file->next) { - mpos = file->current() - old_data; - if (amount > 0) - { - if (mpos > high && mpos < high + amount) - mpos = high + amount; - } - else - { - if (mpos > low + amount && mpos <= low) - mpos = low + amount; - } - if (mpos > low && mpos <= high) - mpos += amount; - char* new_pos = data + mpos; - file->set_current(new_pos, file->is_reading()); - } -} - -#if 0 -stdio_ - __off == index at start of buffer (need only be valid after seek ? ) - __buf == - -if read/read_delete/overwrite mode: - __endp <= min(*gap_start_ptr, edit_string->end->ptr(buffer)) - -if inserting: - must have *gap_start_ptr == __bufp && *gap_start_ptr+gap == __endp - file->edit_string->end->ptr(buffer) == *gap_start_ptr+end -if write_mode: - if before gap -#endif - -int edit_streambuf::underflow() -{ - if (!(_mode & ios::in)) - return EOF; - struct edit_buffer *buffer = str->buffer; - if (!is_reading()) { // Must switch from put to get mode. - disconnect_gap_from_file(buffer); - set_current(pptr(), 1); - } - buf_char *str_end = str->end->ptr(buffer); - retry: - if (gptr() < egptr()) { - return *gptr(); - } - if ((buf_char*)gptr() == str_end) - return EOF; - if (str_end <= buffer->gap_start()) { - setg(eback(), gptr(), str_end); - goto retry; - } - if (gptr() < buffer->gap_start()) { - setg(eback(), gptr(), buffer->gap_start()); - goto retry; - } - if (gptr() == buffer->gap_start()) { - disconnect_gap_from_file(buffer); -// fp->__offset += fp->__bufp - fp->__buffer; - setg(buffer->gap_end(), buffer->gap_end(), str_end); - } - else - setg(eback(), gptr(), str_end); - goto retry; -} - -int edit_streambuf::overflow(int ch) -{ - if (_mode == ios::in) - return EOF; - struct edit_buffer *buffer = str->buffer; - flush_to_buffer(buffer); - if (ch == EOF) - return 0; - if (is_reading()) { // Must switch from get to put mode. - set_current(gptr(), 0); - } - buf_char *str_end = str->end->ptr(buffer); - retry: - if (pptr() < epptr()) { - *pptr() = ch; - pbump(1); - return (unsigned char)ch; - } - if ((buf_char*)pptr() == str_end || inserting()) { - /* insert instead */ - if (buffer->_writer) - buffer->_writer->flush_to_buffer(); // Redundant? - buffer->_writer = NULL; - if (pptr() >= buffer->gap_end()) - buffer->move_gap(pptr() - buffer->gap_size()); - else - buffer->move_gap(pptr()); - buffer->make_gap(1); - setp(buffer->gap_start(), buffer->gap_end()); - buffer->_writer = this; - *pptr() = ch; - pbump(1); - return (unsigned char)ch; - } - if (str_end <= buffer->gap_start()) { - // Entire string is left of gap. - setp(pptr(), str_end); - } - else if (pptr() < buffer->gap_start()) { - // Current pos is left of gap. - setp(pptr(), buffer->gap_start()); - goto retry; - } - else if (pptr() == buffer->gap_start()) { - // Current pos is at start of gap; move to end of gap. -// disconnect_gap_from_file(buffer); - setp(buffer->gap_end(), str_end); -// __offset += __bufp - __buffer; - } - else { - // Otherwise, current pos is right of gap. - setp(pptr(), str_end); - } - goto retry; -} - -void edit_streambuf::set_current(char *new_pos, int reading) -{ - if (reading) { - setg(new_pos, new_pos, new_pos); - setp(NULL, NULL); - } - else { - setg(NULL, NULL, NULL); - setp(new_pos, new_pos); - } -} - -// Called by fseek(fp, pos, whence) if fp is bound to a edit_buffer. - -streampos edit_streambuf::seekoff(streamoff offset, _seek_dir dir, - int mode /* =ios::in|ios::out*/) -{ - struct edit_buffer *buffer = str->buffer; - disconnect_gap_from_file(buffer); - buf_index cur_pos = buffer->tell((buf_char*)current());; - buf_index start_pos = buffer->tell(str->start); - buf_index end_pos = buffer->tell(str->end); - switch (dir) { - case ios::beg: - offset += start_pos; - break; - case ios::cur: - offset += cur_pos; - break; - case ios::end: - offset += end_pos; - break; - } - if (offset < start_pos || offset > end_pos) - return EOF; - buf_char *new_pos = buffer->data + offset; - buf_char* gap_start = buffer->gap_start(); - if (new_pos > gap_start) { - buf_char* gap_end = buffer->gap_end(); - new_pos += gap_end - gap_start; - if (new_pos >= buffer->data + buffer->buf_size) abort(); // Paranoia. - } - set_current(new_pos, is_reading()); - return EOF; -} - -#if 0 -int buf_seek(void *arg_cookie, fpos_t * pos, int whence) -{ - struct buf_cookie *cookie = arg_cookie; - FILE *file = cookie->file; - struct edit_buffer *buffer = cookie->str->buffer; - buf_char *str_start = cookie->str->start->ptr(buffer); - disconnect_gap_from_file(buffer, cookie->file); - fpos_t cur_pos, new_pos; - if (file->__bufp <= *buffer->gap_start_ptr - || str_start >= buffer->__gap_end) - cur_pos = str_start - file->__bufp; - else - cur_pos = - (*buffer->gap_start_ptr - str_start) + (file->__bufp - __gap_end); - end_pos = ...; - switch (whence) { - case SEEK_SET: - new_pos = *pos; - break; - case SEEK_CUR: - new_pos = cur_pos + *pos; - break; - case SEEK_END: - new_pos = end_pos + *pos; - break; - } - if (new_pos > end_pos) { - seek to end_pos; - insert_nulls(new_pos - end_pos); - return; - } - if (str_start + new_pos <= *gap_start_ptr &* *gap_start_ptr < end) { - __buffer = str_start; - __off = 0; - __bufp = str_start + new_pos; - file->__get_limit = - *buffer->gap_start_ptr; /* what if gap_start_ptr == &bufp ??? */ - } else if () { - - } - *pos = new_pos; -} -#endif - -/* Delete characters from `from' up to (but not incl) `to' */ - -void edit_buffer::delete_range (buf_index from, buf_index to) -{ - register int numdel; - - if ((numdel = to - from) <= 0) - return; - - /* Make sure the gap is somewhere in or next to what we are deleting */ - if (from > size1()) - gap_right (from); - if (to < size1()) - gap_left (to); - - /* Relocate all markers pointing into the new, larger gap - to point at the end of the text before the gap. */ - adjust_markers ((to + gap_size()) << 1, (to + gap_size()) << 1, - - numdel - gap_size(), data); - - __gap_end_pos = to + gap_size(); - _gap_start = data + from; -} - -void edit_buffer::delete_range(struct edit_mark *start, struct edit_mark *end) -{ - delete_range(tell(start), tell(end)); -} - -void buf_delete_chars(struct edit_buffer *buf, struct edit_mark *mark, size_t count) -{ - abort(); -} - -edit_streambuf::edit_streambuf(edit_string* bstr, int mode) -{ - _mode = mode; - str = bstr; - edit_buffer* buffer = bstr->buffer; - next = buffer->files; - buffer->files = this; - char* buf_ptr = bstr->start->ptr(buffer); - _inserting = 0; -// setb(buf_ptr, buf_ptr, 0); - set_current(buf_ptr, !(mode & ios::out+ios::trunc+ios::app)); - if (_mode & ios::trunc) - truncate(); - if (_mode & ios::ate) - seekoff(0, ios::end); -} - -// Called by fclose(fp) if fp is bound to a edit_buffer. - -#if 0 -static int buf_close(void *arg) -{ - register struct buf_cookie *cookie = arg; - struct edit_buffer *buffer = cookie->str->buffer; - struct buf_cookie **ptr; - for (ptr = &buffer->files; *ptr != cookie; ptr = &(*ptr)->next) ; - *ptr = cookie->next; - disconnect_gap_from_file(buffer, cookie->file); - free (cookie); - return 0; -} -#endif - -edit_streambuf::~edit_streambuf() -{ - if (_mode == ios::out) - truncate(); - // Unlink this from list of files associated with bstr->buffer. - edit_streambuf **ptr = &str->buffer->files; - for (; *ptr != this; ptr = &(*ptr)->next) { } - *ptr = next; - - disconnect_gap_from_file(str->buffer); -} - -edit_buffer::edit_buffer() -{ - buf_size = /*200;*/ 15; /* for testing! */ - data = (buf_char*)malloc(buf_size); - files = NULL; -#ifndef OLD_STDIO - _gap_start = data; - _writer = NULL; -#else - gap_start_normal = data; - gap_start_ptr = &gap_start_normal; -#endif - __gap_end_pos = buf_size; - start_mark.chain = &end_mark; - start_mark._pos = 0; - end_mark.chain = NULL; - end_mark._pos = 2 * buf_size + 1; -} - -// Allocate a new mark, which is adjusted by 'delta' bytes from 'this'. -// Restrict new mark to lie within 'str'. - -edit_mark::edit_mark(struct edit_string *str, long delta) -{ - struct edit_buffer *buf = str->buffer; - chain = buf->start_mark.chain; - buf->start_mark.chain = this; - mark_pointer size1 = buf->size1() << 1; - int gap_size = buf->gap_size() << 1; - delta <<= 1; - - // check if new and old marks are opposite sides of gap - if (_pos <= size1 && _pos + delta > size1) - delta += gap_size; - else if (_pos >= size1 + gap_size && _pos + delta < size1 + gap_size) - delta -= gap_size; - - _pos = _pos + delta; - if (_pos < str->start->_pos & ~1) - _pos = (str->start->_pos & ~ 1) + (_pos & 1); - else if (_pos >= str->end->_pos) - _pos = (str->end->_pos & ~ 1) + (_pos & 1); -} - -// A (slow) way to find the buffer a mark belongs to. - -edit_buffer * edit_mark::buffer() -{ - struct edit_mark *mark; - for (mark = this; mark->chain != NULL; mark = mark->chain) ; - // Assume that the last mark on the chain is the end_mark. - return (edit_buffer *)((char*)mark - offsetof(edit_buffer, end_mark)); -} - -edit_mark::~edit_mark() -{ - // Must unlink mark from chain of owning buffer - struct edit_buffer *buf = buffer(); - if (this == &buf->start_mark || this == &buf->end_mark) abort(); - edit_mark **ptr; - for (ptr = &buf->start_mark.chain; *ptr != this; ptr = &(*ptr)->chain) ; - *ptr = this->chain; -} - -int edit_string::length() const -{ - ptrdiff_t delta = end->ptr(buffer) - start->ptr(buffer); - if (end->ptr(buffer) <= buffer->gap_start() || - start->ptr(buffer) >= buffer->gap_end()) - return delta; - return delta - buffer->gap_size(); -} - -buf_char * edit_string::copy_bytes(int *lenp) const -{ - char *new_str; - int len1, len2; - buf_char *start1, *start2; - start1 = start->ptr(buffer); - if (end->ptr(buffer) <= buffer->gap_start() - || start->ptr(buffer) >= buffer->gap_end()) { - len1 = end->ptr(buffer) - start1; - len2 = 0; - start2 = NULL; // To avoid a warning from g++. - } - else { - len1 = buffer->gap_start() - start1; - start2 = buffer->gap_end(); - len2 = end->ptr(buffer) - start2; - } - new_str = (char*)malloc(len1 + len2 + 1); - memcpy(new_str, start1, len1); - if (len2 > 0) memcpy(new_str + len1, start2, len2); - new_str[len1+len2] = '\0'; - *lenp = len1+len2; - return new_str; -} - -// Replace the buf_chars in 'this' with ones from 'src'. -// Equivalent to deleting this, then inserting src, except tries -// to leave marks in place: Marks whose offset from the start -// of 'this' is less than 'src->length()' will still have the -// same offset in 'this' when done. - -void edit_string::assign(struct edit_string *src) -{ - edit_streambuf dst_file(this, ios::out); - if (buffer == src->buffer /*&& ???*/) { /* overly conservative */ - int src_len; - buf_char *new_str; - new_str = src->copy_bytes(&src_len); - dst_file.sputn(new_str, src_len); - free (new_str); - } else { - edit_streambuf src_file(src, ios::in); - for ( ; ; ) { - int ch = src_file.sbumpc(); - if (ch == EOF) break; - dst_file.sputc(ch); - } - } -} |