Subversion Repositories HelenOS

Rev

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

Rev 4210 Rev 4213
Line 80... Line 80...
80
 
80
 
81
static char nullstr[] = "(NULL)";
81
static char nullstr[] = "(NULL)";
82
static char digits_small[] = "0123456789abcdef";
82
static char digits_small[] = "0123456789abcdef";
83
static char digits_big[] = "0123456789ABCDEF";
83
static char digits_big[] = "0123456789ABCDEF";
84
 
84
 
85
/** Print one or more UTF-8 characters without adding newline.
85
/** Print one or more characters without adding newline.
86
 *
86
 *
87
 * @param buf  Buffer holding UTF-8 characters with size of
87
 * @param buf  Buffer holding characters with size of
88
 *             at least size bytes. NULL is not allowed!
88
 *             at least size bytes. NULL is not allowed!
89
 * @param size Size of the buffer in bytes.
89
 * @param size Size of the buffer in bytes.
90
 * @param ps   Output method and its data.
90
 * @param ps   Output method and its data.
91
 *
91
 *
92
 * @return Number of UTF-8 characters printed.
92
 * @return Number of characters printed.
93
 *
93
 *
94
 */
94
 */
95
static int printf_putnchars_utf8(const char *buf, size_t size,
95
static int printf_putnchars(const char *buf, size_t size,
96
    printf_spec_t *ps)
96
    printf_spec_t *ps)
97
{
97
{
98
    return ps->write_utf8((void *) buf, size, ps->data);
98
    return ps->str_write((void *) buf, size, ps->data);
99
}
99
}
100
 
100
 
101
/** Print one or more UTF-32 characters without adding newline.
101
/** Print one or more wide characters without adding newline.
102
 *
102
 *
103
 * @param buf  Buffer holding UTF-32 characters with size of
103
 * @param buf  Buffer holding wide characters with size of
104
 *             at least size bytes. NULL is not allowed!
104
 *             at least size bytes. NULL is not allowed!
105
 * @param size Size of the buffer in bytes.
105
 * @param size Size of the buffer in bytes.
106
 * @param ps   Output method and its data.
106
 * @param ps   Output method and its data.
107
 *
107
 *
108
 * @return Number of UTF-32 characters printed.
108
 * @return Number of wide characters printed.
109
 *
109
 *
110
 */
110
 */
111
static int printf_putnchars_utf32(const wchar_t *buf, size_t size,
111
static int printf_wputnchars(const wchar_t *buf, size_t size,
112
    printf_spec_t *ps)
112
    printf_spec_t *ps)
113
{
113
{
114
    return ps->write_utf32((void *) buf, size, ps->data);
114
    return ps->wstr_write((void *) buf, size, ps->data);
115
}
115
}
116
 
116
 
117
/** Print string without adding newline.
117
/** Print string without adding a newline.
118
 *
118
 *
119
 * @param str   String to print.
119
 * @param str String to print.
120
 * @param ps    Write function specification and support data.
120
 * @param ps  Write function specification and support data.
121
 *
121
 *
122
 * @return Number of characters printed.
122
 * @return Number of characters printed.
123
 *
123
 *
124
 */
124
 */
125
static int printf_putstr(const char *str, printf_spec_t *ps)
125
static int printf_putstr(const char *str, printf_spec_t *ps)
126
{
126
{
127
    if (str == NULL)
127
    if (str == NULL)
128
        return printf_putnchars_utf8(nullstr, str_size(nullstr), ps);
128
        return printf_putnchars(nullstr, str_size(nullstr), ps);
129
   
129
   
130
    return ps->write_utf8((void *) str, str_size(str), ps->data);
130
    return ps->str_write((void *) str, str_size(str), ps->data);
131
}
131
}
132
 
132
 
133
/** Print one ASCII character.
133
/** Print one ASCII character.
134
 *
134
 *
135
 * @param c  ASCII character to be printed.
135
 * @param c  ASCII character to be printed.
Line 139... Line 139...
139
 *
139
 *
140
 */
