while (strchr(spec + 1, *++p1));
while (*++p1 && strchr(spec + 1, *p1));
rewrite(FS *fs){	enum { NOTOKAY, USEBCNT, USEPREC } sokay;	PR *pr, **nextpr;	FU *fu;	char *p1, *p2;	char savech, *fmtp, cs[3];	int nconv, prec;	size_t len;	nextpr = NULL;	prec = 0;	for (fu = fs->nextfu; fu; fu = fu->nextfu) {		/*		 * Break each format unit into print units; each conversion		 * character gets its own.		 */		for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {			pr = emalloc(sizeof(PR));			if (!fu->nextpr)				fu->nextpr = pr;			else				*nextpr = pr;			/* Skip preceding text and up to the next % sign. */			for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);			/* Only text in the string. */			if (!*p1) {				pr->fmt = fmtp;				pr->flags = F_TEXT;				break;			}			/*			 * Get precision for %s -- if have a byte count, don't			 * need it.			 */			if (fu->bcnt) {				sokay = USEBCNT;				/* Skip to conversion character. */				for (++p1; strchr(spec, *p1); ++p1);			} else {				/* Skip any special chars, field width. */				while (strchr(spec + 1, *++p1));				if (*p1 == '.' &&				    isdigit((unsigned char)*++p1)) {					sokay = USEPREC;					prec = atoi(p1);					while (isdigit((unsigned char)*++p1))						continue;				} else					sokay = NOTOKAY;			}			p2 = p1 + 1;		/* Set end pointer. */			cs[0] = *p1;		/* Set conversion string. */			cs[1] = '\0';			/*			 * Figure out the byte count for each conversion;			 * rewrite the format as necessary, set up blank-			 * padding for end of data.			 */			switch(cs[0]) {			case 'c':				pr->flags = F_CHAR;				switch(fu->bcnt) {				case 0: case 1:					pr->bcnt = 1;					break;				default:					p1[1] = '\0';					badcnt(p1);				}				break;			case 'd': case 'i':				pr->flags = F_INT;				goto isint;			case 'o': case 'u': case 'x': case 'X':				pr->flags = F_UINT;isint:				cs[2] = '\0';				cs[1] = cs[0];				cs[0] = 'q';				switch(fu->bcnt) {				case 0: case 4:					pr->bcnt = 4;					break;				case 1:					pr->bcnt = 1;					break;				case 2:					pr->bcnt = 2;					break;				case 8:					pr->bcnt = 8;					break;				default:					p1[1] = '\0';					badcnt(p1);				}				break;			case 'e': case 'E': case 'f': case 'g': case 'G':				pr->flags = F_DBL;				switch(fu->bcnt) {				case 0: case 8:					pr->bcnt = 8;					break;				case 4:					pr->bcnt = 4;					break;				default:					p1[1] = '\0';					badcnt(p1);				}				break;			case 's':				pr->flags = F_STR;				switch(sokay) {				case NOTOKAY:					badsfmt();				case USEBCNT:					pr->bcnt = fu->bcnt;					break;				case USEPREC:					pr->bcnt = prec;					break;				}				break;			case '_':				++p2;				switch(p1[1]) {				case 'A':					endfu = fu;					fu->flags |= F_IGNORE;					/* FALLTHROUGH */				case 'a':					pr->flags = F_ADDRESS;					++p2;					switch(p1[2]) {					case 'd': case 'o': case'x':						cs[0] = 'q';						cs[1] = p1[2];						cs[2] = '\0';						break;					default:						p1[3] = '\0';						badconv(p1);					}					break;				case 'c':					pr->flags = F_C;					/* cs[0] = 'c';	set in conv_c */					goto isint2;				case 'p':					pr->flags = F_P;					cs[0] = 'c';					goto isint2;				case 'u':					pr->flags = F_U;					/* cs[0] = 'c';	set in conv_u */isint2:					switch(fu->bcnt) {					case 0: case 1:						pr->bcnt = 1;						break;					default:						p1[2] = '\0';						badcnt(p1);					}					break;				default:					p1[2] = '\0';					badconv(p1);				}				break;			default:				p1[1] = '\0';				badconv(p1);			}			/*			 * Copy to PR format string, set conversion character			 * pointer, update original.			 */			savech = *p2;			p1[0] = '\0';			len = strlen(fmtp) + strlen(cs) + 1;			pr->fmt = emalloc(len);			snprintf(pr->fmt, len, "%s%s", fmtp, cs);			*p2 = savech;			pr->cchar = pr->fmt + (p1 - fmtp);			fmtp = p2;			/* Only one conversion character if byte count. */			if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)				errx(1,			    "byte count with multiple conversion characters");		}		/*		 * If format unit byte count not specified, figure it out		 * so can adjust rep count later.		 */		if (!fu->bcnt)			for (pr = fu->nextpr; pr; pr = pr->nextpr)				fu->bcnt += pr->bcnt;	}	/*	 * If the format string interprets any data at all, and it's	 * not the same as the blocksize, and its last format unit	 * interprets any data at all, and has no iteration count,	 * repeat it as necessary.	 *	 * If, rep count is greater than 1, no trailing whitespace	 * gets output from the last iteration of the format unit.	 */	for (fu = fs->nextfu; fu; fu = fu->nextfu) {		if (!fu->nextfu && fs->bcnt < blocksize &&		    !(fu->flags&F_SETREP) && fu->bcnt)			fu->reps += (blocksize - fs->bcnt) / fu->bcnt;		if (fu->reps > 1) {			for (pr = fu->nextpr;; pr = pr->nextpr)				if (!pr->nextpr)					break;			for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)				p2 = isspace((unsigned char)*p1) ? p1 : NULL;			if (p2)				pr->nospace = p2;		}	}#ifdef DEBUG	for (fu = fs->nextfu; fu; fu = fu->nextfu) {		(void)printf("fmt:");		for (pr = fu->nextpr; pr; pr = pr->nextpr)			(void)printf(" {%s}", pr->fmt);		(void)printf("\n");	}#endif}