diff options
| author | Paul Eggert | 2011-04-30 13:05:43 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-04-30 13:05:43 -0700 |
| commit | ad5f9eeaa2f0f872e063849f8f0d24d2c200acfa (patch) | |
| tree | 76239a33017e6e08652b9067af7f34c8fe809081 /src | |
| parent | b5611f17a7bd64578fc43874a727a8f1081614e9 (diff) | |
| download | emacs-ad5f9eeaa2f0f872e063849f8f0d24d2c200acfa.tar.gz emacs-ad5f9eeaa2f0f872e063849f8f0d24d2c200acfa.zip | |
* doprnt.c (doprnt): Support arbitrary pI values, such as "I64".
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 2 | ||||
| -rw-r--r-- | src/doprnt.c | 58 |
2 files changed, 28 insertions, 32 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 310d32a6432..d043bf7f691 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | 2011-04-30 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-04-30 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | * doprnt.c (doprnt): Support arbitrary pI values, such as "I64". | ||
| 4 | |||
| 3 | * dispnew.c (scrolling_window): Return 1 if we scrolled, | 5 | * dispnew.c (scrolling_window): Return 1 if we scrolled, |
| 4 | to match comment at start of function. This also removes a | 6 | to match comment at start of function. This also removes a |
| 5 | GCC warning about overflow in a 32+64-bit port. | 7 | GCC warning about overflow in a 32+64-bit port. |
diff --git a/src/doprnt.c b/src/doprnt.c index 7b4bd35d5b1..d2abc119912 100644 --- a/src/doprnt.c +++ b/src/doprnt.c | |||
| @@ -70,9 +70,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 70 | %<flags><width><precision><length>character | 70 | %<flags><width><precision><length>character |
| 71 | 71 | ||
| 72 | where flags is [+ -0], width is [0-9]+, precision is .[0-9]+, and length | 72 | where flags is [+ -0], width is [0-9]+, precision is .[0-9]+, and length |
| 73 | is empty or l or ll. Also, %% in a format stands for a single % in the | 73 | is empty or l or the value of the pI macro. Also, %% in a format |
| 74 | output. A % that does not introduce a valid %-sequence causes | 74 | stands for a single % in the output. A % that does not introduce a |
| 75 | undefined behavior. | 75 | valid %-sequence causes undefined behavior. |
| 76 | 76 | ||
| 77 | The + flag character inserts a + before any positive number, while a space | 77 | The + flag character inserts a + before any positive number, while a space |
| 78 | inserts a space before any positive number; these flags only affect %d, %o, | 78 | inserts a space before any positive number; these flags only affect %d, %o, |
| @@ -85,11 +85,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 85 | modifier: it is supported for %d, %o, and %x conversions of integral | 85 | modifier: it is supported for %d, %o, and %x conversions of integral |
| 86 | arguments, must immediately precede the conversion specifier, and means that | 86 | arguments, must immediately precede the conversion specifier, and means that |
| 87 | the respective argument is to be treated as `long int' or `unsigned long | 87 | the respective argument is to be treated as `long int' or `unsigned long |
| 88 | int'. Similarly, ll (two letter ells) means to use `long long int' or | 88 | int'. Similarly, the value of the pI macro means to use EMACS_INT or |
| 89 | `unsigned long long int'; this can be used only on hosts that have | 89 | EMACS_UINT and the empty length modifier means `int' or `unsigned int'. |
| 90 | these two types. The empty length modifier means to use `int' or | ||
| 91 | `unsigned int'. EMACS_INT arguments should use the pI macro, which | ||
| 92 | expands to whatever length modifier is needed for the target host. | ||
| 93 | 90 | ||
| 94 | The width specifier supplies a lower limit for the length of the printed | 91 | The width specifier supplies a lower limit for the length of the printed |
| 95 | representation. The padding, if any, normally goes on the left, but it goes | 92 | representation. The padding, if any, normally goes on the left, but it goes |
| @@ -186,6 +183,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 186 | size_t size_bound = 0; | 183 | size_t size_bound = 0; |
| 187 | EMACS_INT width; /* Columns occupied by STRING on display. */ | 184 | EMACS_INT width; /* Columns occupied by STRING on display. */ |
| 188 | int long_flag = 0; | 185 | int long_flag = 0; |
| 186 | int pIlen = sizeof pI - 1; | ||
| 189 | 187 | ||
| 190 | fmt++; | 188 | fmt++; |
| 191 | /* Copy this one %-spec into fmtcpy. */ | 189 | /* Copy this one %-spec into fmtcpy. */ |
| @@ -201,7 +199,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 201 | %1.1000f and %1000.1f both might need 1000+ bytes. | 199 | %1.1000f and %1000.1f both might need 1000+ bytes. |
| 202 | Parse the width or precision, checking for overflow. */ | 200 | Parse the width or precision, checking for overflow. */ |
| 203 | size_t n = *fmt - '0'; | 201 | size_t n = *fmt - '0'; |
| 204 | while (fmt < format_end | 202 | while (fmt + 1 < format_end |
| 205 | && '0' <= fmt[1] && fmt[1] <= '9') | 203 | && '0' <= fmt[1] && fmt[1] <= '9') |
| 206 | { | 204 | { |
| 207 | /* Avoid size_t overflow. Avoid int overflow too, as | 205 | /* Avoid size_t overflow. Avoid int overflow too, as |
| @@ -218,20 +216,25 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 218 | if (size_bound < n) | 216 | if (size_bound < n) |
| 219 | size_bound = n; | 217 | size_bound = n; |
| 220 | } | 218 | } |
| 221 | else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+') | 219 | else if (! (*fmt == '-' || *fmt == ' ' || *fmt == '.' |
| 222 | ; | 220 | || *fmt == '+')) |
| 223 | else if (*fmt == 'l') | ||
| 224 | { | ||
| 225 | long_flag = 1 + (fmt + 1 < format_end && fmt[1] == 'l'); | ||
| 226 | fmt += long_flag; | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | else | ||
| 230 | break; | 221 | break; |
| 231 | fmt++; | 222 | fmt++; |
| 232 | } | 223 | } |
| 233 | if (fmt > format_end) | 224 | |
| 234 | fmt = format_end; | 225 | if (0 < pIlen && pIlen <= format_end - fmt |
| 226 | && memcmp (fmt, pI, pIlen) == 0) | ||
| 227 | { | ||
| 228 | long_flag = 2; | ||
| 229 | memcpy (string, fmt + 1, pIlen); | ||
| 230 | string += pIlen; | ||
| 231 | fmt += pIlen; | ||
| 232 | } | ||
| 233 | else if (fmt < format_end && *fmt == 'l') | ||
| 234 | { | ||
| 235 | long_flag = 1; | ||
| 236 | *string++ = *++fmt; | ||
| 237 | } | ||
| 235 | *string = 0; | 238 | *string = 0; |
| 236 | 239 | ||
| 237 | /* Make the size bound large enough to handle floating point formats | 240 | /* Make the size bound large enough to handle floating point formats |
| @@ -253,8 +256,7 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 253 | switch (*fmt++) | 256 | switch (*fmt++) |
| 254 | { | 257 | { |
| 255 | default: | 258 | default: |
| 256 | error ("Invalid format operation %%%s%c", | 259 | error ("Invalid format operation %s", fmtcpy); |
| 257 | "ll" + 2 - long_flag, fmt[-1]); | ||
| 258 | 260 | ||
| 259 | /* case 'b': */ | 261 | /* case 'b': */ |
| 260 | case 'l': | 262 | case 'l': |
| @@ -265,12 +267,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 265 | 267 | ||
| 266 | if (1 < long_flag) | 268 | if (1 < long_flag) |
| 267 | { | 269 | { |
| 268 | #ifdef HAVE_LONG_LONG_INT | 270 | EMACS_INT ll = va_arg (ap, EMACS_INT); |
| 269 | long long ll = va_arg (ap, long long); | ||
| 270 | sprintf (sprintf_buffer, fmtcpy, ll); | 271 | sprintf (sprintf_buffer, fmtcpy, ll); |
| 271 | #else | ||
| 272 | error ("Invalid format operation %%ll%c", fmt[-1]); | ||
| 273 | #endif | ||
| 274 | } | 272 | } |
| 275 | else if (long_flag) | 273 | else if (long_flag) |
| 276 | { | 274 | { |
| @@ -295,12 +293,8 @@ doprnt (char *buffer, register size_t bufsize, const char *format, | |||
| 295 | 293 | ||
| 296 | if (1 < long_flag) | 294 | if (1 < long_flag) |
| 297 | { | 295 | { |
| 298 | #ifdef HAVE_UNSIGNED_LONG_LONG_INT | 296 | EMACS_UINT ull = va_arg (ap, EMACS_UINT); |
| 299 | unsigned long long ull = va_arg (ap, unsigned long long); | ||
| 300 | sprintf (sprintf_buffer, fmtcpy, ull); | 297 | sprintf (sprintf_buffer, fmtcpy, ull); |
| 301 | #else | ||
| 302 | error ("Invalid format operation %%ll%c", fmt[-1]); | ||
| 303 | #endif | ||
| 304 | } | 298 | } |
| 305 | else if (long_flag) | 299 | else if (long_flag) |
| 306 | { | 300 | { |