140
 */
141
static int printf_putchar(const char ch, printf_spec_t *ps)
141
static int printf_putchar(const char ch, printf_spec_t *ps)
142
{
142
{
143
    if (!ascii_check(ch))
143
    if (!ascii_check(ch))
144
        return ps->write_utf8((void *) &invalch, 1, ps->data);
144
        return ps->str_write((void *) &invalch, 1, ps->data);
145
   
145
   
146
    return ps->write_utf8(&ch, 1, ps->data);
146
    return ps->str_write(&ch, 1, ps->data);
147
}
147
}
148
 
148
 
149
/** Print one UTF-32 character.
149
/** Print one wide character.
150
 *
150
 *
151
 * @param c  UTF-32 character to be printed.
151
 * @param c  Wide character to be printed.
152
 * @param ps Output method.
152
 * @param ps Output method.
153
 *
153
 *
154
 * @return Number of characters printed.
154
 * @return Number of characters printed.
155
 *
155
 *
156
 */
156
 */
157
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
157
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
158
{
158
{
159
    if (!unicode_check(ch))
159
    if (!chr_check(ch))
160
        return ps->write_utf8((void *) &invalch, 1, ps->data);
160
        return ps->str_write((void *) &invalch, 1, ps->data);
161
   
161
   
162
    return ps->write_utf32(&ch, sizeof(wchar_t), ps->data);
162
    return ps->wstr_write(&ch, sizeof(wchar_t), ps->data);
163
}
163
}
164
 
164
 
165
/** Print one formatted ASCII character.
165
/** Print one formatted ASCII character.
166
 *
166
 *
167
 * @param ch    Character to print.
167
 * @param ch    Character to print.
Line 198... Line 198...
198
    }
198
    }
199
   
199
   
200
    return (int) (counter + 1);
200
    return (int) (counter + 1);
201
}
201
}
202
 
202
 
203
/** Print one formatted UTF-32 character.
203
/** Print one formatted wide character.
204
 *
204
 *
205
 * @param ch    Character to print.
205
 * @param ch    Character to print.
206
 * @param width Width modifier.
206
 * @param width Width modifier.
207
 * @param flags Flags that change the way the character is printed.
207
 * @param flags Flags that change the way the character is printed.
208
 *
208
 *
Line 236... Line 236...
236
    }
236
    }
237
   
237
   
238
    return (int) (counter + 1);
238
    return (int) (counter + 1);
239
}
239
}
240
 
240
 
241
/** Format and print a string.
241
/** Print string.
242
 *
242
 *
243
 * @param str       String to be printed.
243
 * @param str       String to be printed.
244
 * @param width     Width modifier.
244
 * @param width     Width modifier.
245
 * @param precision Precision modifier.
245
 * @param precision Precision modifier.
246
 * @param flags     Flags that modify the way the string is printed.
246
 * @param flags     Flags that modify the way the string is printed.
Line 268... Line 268...
268
        }
268
        }
269
    }
269
    }
270
 
270
 
271
    /* Part of @a str fitting into the alloted space. */
271
    /* Part of @a str fitting into the alloted space. */
272
    int retval;
272
    int retval;
273
    size_t size = str_wsize(str, precision);
273
    size_t size = str_lsize(str, precision);
274
    if ((retval = printf_putnchars_utf8(str, size, ps)) < 0)
274
    if ((retval = printf_putnchars(str, size, ps)) < 0)
275
        return -counter;
275
        return -counter;
276
 
276
 
277
    counter += retval;
277
    counter += retval;
278
 
278
 
279
    /* Right padding */
279
    /* Right padding */
Line 284... Line 284...
284
 
284
 
285
    return ((int) counter);
285
    return ((int) counter);
286
 
286
 
287
}
287
}
288
 
288
 
