Mercurial > vim
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 */ |