Subversion Repositories HelenOS

Rev

Rev 4581 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4581 Rev 4718
Line 87... Line 87...
87
FILE *stdout = NULL;
87
FILE *stdout = NULL;
88
FILE *stderr = NULL;
88
FILE *stderr = NULL;
89
 
89
 
90
static LIST_INITIALIZE(files);
90
static LIST_INITIALIZE(files);
91
 
91
 
92
void stdio_init(int filc, fdi_node_t *filv[])
92
void __stdio_init(int filc, fdi_node_t *filv[])
93
{
93
{
94
    if (filc > 0) {
94
    if (filc > 0) {
95
        stdin = fopen_node(filv[0], "r");
95
        stdin = fopen_node(filv[0], "r");
96
    } else {
96
    } else {
97
        stdin = &stdin_null;
97
        stdin = &stdin_null;
Line 111... Line 111...
111
        stderr = &stderr_klog;
111
        stderr = &stderr_klog;
112
        list_append(&stderr->link, &files);
112
        list_append(&stderr->link, &files);
113
    }
113
    }
114
}
114
}
115
 
115
 
116
void stdio_done(void)
116
void __stdio_done(void)
117
{
117
{
118
    link_t *link = files.next;
118
    link_t *link = files.next;
119
   
119
   
120
    while (link != &files) {
120
    while (link != &files) {
121
        FILE *file = list_get_instance(link, FILE, link);
121
        FILE *file = list_get_instance(link, FILE, link);
Line 178... Line 178...
178
    stream->buf = buf;
178
    stream->buf = buf;
179
    stream->buf_size = size;
179
    stream->buf_size = size;
180
    stream->buf_head = stream->buf;
180
    stream->buf_head = stream->buf;
181
}
181
}
182
 
182
 
-
 
183
static void _setvbuf(FILE *stream)
-
 
184
{
-
 
185
    /* FIXME: Use more complex rules for setting buffering options. */
-
 
186
   
-
 
187
    switch (stream->fd) {
-
 
188
    case 1:
-
 
189
        setvbuf(stream, NULL, _IOLBF, BUFSIZ);
-
 
190
        break;
-
 
191
    case 0:
-
 
192
    case 2:
-
 
193
        setvbuf(stream, NULL, _IONBF, 0);
-
 
194
        break;
-
 
195
    default:
-
 
196
        setvbuf(stream, NULL, _IOFBF, BUFSIZ);
-
 
197
    }
-
 
198
}
-
 
199
 
183
/** Allocate stream buffer. */
200
/** Allocate stream buffer. */
184
static int _fallocbuf(FILE *stream)
201
static int _fallocbuf(FILE *stream)
185
{
202
{
186
    assert(stream->buf == NULL);
203
    assert(stream->buf == NULL);
187
 
204
   
188
    stream->buf = malloc(stream->buf_size);
205
    stream->buf = malloc(stream->buf_size);
189
    if (stream->buf == NULL) {
206
    if (stream->buf == NULL) {
190
        errno = ENOMEM;
207
        errno = ENOMEM;
191
        return -1;
208
        return -1;
192
    }
209
    }
193
 
210
   
194
    stream->buf_head = stream->buf;
211
    stream->buf_head = stream->buf;
195
    return 0;
212
    return 0;
196
}
213
}
197
 
214
 
198
/** Open a stream.
215
/** Open a stream.
Line 223... Line 240...
223
   
240
   
224
    stream->error = false;
241
    stream->error = false;
225
    stream->eof = false;
242
    stream->eof = false;
226
    stream->klog = false;
243
    stream->klog = false;
227
    stream->phone = -1;
244
    stream->phone = -1;
228
 
-
 
229
    /* FIXME: Should select buffering type based on what was opened. */
-
 
230
    setvbuf(stream, NULL, _IOFBF, BUFSIZ);
245
    _setvbuf(stream);
231
   
246
   
232
    list_append(&stream->link, &files);
247
    list_append(&stream->link, &files);
233
   
248
   
234
    return stream;
249
    return stream;
235
}
250
}
Line 246... Line 261...
246
    stream->fd = fd;
261
    stream->fd = fd;