289
/** Format and print a wide string.
289
/** Print wide string.
290
 *
290
 *
291
 * @param wstr      Wide string to be printed.
291
 * @param str       Wide string to be printed.
292
 * @param width     Width modifier.
292
 * @param width     Width modifier.
293
 * @param precision Precision modifier.
293
 * @param precision Precision modifier.
294
 * @param flags     Flags that modify the way the string is printed.
294
 * @param flags     Flags that modify the way the string is printed.
295
 *
295
 *
296
 * @return      Number of characters printed, negative value
296
 * @return Number of wide characters printed, negative value on failure.
297
 *          on failure.
-
 
298
 */
297
 */
299
static int print_wstr(wchar_t *wstr, int width, unsigned int precision,
298
static int print_wstr(wchar_t *str, int width, unsigned int precision,
300
    uint32_t flags, printf_spec_t *ps)
299
    uint32_t flags, printf_spec_t *ps)
301
{
300
{
302
    if (wstr == NULL)
301
    if (str == NULL)
303
        return printf_putstr(nullstr, ps);
302
        return printf_putstr(nullstr, ps);
304
 
303
 
305
    /* Print leading spaces. */
304
    /* Print leading spaces. */
306
    size_t strw = wstr_length(wstr);
305
    size_t strw = wstr_length(str);
307
    if (precision == 0)
306
    if (precision == 0)
308
        precision = strw;
307
        precision = strw;
309
 
308
 
310
    /* Left padding */
309
    /* Left padding */
311
    count_t counter = 0;
310
    count_t counter = 0;
Line 317... Line 316...
317
        }
316
        }
318
    }
317
    }
319
 
318
 
320
    /* Part of @a wstr fitting into the alloted space. */
319
    /* Part of @a wstr fitting into the alloted space. */
321
    int retval;
320
    int retval;
322
    size_t size = wstr_wlength(wstr, precision) * sizeof(wchar_t);
321
    size_t size = wstr_lsize(str, precision);
323
    if ((retval = printf_putnchars_utf32(wstr, size, ps)) < 0)
322
    if ((retval = printf_wputnchars(str, size, ps)) < 0)
324
        return -counter;
323
        return -counter;
325
 
324
 
326
    counter += retval;
325
    counter += retval;
327
 
326
 
328
    /* Right padding */
327
    /* Right padding */
Line 421... Line 420...
421
    if (flags & __PRINTF_FLAG_ZEROPADDED) {
420
    if (flags & __PRINTF_FLAG_ZEROPADDED) {
422
        if ((precision == 0) && (width > size))
421
        if ((precision == 0) && (width > size))
423
            precision = width - size + number_size;
422
            precision = width - size + number_size;
424
    }
423
    }
425
   
424
   
426
    /* Print leading spaces. */
425
    /* Print leading spaces */
427
    if (number_size > precision) {
426
    if (number_size > precision) {
428
        /* Print the whole number, not only a part. */
427
        /* Print the whole number, not only a part */
429
        precision = number_size;
428
        precision = number_size;
430
    }
429
    }
431
   
430
   
432
    width -= precision + size - number_size;
431
    width -= precision + size - number_size;
433
    count_t counter = 0;
432
    count_t counter = 0;
Line 437... Line 436...
437
            if (printf_putchar(' ', ps) == 1)
436
            if (printf_putchar(' ', ps) == 1)
438
                counter++;
437
                counter++;
439
        }
438
        }
440
    }
439
    }
441
   
440
   
442
    /* Print sign. */
441
    /* Print sign */
443
    if (sgn) {
442
    if (sgn) {
444
        if (printf_putchar(sgn, ps) == 1)
443
        if (printf_putchar(sgn, ps) == 1)
445
            counter++;
444
            counter++;
446
    }
445
    }
447
   
446
   
448
    /* Print prefix. */
447
    /* Print prefix */
