Mercurial > nand-ecoscentric
comparison packages/language/c/libc/current/src/stdio/common/stream.cxx @ 2:443894e2e912 ecos-v1_2_1-release
Block commit of eCos version 1.2.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 12:24:34 +0000 |
| parents | 3111d98ba7b3 |
| children | c38311975d4f |
comparison
equal
deleted
inserted
replaced
| 1:72f549f0d891 | 2:443894e2e912 |
|---|---|
| 20 // | 20 // |
| 21 // The Original Code is eCos - Embedded Cygnus Operating System, released | 21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
| 22 // September 30, 1998. | 22 // September 30, 1998. |
| 23 // | 23 // |
| 24 // The Initial Developer of the Original Code is Cygnus. Portions created | 24 // The Initial Developer of the Original Code is Cygnus. Portions created |
| 25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. | 25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
| 26 // ------------------------------------------- | 26 // ------------------------------------------- |
| 27 // | 27 // |
| 28 //####COPYRIGHTEND#### | 28 //####COPYRIGHTEND#### |
| 29 //======================================================================== | 29 //======================================================================== |
| 30 //#####DESCRIPTIONBEGIN#### | 30 //#####DESCRIPTIONBEGIN#### |
| 31 // | 31 // |
| 32 // Author(s): jlarmour@cygnus.co.uk | 32 // Author(s): jlarmour |
| 33 // Contributors: jlarmour@cygnus.co.uk | 33 // Contributors: jlarmour |
| 34 // Date: 1998-02-13 | 34 // Date: 1999-03-16 |
| 35 // Purpose: | 35 // Purpose: |
| 36 // Description: | 36 // Description: |
| 37 // Usage: | 37 // Usage: |
| 38 // | 38 // |
| 39 //####DESCRIPTIONEND#### | 39 //####DESCRIPTIONEND#### |
| 44 | 44 |
| 45 #include <pkgconf/libc.h> // Configuration header | 45 #include <pkgconf/libc.h> // Configuration header |
| 46 | 46 |
| 47 | 47 |
| 48 // Include the C library? And do we want the stdio stuff? | 48 // Include the C library? And do we want the stdio stuff? |
| 49 #if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) | 49 #ifdef CYGPKG_LIBC_STDIO |
| 50 | 50 |
| 51 // INCLUDES | 51 // INCLUDES |
| 52 | 52 |
| 53 #include <cyg/infra/cyg_type.h> // Common project-wide type definitions | 53 #include <cyg/infra/cyg_type.h> // Common project-wide type definitions |
| 54 #include <stddef.h> // NULL and size_t from compiler | 54 #include <cyg/infra/cyg_ass.h> // Assertion infrastructure |
| 55 #include <errno.h> // Error codes | 55 #include <stddef.h> // NULL and size_t from compiler |
| 56 #include "clibincl/stringsupp.hxx" // _memcpy() | 56 #include <errno.h> // Error codes |
| 57 #include "clibincl/stream.hxx" // Header for this file | 57 #include "clibincl/stringsupp.hxx" // _memcpy() |
| 58 #include <cyg/devs/common/iorb.h> // Cyg_IORB | 58 #include "clibincl/stream.hxx" // Header for this file |
| 59 #include <cyg/devs/common/table.h> // Device table | 59 #include "clibincl/stdiosupp.hxx" // Stdio support functions |
| 60 #include <cyg/io/io.h> // I/O system | |
| 61 #include <cyg/io/config_keys.h> // CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN | |
| 60 | 62 |
| 61 | 63 |
| 62 // FUNCTIONS | 64 // FUNCTIONS |
| 63 | 65 |
| 64 Cyg_StdioStream::Cyg_StdioStream(Cyg_Device_Table_t *dev, | 66 Cyg_StdioStream::Cyg_StdioStream(cyg_io_handle_t dev, |
| 65 OpenMode open_mode, | 67 OpenMode open_mode, |
| 66 cyg_bool append, cyg_bool binary, | 68 cyg_bool append, cyg_bool binary, |
| 67 int buffer_mode, cyg_ucount32 buffer_size, | 69 int buffer_mode, cyg_ucount32 buffer_size, |
| 68 cyg_uint8 *buffer_addr ) | 70 cyg_uint8 *buffer_addr ) |
| 69 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 71 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 70 : io_buf( buffer_size, buffer_addr ) | 72 : io_buf( buffer_size, buffer_addr ) |
| 71 #endif | 73 #endif |
| 72 | 74 |
| 73 { | 75 { |
| 76 | |
| 77 CYG_CHECK_DATA_PTR(dev, "Attempt to open invalid device!"); | |
| 78 | |
| 74 #ifdef CYGDBG_USE_ASSERTS | 79 #ifdef CYGDBG_USE_ASSERTS |
| 75 magic_validity_word = 0xbadbad; | 80 magic_validity_word = 0xbadbad; |
| 76 #endif | 81 #endif |
| 77 | 82 |
| 78 my_device = dev; | 83 my_device = dev; |
| 96 return; | 101 return; |
| 97 } // switch | 102 } // switch |
| 98 | 103 |
| 99 | 104 |
| 100 if (flags.opened_for_write) { | 105 if (flags.opened_for_write) { |
| 106 #if 0 | |
| 107 // FIXME: need some replacement for this | |
| 101 if (!my_device->write_blocking) { | 108 if (!my_device->write_blocking) { |
| 102 error = EDEVNOSUPP; | 109 error = EDEVNOSUPP; |
| 103 return; | 110 return; |
| 104 } // if | 111 } // if |
| 105 | 112 #endif |
| 106 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 113 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 107 flags.last_buffer_op_was_read = false; | 114 flags.last_buffer_op_was_read = false; |
| 108 #endif | 115 #endif |
| 109 } // if | 116 } // if |
| 110 | 117 |
| 111 | 118 |
| 112 if (flags.opened_for_read) { | 119 if (flags.opened_for_read) { |
| 120 #if 0 | |
| 121 // FIXME: need some replacement for this | |
| 113 if (!my_device->read_blocking) { | 122 if (!my_device->read_blocking) { |
| 114 error = EDEVNOSUPP; | 123 error = EDEVNOSUPP; |
| 115 return; | 124 return; |
| 116 } // if | 125 } // if |
| 126 #endif | |
| 117 | 127 |
| 118 // NB also if opened for read AND write, then say last op was read | 128 // NB also if opened for read AND write, then say last op was read |
| 119 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 129 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 120 flags.last_buffer_op_was_read = true; | 130 flags.last_buffer_op_was_read = true; |
| 121 #endif | 131 #endif |
| 152 error = EINVAL; | 162 error = EINVAL; |
| 153 return; | 163 return; |
| 154 } // switch | 164 } // switch |
| 155 | 165 |
| 156 // one way of checking the buffer was set up correctly | 166 // one way of checking the buffer was set up correctly |
| 157 if (io_buf.get_buffer_size()==-1) { | 167 if (flags.buffering && io_buf.get_buffer_size()==-1) { |
| 158 error = ENOMEM; | 168 error = ENOMEM; |
| 159 return; | 169 return; |
| 160 } | 170 } |
| 161 | 171 |
| 162 #endif | 172 #endif |
| 163 | 173 |
| 174 #if 0 // FIXME - Need to set binary mode. | |
| 164 if (my_device->open) { | 175 if (my_device->open) { |
| 165 error = (*my_device->open)( my_device->cookie, | 176 error = (*my_device->open)( my_device->cookie, |
| 166 binary ? CYG_DEVICE_OPEN_MODE_RAW | 177 binary ? CYG_DEVICE_OPEN_MODE_RAW |
| 167 : CYG_DEVICE_OPEN_MODE_TEXT ); | 178 : CYG_DEVICE_OPEN_MODE_TEXT ); |
| 168 if (error != ENOERR) | 179 if (error != ENOERR) |
| 169 return; // keep error code the same | 180 return; // keep error code the same |
| 170 } // if | 181 } // if |
| 171 | 182 |
| 183 #endif | |
| 172 | 184 |
| 173 #ifdef CYGDBG_USE_ASSERTS | 185 #ifdef CYGDBG_USE_ASSERTS |
| 174 magic_validity_word = 0x7b4321ce; | 186 magic_validity_word = 0x7b4321ce; |
| 175 #endif | 187 #endif |
| 176 | 188 |
| 180 | 192 |
| 181 Cyg_ErrNo | 193 Cyg_ErrNo |
| 182 Cyg_StdioStream::refill_read_buffer( void ) | 194 Cyg_StdioStream::refill_read_buffer( void ) |
| 183 { | 195 { |
| 184 Cyg_ErrNo read_err; | 196 Cyg_ErrNo read_err; |
| 185 Cyg_IORB iorb; | 197 cyg_uint8 *buffer; |
| 198 cyg_uint32 len; | |
| 186 | 199 |
| 187 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | 200 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); |
| 188 | 201 |
| 189 if (!lock_me()) | 202 if (!lock_me()) |
| 190 return EBADF; // assume file is now invalid | 203 return EBADF; // assume file is now invalid |
| 211 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 224 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 212 // we're now reading | 225 // we're now reading |
| 213 flags.last_buffer_op_was_read = true; | 226 flags.last_buffer_op_was_read = true; |
| 214 | 227 |
| 215 if (flags.buffering) { | 228 if (flags.buffering) { |
| 216 iorb.buffer_length = | 229 len = io_buf.get_buffer_addr_to_write( (cyg_uint8**)&buffer ); |
| 217 io_buf.get_buffer_addr_to_write( (cyg_uint8**)&iorb.buffer ); | 230 if (!len) { // no buffer space available |
| 231 unlock_me(); | |
| 232 return ENOERR; // isn't an error, just needs user to read out data | |
| 233 } // if | |
| 218 } | 234 } |
| 219 else | 235 else |
| 220 #endif | 236 #endif |
| 221 | 237 |
| 222 if (!flags.readbuf_char_in_use) { | 238 if (!flags.readbuf_char_in_use) { |
| 223 iorb.buffer_length = 1; | 239 len = 1; |
| 224 iorb.buffer = &readbuf_char; | 240 buffer = &readbuf_char; |
| 225 } | 241 } |
| 242 else { | |
| 243 // no buffer space available | |
| 244 unlock_me(); | |
| 245 return ENOERR; // isn't an error, just needs user to read out data | |
| 246 } // else | |
| 247 | |
| 248 read_err = cyg_io_read(my_device, buffer, &len); | |
| 249 | |
| 250 | |
| 251 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 252 if (flags.buffering) | |
| 253 io_buf.set_bytes_written( len ); | |
| 226 else | 254 else |
| 227 iorb.buffer_length = 0; | 255 #endif |
| 228 | 256 flags.readbuf_char_in_use = len ? 1 : 0; |
| 229 if (!iorb.buffer_length) { // no buffer space available | |
| 230 unlock_me(); | |
| 231 return ENOERR; // isn't an error, just needs user to read out data | |
| 232 } // if | |
| 233 | |
| 234 read_err = (*my_device->read_blocking)( my_device->cookie, &iorb ); | |
| 235 | |
| 236 | |
| 237 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 238 if (flags.buffering) | |
| 239 io_buf.set_bytes_written( iorb.xferred_length ); | |
| 240 else | |
| 241 #endif | |
| 242 flags.readbuf_char_in_use = iorb.xferred_length ? 1 : 0; | |
| 243 | 257 |
| 244 unlock_me(); | 258 unlock_me(); |
| 245 | 259 |
| 246 if (read_err == ENOERR) { | 260 if (read_err == ENOERR) { |
| 247 if (iorb.xferred_length == 0) | 261 if (len == 0) |
| 248 read_err = EAGAIN; | 262 read_err = EAGAIN; |
| 249 } // if | 263 } // if |
| 250 | 264 |
| 251 return read_err; | 265 return read_err; |
| 252 } // refill_read_buffer() | 266 } // refill_read_buffer() |
| 285 Cyg_ErrNo err; | 299 Cyg_ErrNo err; |
| 286 | 300 |
| 287 // this should really only be called after refill_read_buffer, but | 301 // this should really only be called after refill_read_buffer, but |
| 288 // just in case | 302 // just in case |
| 289 err = flush_output_unlocked(); | 303 err = flush_output_unlocked(); |
| 304 if (ENOERR == err) | |
| 305 err = cyg_libc_stdio_flush_all_but(this); | |
| 290 | 306 |
| 291 if (err != ENOERR) { | 307 if (err != ENOERR) { |
| 292 unlock_me(); | 308 unlock_me(); |
| 293 return err; | 309 return err; |
| 294 } | 310 } |
| 341 // this should really only be called after refill_read_buffer, but just | 357 // this should really only be called after refill_read_buffer, but just |
| 342 // in case | 358 // in case |
| 343 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 359 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 344 if (flags.buffering) | 360 if (flags.buffering) |
| 345 err = flush_output_unlocked(); | 361 err = flush_output_unlocked(); |
| 362 if (ENOERR == err) | |
| 363 err = cyg_libc_stdio_flush_all_but(this); | |
| 346 | 364 |
| 347 if (err != ENOERR) | 365 if (err != ENOERR) |
| 348 return err; | 366 return err; |
| 349 | 367 |
| 350 // we're now reading | 368 // we're now reading |
| 460 | 478 |
| 461 Cyg_ErrNo | 479 Cyg_ErrNo |
| 462 Cyg_StdioStream::flush_output_unlocked( void ) | 480 Cyg_StdioStream::flush_output_unlocked( void ) |
| 463 { | 481 { |
| 464 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 482 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 465 Cyg_IORB iorb; | |
| 466 Cyg_ErrNo write_err=ENOERR; | 483 Cyg_ErrNo write_err=ENOERR; |
| 484 cyg_uint8 *buffer; | |
| 485 cyg_uint32 len; | |
| 467 | 486 |
| 468 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | 487 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); |
| 469 | 488 |
| 470 if ( flags.last_buffer_op_was_read ) | 489 if ( flags.last_buffer_op_was_read ) |
| 471 return ENOERR; | 490 return ENOERR; |
| 476 | 495 |
| 477 // shortcut if nothing to do | 496 // shortcut if nothing to do |
| 478 if (io_buf.get_buffer_space_used() == 0) | 497 if (io_buf.get_buffer_space_used() == 0) |
| 479 return ENOERR; | 498 return ENOERR; |
| 480 | 499 |
| 481 iorb.buffer_length = | 500 len = io_buf.get_buffer_addr_to_read( (cyg_uint8 **)&buffer ); |
| 482 io_buf.get_buffer_addr_to_read( (cyg_uint8 **)&iorb.buffer ); | 501 |
| 483 | 502 CYG_ASSERT( len > 0, |
| 484 CYG_ASSERT( iorb.buffer_length > 0, | |
| 485 "There should be data to read but there isn't!"); | 503 "There should be data to read but there isn't!"); |
| 486 | 504 |
| 487 write_err = (*my_device->write_blocking)( my_device->cookie, &iorb ); | 505 write_err = cyg_io_write(my_device, buffer, &len); |
| 506 | |
| 507 // since we're doing a concerted flush, we tell the I/O layer to | |
| 508 // flush too, otherwise output may just sit there forever | |
| 509 if (!write_err) | |
| 510 write_err = cyg_io_get_config(my_device, | |
| 511 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, | |
| 512 NULL, NULL); | |
| 488 | 513 |
| 489 // we've just read it all, so just wipe it out | 514 // we've just read it all, so just wipe it out |
| 490 io_buf.drain_buffer(); | 515 io_buf.drain_buffer(); |
| 491 | 516 |
| 492 return write_err; | 517 return write_err; |
| 528 | 553 |
| 529 flags.last_buffer_op_was_read = false; | 554 flags.last_buffer_op_was_read = false; |
| 530 | 555 |
| 531 if (!flags.buffering) { | 556 if (!flags.buffering) { |
| 532 #endif | 557 #endif |
| 533 Cyg_IORB iorb; | 558 cyg_uint32 len = buffer_length; |
| 534 iorb.buffer = (char *)buffer; | 559 |
| 535 iorb.buffer_length = buffer_length; | 560 write_err = cyg_io_write(my_device, buffer, &len); |
| 536 | 561 |
| 537 write_err = (*my_device->write_blocking)( my_device->cookie, | 562 *bytes_written = len; |
| 538 &iorb ); | |
| 539 | |
| 540 *bytes_written = iorb.xferred_length; | |
| 541 | 563 |
| 542 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | 564 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO |
| 543 } // if | 565 } // if |
| 544 else { | 566 else { |
| 545 cyg_ucount32 bytes_available; | 567 cyg_ucount32 bytes_available; |
| 616 | 638 |
| 617 return write_err; | 639 return write_err; |
| 618 } // write() | 640 } // write() |
| 619 | 641 |
| 620 | 642 |
| 621 #endif // if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) | 643 #endif // ifdef CYGPKG_LIBC_STDIO |
| 622 | 644 |
| 623 // EOF stream.cxx | 645 // EOF stream.cxx |
