OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [language/] [c/] [libc/] [stdio/] [current/] [include/] [stream.inl] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
#ifndef CYGONCE_LIBC_STDIO_STREAM_INL
2
#define CYGONCE_LIBC_STDIO_STREAM_INL
3
//========================================================================
4
//
5
//      stream.inl
6
//
7
//      Inline functions for internal C library stdio stream interface
8
//
9
//========================================================================
10
// ####ECOSGPLCOPYRIGHTBEGIN####
11
// -------------------------------------------
12
// This file is part of eCos, the Embedded Configurable Operating System.
13
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
14
//
15
// eCos is free software; you can redistribute it and/or modify it under
16
// the terms of the GNU General Public License as published by the Free
17
// Software Foundation; either version 2 or (at your option) any later
18
// version.
19
//
20
// eCos is distributed in the hope that it will be useful, but WITHOUT
21
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23
// for more details.
24
//
25
// You should have received a copy of the GNU General Public License
26
// along with eCos; if not, write to the Free Software Foundation, Inc.,
27
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
28
//
29
// As a special exception, if other files instantiate templates or use
30
// macros or inline functions from this file, or you compile this file
31
// and link it with other works to produce a work based on this file,
32
// this file does not by itself cause the resulting work to be covered by
33
// the GNU General Public License. However the source code for this file
34
// must still be made available in accordance with section (3) of the GNU
35
// General Public License v2.
36
//
37
// This exception does not invalidate any other reasons why a work based
38
// on this file might be covered by the GNU General Public License.
39
// -------------------------------------------
40
// ####ECOSGPLCOPYRIGHTEND####
41
//========================================================================
42
//#####DESCRIPTIONBEGIN####
43
//
44
// Author(s):     jlarmour
45
// Contributors:
46
// Date:          2000-04-19
47
// Purpose:
48
// Description:
49
// Usage:         Do not include this file -
50
//                #include  instead.
51
//
52
//####DESCRIPTIONEND####
53
//
54
//========================================================================
55
 
56
// CONFIGURATION
57
 
58
#include     // Configuration header
59
 
60
// INCLUDES
61
 
62
#include     // Common project-wide type definitions
63
#include                 // NULL and size_t from compiler
64
#include                  // Error codes
65
#include  // Just be sure that this really is
66
                                   // included
67
 
68
#include      // I/O system inlines
69
 
70
// FUNCTIONS
71
 
72
#ifdef CYGDBG_USE_ASSERTS
73
inline cyg_bool
74
Cyg_StdioStream::check_this( cyg_assert_class_zeal zeal ) const
75
{
76
    // check that it has the magic word set meaning it is valid.
77
    if ( magic_validity_word != 0x7b4321ce )
78
        return false;
79
    return true;
80
} // check_this()
81
 
82
#endif // ifdef CYGDBG_USE_ASSERTS
83
 
84
 
85
 
86
// LOCKING FUNCTIONS
87
 
88
// returns true on success
89
inline cyg_bool
90
Cyg_StdioStream::lock_me( void )
91
{
92
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
93
 
94
#ifdef CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
95
    return stream_lock.lock();
96
#else
97
    // otherwise it "worked"
98
    return true;
99
#endif
100
 
101
} // lock_me()
102
 
103
 
104
// returns true on success
105
inline cyg_bool
106
Cyg_StdioStream::trylock_me( void )
107
{
108
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
109
 
110
#ifdef CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
111
    return stream_lock.trylock();
112
#else
113
    // otherwise it "worked"
114
    return true;
115
#endif
116
 
117
} // lock_me()
118
 
119
 
120
inline void
121
Cyg_StdioStream::unlock_me( void )
122
{
123
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
124
 
125
#ifdef CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS
126
    stream_lock.unlock();
127
#endif
128
} // unlock_me()
129
 
130
 
131
// DESTRUCTOR
132
 
133
inline Cyg_ErrNo
134
Cyg_StdioStream::close()
135
{
136
    Cyg_ErrNo err = ENOERR;
137
 
138
    if (!lock_me())
139
        return EBADF;
140
 
141
    if( my_device != CYG_STDIO_HANDLE_NULL )
142
    {
143
        flush_output_unlocked();
144
 
145
        err = cyg_stdio_close( my_device );
146
 
147
        if( err == ENOERR )
148
            my_device = CYG_STDIO_HANDLE_NULL;
149
    }
150
 
151
    unlock_me();
152
 
153
    return err;
154
} // close()
155
 