247
    stream->error = false;
262
    stream->error = false;
248
    stream->eof = false;
263
    stream->eof = false;
249
    stream->klog = false;
264
    stream->klog = false;
250
    stream->phone = -1;
265
    stream->phone = -1;
251
 
-
 
252
    /* FIXME: Should select buffering type based on what was opened. */
-
 
253
    setvbuf(stream, NULL, _IOLBF, BUFSIZ);
266
    _setvbuf(stream);
254
   
267
   
255
    list_append(&stream->link, &files);
268
    list_append(&stream->link, &files);
256
   
269
   
257
    return stream;
270
    return stream;
258
}
271
}
Line 279... Line 292...
279
   
292
   
280
    stream->error = false;
293
    stream->error = false;
281
    stream->eof = false;
294
    stream->eof = false;
282
    stream->klog = false;
295
    stream->klog = false;
283
    stream->phone = -1;
296
    stream->phone = -1;
284
 
-
 
285
    /* FIXME: Should select buffering type based on what was opened. */
-
 
286
    setvbuf(stream, NULL, _IOLBF, BUFSIZ);
297
    _setvbuf(stream);
287
   
298
   
288
    list_append(&stream->link, &files);
299
    list_append(&stream->link, &files);
289
   
300
   
290
    return stream;
301
    return stream;
291
}
302
}
Line 329... Line 340...
329
 */
340
 */
330
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
341
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
331
{
342
{
332
    size_t left = size * nmemb;
343
    size_t left = size * nmemb;
333
    size_t done = 0;
344
    size_t done = 0;
334
 
345
   
335
    /* Make sure no data is pending write. */
346
    /* Make sure no data is pending write. */
336
    _fflushbuf(stream);
347
    _fflushbuf(stream);
337
 
348
   
338
    while ((left > 0) && (!stream->error) && (!stream->eof)) {
349
    while ((left > 0) && (!stream->error) && (!stream->eof)) {
339
        ssize_t rd = read(stream->fd, buf + done, left);
350
        ssize_t rd = read(stream->fd, buf + done, left);
340
       
351
       
341
        if (rd < 0)
352
        if (rd < 0)
342
            stream->error = true;
353
            stream->error = true;
Line 377... Line 388...
377
 
388
 
378
/** Drain stream buffer, do not sync stream. */
389
/** Drain stream buffer, do not sync stream. */
379
static void _fflushbuf(FILE *stream)
390
static void _fflushbuf(FILE *stream)
380
{
391
{
381
    size_t bytes_used;
392
    size_t bytes_used;
382
 
393
   
383
    if (!stream->buf || stream->btype == _IONBF || stream->error)
394
    if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error))
384
        return;
395
        return;
385
 
396
   
386
    bytes_used = stream->buf_head - stream->buf;
397
    bytes_used = stream->buf_head - stream->buf;
387
    if (bytes_used == 0)
398
    if (bytes_used == 0)
388
        return;
399
        return;
389
 
400
   
390
    (void) _fwrite(stream->buf, 1, bytes_used, stream);
401
    (void) _fwrite(stream->buf, 1, bytes_used, stream);
391
    stream->buf_head = stream->buf;
402
    stream->buf_head = stream->buf;
392
}
403
}
393
 
404
 
394
/** Write to a stream.
405
/** Write to a stream.
Line 407... Line 418...
407
    size_t buf_free;
418
    size_t buf_free;
408
    size_t total_written;
419
    size_t total_written;
409
    size_t i;
420
    size_t i;
410
    uint8_t b;
421
    uint8_t b;
411
    bool need_flush;
422
    bool need_flush;
412
 
423
   
413
    /* If not buffered stream, write out directly. */
424
    /* If not buffered stream, write out directly. */
414
    if (stream->btype == _IONBF)
425
    if (stream->btype == _IONBF) {
415
        return _fwrite(buf, size, nmemb, stream);
426
        now = _fwrite(buf, size, nmemb, stream);
-
 
427
        fflush(stream);
-
 
428
        return now;
-
 
429
    }
416
 
430
   
417
    /* Perform lazy allocation of stream buffer. */
431
    /* Perform lazy allocation of stream buffer. */
418
    if (stream->buf == NULL) {
432
    if (stream->buf == NULL) {
419
        if (_fallocbuf(stream) != 0)
433
        if (_fallocbuf(stream) != 0)
420
            return 0; /* Errno set by _fallocbuf(). */
434
            return 0; /* Errno set by _fallocbuf(). */
421
    }
435
    }
422
 
436
   
423
    data = (uint8_t *) buf;
437
    data = (uint8_t *) buf;
424
    bytes_left = size * nmemb;
438
    bytes_left = size * nmemb;
425
    total_written = 0;
439
    total_written = 0;
426
    need_flush = false;
440
    need_flush = false;
427
 
441
   
428
    while (!stream->error && bytes_left > 0) {
442
    while ((!stream->error) && (bytes_left > 0)) {
429
 
-
 
430
        buf_free = stream->buf_size - (stream->buf_head - stream->buf);
443
        buf_free = stream->buf_size - (stream->buf_head - stream->buf);
431
        if (bytes_left > buf_free)
444
        if (bytes_left > buf_free)
432
            now = buf_free;
445
            now = buf_free;
433
        else
446
        else
434
            now = bytes_left;
447
            now = bytes_left;
435
 
448
       
436
        for (i = 0; i < now; i++) {
449
        for (i = 0; i < now; i++) {
437
            b = data[i];
450
            b = data[i];
438
            stream->buf_head[i] = b;
451
            stream->buf_head[i] = b;
439
 
452
           
440
            if (b == '\n' && stream->btype == _IOLBF)
453
            if ((b == '\n') && (stream->btype == _IOLBF))
441
                need_flush = true;
454
                need_flush = true;
442
        }
455
        }
443
 
456
       
444
        buf += now;
457
        buf += now;
445
        stream->buf_head += now;
458
        stream->buf_head += now;
446
        buf_free -= now;
459
        buf_free -= now;
447
        bytes_left -= now;
460
        bytes_left -= now;
448
        total_written += now;
461
        total_written += now;
449
 
462
       
450
        if (buf_free == 0) {
463
        if (buf_free == 0) {
451
            /* Only need to drain buffer. */
464
            /* Only need to drain buffer. */
452
            _fflushbuf(stream);
465
            _fflushbuf(stream);
453
            need_flush = false;
466
            need_flush = false;
454
        }
467
        }
455
    }
468
    }
456
 
469
   
457
    if (need_flush)
470
    if (need_flush)
458
        fflush(stream);
471
        fflush(stream);
459
 
472
   
460
    return (total_written / size);
473
    return (total_written / size);
461
}
474
}
462
 
