Mercurial > ecos
comparison packages/language/c/libc/current/src/stdio/common/stream.cxx @ 0:3111d98ba7b3 ecos-v1_1-release
Initial commit of eCos version 1.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 11:16:07 +0000 |
| parents | |
| children | 443894e2e912 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:3111d98ba7b3 |
|---|---|
| 1 //======================================================================== | |
| 2 // | |
| 3 // stream.cxx | |
| 4 // | |
| 5 // Implementations of internal C library stdio stream functions | |
| 6 // | |
| 7 //======================================================================== | |
| 8 //####COPYRIGHTBEGIN#### | |
| 9 // | |
| 10 // ------------------------------------------- | |
| 11 // The contents of this file are subject to the Cygnus eCos Public License | |
| 12 // Version 1.0 (the "License"); you may not use this file except in | |
| 13 // compliance with the License. You may obtain a copy of the License at | |
| 14 // http://sourceware.cygnus.com/ecos | |
| 15 // | |
| 16 // Software distributed under the License is distributed on an "AS IS" | |
| 17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 18 // License for the specific language governing rights and limitations under | |
| 19 // the License. | |
| 20 // | |
| 21 // The Original Code is eCos - Embedded Cygnus Operating System, released | |
| 22 // September 30, 1998. | |
| 23 // | |
| 24 // The Initial Developer of the Original Code is Cygnus. Portions created | |
| 25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. | |
| 26 // ------------------------------------------- | |
| 27 // | |
| 28 //####COPYRIGHTEND#### | |
| 29 //======================================================================== | |
| 30 //#####DESCRIPTIONBEGIN#### | |
| 31 // | |
| 32 // Author(s): jlarmour@cygnus.co.uk | |
| 33 // Contributors: jlarmour@cygnus.co.uk | |
| 34 // Date: 1998-02-13 | |
| 35 // Purpose: | |
| 36 // Description: | |
| 37 // Usage: | |
| 38 // | |
| 39 //####DESCRIPTIONEND#### | |
| 40 // | |
| 41 //======================================================================== | |
| 42 | |
| 43 // CONFIGURATION | |
| 44 | |
| 45 #include <pkgconf/libc.h> // Configuration header | |
| 46 | |
| 47 | |
| 48 // Include the C library? And do we want the stdio stuff? | |
| 49 #if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) | |
| 50 | |
| 51 // INCLUDES | |
| 52 | |
| 53 #include <cyg/infra/cyg_type.h> // Common project-wide type definitions | |
| 54 #include <stddef.h> // NULL and size_t from compiler | |
| 55 #include <errno.h> // Error codes | |
| 56 #include "clibincl/stringsupp.hxx" // _memcpy() | |
| 57 #include "clibincl/stream.hxx" // Header for this file | |
| 58 #include <cyg/devs/common/iorb.h> // Cyg_IORB | |
| 59 #include <cyg/devs/common/table.h> // Device table | |
| 60 | |
| 61 | |
| 62 // FUNCTIONS | |
| 63 | |
| 64 Cyg_StdioStream::Cyg_StdioStream(Cyg_Device_Table_t *dev, | |
| 65 OpenMode open_mode, | |
| 66 cyg_bool append, cyg_bool binary, | |
| 67 int buffer_mode, cyg_ucount32 buffer_size, | |
| 68 cyg_uint8 *buffer_addr ) | |
| 69 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 70 : io_buf( buffer_size, buffer_addr ) | |
| 71 #endif | |
| 72 | |
| 73 { | |
| 74 #ifdef CYGDBG_USE_ASSERTS | |
| 75 magic_validity_word = 0xbadbad; | |
| 76 #endif | |
| 77 | |
| 78 my_device = dev; | |
| 79 | |
| 80 // Clear all flags | |
| 81 _memset( &flags, 0, sizeof(flags) ); | |
| 82 | |
| 83 switch (open_mode) { | |
| 84 case CYG_STREAM_READ: | |
| 85 flags.opened_for_read = true; | |
| 86 break; | |
| 87 case CYG_STREAM_WRITE: | |
| 88 flags.opened_for_write = true; | |
| 89 break; | |
| 90 case CYG_STREAM_READWRITE: | |
| 91 flags.opened_for_read = true; | |
| 92 flags.opened_for_write = true; | |
| 93 break; | |
| 94 default: | |
| 95 error=EINVAL; | |
| 96 return; | |
| 97 } // switch | |
| 98 | |
| 99 | |
| 100 if (flags.opened_for_write) { | |
| 101 if (!my_device->write_blocking) { | |
| 102 error = EDEVNOSUPP; | |
| 103 return; | |
| 104 } // if | |
| 105 | |
| 106 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 107 flags.last_buffer_op_was_read = false; | |
| 108 #endif | |
| 109 } // if | |
| 110 | |
| 111 | |
| 112 if (flags.opened_for_read) { | |
| 113 if (!my_device->read_blocking) { | |
| 114 error = EDEVNOSUPP; | |
| 115 return; | |
| 116 } // if | |
| 117 | |
| 118 // NB also if opened for read AND write, then say last op was read | |
| 119 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 120 flags.last_buffer_op_was_read = true; | |
| 121 #endif | |
| 122 } // if | |
| 123 | |
| 124 flags.binary = binary ? 1 : 0; | |
| 125 | |
| 126 error = ENOERR; | |
| 127 | |
| 128 // in due course we would do an equivalent to fseek(...,0, SEEK_END); | |
| 129 // when appending. for now, there's nothing, except set eof | |
| 130 | |
| 131 flags.at_eof = append ? 1 : 0; | |
| 132 | |
| 133 position = 0; | |
| 134 | |
| 135 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 136 | |
| 137 switch (buffer_mode) { | |
| 138 case _IONBF: | |
| 139 CYG_ASSERT( (buffer_size == 0) && (buffer_addr == NULL), | |
| 140 "No buffering wanted but size/address specified!" ); | |
| 141 flags.buffering = flags.line_buffering = false; | |
| 142 break; | |
| 143 case _IOLBF: | |
| 144 flags.buffering = true; | |
| 145 flags.line_buffering = true; | |
| 146 break; | |
| 147 case _IOFBF: | |
| 148 flags.buffering = true; | |
| 149 flags.line_buffering = false; | |
| 150 break; | |
| 151 default: | |
| 152 error = EINVAL; | |
| 153 return; | |
| 154 } // switch | |
| 155 | |
| 156 // one way of checking the buffer was set up correctly | |
| 157 if (io_buf.get_buffer_size()==-1) { | |
| 158 error = ENOMEM; | |
| 159 return; | |
| 160 } | |
| 161 | |
| 162 #endif | |
| 163 | |
| 164 if (my_device->open) { | |
| 165 error = (*my_device->open)( my_device->cookie, | |
| 166 binary ? CYG_DEVICE_OPEN_MODE_RAW | |
| 167 : CYG_DEVICE_OPEN_MODE_TEXT ); | |
| 168 if (error != ENOERR) | |
| 169 return; // keep error code the same | |
| 170 } // if | |
| 171 | |
| 172 | |
| 173 #ifdef CYGDBG_USE_ASSERTS | |
| 174 magic_validity_word = 0x7b4321ce; | |
| 175 #endif | |
| 176 | |
| 177 } // Cyg_StdioStream constructor | |
| 178 | |
| 179 | |
| 180 | |
| 181 Cyg_ErrNo | |
| 182 Cyg_StdioStream::refill_read_buffer( void ) | |
| 183 { | |
| 184 Cyg_ErrNo read_err; | |
| 185 Cyg_IORB iorb; | |
| 186 | |
| 187 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 188 | |
| 189 if (!lock_me()) | |
| 190 return EBADF; // assume file is now invalid | |
| 191 | |
| 192 // first just check that we _can_ read this device! | |
| 193 if (!flags.opened_for_read) { | |
| 194 unlock_me(); | |
| 195 return EINVAL; | |
| 196 } | |
| 197 | |
| 198 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 199 // If there is pending output to write, then this will check and | |
| 200 // write it | |
| 201 if (flags.buffering) { | |
| 202 read_err = flush_output_unlocked(); | |
| 203 | |
| 204 if (read_err != ENOERR) { | |
| 205 unlock_me(); | |
| 206 return read_err; | |
| 207 } // if | |
| 208 } // if | |
| 209 #endif | |
| 210 | |
| 211 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 212 // we're now reading | |
| 213 flags.last_buffer_op_was_read = true; | |
| 214 | |
| 215 if (flags.buffering) { | |
| 216 iorb.buffer_length = | |
| 217 io_buf.get_buffer_addr_to_write( (cyg_uint8**)&iorb.buffer ); | |
| 218 } | |
| 219 else | |
| 220 #endif | |
| 221 | |
| 222 if (!flags.readbuf_char_in_use) { | |
| 223 iorb.buffer_length = 1; | |
| 224 iorb.buffer = &readbuf_char; | |
| 225 } | |
| 226 else | |
| 227 iorb.buffer_length = 0; | |
| 228 | |
| 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 | |
| 244 unlock_me(); | |
| 245 | |
| 246 if (read_err == ENOERR) { | |
| 247 if (iorb.xferred_length == 0) | |
| 248 read_err = EAGAIN; | |
| 249 } // if | |
| 250 | |
| 251 return read_err; | |
| 252 } // refill_read_buffer() | |
| 253 | |
| 254 | |
| 255 Cyg_ErrNo | |
| 256 Cyg_StdioStream::read( cyg_uint8 *user_buffer, cyg_ucount32 buffer_length, | |
| 257 cyg_ucount32 *bytes_read ) | |
| 258 { | |
| 259 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 260 | |
| 261 *bytes_read = 0; | |
| 262 | |
| 263 if (!lock_me()) | |
| 264 return EBADF; // assume file is now invalid | |
| 265 | |
| 266 if (!flags.opened_for_read) { | |
| 267 unlock_me(); | |
| 268 return EINVAL; | |
| 269 } | |
| 270 | |
| 271 #ifdef CYGFUN_LIBC_STDIO_ungetc | |
| 272 if (flags.unread_char_buf_in_use && buffer_length) { | |
| 273 *user_buffer++ = unread_char_buf; | |
| 274 ++*bytes_read; | |
| 275 flags.unread_char_buf_in_use = false; | |
| 276 --buffer_length; | |
| 277 } // if | |
| 278 | |
| 279 #endif // ifdef CYGFUN_LIBC_STDIO_ungetc | |
| 280 | |
| 281 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 282 if (flags.buffering) { | |
| 283 cyg_uint8 *buff_to_read_from; | |
| 284 cyg_ucount32 bytes_available; | |
| 285 Cyg_ErrNo err; | |
| 286 | |
| 287 // this should really only be called after refill_read_buffer, but | |
| 288 // just in case | |
| 289 err = flush_output_unlocked(); | |
| 290 | |
| 291 if (err != ENOERR) { | |
| 292 unlock_me(); | |
| 293 return err; | |
| 294 } | |
| 295 | |
| 296 // we're now reading | |
| 297 flags.last_buffer_op_was_read = true; | |
| 298 | |
| 299 bytes_available = io_buf.get_buffer_addr_to_read( | |
| 300 (cyg_uint8 **)&buff_to_read_from ); | |
| 301 | |
| 302 *bytes_read += (bytes_available < buffer_length) ? bytes_available | |
| 303 : buffer_length; | |
| 304 if (*bytes_read) { | |
| 305 memcpy( user_buffer, buff_to_read_from, *bytes_read ); | |
| 306 io_buf.set_bytes_read( *bytes_read ); | |
| 307 } // if | |
| 308 | |
| 309 } // if | |
| 310 else | |
| 311 | |
| 312 #endif | |
| 313 | |
| 314 if (flags.readbuf_char_in_use && buffer_length) { | |
| 315 *user_buffer = readbuf_char; | |
| 316 *bytes_read = 1; | |
| 317 flags.readbuf_char_in_use = false; | |
| 318 } | |
| 319 | |
| 320 unlock_me(); | |
| 321 | |
| 322 return ENOERR; | |
| 323 } // read() | |
| 324 | |
| 325 | |
| 326 Cyg_ErrNo | |
| 327 Cyg_StdioStream::read_byte( cyg_uint8 *c ) | |
| 328 { | |
| 329 Cyg_ErrNo err=ENOERR; | |
| 330 | |
| 331 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 332 | |
| 333 if (!lock_me()) | |
| 334 return EBADF; // assume file is now invalid | |
| 335 | |
| 336 if (!flags.opened_for_read) { | |
| 337 unlock_me(); | |
| 338 return EINVAL; | |
| 339 } | |
| 340 | |
| 341 // this should really only be called after refill_read_buffer, but just | |
| 342 // in case | |
| 343 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 344 if (flags.buffering) | |
| 345 err = flush_output_unlocked(); | |
| 346 | |
| 347 if (err != ENOERR) | |
| 348 return err; | |
| 349 | |
| 350 // we're now reading | |
| 351 flags.last_buffer_op_was_read = true; | |
| 352 #endif | |
| 353 | |
| 354 # ifdef CYGFUN_LIBC_STDIO_ungetc | |
| 355 if (flags.unread_char_buf_in_use) { | |
| 356 *c = unread_char_buf; | |
| 357 flags.unread_char_buf_in_use = false; | |
| 358 unlock_me(); | |
| 359 return ENOERR; | |
| 360 } // if | |
| 361 # endif // ifdef CYGFUN_LIBC_STDIO_ungetc | |
| 362 | |
| 363 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 364 if (flags.buffering) { | |
| 365 cyg_uint8 *buff_to_read_from; | |
| 366 cyg_ucount32 bytes_available; | |
| 367 | |
| 368 bytes_available=io_buf.get_buffer_addr_to_read(&buff_to_read_from); | |
| 369 | |
| 370 if (bytes_available) { | |
| 371 *c = *buff_to_read_from; | |
| 372 io_buf.set_bytes_read(1); | |
| 373 } | |
| 374 else | |
| 375 err = EAGAIN; | |
| 376 } // if | |
| 377 else | |
| 378 | |
| 379 #endif | |
| 380 | |
| 381 | |
| 382 if (flags.readbuf_char_in_use) { | |
| 383 *c = readbuf_char; | |
| 384 flags.readbuf_char_in_use = false; | |
| 385 } | |
| 386 else | |
| 387 err = EAGAIN; | |
| 388 | |
| 389 unlock_me(); | |
| 390 | |
| 391 return err; | |
| 392 } // read_byte() | |
| 393 | |
| 394 | |
| 395 Cyg_ErrNo | |
| 396 Cyg_StdioStream::peek_byte( cyg_uint8 *c ) | |
| 397 { | |
| 398 Cyg_ErrNo err=ENOERR; | |
| 399 | |
| 400 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 401 | |
| 402 if (!lock_me()) | |
| 403 return EBADF; // assume file is now invalid | |
| 404 | |
| 405 if (!flags.opened_for_read) { | |
| 406 unlock_me(); | |
| 407 return EINVAL; | |
| 408 } | |
| 409 | |
| 410 // this should really only be called after refill_read_buffer, but just | |
| 411 // in case | |
| 412 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 413 if (flags.buffering) | |
| 414 err = flush_output_unlocked(); | |
| 415 | |
| 416 if (err != ENOERR) | |
| 417 return err; | |
| 418 | |
| 419 // we're now reading | |
| 420 flags.last_buffer_op_was_read = true; | |
| 421 #endif | |
| 422 | |
| 423 # ifdef CYGFUN_LIBC_STDIO_ungetc | |
| 424 if (flags.unread_char_buf_in_use) { | |
| 425 *c = unread_char_buf; | |
| 426 unlock_me(); | |
| 427 return ENOERR; | |
| 428 } // if | |
| 429 # endif // ifdef CYGFUN_LIBC_STDIO_ungetc | |
| 430 | |
| 431 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 432 if (flags.buffering) { | |
| 433 cyg_uint8 *buff_to_read_from; | |
| 434 cyg_ucount32 bytes_available; | |
| 435 | |
| 436 bytes_available=io_buf.get_buffer_addr_to_read(&buff_to_read_from); | |
| 437 | |
| 438 if (bytes_available) { | |
| 439 *c = *buff_to_read_from; | |
| 440 } | |
| 441 else | |
| 442 err = EAGAIN; | |
| 443 } // if | |
| 444 else | |
| 445 | |
| 446 #endif | |
| 447 | |
| 448 | |
| 449 if (flags.readbuf_char_in_use) { | |
| 450 *c = readbuf_char; | |
| 451 } | |
| 452 else | |
| 453 err = EAGAIN; | |
| 454 | |
| 455 unlock_me(); | |
| 456 | |
| 457 return err; | |
| 458 } // peek_byte() | |
| 459 | |
| 460 | |
| 461 Cyg_ErrNo | |
| 462 Cyg_StdioStream::flush_output_unlocked( void ) | |
| 463 { | |
| 464 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 465 Cyg_IORB iorb; | |
| 466 Cyg_ErrNo write_err=ENOERR; | |
| 467 | |
| 468 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 469 | |
| 470 if ( flags.last_buffer_op_was_read ) | |
| 471 return ENOERR; | |
| 472 | |
| 473 // first just check that we _can_ write to the device! | |
| 474 if ( !flags.opened_for_write ) | |
| 475 return EINVAL; | |
| 476 | |
| 477 // shortcut if nothing to do | |
| 478 if (io_buf.get_buffer_space_used() == 0) | |
| 479 return ENOERR; | |
| 480 | |
| 481 iorb.buffer_length = | |
| 482 io_buf.get_buffer_addr_to_read( (cyg_uint8 **)&iorb.buffer ); | |
| 483 | |
| 484 CYG_ASSERT( iorb.buffer_length > 0, | |
| 485 "There should be data to read but there isn't!"); | |
| 486 | |
| 487 write_err = (*my_device->write_blocking)( my_device->cookie, &iorb ); | |
| 488 | |
| 489 // we've just read it all, so just wipe it out | |
| 490 io_buf.drain_buffer(); | |
| 491 | |
| 492 return write_err; | |
| 493 | |
| 494 #else // ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 495 | |
| 496 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 497 | |
| 498 return ENOERR; | |
| 499 | |
| 500 #endif // ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 501 } // flush_output_unlocked() | |
| 502 | |
| 503 | |
| 504 | |
| 505 Cyg_ErrNo | |
| 506 Cyg_StdioStream::write( const cyg_uint8 *buffer, | |
| 507 cyg_ucount32 buffer_length, | |
| 508 cyg_ucount32 *bytes_written ) | |
| 509 { | |
| 510 Cyg_ErrNo write_err = ENOERR; | |
| 511 | |
| 512 CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" ); | |
| 513 | |
| 514 *bytes_written = 0; | |
| 515 | |
| 516 if (!lock_me()) | |
| 517 return EBADF; // assume file is now invalid | |
| 518 | |
| 519 // first just check that we _can_ write to the device! | |
| 520 if ( !flags.opened_for_write ) { | |
| 521 unlock_me(); | |
| 522 return EINVAL; | |
| 523 } | |
| 524 | |
| 525 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 526 if (flags.last_buffer_op_was_read == true) | |
| 527 io_buf.drain_buffer(); // nuke input bytes to prevent confusion | |
| 528 | |
| 529 flags.last_buffer_op_was_read = false; | |
| 530 | |
| 531 if (!flags.buffering) { | |
| 532 #endif | |
| 533 Cyg_IORB iorb; | |
| 534 iorb.buffer = (char *)buffer; | |
| 535 iorb.buffer_length = buffer_length; | |
| 536 | |
| 537 write_err = (*my_device->write_blocking)( my_device->cookie, | |
| 538 &iorb ); | |
| 539 | |
| 540 *bytes_written = iorb.xferred_length; | |
| 541 | |
| 542 #ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 543 } // if | |
| 544 else { | |
| 545 cyg_ucount32 bytes_available; | |
| 546 cyg_ucount32 bytes_to_write; | |
| 547 cyg_ucount32 newline_pos; | |
| 548 cyg_uint8 *write_addr; | |
| 549 cyg_bool must_flush = false; | |
| 550 | |
| 551 while ( buffer_length > 0 ) { | |
| 552 bytes_available = | |
| 553 io_buf.get_buffer_addr_to_write( &write_addr ); | |
| 554 | |
| 555 // we need to flush if we've no room or the buffer has an up | |
| 556 // and coming newline | |
| 557 if ( !bytes_available || must_flush ) { | |
| 558 write_err = flush_output_unlocked(); | |
| 559 | |
| 560 // harmless even if there was an error | |
| 561 bytes_available = | |
| 562 io_buf.get_buffer_addr_to_write( &write_addr ); | |
| 563 | |
| 564 CYG_ASSERT( bytes_available > 0, | |
| 565 "Help! still no bytes available in " | |
| 566 "write buffer" ); | |
| 567 } // if | |
| 568 | |
| 569 if (write_err) { | |
| 570 unlock_me(); | |
| 571 return write_err; | |
| 572 } // if | |
| 573 | |
| 574 // choose the lower of the buffer available and the length | |
| 575 // to write | |
| 576 bytes_to_write=(bytes_available < buffer_length) | |
| 577 ? bytes_available | |
| 578 : buffer_length; | |
| 579 | |
| 580 // if we're line buffered, we may want want to flush if there's | |
| 581 // a newline character, so lets find out | |
| 582 | |
| 583 if (flags.line_buffering) { | |
| 584 for (newline_pos=0; | |
| 585 newline_pos<bytes_to_write; | |
| 586 newline_pos++) { | |
| 587 if (buffer[newline_pos] == '\n') { | |
| 588 break; | |
| 589 } // if | |
| 590 } // for | |
| 591 // if we didn't reach the end | |
| 592 if (newline_pos != bytes_to_write) { | |
| 593 // shrink bytes_to_write down to the bit we need to | |
| 594 // flush including the newline itself | |
| 595 bytes_to_write = newline_pos + 1; | |
| 596 must_flush = true; | |
| 597 } // if | |
| 598 } // if | |
| 599 | |
| 600 _memcpy( write_addr, buffer, bytes_to_write ); | |
| 601 | |
| 602 *bytes_written += bytes_to_write; | |
| 603 buffer += bytes_to_write; | |
| 604 buffer_length -= bytes_to_write; | |
| 605 io_buf.set_bytes_written( bytes_to_write ); | |
| 606 | |
| 607 } // while | |
| 608 | |
| 609 if ( must_flush ) { | |
| 610 write_err = flush_output_unlocked(); | |
| 611 } // if | |
| 612 } // else | |
| 613 #endif // ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO | |
| 614 | |
| 615 unlock_me(); | |
| 616 | |
| 617 return write_err; | |
| 618 } // write() | |
| 619 | |
| 620 | |
| 621 #endif // if defined(CYGPKG_LIBC) && defined(CYGPKG_LIBC_STDIO) | |
| 622 | |
| 623 // EOF stream.cxx |