156
inline
157
Cyg_StdioStream::~Cyg_StdioStream()
158
{
159
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
160
 
161
    // Close the device if it has not already been closed.
162
    if( my_device != CYG_STDIO_HANDLE_NULL )
163
        close();
164
 
165
#ifdef CYGDBG_USE_ASSERTS
166
    magic_validity_word = 0xbadbad;
167
#endif
168
} // Cyg_StdioStream destructor
169
 
170
 
171
// MEMBER FUNCTIONS
172
 
173
 
174
// this is currently just a wrapper around write, but having this interface
175
// leaves scope for optimisations in future
176
inline Cyg_ErrNo
177
Cyg_StdioStream::write_byte( cyg_uint8 c )
178
{
179
    cyg_ucount32 dummy_bytes_written;
180
    Cyg_ErrNo err;
181
 
182
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
183
 
184
    err = write( &c, 1, &dummy_bytes_written );
185
 
186
    CYG_ASSERT( (err!=ENOERR) || (dummy_bytes_written==1),
187
                "Single byte not written, but no error returned!" );
188
 
189
    return err;
190
} // write_byte()
191
 
192
 
193
inline Cyg_ErrNo
194
Cyg_StdioStream::unread_byte( cyg_uint8 c )
195
{
196
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
197
 
198
#ifdef CYGFUN_LIBC_STDIO_ungetc
199
    if (!lock_me())
200
        return EBADF;  // assume file is now invalid
201
 
202
    if (flags.unread_char_buf_in_use) {
203
        unlock_me();
204
        return ENOMEM;
205
    } // if
206
 
207
    flags.unread_char_buf_in_use = true;
208
    unread_char_buf = c;
209
 
210
    // can't be at EOF any more
211
    flags.at_eof = false;
212
 
213
    if (position)    // position is always 0 for certain devices
214
        --position;
215
 
216
    unlock_me();
217
 
218
    return ENOERR;
219
 
220
#else // ifdef CYGFUN_LIBC_STDIO_ungetc
221
 
222
    return ENOSYS;
223
#endif // ifdef CYGFUN_LIBC_STDIO_ungetc
224
} // unread_byte()
225
 
226
 
227
inline cyg_ucount32
228
Cyg_StdioStream::bytes_available_to_read( void )
229
{
230
    cyg_ucount32 bytes=0;
231
 
232
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
233
 
234
#ifdef CYGFUN_LIBC_STDIO_ungetc
235
    if (flags.unread_char_buf_in_use)
236
        ++bytes;
237
#endif
238
 
239
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
240
 
241
    // either the last operation was a read, which attempted to read bytes
242
    // into the buffer, or there are no bytes in the buffer
243
 
244
    if (flags.buffering) {
245
        if (flags.last_buffer_op_was_read == true)
246
            bytes += io_buf.get_buffer_space_used();
247
    }
248
    else
249
 
250
#endif
251
 
252
    if (flags.readbuf_char_in_use)
253
        ++bytes;
254
 
255
    return bytes;
256
} // bytes_available_to_read()
257
 
258
 
259
 
260
inline Cyg_ErrNo
261
Cyg_StdioStream::flush_output( void )
262
{
263
    Cyg_ErrNo err;
264
 
265
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
266
 
267
    if (!lock_me())
268
        return EBADF;  // assume file is now invalid
269
 
270
    err = flush_output_unlocked();
271
 
272
    unlock_me();
273
 
274
    return err;
275
} // flush_output()
276
 
277
 
278
// get error status for this file
279
inline Cyg_ErrNo
280
Cyg_StdioStream::get_error( void )
281
{
282
    Cyg_ErrNo err_temp;
283
 
284
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
285
 
286
    if (!lock_me())
287
        return EBADF;     // well, we've certainly got an error now!
288
 
289
    err_temp = error;
290
 
291
    unlock_me();
292
 
293
    return err_temp;
294
} // get_error()
295
 
296
 
297
// set error status for this file
298
inline void
299
Cyg_StdioStream::set_error( Cyg_ErrNo errno_to_set )
300
{
301
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
302
 
303
    if (!lock_me())
304
    {
305
        errno = EBADF; // best we can do - we can't trust error to be there
306
        return;
307
    } // if
308
 
309
    errno = error = errno_to_set;
310
 
311
    if ( EEOF == error )
312
        flags.at_eof = 1;
313
 
314
    unlock_me();
315
} // set_error()
316
 
317
 
318
// are we at EOF? true means we are, false means no
319
inline cyg_bool
320
Cyg_StdioStream::get_eof_state( void )
321
{
322
    cyg_bool eof_temp;
323
 
324
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
325
 
326
    if (!lock_me())
327
        return false;     // not much we can do here
328
 
329
    eof_temp = flags.at_eof;
330
 
331
    unlock_me();
332
 
333
    return eof_temp;
334
} // get_eof_state()
335
 