475
 
463
int fputc(wchar_t c, FILE *stream)
476
int fputc(wchar_t c, FILE *stream)
464
{
477
{
Line 493... Line 506...
493
}
506
}
494
 
507
 
495
int fgetc(FILE *stream)
508
int fgetc(FILE *stream)
496
{
509
{
497
    char c;
510
    char c;
498
 
511
   
499
    /* This could be made faster by only flushing when needed. */
512
    /* This could be made faster by only flushing when needed. */
500
    if (stdout)
513
    if (stdout)
501
        fflush(stdout);
514
        fflush(stdout);
502
    if (stderr)
515
    if (stderr)
503
        fflush(stderr);
516
        fflush(stderr);
504
 
517
   
505
    if (fread(&c, sizeof(char), 1, stream) < sizeof(char))
518
    if (fread(&c, sizeof(char), 1, stream) < sizeof(char))
506
        return EOF;
519
        return EOF;
507
   
520
   
508
    return (int) c;
521
    return (int) c;
509
}
522
}
Line 532... Line 545...
532
}
545
}
533
 
546
 
534
int fflush(FILE *stream)
547
int fflush(FILE *stream)
535
{
548
{
536
    _fflushbuf(stream);
549
    _fflushbuf(stream);
537
 
550
   
538
    if (stream->klog) {
551
    if (stream->klog) {
539
        klog_update();
552
        klog_update();
540
        return EOK;
553
        return EOK;
541
    }
554
    }
542
   
555