xref: /plan9-contrib/sys/src/ape/lib/ap/stdio/vfscanf.c (revision 22df390c30710ddd2119f3e7bb6c92dc399cabb9)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * pANS stdio -- vfscanf
33e12c5d1SDavid du Colombier  */
43e12c5d1SDavid du Colombier #include "iolib.h"
53e12c5d1SDavid du Colombier #include <stdarg.h>
63e12c5d1SDavid du Colombier #include <math.h>
73e12c5d1SDavid du Colombier #include <ctype.h>
83e12c5d1SDavid du Colombier static int icvt_f(FILE *f, va_list *args, int store, int width, int type);
93e12c5d1SDavid du Colombier static int icvt_x(FILE *f, va_list *args, int store, int width, int type);
103e12c5d1SDavid du Colombier static int icvt_sq(FILE *f, va_list *args, int store, int width, int type);
113e12c5d1SDavid du Colombier static int icvt_c(FILE *f, va_list *args, int store, int width, int type);
123e12c5d1SDavid du Colombier static int icvt_d(FILE *f, va_list *args, int store, int width, int type);
133e12c5d1SDavid du Colombier static int icvt_i(FILE *f, va_list *args, int store, int width, int type);
143e12c5d1SDavid du Colombier static int icvt_n(FILE *f, va_list *args, int store, int width, int type);
153e12c5d1SDavid du Colombier static int icvt_o(FILE *f, va_list *args, int store, int width, int type);
163e12c5d1SDavid du Colombier static int icvt_p(FILE *f, va_list *args, int store, int width, int type);
173e12c5d1SDavid du Colombier static int icvt_s(FILE *f, va_list *args, int store, int width, int type);
183e12c5d1SDavid du Colombier static int icvt_u(FILE *f, va_list *args, int store, int width, int type);
193e12c5d1SDavid du Colombier static int (*icvt[])(FILE *, va_list *, int, int, int)={
203e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/* ^@ ^A ^B ^C ^D ^E ^F ^G */
213e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/* ^H ^I ^J ^K ^L ^M ^N ^O */
223e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/* ^P ^Q ^R ^S ^T ^U ^V ^W */
233e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
243e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/* sp  !  "  #  $  %  &  ' */
253e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/*  (  )  *  +  ,  -  .  / */
263e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/*  0  1  2  3  4  5  6  7 */
273e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/*  8  9  :  ;  <  =  >  ? */
283e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	icvt_f,	0,	icvt_f,	/*  @  A  B  C  D  E  F  G */
293e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/*  H  I  J  K  L  M  N  O */
303e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,	/*  P  Q  R  S  T  U  V  W */
313e12c5d1SDavid du Colombier icvt_x,	0,	0,	icvt_sq,0,	0,	0,	0,	/*  X  Y  Z  [  \  ]  ^  _ */
323e12c5d1SDavid du Colombier 0,	0,	0,	icvt_c,	icvt_d,	icvt_f,	icvt_f,	icvt_f,	/*  `  a  b  c  d  e  f  g */
333e12c5d1SDavid du Colombier 0,	icvt_i,	0,	0,	0,	0,	icvt_n,	icvt_o,	/*  h  i  j  k  l  m  n  o */
343e12c5d1SDavid du Colombier icvt_p,	0,	0,	icvt_s,	0,	icvt_u,	0,	0,	/*  p  q  r  s  t  u  v  w */
353e12c5d1SDavid du Colombier icvt_x,	0,	0,	0,	0,	0,	0,	0,	/*  x  y  z  {  |  }  ~ ^? */
363e12c5d1SDavid du Colombier 
373e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
383e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
393e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
403e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
413e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
423e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
433e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
443e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
453e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
463e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
473e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
483e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
493e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
503e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
513e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
523e12c5d1SDavid du Colombier 0,	0,	0,	0,	0,	0,	0,	0,
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier };
553e12c5d1SDavid du Colombier #define	ngetc(f)		(nread++, getc(f))
563e12c5d1SDavid du Colombier #define	nungetc(c, f)		(--nread, ungetc((c), f))
573e12c5d1SDavid du Colombier #define	wgetc(c, f, out)	if(width--==0) goto out; (c)=ngetc(f)
583e12c5d1SDavid du Colombier #define	wungetc(c, f)		(++width, nungetc(c, f))
593e12c5d1SDavid du Colombier static int nread, ncvt;
603e12c5d1SDavid du Colombier static const char *fmtp;
613e12c5d1SDavid du Colombier 
vfscanf(FILE * f,const char * s,va_list args)623e12c5d1SDavid du Colombier int vfscanf(FILE *f, const char *s, va_list args){
633e12c5d1SDavid du Colombier 	int c, width, type, store;
643e12c5d1SDavid du Colombier 	nread=0;
653e12c5d1SDavid du Colombier 	ncvt=0;
663e12c5d1SDavid du Colombier 	fmtp=s;
673e12c5d1SDavid du Colombier 	for(;*fmtp;fmtp++) switch(*fmtp){
683e12c5d1SDavid du Colombier 	default:
693e12c5d1SDavid du Colombier 		if(isspace(*fmtp)){
703e12c5d1SDavid du Colombier 			do
713e12c5d1SDavid du Colombier 				c=ngetc(f);
723e12c5d1SDavid du Colombier 			while(isspace(c));
733e12c5d1SDavid du Colombier 			if(c==EOF) return ncvt?ncvt:EOF;
743e12c5d1SDavid du Colombier 			nungetc(c, f);
753e12c5d1SDavid du Colombier 			break;
763e12c5d1SDavid du Colombier 		}
773e12c5d1SDavid du Colombier 	NonSpecial:
783e12c5d1SDavid du Colombier 		c=ngetc(f);
793e12c5d1SDavid du Colombier 		if(c==EOF) return ncvt?ncvt:EOF;
803e12c5d1SDavid du Colombier 		if(c!=*fmtp){
813e12c5d1SDavid du Colombier 			nungetc(c, f);
823e12c5d1SDavid du Colombier 			return ncvt;
833e12c5d1SDavid du Colombier 		}
843e12c5d1SDavid du Colombier 		break;
853e12c5d1SDavid du Colombier 	case '%':
863e12c5d1SDavid du Colombier 		fmtp++;
873e12c5d1SDavid du Colombier 		if(*fmtp!='*') store=1;
883e12c5d1SDavid du Colombier 		else{
893e12c5d1SDavid du Colombier 			store=0;
903e12c5d1SDavid du Colombier 			fmtp++;
913e12c5d1SDavid du Colombier 		}
923e12c5d1SDavid du Colombier 		if('0'<=*fmtp && *fmtp<='9'){
933e12c5d1SDavid du Colombier 			width=0;
943e12c5d1SDavid du Colombier 			while('0'<=*fmtp && *fmtp<='9') width=width*10 + *fmtp++ - '0';
953e12c5d1SDavid du Colombier 		}
963e12c5d1SDavid du Colombier 		else
973e12c5d1SDavid du Colombier 			width=-1;
983e12c5d1SDavid du Colombier 		type=*fmtp=='h' || *fmtp=='l' || *fmtp=='L'?*fmtp++:'n';
993e12c5d1SDavid du Colombier 		if(!icvt[*fmtp]) goto NonSpecial;
1003e12c5d1SDavid du Colombier 		if(!(*icvt[*fmtp])(f, &args, store, width, type))
1013e12c5d1SDavid du Colombier 			return ncvt?ncvt:EOF;
1023e12c5d1SDavid du Colombier 		if(*fmtp=='\0') break;
1033e12c5d1SDavid du Colombier 		if(store) ncvt++;
1043e12c5d1SDavid du Colombier 	}
1053e12c5d1SDavid du Colombier 	return ncvt;
1063e12c5d1SDavid du Colombier }
icvt_n(FILE * f,va_list * args,int store,int width,int type)1073e12c5d1SDavid du Colombier static int icvt_n(FILE *f, va_list *args, int store, int width, int type){
108*22df390cSDavid du Colombier 	USED(f, width);
1093e12c5d1SDavid du Colombier 	if(store){
1103e12c5d1SDavid du Colombier 		--ncvt;	/* this assignment doesn't count! */
1113e12c5d1SDavid du Colombier 		switch(type){
1123e12c5d1SDavid du Colombier 		case 'h': *va_arg(*args, short *)=nread; break;
1133e12c5d1SDavid du Colombier 		case 'n': *va_arg(*args, int *)=nread; break;
1143e12c5d1SDavid du Colombier 		case 'l':
1153e12c5d1SDavid du Colombier 		case 'L': *va_arg(*args, long *)=nread; break;
1163e12c5d1SDavid du Colombier 		}
1173e12c5d1SDavid du Colombier 	}
1183e12c5d1SDavid du Colombier 	return 1;
1193e12c5d1SDavid du Colombier }
1203e12c5d1SDavid du Colombier #define	SIGNED		1
1213e12c5d1SDavid du Colombier #define	UNSIGNED	2
1223e12c5d1SDavid du Colombier #define	POINTER		3
1233e12c5d1SDavid du Colombier /*
1243e12c5d1SDavid du Colombier  * Generic fixed-point conversion
1253e12c5d1SDavid du Colombier  *	f is the input FILE *;
1263e12c5d1SDavid du Colombier  *	args is the va_list * into which to store the number;
1273e12c5d1SDavid du Colombier  *	store is a flag to enable storing;
1283e12c5d1SDavid du Colombier  *	width is the maximum field width;
1293e12c5d1SDavid du Colombier  *	type is 'h' 'l' or 'L', the scanf type modifier;
1303e12c5d1SDavid du Colombier  *	unsgned is SIGNED, UNSIGNED or POINTER, giving part of the type to store in;
1313e12c5d1SDavid du Colombier  *	base is the number base -- if 0, C number syntax is used.
1323e12c5d1SDavid du Colombier  */
icvt_fixed(FILE * f,va_list * args,int store,int width,int type,int unsgned,int base)1333e12c5d1SDavid du Colombier static int icvt_fixed(FILE *f, va_list *args,
1343e12c5d1SDavid du Colombier 				int store, int width, int type, int unsgned, int base){
1353e12c5d1SDavid du Colombier 	unsigned long int num=0;
1363e12c5d1SDavid du Colombier 	int sign=1, ndig=0, dig;
1373e12c5d1SDavid du Colombier 	int c;
1383e12c5d1SDavid du Colombier 	do
1393e12c5d1SDavid du Colombier 		c=ngetc(f);
1403e12c5d1SDavid du Colombier 	while(isspace(c));
1413e12c5d1SDavid du Colombier 	if(width--==0){
1423e12c5d1SDavid du Colombier 		nungetc(c, f);
1433e12c5d1SDavid du Colombier 		goto Done;
1443e12c5d1SDavid du Colombier 	}
1453e12c5d1SDavid du Colombier 	if(c=='+'){
1463e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
1473e12c5d1SDavid du Colombier 	}
1483e12c5d1SDavid du Colombier 	else if(c=='-'){
1493e12c5d1SDavid du Colombier 		sign=-1;
1503e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
1513e12c5d1SDavid du Colombier 	}
1523e12c5d1SDavid du Colombier 	switch(base){
1533e12c5d1SDavid du Colombier 	case 0:
1543e12c5d1SDavid du Colombier 		if(c=='0'){
1553e12c5d1SDavid du Colombier 			wgetc(c, f, Done);
1563e12c5d1SDavid du Colombier 			if(c=='x' || c=='X'){
1573e12c5d1SDavid du Colombier 				wgetc(c, f, Done);
1583e12c5d1SDavid du Colombier 				base=16;
1593e12c5d1SDavid du Colombier 			}
1603e12c5d1SDavid du Colombier 			else{
1613e12c5d1SDavid du Colombier 				ndig=1;
1623e12c5d1SDavid du Colombier 				base=8;
1633e12c5d1SDavid du Colombier 			}
1643e12c5d1SDavid du Colombier 		}
1653e12c5d1SDavid du Colombier 		else
1663e12c5d1SDavid du Colombier 			base=10;
1673e12c5d1SDavid du Colombier 		break;
1683e12c5d1SDavid du Colombier 	case 16:
1693e12c5d1SDavid du Colombier 		if(c=='0'){
1703e12c5d1SDavid du Colombier 			wgetc(c, f, Done);
1713e12c5d1SDavid du Colombier 			if(c=='x' || c=='X'){
1723e12c5d1SDavid du Colombier 				wgetc(c, f, Done);
1733e12c5d1SDavid du Colombier 			}
1743e12c5d1SDavid du Colombier 			else ndig=1;
1753e12c5d1SDavid du Colombier 		}
1763e12c5d1SDavid du Colombier 		break;
1773e12c5d1SDavid du Colombier 	}
1783e12c5d1SDavid du Colombier 	while('0'<=c && c<='9' || 'a'<=c && c<='f' || 'A'<=c && c<='F'){
1793e12c5d1SDavid du Colombier 		dig='0'<=c && c<='9'?c-'0':'a'<=c && c<='f'?c-'a'+10:c-'A'+10;
1803e12c5d1SDavid du Colombier 		if(dig>=base) break;
1813e12c5d1SDavid du Colombier 		ndig++;
1823e12c5d1SDavid du Colombier 		num=num*base+dig;
1833e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
1843e12c5d1SDavid du Colombier 	}
1853e12c5d1SDavid du Colombier 	nungetc(c, f);
1863e12c5d1SDavid du Colombier Done:
1873e12c5d1SDavid du Colombier 	if(ndig==0) return 0;
1883e12c5d1SDavid du Colombier 	if(store){
1893e12c5d1SDavid du Colombier 		switch(unsgned){
1903e12c5d1SDavid du Colombier 		case SIGNED:
1913e12c5d1SDavid du Colombier 			switch(type){
1923e12c5d1SDavid du Colombier 			case 'h': *va_arg(*args,  short *)=num*sign; break;
1933e12c5d1SDavid du Colombier 			case 'n': *va_arg(*args,  int *)=num*sign; break;
1943e12c5d1SDavid du Colombier 			case 'l':
1953e12c5d1SDavid du Colombier 			case 'L': *va_arg(*args,  long *)=num*sign; break;
1963e12c5d1SDavid du Colombier 			}
1973e12c5d1SDavid du Colombier 			break;
1983e12c5d1SDavid du Colombier 		case UNSIGNED:
1993e12c5d1SDavid du Colombier 			switch(type){
2003e12c5d1SDavid du Colombier 			case 'h': *va_arg(*args, unsigned short *)=num*sign; break;
2013e12c5d1SDavid du Colombier 			case 'n': *va_arg(*args, unsigned int *)=num*sign; break;
2023e12c5d1SDavid du Colombier 			case 'l':
2033e12c5d1SDavid du Colombier 			case 'L': *va_arg(*args, unsigned long *)=num*sign; break;
2043e12c5d1SDavid du Colombier 			}
2053e12c5d1SDavid du Colombier 			break;
2063e12c5d1SDavid du Colombier 		case POINTER:
2073e12c5d1SDavid du Colombier 			*va_arg(*args, void **)=(void *)(num*sign); break;
2083e12c5d1SDavid du Colombier 		}
2093e12c5d1SDavid du Colombier 	}
2103e12c5d1SDavid du Colombier 	return 1;
2113e12c5d1SDavid du Colombier }
icvt_d(FILE * f,va_list * args,int store,int width,int type)2123e12c5d1SDavid du Colombier static int icvt_d(FILE *f, va_list *args, int store, int width, int type){
2133e12c5d1SDavid du Colombier 	return icvt_fixed(f, args, store, width, type, SIGNED, 10);
2143e12c5d1SDavid du Colombier }
icvt_x(FILE * f,va_list * args,int store,int width,int type)2153e12c5d1SDavid du Colombier static int icvt_x(FILE *f, va_list *args, int store, int width, int type){
2163e12c5d1SDavid du Colombier 	return icvt_fixed(f, args, store, width, type, UNSIGNED, 16);
2173e12c5d1SDavid du Colombier }
icvt_o(FILE * f,va_list * args,int store,int width,int type)2183e12c5d1SDavid du Colombier static int icvt_o(FILE *f, va_list *args, int store, int width, int type){
2193e12c5d1SDavid du Colombier 	return icvt_fixed(f, args, store, width, type, UNSIGNED, 8);
2203e12c5d1SDavid du Colombier }
icvt_i(FILE * f,va_list * args,int store,int width,int type)2213e12c5d1SDavid du Colombier static int icvt_i(FILE *f, va_list *args, int store, int width, int type){
2223e12c5d1SDavid du Colombier 	return icvt_fixed(f, args, store, width, type, SIGNED, 0);
2233e12c5d1SDavid du Colombier }
icvt_u(FILE * f,va_list * args,int store,int width,int type)2243e12c5d1SDavid du Colombier static int icvt_u(FILE *f, va_list *args, int store, int width, int type){
2253e12c5d1SDavid du Colombier 	return icvt_fixed(f, args, store, width, type, UNSIGNED, 10);
2263e12c5d1SDavid du Colombier }
icvt_p(FILE * f,va_list * args,int store,int width,int type)2273e12c5d1SDavid du Colombier static int icvt_p(FILE *f, va_list *args, int store, int width, int type){
2283e12c5d1SDavid du Colombier 	return icvt_fixed(f, args, store, width, type, POINTER, 16);
2293e12c5d1SDavid du Colombier }
2303e12c5d1SDavid du Colombier #define	NBUF	509
icvt_f(FILE * f,va_list * args,int store,int width,int type)2313e12c5d1SDavid du Colombier static int icvt_f(FILE *f, va_list *args, int store, int width, int type){
2323e12c5d1SDavid du Colombier 	char buf[NBUF+1];
2333e12c5d1SDavid du Colombier 	char *s=buf;
2343e12c5d1SDavid du Colombier 	int c, ndig=0, ndpt=0, nexp=1;
2353e12c5d1SDavid du Colombier 	if(width<0 || NBUF<width) width=NBUF;	/* bug -- no limit specified in ansi */
2363e12c5d1SDavid du Colombier 	do
2373e12c5d1SDavid du Colombier 		c=ngetc(f);
2383e12c5d1SDavid du Colombier 	while(isspace(c));
2393e12c5d1SDavid du Colombier 	if(width--==0){
2403e12c5d1SDavid du Colombier 		nungetc(c, f);
2413e12c5d1SDavid du Colombier 		goto Done;
2423e12c5d1SDavid du Colombier 	}
2433e12c5d1SDavid du Colombier 	if(c=='+' || c=='-'){
2443e12c5d1SDavid du Colombier 		*s++=c;
2453e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
2463e12c5d1SDavid du Colombier 	}
2473e12c5d1SDavid du Colombier 	while('0'<=c && c<='9' || ndpt==0 && c=='.'){
2483e12c5d1SDavid du Colombier 		if(c=='.') ndpt++;
2493e12c5d1SDavid du Colombier 		else ndig++;
2503e12c5d1SDavid du Colombier 		*s++=c;
2513e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
2523e12c5d1SDavid du Colombier 	}
2533e12c5d1SDavid du Colombier 	if(c=='e' || c=='E'){
2543e12c5d1SDavid du Colombier 		*s++=c;
2553e12c5d1SDavid du Colombier 		nexp=0;
2563e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
2573e12c5d1SDavid du Colombier 		if(c=='+' || c=='-'){
2583e12c5d1SDavid du Colombier 			*s++=c;
2593e12c5d1SDavid du Colombier 			wgetc(c, f, Done);
2603e12c5d1SDavid du Colombier 		}
2613e12c5d1SDavid du Colombier 		while('0'<=c && c<='9'){
2623e12c5d1SDavid du Colombier 			*s++=c;
2633e12c5d1SDavid du Colombier 			nexp++;
2643e12c5d1SDavid du Colombier 			wgetc(c, f, Done);
2653e12c5d1SDavid du Colombier 		}
2663e12c5d1SDavid du Colombier 	}
2673e12c5d1SDavid du Colombier 	nungetc(c, f);
2683e12c5d1SDavid du Colombier Done:
2693e12c5d1SDavid du Colombier 	if(ndig==0 || nexp==0) return 0;
2703e12c5d1SDavid du Colombier 	*s='\0';
2713e12c5d1SDavid du Colombier 	if(store) switch(type){
2723e12c5d1SDavid du Colombier 	case 'h':
2733e12c5d1SDavid du Colombier 	case 'n': *va_arg(*args, float *)=atof(buf); break;
2743e12c5d1SDavid du Colombier 	case 'L': /* bug -- should store in a long double */
2753e12c5d1SDavid du Colombier 	case 'l': *va_arg(*args, double *)=atof(buf); break;
2763e12c5d1SDavid du Colombier 	}
2773e12c5d1SDavid du Colombier 	return 1;
2783e12c5d1SDavid du Colombier }
icvt_s(FILE * f,va_list * args,int store,int width,int type)2793e12c5d1SDavid du Colombier static int icvt_s(FILE *f, va_list *args, int store, int width, int type){
2803e12c5d1SDavid du Colombier 	int c, nn;
2813e12c5d1SDavid du Colombier 	register char *s;
282*22df390cSDavid du Colombier 
283*22df390cSDavid du Colombier 	USED(type);
284*22df390cSDavid du Colombier 	s = 0;
2853e12c5d1SDavid du Colombier 	if(store) s=va_arg(*args, char *);
2863e12c5d1SDavid du Colombier 	do
2873e12c5d1SDavid du Colombier 		c=ngetc(f);
2883e12c5d1SDavid du Colombier 	while(isspace(c));
2893e12c5d1SDavid du Colombier 	if(width--==0){
2903e12c5d1SDavid du Colombier 		nungetc(c, f);
2913e12c5d1SDavid du Colombier 		goto Done;
2923e12c5d1SDavid du Colombier 	}
2933e12c5d1SDavid du Colombier 	nn=0;
2943e12c5d1SDavid du Colombier 	while(!isspace(c)){
2953e12c5d1SDavid du Colombier 		if(c==EOF){
29643751f27SDavid du Colombier 			nread--;
2973e12c5d1SDavid du Colombier 			if(nn==0) return 0;
2983e12c5d1SDavid du Colombier 			else goto Done;
2993e12c5d1SDavid du Colombier 		}
3003e12c5d1SDavid du Colombier 		nn++;
3013e12c5d1SDavid du Colombier 		if(store) *s++=c;
3023e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
3033e12c5d1SDavid du Colombier 	}
3043e12c5d1SDavid du Colombier 	nungetc(c, f);
3053e12c5d1SDavid du Colombier Done:
3063e12c5d1SDavid du Colombier 	if(store) *s='\0';
3073e12c5d1SDavid du Colombier 	return 1;
3083e12c5d1SDavid du Colombier }
icvt_c(FILE * f,va_list * args,int store,int width,int type)3093e12c5d1SDavid du Colombier static int icvt_c(FILE *f, va_list *args, int store, int width, int type){
3103e12c5d1SDavid du Colombier 	int c;
3113e12c5d1SDavid du Colombier 	register char *s;
312*22df390cSDavid du Colombier 
313*22df390cSDavid du Colombier 	USED(type);
314*22df390cSDavid du Colombier 	s = 0;
3153e12c5d1SDavid du Colombier 	if(store) s=va_arg(*args, char *);
3163e12c5d1SDavid du Colombier 	if(width<0) width=1;
3173e12c5d1SDavid du Colombier 	for(;;){
3183e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
3193e12c5d1SDavid du Colombier 		if(c==EOF) return 0;
3203e12c5d1SDavid du Colombier 		if(store) *s++=c;
3213e12c5d1SDavid du Colombier 	}
3223e12c5d1SDavid du Colombier Done:
3233e12c5d1SDavid du Colombier 	return 1;
3243e12c5d1SDavid du Colombier }
match(int c,const char * pat)3253e12c5d1SDavid du Colombier static int match(int c, const char *pat){
3263e12c5d1SDavid du Colombier 	int ok=1;
3273e12c5d1SDavid du Colombier 	if(*pat=='^'){
3283e12c5d1SDavid du Colombier 		ok=!ok;
3293e12c5d1SDavid du Colombier 		pat++;
3303e12c5d1SDavid du Colombier 	}
3313e12c5d1SDavid du Colombier 	while(pat!=fmtp){
3323e12c5d1SDavid du Colombier 		if(pat+2<fmtp && pat[1]=='-'){
3333e12c5d1SDavid du Colombier 			if(pat[0]<=c && c<=pat[2]
3343e12c5d1SDavid du Colombier 			|| pat[2]<=c && c<=pat[0])
3353e12c5d1SDavid du Colombier 				return ok;
3363e12c5d1SDavid du Colombier 			pat+=2;
3373e12c5d1SDavid du Colombier 		}
3383e12c5d1SDavid du Colombier 		else if(c==*pat) return ok;
3393e12c5d1SDavid du Colombier 		pat++;
3403e12c5d1SDavid du Colombier 	}
3413e12c5d1SDavid du Colombier 	return !ok;
3423e12c5d1SDavid du Colombier }
icvt_sq(FILE * f,va_list * args,int store,int width,int type)3433e12c5d1SDavid du Colombier static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){
3443e12c5d1SDavid du Colombier 	int c, nn;
3453e12c5d1SDavid du Colombier 	register char *s;
3463e12c5d1SDavid du Colombier 	register const char *pat;
347*22df390cSDavid du Colombier 	USED(type);
348*22df390cSDavid du Colombier 	s = 0;
3493e12c5d1SDavid du Colombier 	pat=++fmtp;
3503e12c5d1SDavid du Colombier 	if(*fmtp=='^') fmtp++;
3513e12c5d1SDavid du Colombier 	if(*fmtp!='\0') fmtp++;
3523e12c5d1SDavid du Colombier 	while(*fmtp!='\0' && *fmtp!=']') fmtp++;
3533e12c5d1SDavid du Colombier 	if(store) s=va_arg(*args, char *);
3543e12c5d1SDavid du Colombier 	nn=0;
3553e12c5d1SDavid du Colombier 	for(;;){
3563e12c5d1SDavid du Colombier 		wgetc(c, f, Done);
3573e12c5d1SDavid du Colombier 		if(c==EOF){
35843751f27SDavid du Colombier 			nread--;
3593e12c5d1SDavid du Colombier 			if(nn==0) return 0;
3603e12c5d1SDavid du Colombier 			else goto Done;
3613e12c5d1SDavid du Colombier 		}
3623e12c5d1SDavid du Colombier 		if(!match(c, pat)) break;
3633e12c5d1SDavid du Colombier 		if(store) *s++=c;
3643e12c5d1SDavid du Colombier 		nn++;
3653e12c5d1SDavid du Colombier 	}
3663e12c5d1SDavid du Colombier 	nungetc(c, f);
3673e12c5d1SDavid du Colombier Done:
3683e12c5d1SDavid du Colombier 	if(store) *s='\0';
3693e12c5d1SDavid du Colombier 	return 1;
3703e12c5d1SDavid du Colombier }
371