+#ifdef VECTORS
+ if (flags & VECTOR) {
+ /*
+ * Do the minimum amount of work necessary to construct
+ * a format specifier that can be used to recursively
+ * call vfprintf() for each element in the vector.
+ */
+ int i, j; /* Counter. */
+ int vcnt; /* Number of elements in vector. */
+ char *vfmt; /* Pointer to format specifier. */
+#define EXTRAHH 2
+ char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
+ int vwidth = 0; /* Width specified via '*'. */
+ int vprec = 0; /* Precision specified via '*'. */
+ char *vstr; /* Used for asprintf(). */
+ int vlen; /* Length returned by asprintf(). */
+ enum {
+ V_CHAR, V_SHORT, V_INT,
+ V_PCHAR, V_PSHORT, V_PINT,
+ V_FLOAT,
+#ifdef V64TYPE
+ V_LONGLONG, V_PLONGLONG,
+ V_DOUBLE,
+#endif /* V64TYPE */
+ } vtype;
+
+ vval.vectorarg = GETARG(VECTORTYPE);
+ /*
+ * Set vfmt. If vfmt_buf may not be big enough,
+ * malloc() space, taking care to free it later.
+ * (EXTRAHH is for possible extra "hh")
+ */
+ if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
+ vfmt = vfmt_buf;
+ else
+ vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
+
+ /* Set the separator character, if not specified. */
+ if (vsep == 'X') {
+ if (ch == 'c')
+ vsep = '\0';
+ else
+ vsep = ' ';
+ }
+
+ /* Create the format specifier. */
+ for (i = j = 0; i < &fmt[-1] - pct; i++) {
+ switch (pct[i]) {
+ case ',': case ';': case ':': case '_':
+ case 'v': case 'h': case 'l':
+ /* Ignore. */
+ break;
+ case '*':
+ if (pct[i - 1] != '.')
+ vwidth = 1;
+ else
+ vprec = 1;
+ /* FALLTHROUGH */
+ default:
+ vfmt[j++] = pct[i];
+ }
+ }
+
+ /*
+ * Determine the number of elements in the vector and
+ * finish up the format specifier.
+ */
+ if (flags & SHORTINT) {
+ switch (ch) {
+ case 'c':
+ vtype = V_SHORT;
+ break;
+ case 'p':
+ vtype = V_PSHORT;
+ break;
+ default:
+ vfmt[j++] = 'h';
+ vtype = V_SHORT;
+ break;
+ }
+ vcnt = 8;
+ } else if (flags & LONGINT) {
+ vcnt = 4;
+ vtype = (ch == 'p') ? V_PINT : V_INT;
+#ifdef V64TYPE
+ } else if (flags & LLONGINT) {
+ switch (ch) {
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ vcnt = 2;
+ vtype = V_DOUBLE;
+ break;
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
+ case 'p':
+ case 'x':
+ case 'X':
+ vfmt[j++] = 'l';
+ vfmt[j++] = 'l';
+ vcnt = 2;
+ vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
+ break;
+ default:
+ /*
+ * The default case should never
+ * happen.
+ */
+ case 'c':
+ vcnt = 16;
+ vtype = V_CHAR;
+ }
+#endif /* V64TYPE */
+ } else {
+ switch (ch) {
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ vcnt = 4;
+ vtype = V_FLOAT;
+ break;
+ default:
+ /*
+ * The default case should never
+ * happen.
+ */
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ vfmt[j++] = 'h';
+ vfmt[j++] = 'h';
+ /* drop through */
+ case 'p':
+ case 'c':
+ vcnt = 16;
+ vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
+ }
+ }
+ vfmt[j++] = ch;
+ vfmt[j++] = '\0';
+
+/* Get a vector element. */
+#ifdef V64TYPE
+#define VPRINT(type, ind, args...) do { \
+ switch (type) { \
+ case V_CHAR: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
+ break; \
+ case V_PCHAR: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
+ break; \
+ case V_SHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
+ break; \
+ case V_PSHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
+ break; \
+ case V_INT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
+ break; \
+ case V_PINT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
+ break; \
+ case V_LONGLONG: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
+ break; \
+ case V_PLONGLONG: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
+ break; \
+ case V_FLOAT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
+ break; \
+ case V_DOUBLE: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
+ break; \
+ } \
+ ret += vlen; \
+ PRINT(vstr, vlen); \
+ FLUSH(); \
+ free(vstr); \
+} while (0)
+#else /* !V64TYPE */
+#define VPRINT(type, ind, args...) do { \
+ switch (type) { \
+ case V_CHAR: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
+ break; \
+ case V_PCHAR: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
+ break; \
+ case V_SHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
+ break; \
+ case V_PSHORT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
+ break; \
+ case V_INT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
+ break; \
+ case V_PINT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
+ break; \
+ case V_FLOAT: \
+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
+ break; \
+ } \
+ ret += vlen; \
+ PRINT(vstr, vlen); \
+ FLUSH(); \
+ free(vstr); \
+} while (0)
+#endif /* V64TYPE */
+
+ /* Actually print. */
+ if (vwidth == 0) {
+ if (vprec == 0) {
+ /* First element. */
+ VPRINT(vtype, 0);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
+ if(vsep)
+ PRINT(&vsep, 1);
+
+ /* Element. */
+ VPRINT(vtype, i);
+ }
+ } else {
+ /* First element. */
+ VPRINT(vtype, 0, prec);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
+ if(vsep)
+ PRINT(&vsep, 1);
+
+ /* Element. */
+ VPRINT(vtype, i, prec);
+ }
+ }
+ } else {
+ if (vprec == 0) {
+ /* First element. */
+ VPRINT(vtype, 0, width);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
+ if(vsep)
+ PRINT(&vsep, 1);
+
+ /* Element. */
+ VPRINT(vtype, i, width);
+ }
+ } else {
+ /* First element. */
+ VPRINT(vtype, 0, width, prec);
+ for (i = 1; i < vcnt; i++) {
+ /* Separator. */
+ if(vsep)
+ PRINT(&vsep, 1);
+
+ /* Element. */
+ VPRINT(vtype, i, width, prec);
+ }
+ }
+ }
+#undef VPRINT
+
+ if (vfmt != vfmt_buf)
+ free(vfmt);
+
+ continue;
+ }
+#endif /* VECTORS */