/* gemdos methods for streamoids */ #include "io-defs.h" #include "com-meth.h" #include "buf-meth.h" #include "input-ed.h" #include #include #include /* get a fresh buffer for a buffered gemdos streamoid. must advance-input-buffer before doing this. */ local DEFMETHOD next_input_buffer(self) struct streamoid * self; { return((long )(Fread(self->gemdos_handle, self->buffer_size, self->buffer))); } /* write the current buffer to the gemdos handle. should advance-output-buffer after this */ local DEFMETHOD send_output_buffer(self) struct streamoid * self; { return(long )(Fwrite(self->gemdos_handle, self->buffer_nbytes, self->buffer)); } local DEFMETHOD seek_internal(self, where, how) struct streamoid * self; long where; int how; { return((long )(Fseek(where, self->gemdos_handle, how))); } local DEFMETHOD close_internal(self) struct streamoid * self; { Fclose(self->gemdos_handle); } /* Unbuffered methods for gem file handles. These are *NOT* suitable for interactive streamoids. */ local DEFMETHOD tyi_binary_simple(self) struct streamoid * self; { int result; char ch[1]; if (self->flags & STR_UNTYIED_P) { self->flags &= ~STR_UNTYIED_P; return(self->untyied_char); } result = Fread(self->gemdos_handle, 1, &ch); if (result == 1) { ++self->file_position; return(ch[0]); } if (result < 0) errno = self->last_error = result; self->flags |= STR_AT_EOF_P; return(EOF_VALUE); } local DEFMETHOD tyi_text_simple(self) struct streamoid * self; { int ch = tyi_binary_simple(self); if (ch == EOF_VALUE) return(ch); if (ch == '\r') { ch = tyi_binary_simple(self); if (ch != '\n') { method_call_1(self, METHOD_UNTYI, ch); return('\r'); } } return(ch); } local DEFMETHOD tyo_binary_simple(self, byte) struct streamoid * self; int byte; { char ch[1]; int result; ch[0] = byte; result = Fwrite(self->gemdos_handle, 1, &ch[0]); if (result < 0) errno = self->last_error = result; else ++self->file_position; return(result); } local DEFMETHOD tyo_text_simple(self, ch) struct streamoid * self; int ch; { if (ch == '\n') tyo_binary_simple(self, '\r'); tyo_binary_simple(self, ch); } local DEFMETHOD seek_simple(self, pos, how) struct streamoid * self; long pos; int how; { int res = Fseek(pos, self->gemdos_handle, how); self->flags &= ~STR_AT_EOF_P; if (res < 0) { errno = self->last_error = res; return(self->file_position = Fseek(0, self->gemdos_handle, L_INCR)); } else return(self->file_position = res); } /* info method for console streamoids */ local short * linea_ptr = (short * )0; local int console_info(self, b) struct streamoid * self; struct console_info_block * b; { if (b) { if (!linea_ptr) { asm volatile (".word 0xA000"); /* line-a init */ asm volatile ("movel a0,_linea_ptr"); } b->linea = linea_ptr; b->maxx = 80; /* kludge! */ b->maxy = 24; b->curx = linea_ptr[-13]; b->curx = linea_ptr[-13]; } return(INF_CONSOLE); /* say we give console info */ } /* special purpose tyi method for interactive streamoids */ local DEFMETHOD tyi_interactive(self) struct streamoid * self; { int ch = tyi_binary_simple(self); if (ch == EOF_VALUE) return(ch); if (ch == 0x1A) /* ^Z */ /* set eof, it can be cleared later */ { self->flags |= STR_AT_EOF_P; return(EOF_VALUE); } if (ch == '\r') { method_call_1(self, METHOD_TYO, '\r'); method_call_1(self, METHOD_TYO, '\n'); return('\n'); } return(ch); } /* fancy line-in method for console streamoids, using input-editor */ local int ie_tyi(self) struct streamoid * self; { return(method_call_0(self, METHOD_TYI)); } local int ie_tyo(self, ch) struct streamoid * self; int ch; { return(method_call_1(self, METHOD_TYO, ch)); } local DEFMETHOD ie_line_in(self, buf, nbytes_buf) struct streamoid * self; char * buf; int nbytes_buf; { int term_char; *buf = '\0'; term_char = __input_editor(self, buf, nbytes_buf - 1, ie_tyi, ie_tyo); if (term_char == '\n') strcat(buf, "\n"); return(strlen(buf)); } /* The method vectors for gem-file streamoids */ local method_fun gem_buffered_text_methods[] = { m_close, /* default close method */ m_tyi_text, /* buffered-stream tyi text */ m_untyi_byte, m_tyo_text, m_line_in, m_line_out, m_string_in, m_string_out, m_seek, m_no_info, /* no info method */ next_input_buffer, send_output_buffer, seek_internal, close_internal }; local method_fun gem_buffered_binary_methods[] = { m_close, /* default close method */ m_tyi_binary, /* buffered-stream tyi bin */ m_untyi_byte, m_tyo_binary, m_line_in, m_line_out, m_string_in, m_string_out, m_seek, m_no_info, /* no info method */ next_input_buffer, send_output_buffer, seek_internal, close_internal }; local method_fun gem_unbuffered_text_methods[] = { m_close, /* default close method */ tyi_text_simple, m_untyi_byte, tyo_text_simple, m_line_in, m_line_out, m_string_in, m_string_out, seek_simple, m_no_info /* no info method. see below */ }; local method_fun gem_unbuffered_binary_methods[] = { m_close, /* default close method */ tyi_binary_simple, m_untyi_byte, tyo_binary_simple, m_line_in, m_line_out, m_string_in, m_string_out, seek_simple, m_no_info /* no info method. see below */ }; /* the thing that constructs combined methods for gem-file frobs. */ gem_method_selector(self, flags) struct streamoid * self; int flags; { method_fun * m; int n; if (flags & STR_BUFFERED_P) { if (flags & STR_TEXT_P) m = gem_buffered_text_methods; else m = gem_buffered_binary_methods; n = METHODS_BUFFERED; } else { if (flags & STR_TEXT_P) m = gem_unbuffered_text_methods; else m = gem_unbuffered_binary_methods; n = METHODS_UNBUFFERED; } self->method = __clone_method_vector(m, n); if (flags & STR_INTERACTIVE_P) { /* this is wrong! need a better way of telling what a handle is connected to! */ self->method[METHOD_INFO] = console_info; self->method[METHOD_TYI] = tyi_interactive; self->method[METHOD_READL] = ie_line_in; } self->n_methods = n; }