diff options
| author | Kai Großjohann | 2002-12-09 10:44:25 +0000 |
|---|---|---|
| committer | Kai Großjohann | 2002-12-09 10:44:25 +0000 |
| commit | ac42d7b99183dc6a2850a1852057b7447ecb148d (patch) | |
| tree | d702e1735e1226d1c41b5f4bc8a786c540242d5d /src | |
| parent | 12332637d4e501df29051beb4b1b999319f31cf0 (diff) | |
| download | emacs-ac42d7b99183dc6a2850a1852057b7447ecb148d.tar.gz emacs-ac42d7b99183dc6a2850a1852057b7447ecb148d.zip | |
(Fformat): Handle precision in string conversion specifiers like libc
functions do (ie, print at most that many characters). From Matthew
Swift <swift@alum.mit.edu>.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 6 | ||||
| -rw-r--r-- | src/editfns.c | 82 |
2 files changed, 70 insertions, 18 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index e6c8c650880..7d1f0999700 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2002-12-09 Kai Gro,A_(Bjohann <kai.grossjohann@uni-duisburg.de> | ||
| 2 | |||
| 3 | * editfns.c (Fformat): Handle precision in string conversion | ||
| 4 | specifiers like libc functions do (ie, print at most that many | ||
| 5 | characters). From Matthew Swift <swift@alum.mit.edu>. | ||
| 6 | |||
| 1 | 2002-12-08 Richard M. Stallman <rms@gnu.org> | 7 | 2002-12-08 Richard M. Stallman <rms@gnu.org> |
| 2 | 8 | ||
| 3 | * xdisp.c (row_containing_pos): Check more carefully | 9 | * xdisp.c (row_containing_pos): Check more carefully |
diff --git a/src/editfns.c b/src/editfns.c index d814f9f857c..8ab359dea96 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -3207,6 +3207,12 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3207 | must consider such a situation or not. */ | 3207 | must consider such a situation or not. */ |
| 3208 | int maybe_combine_byte; | 3208 | int maybe_combine_byte; |
| 3209 | unsigned char *this_format; | 3209 | unsigned char *this_format; |
| 3210 | /* Precision for each spec, or -1, a flag value meaning no precision | ||
| 3211 | was given in that spec. Element 0, corresonding to the format | ||
| 3212 | string itself, will not be used. Element NARGS, corresponding to | ||
| 3213 | no argument, *will* be assigned to in the case that a `%' and `.' | ||
| 3214 | occur after the final format specifier. */ | ||
| 3215 | int precision[nargs]; | ||
| 3210 | int longest_format; | 3216 | int longest_format; |
| 3211 | Lisp_Object val; | 3217 | Lisp_Object val; |
| 3212 | struct info | 3218 | struct info |
| @@ -3221,9 +3227,12 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3221 | This is not always right; sometimes the result needs to be multibyte | 3227 | This is not always right; sometimes the result needs to be multibyte |
| 3222 | because of an object that we will pass through prin1, | 3228 | because of an object that we will pass through prin1, |
| 3223 | and in that case, we won't know it here. */ | 3229 | and in that case, we won't know it here. */ |
| 3224 | for (n = 0; n < nargs; n++) | 3230 | for (n = 0; n < nargs; n++) { |
| 3225 | if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n])) | 3231 | if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n])) |
| 3226 | multibyte = 1; | 3232 | multibyte = 1; |
| 3233 | /* Piggyback on this loop to initialize precision[N]. */ | ||
| 3234 | precision[n] = -1; | ||
| 3235 | } | ||
| 3227 | 3236 | ||
| 3228 | CHECK_STRING (args[0]); | 3237 | CHECK_STRING (args[0]); |
| 3229 | 3238 | ||
| @@ -3247,7 +3256,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3247 | int thissize = 0; | 3256 | int thissize = 0; |
| 3248 | int actual_width = 0; | 3257 | int actual_width = 0; |
| 3249 | unsigned char *this_format_start = format - 1; | 3258 | unsigned char *this_format_start = format - 1; |
| 3250 | int field_width, precision; | 3259 | int field_width = 0; |
| 3251 | 3260 | ||
| 3252 | /* General format specifications look like | 3261 | /* General format specifications look like |
| 3253 | 3262 | ||
| @@ -3263,12 +3272,17 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3263 | the output should be padded with blanks, iff the output | 3272 | the output should be padded with blanks, iff the output |
| 3264 | string is shorter than field-width. | 3273 | string is shorter than field-width. |
| 3265 | 3274 | ||
| 3266 | if precision is specified, it specifies the number of | 3275 | If precision is specified, it specifies the number of |
| 3267 | digits to print after the '.' for floats, or the max. | 3276 | digits to print after the '.' for floats, or the max. |
| 3268 | number of chars to print from a string. */ | 3277 | number of chars to print from a string. */ |
| 3269 | 3278 | ||
| 3270 | precision = field_width = 0; | 3279 | /* NOTE the handling of specifiers here differs in some ways |
| 3271 | 3280 | from the libc model. There are bugs in this code that lead | |
| 3281 | to incorrect formatting when flags recognized by C but | ||
| 3282 | neither parsed nor rejected here are used. Further | ||
| 3283 | revisions will be made soon. */ | ||
| 3284 | |||
| 3285 | /* incorrect list of flags to skip; will be fixed */ | ||
| 3272 | while (index ("-*# 0", *format)) | 3286 | while (index ("-*# 0", *format)) |
| 3273 | ++format; | 3287 | ++format; |
| 3274 | 3288 | ||
| @@ -3278,11 +3292,13 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3278 | field_width = 10 * field_width + *format - '0'; | 3292 | field_width = 10 * field_width + *format - '0'; |
| 3279 | } | 3293 | } |
| 3280 | 3294 | ||
| 3295 | /* N is not incremented for another few lines below, so refer to | ||
| 3296 | element N+1 (which might be precision[NARGS]). */ | ||
| 3281 | if (*format == '.') | 3297 | if (*format == '.') |
| 3282 | { | 3298 | { |
| 3283 | ++format; | 3299 | ++format; |
| 3284 | for (precision = 0; *format >= '0' && *format <= '9'; ++format) | 3300 | for (precision[n+1] = 0; *format >= '0' && *format <= '9'; ++format) |
| 3285 | precision = 10 * precision + *format - '0'; | 3301 | precision[n+1] = 10 * precision[n+1] + *format - '0'; |
| 3286 | } | 3302 | } |
| 3287 | 3303 | ||
| 3288 | if (format - this_format_start + 1 > longest_format) | 3304 | if (format - this_format_start + 1 > longest_format) |
| @@ -3322,7 +3338,10 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3322 | string: | 3338 | string: |
| 3323 | if (*format != 's' && *format != 'S') | 3339 | if (*format != 's' && *format != 'S') |
| 3324 | error ("Format specifier doesn't match argument type"); | 3340 | error ("Format specifier doesn't match argument type"); |
| 3325 | thissize = CONVERTED_BYTE_SIZE (multibyte, args[n]); | 3341 | /* In the case (PRECISION[N] > 0), THISSIZE may not need |
| 3342 | to be as large as is calculated here. Easy check for | ||
| 3343 | the case PRECISION = 0. */ | ||
| 3344 | thissize = precision[n] ? CONVERTED_BYTE_SIZE (multibyte, args[n]) : 0; | ||
| 3326 | actual_width = lisp_string_width (args[n], -1, NULL, NULL); | 3345 | actual_width = lisp_string_width (args[n], -1, NULL, NULL); |
| 3327 | } | 3346 | } |
| 3328 | /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */ | 3347 | /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */ |
| @@ -3366,7 +3385,10 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3366 | /* Note that we're using sprintf to print floats, | 3385 | /* Note that we're using sprintf to print floats, |
| 3367 | so we have to take into account what that function | 3386 | so we have to take into account what that function |
| 3368 | prints. */ | 3387 | prints. */ |
| 3369 | thissize = MAX_10_EXP + 100 + precision; | 3388 | /* Filter out flag value of -1. This is a conditional with omitted |
| 3389 | operand: the value is PRECISION[N] if the conditional is >=0 and | ||
| 3390 | otherwise is 0. */ | ||
| 3391 | thissize = MAX_10_EXP + 100 + (precision[n] > 0 ? : 0); | ||
| 3370 | } | 3392 | } |
| 3371 | else | 3393 | else |
| 3372 | { | 3394 | { |
| @@ -3416,10 +3438,14 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3416 | format++; | 3438 | format++; |
| 3417 | 3439 | ||
| 3418 | /* Process a numeric arg and skip it. */ | 3440 | /* Process a numeric arg and skip it. */ |
| 3441 | /* NOTE atoi is the wrong thing to use here; will be fixed */ | ||
| 3419 | minlen = atoi (format); | 3442 | minlen = atoi (format); |
| 3420 | if (minlen < 0) | 3443 | if (minlen < 0) |
| 3421 | minlen = - minlen, negative = 1; | 3444 | minlen = - minlen, negative = 1; |
| 3422 | 3445 | ||
| 3446 | /* NOTE the parsing here is not consistent with the first | ||
| 3447 | pass, and neither attempt is what we want to do. Will be | ||
| 3448 | fixed. */ | ||
| 3423 | while ((*format >= '0' && *format <= '9') | 3449 | while ((*format >= '0' && *format <= '9') |
| 3424 | || *format == '-' || *format == ' ' || *format == '.') | 3450 | || *format == '-' || *format == ' ' || *format == '.') |
| 3425 | format++; | 3451 | format++; |
| @@ -3435,8 +3461,28 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3435 | 3461 | ||
| 3436 | if (STRINGP (args[n])) | 3462 | if (STRINGP (args[n])) |
| 3437 | { | 3463 | { |
| 3438 | int padding, nbytes, start, end; | 3464 | /* handle case (precision[n] >= 0) */ |
| 3439 | int width = lisp_string_width (args[n], -1, NULL, NULL); | 3465 | |
| 3466 | int width, padding; | ||
| 3467 | int nbytes, start, end; | ||
| 3468 | int nchars_string; | ||
| 3469 | |||
| 3470 | /* lisp_string_width ignores a precision of 0, but GNU | ||
| 3471 | libc functions print 0 characters when the precision | ||
| 3472 | is 0. Imitate libc behavior here. Changing | ||
| 3473 | lisp_string_width is the right thing, and will be | ||
| 3474 | done, but meanwhile we work with it. */ | ||
| 3475 | |||
| 3476 | if (precision[n] == 0) | ||
| 3477 | width = nchars_string = nbytes = 0; | ||
| 3478 | else if (precision[n] > 0) | ||
| 3479 | width = lisp_string_width (args[n], precision[n], &nchars_string, &nbytes); | ||
| 3480 | else | ||
| 3481 | { /* no precision spec given for this argument */ | ||
| 3482 | width = lisp_string_width (args[n], -1, NULL, NULL); | ||
| 3483 | nbytes = SBYTES (args[n]); | ||
| 3484 | nchars_string = SCHARS (args[n]); | ||
| 3485 | } | ||
| 3440 | 3486 | ||
| 3441 | /* If spec requires it, pad on right with spaces. */ | 3487 | /* If spec requires it, pad on right with spaces. */ |
| 3442 | padding = minlen - width; | 3488 | padding = minlen - width; |
| @@ -3448,19 +3494,19 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3448 | } | 3494 | } |
| 3449 | 3495 | ||
| 3450 | start = nchars; | 3496 | start = nchars; |
| 3451 | 3497 | nchars += nchars_string; | |
| 3498 | end = nchars; | ||
| 3499 | |||
| 3452 | if (p > buf | 3500 | if (p > buf |
| 3453 | && multibyte | 3501 | && multibyte |
| 3454 | && !ASCII_BYTE_P (*((unsigned char *) p - 1)) | 3502 | && !ASCII_BYTE_P (*((unsigned char *) p - 1)) |
| 3455 | && STRING_MULTIBYTE (args[n]) | 3503 | && STRING_MULTIBYTE (args[n]) |
| 3456 | && !CHAR_HEAD_P (SREF (args[n], 0))) | 3504 | && !CHAR_HEAD_P (SREF (args[n], 0))) |
| 3457 | maybe_combine_byte = 1; | 3505 | maybe_combine_byte = 1; |
| 3458 | nbytes = copy_text (SDATA (args[n]), p, | 3506 | |
| 3459 | SBYTES (args[n]), | 3507 | p += copy_text (SDATA (args[n]), p, |
| 3460 | STRING_MULTIBYTE (args[n]), multibyte); | 3508 | nbytes, |
| 3461 | p += nbytes; | 3509 | STRING_MULTIBYTE (args[n]), multibyte); |
| 3462 | nchars += SCHARS (args[n]); | ||
| 3463 | end = nchars; | ||
| 3464 | 3510 | ||
| 3465 | if (negative) | 3511 | if (negative) |
| 3466 | while (padding-- > 0) | 3512 | while (padding-- > 0) |