449
    if (flags & __PRINTF_FLAG_PREFIX) {
448
    if (flags & __PRINTF_FLAG_PREFIX) {
450
        switch(base) {
449
        switch(base) {
451
        case 2:
450
        case 2:
452
            /* Binary formating is not standard, but usefull */
451
            /* Binary formating is not standard, but usefull */
453
            if (printf_putchar('0', ps) == 1)
452
            if (printf_putchar('0', ps) == 1)
Line 476... Line 475...
476
            }
475
            }
477
            break;
476
            break;
478
        }
477
        }
479
    }
478
    }
480
   
479
   
481
    /* Print leading zeroes. */
480
    /* Print leading zeroes */
482
    precision -= number_size;
481
    precision -= number_size;
483
    while (precision-- > 0) {
482
    while (precision-- > 0) {
484
        if (printf_putchar('0', ps) == 1)
483
        if (printf_putchar('0', ps) == 1)
485
            counter++;
484
            counter++;
486
    }
485
    }
487
   
486
   
488
    /* Print the number itself. */
487
    /* Print the number itself */
489
    int retval;
488
    int retval;
490
    if ((retval = printf_putstr(++ptr, ps)) > 0)
489
    if ((retval = printf_putstr(++ptr, ps)) > 0)
491
        counter += retval;
490
        counter += retval;
492
   
491
   
493
    /* Print tailing spaces. */
492
    /* Print tailing spaces */
494
   
493
   
495
    while (width-- > 0) {
494
    while (width-- > 0) {
496
        if (printf_putchar(' ', ps) == 1)
495
        if (printf_putchar(' ', ps) == 1)
497
            counter++;
496
            counter++;
498
    }
497
    }
Line 543... Line 542...
543
 * TYPE:@n
542
 * TYPE:@n
544
 *  - "hh" Signed or unsigned char.@n
543
 *  - "hh" Signed or unsigned char.@n
545
 *  - "h"  Signed or unsigned short.@n
544
 *  - "h"  Signed or unsigned short.@n
546
 *  - ""   Signed or unsigned int (default value).@n
545
 *  - ""   Signed or unsigned int (default value).@n
547
 *  - "l"  Signed or unsigned long int.@n
546
 *  - "l"  Signed or unsigned long int.@n
548
 *         If conversion is "c", the character is wchar_t (UTF-32).@n
547
 *         If conversion is "c", the character is wchar_t (wide character).@n
549
 *         If conversion is "s", the string is wchar_t * (UTF-32).@n
548
 *         If conversion is "s", the string is wchar_t * (wide string).@n
550
 *  - "ll" Signed or unsigned long long int.@n
549
 *  - "ll" Signed or unsigned long long int.@n
551
 *
550
 *
552
 * CONVERSION:@n
551
 * CONVERSION:@n
553
 *  - % Print percentile character itself.
552
 *  - % Print percentile character itself.
554
 *
553
 *
555
 *  - c Print single character. The character is expected to be plain
554
 *  - c Print single character. The character is expected to be plain
556
 *      ASCII (e.g. only values 0 .. 127 are valid).@n
555
 *      ASCII (e.g. only values 0 .. 127 are valid).@n
557
 *      If type is "l", then the character is expected to be UTF-32
556
 *      If type is "l", then the character is expected to be wide character
558
 *      (e.g. values 0 .. 0x10ffff are valid).
557
 *      (e.g. values 0 .. 0x10ffff are valid).
559
 *
558
 *
560
 *  - s Print zero terminated string. If a NULL value is passed as
559
 *  - s Print zero terminated string. If a NULL value is passed as
561
 *      value, "(NULL)" is printed instead.@n
560
 *      value, "(NULL)" is printed instead.@n
562
 *      The string is expected to be correctly encoded UTF-8 (or plain
-
 
563
 *      ASCII, which is a subset of UTF-8).@n
-
 
564
 *      If type is "l", then the string is expected to be correctly
561
 *      If type is "l", then the string is expected to be wide string.
565
 *      encoded UTF-32.
-
 
566
 *
562
 *
567
 *  - P, p Print value of a pointer. Void * value is expected and it is
