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);