comparison src/message.c @ 272:ddada568db54

updated for version 7.0073
author vimboss
date Thu, 19 May 2005 20:53:52 +0000
parents 723a01584c3e
children fb70e333c94e
comparison
equal deleted inserted replaced
271:8d34af900bae 272:ddada568db54
311 _RTLENTRYF 311 _RTLENTRYF
312 #endif 312 #endif
313 smsg_attr __ARGS((int, char_u *, long, long, long, 313 smsg_attr __ARGS((int, char_u *, long, long, long,
314 long, long, long, long, long, long, long)); 314 long, long, long, long, long, long, long));
315 315
316 int vim_snprintf __ARGS((char *, size_t, char *, long, long, long,
317 long, long, long, long, long, long, long));
318
319 /*
320 * smsg(str, arg, ...) is like using sprintf(buf, str, arg, ...) and then
321 * calling msg(buf).
322 * The buffer used is IObuff, the message is truncated at IOSIZE.
323 */
324
316 /* VARARGS */ 325 /* VARARGS */
317 int 326 int
318 #ifdef __BORLANDC__ 327 #ifdef __BORLANDC__
319 _RTLENTRYF 328 _RTLENTRYF
320 #endif 329 #endif
333 smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) 342 smsg_attr(attr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
334 int attr; 343 int attr;
335 char_u *s; 344 char_u *s;
336 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; 345 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
337 { 346 {
338 sprintf((char *)IObuff, (char *)s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); 347 vim_snprintf((char *)IObuff, IOSIZE, (char *)s,
348 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
339 return msg_attr(IObuff, attr); 349 return msg_attr(IObuff, attr);
340 } 350 }
341 351
342 # else /* HAVE_STDARG_H */ 352 # else /* HAVE_STDARG_H */
353
354 int vim_snprintf(char *str, size_t str_m, char *fmt, ...);
355 static int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap);
343 356
344 int 357 int
345 #ifdef __BORLANDC__ 358 #ifdef __BORLANDC__
346 _RTLENTRYF 359 _RTLENTRYF
347 #endif 360 #endif
348 smsg(char_u *s, ...) 361 smsg(char_u *s, ...)
349 { 362 {
350 va_list arglist; 363 va_list arglist;
351 364
352 va_start(arglist, s); 365 va_start(arglist, s);
353 # ifdef HAVE_VSNPRINTF 366 vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
354 vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
355 # else
356 vsprintf((char *)IObuff, (char *)s, arglist);
357 # endif
358 va_end(arglist); 367 va_end(arglist);
359 return msg(IObuff); 368 return msg(IObuff);
360 } 369 }
361 370
362 int 371 int
366 smsg_attr(int attr, char_u *s, ...) 375 smsg_attr(int attr, char_u *s, ...)
367 { 376 {
368 va_list arglist; 377 va_list arglist;
369 378
370 va_start(arglist, s); 379 va_start(arglist, s);
371 # ifdef HAVE_VSNPRINTF 380 vim_vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
372 vsnprintf((char *)IObuff, IOSIZE, (char *)s, arglist);
373 # else
374 vsprintf((char *)IObuff, (char *)s, arglist);
375 # endif
376 va_end(arglist); 381 va_end(arglist);
377 return msg_attr(IObuff, attr); 382 return msg_attr(IObuff, attr);
378 } 383 }
379 384
380 # endif /* HAVE_STDARG_H */ 385 # endif /* HAVE_STDARG_H */
643 #ifdef FEAT_EVAL 648 #ifdef FEAT_EVAL
644 || emsg_skip > 0 649 || emsg_skip > 0
645 #endif 650 #endif
646 ) 651 )
647 return TRUE; /* no error messages at the moment */ 652 return TRUE; /* no error messages at the moment */
648 653 vim_snprintf((char *)IObuff, IOSIZE, (char *)s, (char *)a1, (char *)a2);
649 /* Check for NULL strings (just in case) */
650 if (a1 == NULL)
651 a1 = (char_u *)"[NULL]";
652 if (a2 == NULL)
653 a2 = (char_u *)"[NULL]";
654
655 /* Check for very long strings (can happen with ":help ^A<CR>"). */
656 if (STRLEN(s) + STRLEN(a1) + STRLEN(a2) >= (size_t)IOSIZE)
657 a1 = a2 = (char_u *)_("[string too long]");
658
659 sprintf((char *)IObuff, (char *)s, (char *)a1, (char *)a2);
660 return emsg(IObuff); 654 return emsg(IObuff);
661 } 655 }
662 656
663 /* 657 /*
664 * Print an error message with one "%ld" and one long int argument. 658 * Print an error message with one "%ld" and one long int argument.
672 #ifdef FEAT_EVAL 666 #ifdef FEAT_EVAL
673 || emsg_skip > 0 667 || emsg_skip > 0
674 #endif 668 #endif
675 ) 669 )
676 return TRUE; /* no error messages at the moment */ 670 return TRUE; /* no error messages at the moment */
677 sprintf((char *)IObuff, (char *)s, n); 671 vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n);
678 return emsg(IObuff); 672 return emsg(IObuff);
679 } 673 }
680 674
681 void 675 void
682 emsg_invreg(name) 676 emsg_invreg(name)
3203 cmdmod.browse = save_browse; 3197 cmdmod.browse = save_browse;
3204 3198
3205 return fname; 3199 return fname;
3206 } 3200 }
3207 #endif 3201 #endif
3202
3203 /*
3204 * This code was included to provide a portable vsnprintf() and snprintf().
3205 * Some systems may provide their own, but we always use these for
3206 * consistency.
3207 *
3208 * This code is based on snprintf.c - a portable implementation of snprintf
3209 * by Mark Martinec <mark.martinec@ijs.si>, Version 2.2, 2000-10-06.
3210 * It was heavely modified to fit in Vim.
3211 * The original code, including useful comments, can be found here:
3212 * http://www.ijs.si/software/snprintf/
3213 *
3214 * This snprintf() only supports the following conversion specifiers:
3215 * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
3216 * with flags: '-', '+', ' ', '0' and '#'.
3217 * An asterisk is supported for field width as well as precision.
3218 *
3219 * Length modifiers 'h' (short int) and 'l' (long int) are supported.
3220 * 'll' (long long int) is not supported.
3221 *
3222 * It is permitted for str_m to be zero, and it is permitted to specify NULL
3223 * pointer for resulting string argument if str_m is zero (as per ISO C99).
3224 *
3225 * The return value is the number of characters which would be generated
3226 * for the given input, excluding the trailing null. If this value
3227 * is greater or equal to str_m, not all characters from the result
3228 * have been stored in str, output bytes beyond the (str_m-1) -th character
3229 * are discarded. If str_m is greater than zero it is guaranteed
3230 * the resulting string will be null-terminated.
3231 */
3232
3233 /*
3234 * When va_list is not supported we only define vim_snprintf().
3235 */
3236
3237 /* When generating prototypes all of this is skipped, cproto doesn't
3238 * understand this. */
3239 #ifndef PROTO
3240 # ifdef HAVE_STDARG_H
3241 int
3242 vim_snprintf(char *str, size_t str_m, char *fmt, ...)
3243 {
3244 va_list ap;
3245 int str_l;
3246
3247 va_start(ap, fmt);
3248 str_l = vim_vsnprintf(str, str_m, fmt, ap);
3249 va_end(ap);
3250 return str_l;
3251 }
3252
3253 static int
3254 vim_vsnprintf(str, str_m, fmt, ap)
3255 # else
3256 /* clumsy way to work around missing va_list */
3257 # define get_a_arg(i) (i == 1 ? a1 : i == 2 ? a2 : i == 3 ? a3 : i == 4 ? a4 : i == 5 ? a5 : i == 6 ? a6 : i == 7 ? a7 : i == 8 ? a8 : i == 9 ? a9 : a10)
3258
3259 /* VARARGS */
3260 int
3261 #ifdef __BORLANDC__
3262 _RTLENTRYF
3263 #endif
3264 vim_snprintf(str, str_m, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
3265 # endif
3266 char *str;
3267 size_t str_m;
3268 char *fmt;
3269 # ifdef HAVE_STDARG_H
3270 va_list ap;
3271 # else
3272 long a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
3273 # endif
3274 {
3275 size_t str_l = 0;
3276 char *p = fmt;
3277 # ifndef HAVE_STDARG_H
3278 int arg_idx = 1;
3279 # endif
3280
3281 if (p == NULL)
3282 p = "";
3283 while (*p != NUL)
3284 {
3285 if (*p != '%')
3286 {
3287 char *q = strchr(p + 1, '%');
3288 size_t n = (q == NULL) ? STRLEN(p) : (q - p);
3289
3290 if (str_l < str_m)
3291 {
3292 size_t avail = str_m - str_l;
3293
3294 mch_memmove(str + str_l, p, n > avail ? avail : n);
3295 }
3296 p += n;
3297 str_l += n;
3298 }
3299 else
3300 {
3301 size_t min_field_width = 0, precision = 0;
3302 int zero_padding = 0, precision_specified = 0, justify_left = 0;
3303 int alternate_form = 0, force_sign = 0;
3304
3305 /* If both the ' ' and '+' flags appear, the ' ' flag should be
3306 * ignored. */
3307 int space_for_positive = 1;
3308
3309 /* allowed values: \0, h, l, L */
3310 char length_modifier = '\0';
3311
3312 /* temporary buffer for simple numeric->string conversion */
3313 char tmp[32];
3314
3315 /* string address in case of string argument */
3316 char *str_arg;
3317
3318 /* natural field width of arg without padding and sign */
3319 size_t str_arg_l;
3320
3321 /* unsigned char argument value - only defined for c conversion.
3322 * N.B. standard explicitly states the char argument for the c
3323 * conversion is unsigned */
3324 unsigned char uchar_arg;
3325
3326 /* number of zeros to be inserted for numeric conversions as
3327 * required by the precision or minimal field width */
3328 size_t number_of_zeros_to_pad = 0;
3329
3330 /* index into tmp where zero padding is to be inserted */
3331 size_t zero_padding_insertion_ind = 0;
3332
3333 /* current conversion specifier character */
3334 char fmt_spec = '\0';
3335
3336 str_arg = NULL;
3337 p++; /* skip '%' */
3338
3339 /* parse flags */
3340 while (*p == '0' || *p == '-' || *p == '+' || *p == ' '
3341 || *p == '#' || *p == '\'')
3342 {
3343 switch (*p)
3344 {
3345 case '0': zero_padding = 1; break;
3346 case '-': justify_left = 1; break;
3347 case '+': force_sign = 1; space_for_positive = 0; break;
3348 case ' ': force_sign = 1;
3349 /* If both the ' ' and '+' flags appear, the ' '
3350 * flag should be ignored */
3351 break;
3352 case '#': alternate_form = 1; break;
3353 case '\'': break;
3354 }
3355 p++;
3356 }
3357 /* If the '0' and '-' flags both appear, the '0' flag should be
3358 * ignored. */
3359
3360 /* parse field width */
3361 if (*p == '*')
3362 {
3363 int j;
3364
3365 p++;
3366 #ifndef HAVE_STDARG_H
3367 j = get_a_arg(arg_idx);
3368 ++arg_idx;
3369 #else
3370 j = va_arg(ap, int);
3371 #endif
3372 if (j >= 0)
3373 min_field_width = j;
3374 else
3375 {
3376 min_field_width = -j;
3377 justify_left = 1;
3378 }
3379 }
3380 else if (VIM_ISDIGIT((int)(*p)))
3381 {
3382 /* size_t could be wider than unsigned int; make sure we treat
3383 * argument like common implementations do */
3384 unsigned int uj = *p++ - '0';
3385
3386 while (VIM_ISDIGIT((int)(*p)))
3387 uj = 10 * uj + (unsigned int)(*p++ - '0');
3388 min_field_width = uj;
3389 }
3390
3391 /* parse precision */
3392 if (*p == '.')
3393 {
3394 p++;
3395 precision_specified = 1;
3396 if (*p == '*')
3397 {
3398 int j;
3399
3400 #ifndef HAVE_STDARG_H
3401 j = get_a_arg(arg_idx);
3402 ++arg_idx;
3403 #else
3404 j = va_arg(ap, int);
3405 #endif
3406 p++;
3407 if (j >= 0)
3408 precision = j;
3409 else
3410 {
3411 precision_specified = 0;
3412 precision = 0;
3413 }
3414 }
3415 else if (VIM_ISDIGIT((int)(*p)))
3416 {
3417 /* size_t could be wider than unsigned int; make sure we
3418 * treat argument like common implementations do */
3419 unsigned int uj = *p++ - '0';
3420
3421 while (VIM_ISDIGIT((int)(*p)))
3422 uj = 10 * uj + (unsigned int)(*p++ - '0');
3423 precision = uj;
3424 }
3425 }
3426
3427 /* parse 'h', 'l' and 'll' length modifiers */
3428 if (*p == 'h' || *p == 'l')
3429 {
3430 length_modifier = *p;
3431 p++;
3432 if (length_modifier == 'l' && *p == 'l')
3433 {
3434 /* double l = long long */
3435 length_modifier = 'l'; /* treat it as a single 'l' */
3436 p++;
3437 }
3438 }
3439 fmt_spec = *p;
3440
3441 /* common synonyms: */
3442 switch (fmt_spec)
3443 {
3444 case 'i': fmt_spec = 'd'; break;
3445 case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
3446 case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
3447 case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
3448 default: break;
3449 }
3450
3451 /* get parameter value, do initial processing */
3452 switch (fmt_spec)
3453 {
3454 /* '%' and 'c' behave similar to 's' regarding flags and field
3455 * widths */
3456 case '%':
3457 case 'c':
3458 case 's':
3459 length_modifier = '\0';
3460 zero_padding = 0; /* turn zero padding off for string
3461 conversions */
3462 str_arg_l = 1;
3463 switch (fmt_spec)
3464 {
3465 case '%':
3466 str_arg = p;
3467 break;
3468
3469 case 'c':
3470 {
3471 int j;
3472 #ifndef HAVE_STDARG_H
3473 j = get_a_arg(arg_idx);
3474 ++arg_idx;
3475 #else
3476 j = va_arg(ap, int);
3477 #endif
3478 /* standard demands unsigned char */
3479 uchar_arg = (unsigned char)j;
3480 str_arg = (char *)&uchar_arg;
3481 break;
3482 }
3483
3484 case 's':
3485 #ifndef HAVE_STDARG_H
3486 str_arg = (char *)get_a_arg(arg_idx);
3487 ++arg_idx;
3488 #else
3489 str_arg = va_arg(ap, char *);
3490 #endif
3491 if (str_arg == NULL)
3492 {
3493 str_arg = "[NULL]";
3494 str_arg_l = 6;
3495 }
3496 /* make sure not to address string beyond the specified
3497 * precision !!! */
3498 else if (!precision_specified)
3499 str_arg_l = strlen(str_arg);
3500 /* truncate string if necessary as requested by precision */
3501 else if (precision == 0)
3502 str_arg_l = 0;
3503 else
3504 {
3505 /* memchr on HP does not like n > 2^31 !!! */
3506 char *q = memchr(str_arg, '\0',
3507 precision <= 0x7fffffff ? precision
3508 : 0x7fffffff);
3509 str_arg_l = (q == NULL) ? precision : q - str_arg;
3510 }
3511 break;
3512
3513 default:
3514 break;
3515 }
3516 break;
3517
3518 case 'd': case 'u': case 'o': case 'x': case 'X': case 'p':
3519 {
3520 /* NOTE: the u, o, x, X and p conversion specifiers
3521 * imply the value is unsigned; d implies a signed
3522 * value */
3523
3524 /* 0 if numeric argument is zero (or if pointer is
3525 * NULL for 'p'), +1 if greater than zero (or nonzero
3526 * for unsigned arguments), -1 if negative (unsigned
3527 * argument is never negative) */
3528 int arg_sign = 0;
3529
3530 /* only defined for length modifier h, or for no
3531 * length modifiers */
3532 int int_arg = 0;
3533 unsigned int uint_arg = 0;
3534
3535 /* only defined for length modifier l */
3536 long int long_arg = 0;
3537 unsigned long int ulong_arg = 0;
3538
3539 /* pointer argument value -only defined for p
3540 * conversion */
3541 void *ptr_arg = NULL;
3542
3543 if (fmt_spec == 'p')
3544 {
3545 length_modifier = '\0';
3546 #ifndef HAVE_STDARG_H
3547 ptr_arg = (void *)get_a_arg(arg_idx);
3548 ++arg_idx;
3549 #else
3550 ptr_arg = va_arg(ap, void *);
3551 #endif
3552 if (ptr_arg != NULL)
3553 arg_sign = 1;
3554 }
3555 else if (fmt_spec == 'd')
3556 {
3557 /* signed */
3558 switch (length_modifier)
3559 {
3560 case '\0':
3561 case 'h':
3562 /* It is non-portable to specify a second argument
3563 * of char or short to va_arg, because arguments
3564 * seen by the called function are not char or
3565 * short. C converts char and short arguments to
3566 * int before passing them to a function. */
3567 #ifndef HAVE_STDARG_H
3568 int_arg = get_a_arg(arg_idx);
3569 ++arg_idx;
3570 #else
3571 int_arg = va_arg(ap, int);
3572 #endif
3573 if (int_arg > 0)
3574 arg_sign = 1;
3575 else if (int_arg < 0)
3576 arg_sign = -1;
3577 break;
3578 case 'l':
3579 #ifndef HAVE_STDARG_H
3580 long_arg = get_a_arg(arg_idx);
3581 ++arg_idx;
3582 #else
3583 long_arg = va_arg(ap, long int);
3584 #endif
3585 if (long_arg > 0)
3586 arg_sign = 1;
3587 else if (long_arg < 0)
3588 arg_sign = -1;
3589 break;
3590 }
3591 }
3592 else
3593 {
3594 /* unsigned */
3595 switch (length_modifier)
3596 {
3597 case '\0':
3598 case 'h':
3599 #ifndef HAVE_STDARG_H
3600 uint_arg = get_a_arg(arg_idx);
3601 ++arg_idx;
3602 #else
3603 uint_arg = va_arg(ap, unsigned int);
3604 #endif
3605 if (uint_arg != 0)
3606 arg_sign = 1;
3607 break;
3608 case 'l':
3609 #ifndef HAVE_STDARG_H
3610 ulong_arg = get_a_arg(arg_idx);
3611 ++arg_idx;
3612 #else
3613 ulong_arg = va_arg(ap, unsigned long int);
3614 #endif
3615 if (ulong_arg != 0)
3616 arg_sign = 1;
3617 break;
3618 }
3619 }
3620
3621 str_arg = tmp;
3622 str_arg_l = 0;
3623
3624 /* NOTE:
3625 * For d, i, u, o, x, and X conversions, if precision is
3626 * specified, the '0' flag should be ignored. This is so
3627 * with Solaris 2.6, Digital UNIX 4.0, HPUX 10, Linux,
3628 * FreeBSD, NetBSD; but not with Perl.
3629 */
3630 if (precision_specified)
3631 zero_padding = 0;
3632 if (fmt_spec == 'd')
3633 {
3634 if (force_sign && arg_sign >= 0)
3635 tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
3636 /* leave negative numbers for sprintf to handle, to
3637 * avoid handling tricky cases like (short int)-32768 */
3638 }
3639 else if (alternate_form)
3640 {
3641 if (arg_sign != 0
3642 && (fmt_spec == 'x' || fmt_spec == 'X') )
3643 {
3644 tmp[str_arg_l++] = '0';
3645 tmp[str_arg_l++] = fmt_spec;
3646 }
3647 /* alternate form should have no effect for p
3648 * conversion, but ... */
3649 }
3650
3651 zero_padding_insertion_ind = str_arg_l;
3652 if (!precision_specified)
3653 precision = 1; /* default precision is 1 */
3654 if (precision == 0 && arg_sign == 0)
3655 {
3656 /* When zero value is formatted with an explicit
3657 * precision 0, the resulting formatted string is
3658 * empty (d, i, u, o, x, X, p). */
3659 }
3660 else
3661 {
3662 char f[5];
3663 int f_l = 0;
3664
3665 /* construct a simple format string for sprintf */
3666 f[f_l++] = '%';
3667 if (!length_modifier)
3668 ;
3669 else if (length_modifier == '2')
3670 {
3671 f[f_l++] = 'l';
3672 f[f_l++] = 'l';
3673 }
3674 else
3675 f[f_l++] = length_modifier;
3676 f[f_l++] = fmt_spec;
3677 f[f_l++] = '\0';
3678
3679 if (fmt_spec == 'p')
3680 str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg);
3681 else if (fmt_spec == 'd')
3682 {
3683 /* signed */
3684 switch (length_modifier)
3685 {
3686 case '\0':
3687 case 'h': str_arg_l += sprintf(
3688 tmp + str_arg_l, f, int_arg);
3689 break;
3690 case 'l': str_arg_l += sprintf(
3691 tmp + str_arg_l, f, long_arg);
3692 break;
3693 }
3694 }
3695 else
3696 {
3697 /* unsigned */
3698 switch (length_modifier)
3699 {
3700 case '\0':
3701 case 'h': str_arg_l += sprintf(
3702 tmp + str_arg_l, f, uint_arg);
3703 break;
3704 case 'l': str_arg_l += sprintf(
3705 tmp + str_arg_l, f, ulong_arg);
3706 break;
3707 }
3708 }
3709
3710 /* include the optional minus sign and possible
3711 * "0x" in the region before the zero padding
3712 * insertion point */
3713 if (zero_padding_insertion_ind < str_arg_l
3714 && tmp[zero_padding_insertion_ind] == '-')
3715 zero_padding_insertion_ind++;
3716 if (zero_padding_insertion_ind + 1 < str_arg_l
3717 && tmp[zero_padding_insertion_ind] == '0'
3718 && (tmp[zero_padding_insertion_ind + 1] == 'x'
3719 || tmp[zero_padding_insertion_ind + 1] == 'X'))
3720 zero_padding_insertion_ind += 2;
3721 }
3722
3723 {
3724 size_t num_of_digits = str_arg_l
3725 - zero_padding_insertion_ind;
3726
3727 if (alternate_form && fmt_spec == 'o'
3728 /* unless zero is already the first
3729 * character */
3730 && !(zero_padding_insertion_ind < str_arg_l
3731 && tmp[zero_padding_insertion_ind] == '0'))
3732 {
3733 /* assure leading zero for alternate-form
3734 * octal numbers */
3735 if (!precision_specified
3736 || precision < num_of_digits + 1)
3737 {
3738 /* precision is increased to force the
3739 * first character to be zero, except if a
3740 * zero value is formatted with an
3741 * explicit precision of zero */
3742 precision = num_of_digits + 1;
3743 precision_specified = 1;
3744 }
3745 }
3746 /* zero padding to specified precision? */
3747 if (num_of_digits < precision)
3748 number_of_zeros_to_pad = precision - num_of_digits;
3749 }
3750 /* zero padding to specified minimal field width? */
3751 if (!justify_left && zero_padding)
3752 {
3753 int n = min_field_width - (str_arg_l
3754 + number_of_zeros_to_pad);
3755 if (n > 0)
3756 number_of_zeros_to_pad += n;
3757 }
3758 break;
3759 }
3760
3761 default:
3762 /* unrecognized conversion specifier, keep format string
3763 * as-is */
3764 zero_padding = 0; /* turn zero padding off for non-numeric
3765 convers. */
3766 justify_left = 1;
3767 min_field_width = 0; /* reset flags */
3768
3769 /* discard the unrecognized conversion, just keep *
3770 * the unrecognized conversion character */
3771 str_arg = p;
3772 str_arg_l = 0;
3773 if (*p != NUL)
3774 str_arg_l++; /* include invalid conversion specifier
3775 unchanged if not at end-of-string */
3776 break;
3777 }
3778
3779 if (*p != NUL)
3780 p++; /* step over the just processed conversion specifier */
3781
3782 /* insert padding to the left as requested by min_field_width;
3783 * this does not include the zero padding in case of numerical
3784 * conversions*/
3785 if (!justify_left)
3786 {
3787 /* left padding with blank or zero */
3788 int n = min_field_width - (str_arg_l + number_of_zeros_to_pad);
3789
3790 if (n > 0)
3791 {
3792 if (str_l < str_m)
3793 {
3794 size_t avail = str_m - str_l;
3795
3796 vim_memset(str + str_l, zero_padding ? '0' : ' ',
3797 n > avail ? avail : n);
3798 }
3799 str_l += n;
3800 }
3801 }
3802
3803 /* zero padding as requested by the precision or by the minimal
3804 * field width for numeric conversions required? */
3805 if (number_of_zeros_to_pad <= 0)
3806 {
3807 /* will not copy first part of numeric right now, *
3808 * force it to be copied later in its entirety */
3809 zero_padding_insertion_ind = 0;
3810 }
3811 else
3812 {
3813 /* insert first part of numerics (sign or '0x') before zero
3814 * padding */
3815 int n = zero_padding_insertion_ind;
3816
3817 if (n > 0)
3818 {
3819 if (str_l < str_m)
3820 {
3821 size_t avail = str_m - str_l;
3822
3823 mch_memmove(str + str_l, str_arg,
3824 n > avail ? avail : n);
3825 }
3826 str_l += n;
3827 }
3828
3829 /* insert zero padding as requested by the precision or min
3830 * field width */
3831 n = number_of_zeros_to_pad;
3832 if (n > 0)
3833 {
3834 if (str_l < str_m)
3835 {
3836 size_t avail = str_m-str_l;
3837
3838 vim_memset(str + str_l, '0', n > avail ? avail : n);
3839 }
3840 str_l += n;
3841 }
3842 }
3843
3844 /* insert formatted string
3845 * (or as-is conversion specifier for unknown conversions) */
3846 {
3847 int n = str_arg_l - zero_padding_insertion_ind;
3848
3849 if (n > 0)
3850 {
3851 if (str_l < str_m)
3852 {
3853 size_t avail = str_m - str_l;
3854
3855 mch_memmove(str + str_l,
3856 str_arg + zero_padding_insertion_ind,
3857 n > avail ? avail : n);
3858 }
3859 str_l += n;
3860 }
3861 }
3862
3863 /* insert right padding */
3864 if (justify_left)
3865 {
3866 /* right blank padding to the field width */
3867 int n = min_field_width - (str_arg_l + number_of_zeros_to_pad);
3868
3869 if (n > 0)
3870 {
3871 if (str_l < str_m)
3872 {
3873 size_t avail = str_m - str_l;
3874
3875 vim_memset(str + str_l, ' ', n > avail ? avail : n);
3876 }
3877 str_l += n;
3878 }
3879 }
3880 }
3881 }
3882
3883 if (str_m > 0)
3884 {
3885 /* make sure the string is null-terminated even at the expense of
3886 * overwriting the last character (shouldn't happen, but just in case)
3887 * */
3888 str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0';
3889 }
3890
3891 /* Return the number of characters formatted (excluding trailing null
3892 * character), that is, the number of characters that would have been
3893 * written to the buffer if it were large enough. */
3894 return (int)str_l;
3895 }
3896
3897 #endif /* PROTO */