563
 *  - P, p Print value of a pointer. Void * value is expected and it is
568
 *         printed in hexadecimal notation with prefix (as with \%#X / \%#x
564
 *         printed in hexadecimal notation with prefix (as with \%#X / \%#x
569
 *         for 32-bit or \%#X / \%#x for 64-bit long pointers).
565
 *         for 32-bit or \%#X / \%#x for 64-bit long pointers).
570
 *
566
 *
Line 583... Line 579...
583
 *         not printed by default.
579
 *         not printed by default.
584
 *
580
 *
585
 * All other characters from fmt except the formatting directives are printed
581
 * All other characters from fmt except the formatting directives are printed
586
 * verbatim.
582
 * verbatim.
587
 *
583
 *
588
 * @param fmt Format string.
584
 * @param fmt Format NULL-terminated string.
-
 
585
 *
589
 * @return Number of characters printed, negative value on failure.
586
 * @return Number of characters printed, negative value on failure.
590
 *
587
 *
591
 */
588
 */
592
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
589
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
593
{
590
{
594
    size_t i = 0;  /* Index of the currently processed character from fmt */
591
    size_t i;        /* Index of the currently processed character from fmt */
595
    size_t nxt = 0;
592
    size_t nxt = 0;  /* Index of the next character from fmt */
596
    size_t j = 0;  /* Index to the first not printed nonformating character */
593
    size_t j = 0;    /* Index to the first not printed nonformating character */
597
   
594
   
598
    wchar_t uc;           /* Current character decoded from fmt */
-
 
599
    count_t counter = 0;  /* Number of characters printed */
595
    count_t counter = 0;  /* Number of characters printed */
600
    int retval;           /* Return values from nested functions */
596
    int retval;           /* Return values from nested functions */
601
   
597
   
602
    while (true) {
598
    while (true) {
603
        i = nxt;
599
        i = nxt;
604
        uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
600
        wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
605
 
601
       
606
        if (uc == '\0') break;
602
        if (uc == 0)
-
 
603
            break;
607
 
604
       
608
        /* Control character */
605
        /* Control character */
609
        if (uc == '%') {
606
        if (uc == '%') {
610
            /* Print common characters if any processed */
607
            /* Print common characters if any processed */
611
            if (i > j) {
608
            if (i > j) {
612
                if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
609
                if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
613
                    /* Error */
610
                    /* Error */
614
                    counter = -counter;
611
                    counter = -counter;
615
                    goto out;
612
                    goto out;
616
                }
613
                }
617
                counter += retval;
614
                counter += retval;
Line 623... Line 620...
623
            uint32_t flags = 0;
620
            uint32_t flags = 0;
624
            bool end = false;
621
            bool end = false;
625
           
622
           
626
            do {
623
            do {
627
                i = nxt;
624
                i = nxt;
628
                uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
625
                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
629
                switch (uc) {
626
                switch (uc) {
630
                case '#':
627
                case '#':
631
                    flags |= __PRINTF_FLAG_PREFIX;
628
                    flags |= __PRINTF_FLAG_PREFIX;
632
                    break;
629
                    break;
633
                case '-':
630
                case '-':
Line 651... Line 648...
651
            int width = 0;
648
            int width = 0;
652
            if (isdigit(uc)) {
649
            if (isdigit(uc)) {
653
                while (true) {
650
                while (true) {
654
                    width *= 10;
651
                    width *= 10;
655
                    width += uc - '0';
652
                    width += uc - '0';
656
 
653
                   
657
                    i = nxt;
654
                    i = nxt;
658
                    uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
655
                    uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
659
                    if (uc == '\0')
656
                    if (uc == 0)
660
                        break;
657
                        break;
661
                    if (!isdigit(uc))
658
                    if (!isdigit(uc))
662
                        break;
659
                        break;
663
                }
660
                }
664
            } else if (uc == '*') {
661
            } else if (uc == '*') {
665
                /* Get width value from argument list */
662
                /* Get width value from argument list */
666
                i = nxt;
663
                i = nxt;
667
                uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
664
                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
668
                width = (int) va_arg(ap, int);
665
                width = (int) va_arg(ap, int);
669
                if (width < 0) {
666
                if (width < 0) {
670
                    /* Negative width sets '-' flag */
667
                    /* Negative width sets '-' flag */
671
                    width *= -1;
668
                    width *= -1;
672
                    flags |= __PRINTF_FLAG_LEFTALIGNED;
669
                    flags |= __PRINTF_FLAG_LEFTALIGNED;
Line 675... Line 672...
675
           
672
           
676
            /* Precision and '*' operator */
673
            /* Precision and '*' operator */
677
            int precision = 0;
674
            int precision = 0;
678
            if (uc == '.') {
675
            if (uc == '.') {
679
                i = nxt;
676
                i = nxt;
680
                uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
677
                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
681
                if (isdigit(uc)) {
678
                if (isdigit(uc)) {
682
                    while (true) {
679
                    while (true) {
683
                        precision *= 10;
680
                        precision *= 10;
684
                        precision += uc - '0';
681
                        precision += uc - '0';
685
 
682
                       
686
                        i = nxt;
683
                        i = nxt;
687
                        uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
684
                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
688
                        if (uc == '\0')
685
                        if (uc == 0)
689
                            break;
686
                            break;
690
                        if (!isdigit(uc))
687
                        if (!isdigit(uc))
691
                            break;
688
                            break;
692
                    }
689
                    }
693
                } else if (uc == '*') {
690
                } else if (uc == '*') {
694
                    /* Get precision value from the argument list */
691
                    /* Get precision value from the argument list */
695
                    i = nxt;
692
                    i = nxt;
696
                    uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
693
                    uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
697
                    precision = (int) va_arg(ap, int);
694
                    precision = (int) va_arg(ap, int);
698
                    if (precision < 0) {
695
                    if (precision < 0) {
699
                        /* Ignore negative precision */
696
                        /* Ignore negative precision */
700
                        precision = 0;
697
                        precision = 0;
701
                    }
698
                    }
Line 710... Line 707...
710
             */
707
             */
711
            case 'h':
708
            case 'h':
712
                /* Char or short */
709
                /* Char or short */
713
                qualifier = PrintfQualifierShort;
710
                qualifier = PrintfQualifierShort;
714
                i = nxt;
711
                i = nxt;
715
                uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
712
                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
716
                if (uc == 'h') {
713
                if (uc == 'h') {
717
                    i = nxt;
714
                    i = nxt;
718
                    uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
715
                    uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
719
                    qualifier = PrintfQualifierByte;
716
                    qualifier = PrintfQualifierByte;
720
                }
717
                }
721
                break;
718
                break;
722
            case 'l':
719
            case 'l':
723
                /* Long or long long */
720
                /* Long or long long */
724
                qualifier = PrintfQualifierLong;
721
                qualifier = PrintfQualifierLong;
725
                i = nxt;
722
                i = nxt;
726
                uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
723
                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
727
                if (uc == 'l') {
724
                if (uc == 'l') {
728
                    i = nxt;
725
                    i = nxt;
729
                    uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
726
                    uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
730
                    qualifier = PrintfQualifierLongLong;
727
                    qualifier = PrintfQualifierLongLong;
731
                }
728
                }
732
                break;
729
                break;
733
            default:
730
            default:
734
                /* Default type */
731
                /* Default type */
Line 876... Line 873...
876
next_char:
873
next_char:
877
        ;
874
        ;
878
    }
875
    }
879
   
876
   
880
    if (i > j) {
877
    if (i > j) {
881
        if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
878
        if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
882
            /* Error */
879
            /* Error */
883
            counter = -counter;
880
            counter = -counter;
884
            goto out;
881
            goto out;
885
        }
882
        }
886
        counter += retval;
883
        counter += retval;