void format (struct obstack *obs, int argc, token_data **argv) { #ifdef HAVE_EFGCVT const char *fmt; /* format control string */ int c; /* a simple character */ char fc; /* format code */ /* Flags. */ char flags; /* 1 iff treating flags */ char ljust; /* left justification */ char mandsign; /* mandatory sign */ char noplus; /* use space if no sign */ char alternate; /* use alternate form */ char zeropad; /* do zero padding */ char plus; /* plus-sign, according to mandatory and noplus */ /* Precision specifiers. */ int width; /* minimum field width */ int prec; /* precision */ int maxch; /* maximum no. of chars to print */ char lflag; /* long flag */ char hflag; /* short flag */ /* Different parts of each specification. */ char sign; /* wanted sign, iff any */ int ppad; /* pre-prefix zero padding */ const char *prefix; /* value prefix */ int lpad; /* zero padding on the left */ register char *s; /* ptr to formatted text */ int rpad; /* zero padding on the rigth*/ const char *suffix; /* value suffix */ /* Buffer and stuff. */ char str[MAXFIELD]; /* buffer for formatted text */ int length; /* length of str */ int padding; /* padding at the left or rigth */ register int i; /* an index */ /* Length of trailing string in str. */ #define LENGTH(s) (&str[MAXFIELD-1] - (s)) #define HAS_SIGN (sign != '\0') fmt = ARG_STR (argc, argv); for (;;) { while ((c = *fmt++) != '%') { if (c == 0) return; obstack_1grow (obs, c); } if (*fmt == '%') { obstack_1grow (obs, '%'); fmt++; continue; } /* Parse flags. */ flags = 1; ljust = mandsign = noplus = alternate = zeropad = 0; do { switch (*fmt) { case '-': /* left justification */ ljust = 1; break; case '+': /* mandatory sign */ mandsign = 1; break; case ' ': /* space instead of positive sign */ noplus = 1; break; case '0': /* zero padding */ zeropad = 1; break; case '#': /* alternate output */ alternate = 1; break; default: flags = 0; break; } } while (flags && fmt++); plus = '\0'; /* what to use as a plus ??? */ if (mandsign) plus = '+'; else if (noplus) plus = ' '; if (ljust) zeropad = 0; /* Minimum field width. */ width = -1; if (*fmt == '*') { width = ARG_INT (argc, argv); fmt++; } else if (isdigit (*fmt)) { width = 0; do { width = width * 10 + *fmt++ - '0'; } while (isdigit (*fmt)); } /* Maximum precision. */ prec = -1; if (*fmt == '.') { if (*(++fmt) == '*') { prec = ARG_INT (argc, argv); ++fmt; } else if (isdigit (*fmt)) { prec = 0; do { prec = prec * 10 + *fmt++ - '0'; } while (isdigit (*fmt)) ; } } /* Length modifiers. */ lflag = (*fmt == 'l'); hflag = (*fmt == 'h'); if (lflag || hflag) fmt++; sign = '\0'; ppad = lpad = rpad = 0; maxch = -1; prefix = suffix = ""; switch (fc = *fmt++) { case '\0': return; case 'c': c = ARG_INT (argc, argv); str[0] = (unsigned char) c; str[1] = '\0'; s = str; break; case 's': s = ARG_STR (argc, argv); maxch = prec; break; case 'd': case 'i': if (lflag) { long val = ARG_LONG (argc, argv); if (val < 0) { val = -val; /* does not work for MINLONG */ sign = '-'; } else sign = plus; s = ulong_to_str ((unsigned long) val, str, 10, digits); } else { int val = ARG_INT (argc, argv); if (hflag) val = (short) val; if (val < 0) { val = -val; /* does not work for MININT */ sign = '-'; } else sign = plus; s = ulong_to_str ((unsigned long) val, str, 10, digits); } if (zeropad) lpad = width - LENGTH (s) - HAS_SIGN; break; case 'o': if (lflag) { unsigned long val = ARG_ULONG (argc, argv); s = ulong_to_str ((unsigned long) val, str, 8, digits); } else { unsigned int val = ARG_UINT (argc, argv); if (hflag) val = (unsigned short) val; s = ulong_to_str ((unsigned long) val, str, 8, digits); } if (alternate) prefix = "0"; if (zeropad) lpad = width - LENGTH (s) - alternate; break; case 'x': case 'X': if (lflag) { unsigned long val = ARG_ULONG (argc, argv); s = ulong_to_str ((unsigned long) val, str, 16, (fc == 'x') ? digits : Digits); } else { unsigned int val = ARG_UINT (argc, argv); if (hflag) val = (unsigned short) val; s = ulong_to_str ((unsigned long) val, str, 16, (fc == 'x') ? digits : Digits); } if (alternate) prefix = (fc == 'X') ? "0X" : "0x"; if (zeropad) lpad = width - LENGTH (s) - 2*alternate; break; case 'u': if (lflag) { unsigned long val = ARG_ULONG (argc, argv); s = ulong_to_str ((unsigned long) val, str, 10, digits); } else { unsigned int val = ARG_UINT (argc, argv); if (hflag) val = (unsigned short) val; s = ulong_to_str ((unsigned long) val, str, 10, digits); } if (zeropad) lpad = width - LENGTH (s); break; case 'e': case 'E': { char *t; int sgn, decpt, exp, n; double val = ARG_DOUBLE (argc, argv); if (prec < 0) prec = 6; t = clr0 (ecvt (val, min (prec + 1, ECVTMAX), &decpt, &sgn)); sign = sgn ? '-' : plus; n = prec; s = str; exp = (t[0] == '0' && t[1] == '\0') ? 0 : decpt - 1; *s++ = *t++; if (n > 0 || alternate) *s++ = '.'; while (*t != '\0' && --n >= 0) *s++ = *t++; *s = '\0'; rpad = n; sgn = 0; if (exp < 0) { exp = -exp; sgn = 1; } t = ulong_to_str ((unsigned long) exp, str, 10, digits); if (exp < 10) *--t = '0'; /* always at least two digits */ *--t = sgn ? '-' : '+'; *--t = fc; if (zeropad) { lpad = width - HAS_SIGN - (s - str) - LENGTH (t); if (rpad > 0) lpad -= rpad; } suffix = t; s = str; } break; case 'f': { const char *t; int sgn, decpt, n; double val = ARG_DOUBLE (argc, argv); if (prec < 0) prec = 6; /* FIXME: For the following line, Dave Anglin reports ``warning: passing arg 1 of `clr0' discards `const' from pointer target type''. I suspect fcvt might be declared as returning const on some systems. Pouah! I should revise this whole module, one of these days... */ t = clr0 (fcvt (val, min (prec, FCVTMAX), &decpt, &sgn)); sign = sgn ? '-' : plus; n = prec; s = str; if (decpt <= 0) { prefix = (n > 0 || alternate) ? "0." : "0"; lpad = min (-decpt, prec); n -= lpad; } else { while (--decpt >= 0) *s++ = *t++; if (n > 0 || alternate) *s++ = '.'; } while (*t && --n >= 0) *s++ = *t++; *s = '\0'; rpad = n; if (zeropad) ppad = width - HAS_SIGN - (prefix[1] ? 2 : 1) - lpad - (s - str) - rpad; s = str; } break; default: continue; } if (lpad < 0) lpad = 0; if (rpad < 0) rpad = 0; if (width < 0) width = 0; i = strlen (s); if (maxch <= 0 || maxch > i) maxch = i; length = (HAS_SIGN + ppad + strlen (prefix) + lpad + maxch + rpad + strlen (suffix)); padding = 0; if (width != 0) { padding = width - length; } if (ljust == 0) /* left padding */ for (i = padding; --i >= 0;) obstack_1grow (obs, ' '); if (HAS_SIGN) /* sign */ obstack_1grow (obs, sign); for (i = ppad; --i >= 0;) /* pre-prefix zero padding */ obstack_1grow (obs, '0'); for (; *prefix; ++prefix) /* prefix */ obstack_1grow (obs, *prefix); for (i = lpad; --i >= 0;) /* left zero padding */ obstack_1grow (obs, '0'); for (i = maxch; --i >= 0; ++s) /* actual text */ obstack_1grow (obs, *s); for (i = rpad; --i >= 0;) /* right zero padding */ obstack_1grow (obs, '0'); for (; *suffix; ++suffix) /* suffix */ obstack_1grow (obs, *suffix); if (ljust != 0) /* right padding */ for (i = padding; --i >= 0;) obstack_1grow (obs, ' '); } #else /* not HAVE_EFGCVT */ char *fmt; /* format control string */ const char *fstart; /* beginning of current format spec */ int c; /* a simple character */ /* Flags. */ char flags; /* 1 iff treating flags */ /* Precision specifiers. */ int width; /* minimum field width */ int prec; /* precision */ char lflag; /* long flag */ char hflag; /* short flag */ /* Buffer and stuff. */ char str[256]; /* buffer for formatted text */ enum {INT, UINT, LONG, ULONG, DOUBLE, STR} datatype; fmt = ARG_STR (argc, argv); for (;;) { while ((c = *fmt++) != '%') { if (c == 0) return; obstack_1grow (obs, c); } fstart = fmt - 1; if (*fmt == '%') { obstack_1grow (obs, '%'); fmt++; continue; } /* Parse flags. */ flags = 1; do { switch (*fmt) { case '-': /* left justification */ case '+': /* mandatory sign */ case ' ': /* space instead of positive sign */ case '0': /* zero padding */ case '#': /* alternate output */ break; default: flags = 0; break; } } while (flags && fmt++); /* Minimum field width. */ width = -1; if (*fmt == '*') { width = ARG_INT (argc, argv); fmt++; } else if (isdigit (*fmt)) { do { fmt++; } while (isdigit (*fmt)); } /* Maximum precision. */ prec = -1; if (*fmt == '.') { if (*(++fmt) == '*') { prec = ARG_INT (argc, argv); ++fmt; } else if (isdigit (*fmt)) { do { fmt++; } while (isdigit (*fmt)); } } /* Length modifiers. */ lflag = (*fmt == 'l'); hflag = (*fmt == 'h'); if (lflag || hflag) fmt++; switch (*fmt++) { case '\0': return; case 'c': datatype = INT; break; case 's': datatype = STR; break; case 'd': case 'i': if (lflag) { datatype = LONG; } else { datatype = INT; } break; case 'o': case 'x': case 'X': case 'u': if (lflag) { datatype = ULONG; } else { datatype = UINT; } break; case 'e': case 'E': case 'f': datatype = DOUBLE; break; default: continue; } c = *fmt; *fmt = '\0'; switch(datatype) { case INT: if (width != -1 && prec != -1) sprintf (str, fstart, width, prec, ARG_INT(argc, argv)); else if (width != -1) sprintf (str, fstart, width, ARG_INT(argc, argv)); else if (prec != -1) sprintf (str, fstart, prec, ARG_INT(argc, argv)); else sprintf (str, fstart, ARG_INT(argc, argv)); break; case UINT: if (width != -1 && prec != -1) sprintf (str, fstart, width, prec, ARG_UINT(argc, argv)); else if (width != -1) sprintf (str, fstart, width, ARG_UINT(argc, argv)); else if (prec != -1) sprintf (str, fstart, prec, ARG_UINT(argc, argv)); else sprintf (str, fstart, ARG_UINT(argc, argv)); break; case LONG: if (width != -1 && prec != -1) sprintf (str, fstart, width, prec, ARG_LONG(argc, argv)); else if (width != -1) sprintf (str, fstart, width, ARG_LONG(argc, argv)); else if (prec != -1) sprintf (str, fstart, prec, ARG_LONG(argc, argv)); else sprintf (str, fstart, ARG_LONG(argc, argv)); break; case ULONG: if (width != -1 && prec != -1) sprintf (str, fstart, width, prec, ARG_ULONG(argc, argv)); else if (width != -1) sprintf (str, fstart, width, ARG_ULONG(argc, argv)); else if (prec != -1) sprintf (str, fstart, prec, ARG_ULONG(argc, argv)); else sprintf (str, fstart, ARG_ULONG(argc, argv)); break; case DOUBLE: if (width != -1 && prec != -1) sprintf (str, fstart, width, prec, ARG_DOUBLE(argc, argv)); else if (width != -1) sprintf (str, fstart, width, ARG_DOUBLE(argc, argv)); else if (prec != -1) sprintf (str, fstart, prec, ARG_DOUBLE(argc, argv)); else sprintf (str, fstart, ARG_DOUBLE(argc, argv)); break; case STR: if (width != -1 && prec != -1) sprintf (str, fstart, width, prec, ARG_STR(argc, argv)); else if (width != -1) sprintf (str, fstart, width, ARG_STR(argc, argv)); else if (prec != -1) sprintf (str, fstart, prec, ARG_STR(argc, argv)); else sprintf (str, fstart, ARG_STR(argc, argv)); break; } *fmt = c; obstack_grow (obs, str, strlen (str)); } #endif /* not HAVE_EFGCVT */ }
DistillerStatus DistillerMain(Argument *args, int nargs, DistillerInput *din, DistillerOutput *dout) { JSAMPROW handoff = NULL; JDIMENSION handoff_height, handoff_width, num_scanlines; int max_x=-1, max_y=-1, min_x=-1, min_y=-1, qual=55, i; int expert=0, resize=0, quality=3, nodistill=0, ismap=0; double scale = 0.5; cjpeg_source_ptr src_mgr; void *phase1_data; INT32 phase1_length; int fin_denom, fin_qual; DistillerStatus result = distBadInput; SetData(dout, NULL); bailout_now = 0; if ( (setjmp(jumpbuffer) != 0) ) { /* * fatal error occurred, so return immediately. */ MonitorClientSend(monID, "Distiller Errors", "Resetting distiller...\n", "Log"); DistillerExit(); DistillerInit(dType, 0, NULL); if (DataPtr(dout) != NULL) DataNeedsFree(dout,gm_True); else DataNeedsFree(dout,gm_False); return distFatalError; } /* * parse distillation arguments. set default values for some * things, then override them if args are specified. Default will * be to scale each axis by 0.5, turn quality down to 55%. */ for (i=0; i<nargs; i++) { INT32 argval = ARG_INT(args[i]); switch(ARG_ID(args[i])) { case GJPG_MAX_X: max_x = (int) argval; break; case GJPG_MAX_Y: max_y = (int) argval; break; case GJPG_MIN_X: min_x = (int) argval; break; case GJPG_MIN_Y: min_y = (int) argval; break; case GJPG_SCALE: scale = (double) ARG_DOUBLE(args[i]); break; case GJPG_QUAL: qual = (int) argval; break; case FRONT_RESIZE: resize = (int) argval; break; case FRONT_NO_DISTILL: nodistill = (int) argval; break; case FRONT_QUALITY: if (argval >= 1 && argval <= 5) quality = (int) argval; break; case FRONT_EXPERT: expert = (int) argval; break; case FRONT_ISMAP: ismap = (int) argval; break; default: break; } } if (nodistill) { return gjpg_passthrough(din, dout); } /* First pass through, we're just going to convert the GIF to JPEG */ phase1_data = NULL; phase1_length = 0; dstinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&dstinfo); src_mgr = jinit_read_gif(&dstinfo, (JOCTET *) DataPtr(din), (INT32) DataLength(din)); (*src_mgr->start_input)(&dstinfo, src_mgr); jpeg_default_colorspace(&dstinfo); jpeg_mem_dest(&dstinfo, (void **) &phase1_data, (UINT32 *) &phase1_length); jpeg_start_compress(&dstinfo, TRUE); while (dstinfo.next_scanline < dstinfo.image_height) { num_scanlines = (*src_mgr->get_pixel_rows)(&dstinfo, src_mgr); jpeg_write_scanlines(&dstinfo, src_mgr->buffer, num_scanlines); } (*src_mgr->finish_input)(&dstinfo, src_mgr); jpeg_finish_compress(&dstinfo); /* early bailout because of animated or transparent gif? */ if (bailout_now && DataLength(din) <= bailout_thresh[quality]) { result = distBadInput; goto JPGMUNGE_RETURN; } /* Now we're into the second pass. Let's do our JPEG->JPEG * distillation. We need to compute the denominator and the quality * knob setting. */ if (expert) { /* Do expert-like things here. Need to work out still. */ fin_qual = qual; fin_denom = compute_scale_denom(max_x, max_y, min_x, min_y, srcinfo.image_width, srcinfo.image_height, scale); } else { /* We're in beginner mode. Life is easier. */ if (ismap) { fin_qual = ismap_qual[quality-1]; fin_denom = ismap_denom[quality-1]; } else if (resize) { fin_qual = noscale_qual[quality-1]; fin_denom = noscale_denom[quality-1]; } else { fin_qual = norm_qual[quality-1]; fin_denom = norm_denom[quality-1]; } } /* Prep the input decompressor */ jpeg_mem_src(&srcinfo, phase1_data, phase1_length); jpeg_read_header(&srcinfo, TRUE); srcinfo.scale_num = 1; srcinfo.scale_denom = fin_denom; srcinfo.dither_mode = JDITHER_ORDERED; srcinfo.dct_method = JDCT_FASTEST; jpeg_start_decompress(&srcinfo); /* Prep the output compressor */ SetDataLength(dout,0); SetData(dout, NULL); sprintf(dout->mimeType, "image/jpeg"); jpeg_mem_dest(&dstinfo, (void **) &(DataPtr(dout)), (UINT32 *) &(DataLength(dout))); dstinfo.image_width = srcinfo.output_width; dstinfo.image_height = srcinfo.output_height; dstinfo.input_components = srcinfo.output_components; dstinfo.in_color_space = srcinfo.out_color_space; jpeg_set_defaults(&dstinfo); jpeg_set_quality(&dstinfo, fin_qual, TRUE); jpeg_start_compress(&dstinfo, TRUE); handoff_height = (JDIMENSION) 1; handoff_width = srcinfo.output_width*sizeof(JSAMPLE)*srcinfo.output_components; handoff = (JSAMPROW) malloc(handoff_width); /* We're going to need some buffer space to hand off data from the decompressor to the compressor. */ while (srcinfo.output_scanline < srcinfo.output_height) { num_scanlines = jpeg_read_scanlines(&srcinfo, &handoff, handoff_height); jpeg_write_scanlines(&dstinfo, &handoff, num_scanlines); } jpeg_finish_decompress(&srcinfo); jpeg_finish_compress(&dstinfo); result = distOk; JPGMUNGE_RETURN: if (handoff) free(handoff); DataNeedsFree(dout,gm_True); if (phase1_data) free(phase1_data); if (DataLength(dout) > DataLength(din)) { SetDataLength(dout, DataLength(din)); memcpy(DataPtr(dout), DataPtr(din), DataLength(din)); sprintf(dout->mimeType, "image/gif"); } DEBUG("finished processing\n"); return result; }
int main(int argc, char *argv[]) { DistillerStatus st; UINT32 len; Argument args[12]; int nargs = 0; int i; char *k; FILE *f; char nextfile[255]; DistillerInput in; DistillerOutput out; C_DistillerType distType; sprintf(distType.string, "test " INPUT_MIME_TYPE); if ((argc < 2) || (argc >= 2 && strncmp(argv[1], "-h", 2) == 0)) { usage(); exit(1); } if ((f = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "Can't open input file %s\n", argv[1]); exit(1); } for (i=2; i<argc-1; i += 2, nargs++) { SET_ARG_ID(args[nargs], strtoul(&argv[i][1], (char**)NULL, 0)); switch (argv[i][0]) { case 'i': SET_ARG_INT(args[nargs], strtol(argv[i+1], (char**)NULL, 0)); fprintf(stderr, "Arg id %lu is %ld\n", ARG_ID(args[nargs]), ARG_INT(args[nargs])); break; case 'f': SET_ARG_DOUBLE(args[nargs], strtod(argv[i+1], (char**)NULL)); fprintf(stderr, "Arg id %lu is %f\n", ARG_ID(args[nargs]), (float)ARG_DOUBLE(args[nargs])); break; case 's': default: SET_ARG_STRING(args[nargs], argv[i+1]); fprintf(stderr, "Arg id %lu is \"%s\"\n", ARG_ID(args[nargs]), ARG_STRING(args[nargs])); } } if ((st = DistillerInit(distType, 0, NULL)) != distOk) { fprintf(stderr, "DistillerInit failed: error %d\n", (int)st); exit(1); } SetMimeType(&in, INPUT_MIME_TYPE); while (fgets(nextfile, 254, f) != NULL) { char nextfile2[255]; int fd; int count; int ii; nextfile[strlen(nextfile)-1] = 0; fd = open(nextfile, O_RDONLY); if (fd == -1) { fprintf(stderr, "Can't read %s, skipping\n", nextfile); continue; } for (len = 0; (count = read(fd, (void*)(buf+len), (sizeof(buf)-len))) > 0; len += count) ; fprintf(stderr, "Read %lu bytes from %s\n", len, nextfile); SetData(&in, (void *)buf); SetDataLength(&in, len); SetMetadata(&in, NULL); SetMetadataLength(&in, 0); for (ii= 0; ii<REPEAT_COUNT; ii++) { fprintf(stderr,"Calling distiller main\n"); st = DistillerMain(args,nargs,&in,&out); if (st != distOk) { fprintf(stderr, "DistillerMain failed: error %d\n", (int)st); } close(fd); strcpy(nextfile2, argv[argc-1]); if (nextfile2[strlen(nextfile2)-1] != '/') strcat(nextfile2,"/"); k = strrchr(nextfile, '/'); if (k) strcat(nextfile2, k+1); else strcat(nextfile2, nextfile); strcat(nextfile2, ".OUT"); fd = open(nextfile2, O_CREAT | O_WRONLY | O_TRUNC, 0666); if (fd == -1) { fprintf(stderr, "Can't write %s, using stdout\n", nextfile2); fd = fileno(stdout); } len = write(fd, (const void *)DataPtr(&out), (size_t)(DataLength(&out))); if (fd != fileno(stdout)) close(fd); fprintf(stderr, "Wrote %lu of %lu bytes to %s\n", len, DataLength(&out), nextfile2); if (out.data.freeMe == gm_True) DistillerFree(DataPtr(&out)); if (out.metadata.freeMe == gm_True) DistillerFree(MetadataPtr(&out)); } } return(1); }
void format (struct obstack *obs, int argc, token_data **argv) { char *fmt; /* format control string */ const char *fstart; /* beginning of current format spec */ int c; /* a simple character */ /* Flags. */ char flags; /* 1 iff treating flags */ /* Precision specifiers. */ int width; /* minimum field width */ int prec; /* precision */ char lflag; /* long flag */ char hflag; /* short flag */ /* Buffer and stuff. */ char *str; /* malloc'd buffer of formatted text */ enum {INT, UINT, LONG, ULONG, DOUBLE, STR} datatype; fmt = (char *) ARG_STR (argc, argv); for (;;) { while ((c = *fmt++) != '%') { if (c == 0) return; obstack_1grow (obs, c); } fstart = fmt - 1; if (*fmt == '%') { obstack_1grow (obs, '%'); fmt++; continue; } /* Parse flags. */ flags = 1; do { switch (*fmt) { case '-': /* left justification */ case '+': /* mandatory sign */ case ' ': /* space instead of positive sign */ case '0': /* zero padding */ case '#': /* alternate output */ break; default: flags = 0; break; } } while (flags && fmt++); /* Minimum field width. */ width = -1; if (*fmt == '*') { width = ARG_INT (argc, argv); fmt++; } else if (isdigit (to_uchar (*fmt))) { do { fmt++; } while (isdigit (to_uchar (*fmt))); } /* Maximum precision. */ prec = -1; if (*fmt == '.') { if (*(++fmt) == '*') { prec = ARG_INT (argc, argv); ++fmt; } else if (isdigit (to_uchar (*fmt))) { do { fmt++; } while (isdigit (to_uchar (*fmt))); } } /* Length modifiers. */ lflag = (*fmt == 'l'); hflag = (*fmt == 'h'); if (lflag || hflag) fmt++; switch (*fmt++) { case '\0': return; case 'c': datatype = INT; break; case 's': datatype = STR; break; case 'd': case 'i': if (lflag) { datatype = LONG; } else { datatype = INT; } break; case 'o': case 'x': case 'X': case 'u': if (lflag) { datatype = ULONG; } else { datatype = UINT; } break; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': datatype = DOUBLE; break; default: continue; } c = *fmt; *fmt = '\0'; switch(datatype) { case INT: if (width != -1 && prec != -1) str = xasprintf (fstart, width, prec, ARG_INT(argc, argv)); else if (width != -1) str = xasprintf (fstart, width, ARG_INT(argc, argv)); else if (prec != -1) str = xasprintf (fstart, prec, ARG_INT(argc, argv)); else str = xasprintf (fstart, ARG_INT(argc, argv)); break; case UINT: if (width != -1 && prec != -1) str = xasprintf (fstart, width, prec, ARG_UINT(argc, argv)); else if (width != -1) str = xasprintf (fstart, width, ARG_UINT(argc, argv)); else if (prec != -1) str = xasprintf (fstart, prec, ARG_UINT(argc, argv)); else str = xasprintf (fstart, ARG_UINT(argc, argv)); break; case LONG: if (width != -1 && prec != -1) str = xasprintf (fstart, width, prec, ARG_LONG(argc, argv)); else if (width != -1) str = xasprintf (fstart, width, ARG_LONG(argc, argv)); else if (prec != -1) str = xasprintf (fstart, prec, ARG_LONG(argc, argv)); else str = xasprintf (fstart, ARG_LONG(argc, argv)); break; case ULONG: if (width != -1 && prec != -1) str = xasprintf (fstart, width, prec, ARG_ULONG(argc, argv)); else if (width != -1) str = xasprintf (fstart, width, ARG_ULONG(argc, argv)); else if (prec != -1) str = xasprintf (fstart, prec, ARG_ULONG(argc, argv)); else str = xasprintf (fstart, ARG_ULONG(argc, argv)); break; case DOUBLE: if (width != -1 && prec != -1) str = xasprintf (fstart, width, prec, ARG_DOUBLE(argc, argv)); else if (width != -1) str = xasprintf (fstart, width, ARG_DOUBLE(argc, argv)); else if (prec != -1) str = xasprintf (fstart, prec, ARG_DOUBLE(argc, argv)); else str = xasprintf (fstart, ARG_DOUBLE(argc, argv)); break; case STR: if (width != -1 && prec != -1) str = xasprintf (fstart, width, prec, ARG_STR(argc, argv)); else if (width != -1) str = xasprintf (fstart, width, ARG_STR(argc, argv)); else if (prec != -1) str = xasprintf (fstart, prec, ARG_STR(argc, argv)); else str = xasprintf (fstart, ARG_STR(argc, argv)); break; default: abort(); } *fmt = c; /* NULL was returned on failure, such as invalid format string. For now, just silently ignore that bad specifier. */ if (str == NULL) continue; obstack_grow (obs, str, strlen (str)); free (str); } }