Mercurial > hg > xemacs-beta
comparison src/doprnt.c @ 203:850242ba4a81 r20-3b28
Import from CVS: tag r20-3b28
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:02:21 +0200 |
parents | b405438285a2 |
children | 92f8ad5d0d3f |
comparison
equal
deleted
inserted
replaced
202:61eefc8fc970 | 203:850242ba4a81 |
---|---|
52 unsigned int space_flag:1; | 52 unsigned int space_flag:1; |
53 unsigned int number_flag:1; | 53 unsigned int number_flag:1; |
54 unsigned int zero_flag:1; | 54 unsigned int zero_flag:1; |
55 unsigned int h_flag:1; | 55 unsigned int h_flag:1; |
56 unsigned int l_flag:1; | 56 unsigned int l_flag:1; |
57 unsigned int forwarding_precision:1; | |
57 char converter; /* converter character or 0 for dummy marker | 58 char converter; /* converter character or 0 for dummy marker |
58 indicating literal text at the end of the | 59 indicating literal text at the end of the |
59 specification */ | 60 specification */ |
60 Bytecount text_before; /* position of the first character of the | 61 Bytecount text_before; /* position of the first character of the |
61 block of literal text before this spec */ | 62 block of literal text before this spec */ |
164 error ("Premature end of format string"); \ | 165 error ("Premature end of format string"); \ |
165 ch = *fmt; \ | 166 ch = *fmt; \ |
166 if (ch >= 0200) \ | 167 if (ch >= 0200) \ |
167 error ("Non-ASCII character in format converter spec"); \ | 168 error ("Non-ASCII character in format converter spec"); \ |
168 fmt++; \ | 169 fmt++; \ |
170 } while (0) | |
171 | |
172 #define RESOLVE_FLAG_CONFLICTS(spec) \ | |
173 do { \ | |
174 if (spec.space_flag && spec.plus_flag) \ | |
175 spec.space_flag = 0; \ | |
176 if (spec.zero_flag && spec.space_flag) \ | |
177 spec.zero_flag = 0; \ | |
169 } while (0) | 178 } while (0) |
170 | 179 |
171 static printf_spec_dynarr * | 180 static printf_spec_dynarr * |
172 parse_doprnt_spec (CONST Bufbyte *format, Bytecount format_length) | 181 parse_doprnt_spec (CONST Bufbyte *format, Bytecount format_length) |
173 { | 182 { |
238 NEXT_ASCII_BYTE (ch); | 247 NEXT_ASCII_BYTE (ch); |
239 } | 248 } |
240 | 249 |
241 /* Parse off the minimum field width */ | 250 /* Parse off the minimum field width */ |
242 fmt--; /* back up */ | 251 fmt--; /* back up */ |
243 fmt = parse_off_posnum (fmt, fmt_end, &spec.minwidth); | 252 |
244 if (spec.minwidth == -1) | 253 /* |
245 spec.minwidth = 0; | 254 * * means the field width was passed as an argument. |
255 * Mark the current spec as one that forwards its | |
256 * field width and flags to the next spec in the array. | |
257 * Then create a new spec and continue with the parsing. | |
258 */ | |
259 if (fmt != fmt_end && *fmt == '*') | |
260 { | |
261 spec.converter = '*'; | |
262 RESOLVE_FLAG_CONFLICTS(spec); | |
263 Dynarr_add (specs, spec); | |
264 memset (&spec, 0, sizeof (spec)); | |
265 spec.argnum = ++prev_argnum; | |
266 fmt++; | |
267 } | |
268 else | |
269 { | |
270 fmt = parse_off_posnum (fmt, fmt_end, &spec.minwidth); | |
271 if (spec.minwidth == -1) | |
272 spec.minwidth = 0; | |
273 } | |
246 | 274 |
247 /* Parse off any precision specified */ | 275 /* Parse off any precision specified */ |
248 NEXT_ASCII_BYTE (ch); | 276 NEXT_ASCII_BYTE (ch); |
249 if (ch == '.') | 277 if (ch == '.') |
250 { | 278 { |
251 fmt = parse_off_posnum (fmt, fmt_end, &spec.precision); | 279 /* |
252 if (spec.precision == -1) | 280 * * means the precision was passed as an argument. |
253 spec.precision = 0; | 281 * Mark the current spec as one that forwards its |
282 * fieldwidth, flags and precision to the next spec in | |
283 * the array. Then create a new spec and continue | |
284 * with the parse. | |
285 */ | |
286 if (fmt != fmt_end && *fmt == '*') | |
287 { | |
288 spec.converter = '*'; | |
289 spec.forwarding_precision = 1; | |
290 RESOLVE_FLAG_CONFLICTS(spec); | |
291 Dynarr_add (specs, spec); | |
292 memset (&spec, 0, sizeof (spec)); | |
293 spec.argnum = ++prev_argnum; | |
294 fmt++; | |
295 } | |
296 else | |
297 { | |
298 fmt = parse_off_posnum (fmt, fmt_end, &spec.precision); | |
299 if (spec.precision == -1) | |
300 spec.precision = 0; | |
301 } | |
254 NEXT_ASCII_BYTE (ch); | 302 NEXT_ASCII_BYTE (ch); |
255 } | 303 } |
256 else | 304 else |
257 /* No precision specified */ | 305 /* No precision specified */ |
258 spec.precision = -1; | 306 spec.precision = -1; |
270 if (!strchr (valid_converters, ch)) | 318 if (!strchr (valid_converters, ch)) |
271 error ("Invalid converter character %c", ch); | 319 error ("Invalid converter character %c", ch); |
272 spec.converter = ch; | 320 spec.converter = ch; |
273 } | 321 } |
274 | 322 |
275 if (spec.space_flag && spec.plus_flag) | 323 RESOLVE_FLAG_CONFLICTS(spec); |
276 spec.space_flag = 0; | |
277 if (spec.zero_flag && spec.space_flag) | |
278 spec.zero_flag = 0; | |
279 | |
280 Dynarr_add (specs, spec); | 324 Dynarr_add (specs, spec); |
281 } | 325 } |
282 | 326 |
283 RETURN_NOT_REACHED(specs) /* suppress compiler warning */ | 327 RETURN_NOT_REACHED(specs) /* suppress compiler warning */ |
284 } | 328 } |
431 continue; | 475 continue; |
432 | 476 |
433 if (ch == '%') | 477 if (ch == '%') |
434 { | 478 { |
435 doprnt_1 (stream, (Bufbyte *) &ch, 1, 0, -1, 0, 0); | 479 doprnt_1 (stream, (Bufbyte *) &ch, 1, 0, -1, 0, 0); |
480 continue; | |
481 } | |
482 | |
483 /* | |
484 * * as converter means the field width, precision was specified | |
485 * as an argument. Extract the data and forward it to the | |
486 * next spec, to which it will apply. | |
487 */ | |
488 if (ch == '*') | |
489 { | |
490 struct printf_spec *nextspec = Dynarr_atp (specs, i + 1); | |
491 Lisp_Object obj = largs[spec->argnum - 1]; | |
492 | |
493 if (INTP (obj)) | |
494 { | |
495 if (spec->forwarding_precision) | |
496 { | |
497 nextspec->precision = XINT (obj); | |
498 nextspec->minwidth = spec->minwidth; | |
499 } | |
500 else | |
501 { | |
502 nextspec->minwidth = XINT (obj); | |
503 } | |
504 nextspec->minus_flag = spec->minus_flag; | |
505 nextspec->plus_flag = spec->plus_flag; | |
506 nextspec->space_flag = spec->space_flag; | |
507 nextspec->number_flag = spec->number_flag; | |
508 nextspec->zero_flag = spec->zero_flag; | |
509 } | |
436 continue; | 510 continue; |
437 } | 511 } |
438 | 512 |
439 if (largs && (spec->argnum < 1 || spec->argnum > nargs)) | 513 if (largs && (spec->argnum < 1 || spec->argnum > nargs)) |
440 error ("Invalid repositioning argument %d", spec->argnum); | 514 error ("Invalid repositioning argument %d", spec->argnum); |