336
 
337
// Set whether we are at EOF.
338
inline void
339
Cyg_StdioStream::set_eof_state( cyg_bool eof_to_set )
340
{
341
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
342
 
343
    if (!lock_me())
344
        return;     // not much we can do here
345
 
346
    flags.at_eof = eof_to_set;
347
 
348
    unlock_me();
349
} // set_eof_state()
350
 
351
 
352
// retrieve position
353
inline Cyg_ErrNo
354
Cyg_StdioStream::get_position( fpos_t *pos )
355
{
356
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
357
 
358
    if (!lock_me())
359
        return EBADF; // assume file is now invalid
360
 
361
    *pos = position;
362
 
363
    unlock_me();
364
 
365
    return ENOERR;
366
 
367
} // get_position()
368
 
369
 
370
// set absolute position
371
inline Cyg_ErrNo
372
Cyg_StdioStream::set_position( fpos_t pos, int whence )
373
{
374
    CYG_ASSERTCLASS( this, "Stream object is not a valid stream!" );
375
 
376
#ifndef CYGPKG_LIBC_STDIO_FILEIO
377
    // this is currently a workaround until we have real files
378
    // this will be corrected when we decide the true filesystem interface
379
 
380
    Cyg_ErrNo err;
381
    cyg_uint8 c;
382
 
383
    if ((whence != SEEK_CUR) || pos < 0)
384
        return ENOSYS;
385
 
386
    if (!lock_me())
387
        return EBADF; // assume file is now invalid
388
 
389
    // Drain read buffer
390
 
391
    for ( ; pos > 0 ; pos-- ) {
392
        err = read_byte( &c );
393
        if (err == EAGAIN)
394
            err=refill_read_buffer();
395
 
396
        // if read_byte retured error, or refill_read_buffer returned error
397
        if (err) {
398
            unlock_me();
399
            return err;
400
        } // if
401
    } // for
402
 
403
    unlock_me();
404
 
405
    return ENOERR;
406
 
407
#else
408
 
409
    if (!lock_me())
410
        return EBADF; // assume file is now invalid
411
 
412
    if ( whence != SEEK_END ) {
413
        off_t bytesavail = (off_t)bytes_available_to_read();
414
        off_t abspos = (whence == SEEK_CUR) ? position + pos : pos;
415
        off_t posdiff = abspos - position;
416
 
417
        if ( posdiff >= 0 && bytesavail > posdiff ) {
418
            // can just "seek" within the existing buffer
419
#ifdef CYGFUN_LIBC_STDIO_ungetc
420
            if (posdiff>0 && flags.unread_char_buf_in_use) {
421
                flags.unread_char_buf_in_use = false;
422
                posdiff--;
423
            }
424
#endif
425
#ifdef CYGSEM_LIBC_STDIO_WANT_BUFFERED_IO
426
            if (posdiff>0 && flags.buffering) {
427
                io_buf.set_bytes_read(posdiff);
428
                posdiff=0;
429
            } else
430
#endif
431
            if (posdiff>0 && flags.readbuf_char_in_use) {
432
                flags.readbuf_char_in_use = false;
433
                posdiff--;
434
            }
435
            CYG_ASSERT(posdiff==0, "Failed to seek within buffer correctly");
436
 
437
            position = abspos;
438
            unlock_me();
439
            return ENOERR;
440
        } // endif (bytesavail > posdiff)
441
 
442
        if (whence == SEEK_CUR) {
443
            position += bytesavail;
444
            pos -= bytesavail;
445
        }
446
    } //endif (whence != SEEK_END)
447
 
448
    Cyg_ErrNo err;
449
 
450
    // Flush output if any present.
451
    err = flush_output_unlocked();
452
 
453
    if( err == ENOERR )
454
    {
455
        off_t newpos=pos;
456
 
457
        // Clear any input out of input buffer and any ungot chars
458
        // from unread buffer.
459
        io_buf.drain_buffer();
460
 
461
#ifdef CYGFUN_LIBC_STDIO_ungetc
462
        flags.unread_char_buf_in_use = false;
463
#endif
464
 
465
        // Clear EOF indicator.
466
        flags.at_eof = false;
467
 
468
        // Seek the file to the correct place
469
        err = cyg_stdio_lseek( my_device, &newpos, whence );
470
 
471
        if ( err == ENOERR) {
472
          // update stream pos
473
          position = newpos;
474
        }
475
    }
476
 
477
    unlock_me();
478
 
479
    return err;
480
#endif
481
 
482
} // set_position()
483
 
484
 
485
#endif // CYGONCE_LIBC_STDIO_STREAM_INL multiple inclusion protection
486
 
487
// EOF stream.inl

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.