SysIII/usr/src/lib/libc/vax/stdio/doscan.c

Compare this file to the similar file:
Show the results in this format:

/*LINTLIBRARY*/
#include <stdio.h>
#include <ctype.h>

#define	SPC	01
#define	STP	02
#define	SHORT	0
#define	REGULAR	1
#define	LONG	2
#define	INT	0
#define	FLOAT	1

char	*_getccl();

char	_sctab[128] = {
	0,0,0,0,0,0,0,0,
	0,SPC,SPC,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	SPC,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
};

_doscan(iop, fmt, argp)
FILE *iop;
register char *fmt;
register int **argp;
{
	register int ch;
	int nmatch, len, ch1;
	int **ptr, fileended, size;

	nmatch = 0;
	fileended = 0;
	while(1) switch(ch = *fmt++) {
	case '\0': 
		return(nmatch);
	case '%': 
		if((ch = *fmt++) == '%')
			goto def;
		ptr = 0;
		if(ch != '*')
			ptr = argp++;
		else
			ch = *fmt++;
		len = 0;
		size = REGULAR;
		while(isdigit(ch)) {
			len = len*10 + ch - '0';
			ch = *fmt++;
		}
		if(len == 0)
			len = 30000;
		if(ch == 'l') {
			size = LONG;
			ch = *fmt++;
		} else if(ch == 'h') {
			size = SHORT;
			ch = *fmt++;
		} else if(ch == '[')
			fmt = _getccl(fmt);
		if(isupper(ch)) {
			size = LONG;
			ch = _tolower(ch);
		}
		if(ch == '\0')
			return(-1);
		if(_innum(ptr, ch, len, size, iop, &fileended) && ptr)
			nmatch++;
		if(fileended)
			return(nmatch? nmatch: -1);
		break;

	case ' ':
	case '\n':
	case '\t': 
		while((ch1 = getc(iop))==' ' || ch1=='\t' || ch1=='\n')
			;
		if(ch1 != EOF)
			ungetc(ch1, iop);
		break;

	default: 
	def:
		ch1 = getc(iop);
		if(ch1 != ch) {
			if(ch1 == EOF)
				return(-1);
			ungetc(ch1, iop);
			return(nmatch);
		}
	}
}

_innum(ptr, type, len, size, iop, eofptr)
int **ptr, *eofptr;
struct _iobuf *iop;
{
	extern double atof();
	register char *np;
	char numbuf[64];
	register c, base;
	int expseen, scale, negflg, c1, ndigit;
	long lcval;

	if(type == 'c' || type == 's' || type == '[')
		return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, eofptr));
	lcval = 0;
	ndigit = 0;
	scale = INT;
	if(type == 'e' || type == 'f')
		scale = FLOAT;
	base = 10;
	if(type == 'o')
		base = 8;
	else if(type == 'x')
		base = 16;
	np = numbuf;
	expseen = 0;
	negflg = 0;
	while((c = getc(iop)) == ' ' || c == '\t' || c == '\n');
	if(c == '-') {
		negflg++;
		*np++ = c;
		c = getc(iop);
		len--;
	} else if(c == '+') {
		len--;
		c = getc(iop);
	}
	for( ; --len >= 0; *np++ = c, c = getc(iop)) {
		if(isdigit(c) || base == 16 && isxdigit(c)) {
			ndigit++;
			if(base == 8)
				lcval <<= 3;
			else if(base == 10)
				lcval = ((lcval<<2) + lcval)<<1;
			else
				lcval <<= 4;
			c1 = c;
			if(isdigit(c))
				c -= '0';
			else if('a' <= c && c <= 'f')
				c -= 'a'-10;
			else
				c -= 'A'-10;
			lcval += c;
			c = c1;
			continue;
		} else if(c == '.') {
			if(base != 10 || scale == INT)
				break;
			ndigit++;
			continue;
		} else if((c == 'e' || c == 'E') && expseen == 0) {
			if(base != 10 || scale == INT || ndigit == 0)
				break;
			expseen++;
			*np++ = c;
			c = getc(iop);
			if(c != '+' && c != '-' && !isdigit(c))
				break;
		} else
			break;
	}
	if(negflg)
		lcval = -lcval;
	if(c != EOF) {
		ungetc(c, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if(ptr == NULL || np == numbuf)
		return(0);
	*np++ = 0;
	switch((scale<<4) | size) {

	case (FLOAT<<4) | SHORT:
	case (FLOAT<<4) | REGULAR:
		**(float **)ptr = atof(numbuf);
		break;

	case (FLOAT<<4) | LONG:
		**(double **)ptr = atof(numbuf);
		break;

	case (INT<<4) | SHORT:
		**(short **)ptr = lcval;
		break;

	case (INT<<4) | REGULAR:
		**(int **)ptr = lcval;
		break;

	case (INT<<4) | LONG:
		**(long **)ptr = lcval;
		break;
	}
	return(1);
}

_instr(ptr, type, len, iop, eofptr)
register char *ptr;
register struct _iobuf *iop;
int *eofptr;
{
	register ch;
	register char *optr;
	int ignstp;

	*eofptr = 0;
	optr = ptr;
	if(type == 'c' && len == 30000)
		len = 1;
	ignstp = 0;
	if(type == 's')
		ignstp = SPC;
	while(_sctab[ch = getc(iop)] & ignstp)
		if(ch == EOF)
			break;
	ignstp = SPC;
	if(type == 'c')
		ignstp = 0;
	else if(type == '[')
		ignstp = STP;
	while(ch != EOF && (_sctab[ch] & ignstp) == 0) {
		if(ptr)
			*ptr++ = ch;
		if(--len <= 0)
			break;
		ch = getc(iop);
	}
	if(ch != EOF) {
		if(len > 0)
			ungetc(ch, iop);
		*eofptr = 0;
	} else
		*eofptr = 1;
	if(ptr && (ptr != optr || type == '[')) {
		if(type != 'c')
			*ptr++ = '\0';
		return(1);
	}
	return(0);
}

char *
_getccl(s)
register char *s;
{
	register c, t;

	t = 0;
	if(*s == '^') {
		t++;
		s++;
	}
	for(c = 0; c < 128; c++)
		if(t)
			_sctab[c] &= ~STP;
		else
			_sctab[c] |= STP;
	while(((c = *s++) & 0177) != ']') {
		if(t)
			_sctab[c++] |= STP;
		else
			_sctab[c++] &= ~STP;
		if(c == 0)
			return(--s);
	}
	return(s);
}