Plan 9 from Bell Labs’s /usr/web/sources/patch/sorry/file-redux/chkfont.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ctype.h>

#define	WHITESPACE(c)		((c) == ' ' || (c) == '\t' || (c) == '\n')
#define	SPACE(c)			((c) == ' ' || (c) == '\t')

int fflag;

enum {
	P9BITLEN 	= 12,
};

typedef struct {
	char	*b;
	char	*file;
	char	*slash;
	Dir	*d;
} Slurp;

int
slurp(char* fil, int fd, int (*f)(Slurp*))
{
	Slurp S;
	int n;
	vlong l;

	memset(&S, 0, sizeof S);
	S.d = dirfstat(fd);
	if(!S.d)
		return 0;
	l = S.d->length;
	S.b = malloc(S.d->length+1);
	if(!S.b)
		sysfatal("malloc");
	seek(fd, 0, 0);
	if(readn(fd, S.b, l) != l){
		n = 0;
		goto done;
	}
	S.b[l] = 0;
	S.file = fil;
	S.slash = strrchr(S.file, '/');

	n = f(&S);
done:
	free(S.d);
	free(S.b);
	return n;
}

/*
 * pick up a number with
 * syntax _*[0-9]+_
 */
int
p9bitnum(char *bp)
{
	int n, c, len;

	len = P9BITLEN;
	while(*bp == ' ') {
		bp++;
		len--;
		if(len <= 0)
			return -1;
	}
	n = 0;
	while(len > 1) {
		c = *bp++;
		if(!isdigit(c))
			return -1;
		n = n*10 + c-'0';
		len--;
	}
	if(*bp != ' ')
		return -1;
	return n;
}

int
depthof(char *s, int *newp)
{
	char *es;
	int d;

	*newp = 0;
	es = s+12;
	while(s<es && *s==' ')
		s++;
	if(s == es)
		return -1;
	if('0'<=*s && *s<='9')
		return 1<<strtol(s, 0, 0);

	*newp = 1;
	d = 0;
	while(s<es && *s!=' '){
		s++;	/* skip letter */
		d += strtoul(s, &s, 10);
	}
	
	switch(d){
	case 32:
	case 24:
	case 16:
	case 8:
	case 4:
	case 2:
	case 1:
		return d;
	}
	return -1;
}

int
p9subfont(char *p)
{
	int n, h, a;

	n = p9bitnum(p + 0*P9BITLEN);	/* char count */
	if (n < 0)
		return 0;
	h = p9bitnum(p + 1*P9BITLEN);	/* height */
	if (h < 0)
		return 0;
	a = p9bitnum(p + 2*P9BITLEN);	/* ascent */
	if (a < 0)
		return 0;
	return 1;
}

int
cfontlen(char* buf, char* bufe, int, int, int loy, int, int hiy)
{
	int miny, maxy, nb;
	char *p;

	p = buf+5*P9BITLEN;
	for(miny = loy; p+24 <= bufe && miny != hiy; p += 24+nb){
		maxy = atoi(p+0*P9BITLEN);
		nb = atoi(p+1*P9BITLEN);
		if(maxy<=loy || hiy<maxy){
			werrstr("cimage: bady");
			return -1;
		}
		miny = maxy;
	}
	if(miny == hiy)
		return p-buf;
	werrstr("cimage: short file");
	return -1;
}

int
fontlen(char*, char*, int dep, int lox, int loy, int hix, int hiy)
{
	int px, t, len;

	if(dep < 8){
		px = 8/dep;	/* pixels per byte */
		/* set l to number of bytes of data per scan line */
		if(lox >= 0)
			len = (hix+px-1)/px - lox/px;
		else{	/* make positive before divide */
			t = (-lox)+px-1;
			t = (t/px)*px;
			len = (t+hix+px-1)/px;
		}
	}else
		len = (hix-lox)*dep/8;
	return len*(hiy-loy) + 5*P9BITLEN;
}

int
isp9bit(Slurp* S)
{
	int dep, lox, loy, hix, hiy, new;
	long len;
	char *buf, *bufe;
	int (*lenfn)(char*, char*, int, int, int, int, int);

	buf = S->b;
	lenfn = fontlen;
	if(strncmp(buf, "compressed\n", 11) == 0){
		lenfn = cfontlen;
		buf += 11;
		
	}
	bufe = S->b+S->d->length;
	if(bufe - buf < 5*P9BITLEN){
		werrstr("image: short file");
		return 0;
	}
	dep = depthof(buf + 0*P9BITLEN, &new);
	lox = p9bitnum(buf + 1*P9BITLEN);
	loy = p9bitnum(buf + 2*P9BITLEN);
	hix = p9bitnum(buf + 3*P9BITLEN);
	hiy = p9bitnum(buf + 4*P9BITLEN);
	if(dep < 0 || lox < 0 || loy < 0 || hix < 0 || hiy < 0){
		werrstr("image: bad rectangle");
		return 0;
	}
	if(lox>hix|| loy>hiy){
		werrstr("image: bad rectangle");
		return 0;
	}
	len = lenfn(buf, bufe, dep, lox, loy, hix, hiy);
	if(len < 0){
		werrstr("image: bady");
		return 0;
	}
	if(S->d->length < len+3*P9BITLEN) {
		werrstr("image: no font info");
		return 0;
	}
	if (p9subfont(buf+len))
		return 1;
	werrstr("image: bad font info");
	return 0;
}

int
getfontnum(char *cp, char **rp)
{
	char *p;
	ulong l;

	*rp = cp;
	l = strtoul(cp, &p, 0);
	if(p == cp || !WHITESPACE(*p))
		return 0;
	if(l < 0 || l > 0xffff)
		return 0;
	*rp = p;
	return 1;
}

int
fchk(char *p, int m)
{
	int fd, r;

	fd = open(p, m);
	if(-1 == fd)
		return -1;
	if(fflag)
		r = 0;
	else
		r = slurp(p, fd, isp9bit);
	close(fd);
	return r;
}

int
faccess(char *p, int m)
{
	char* s;
	int i, r, err;

	r = fchk(p, m);
	if(r != -1)
		return r;
	s = p + strlen(p);
	r = 0;
	for(i = 0; i < 2; i++) {
		snprint(s, 4, ".%d", i);
		err = fchk(p, m);
		*s = 0;
		if(r != -1)
			r = err;
	}
	return r;
}
	
int
isp9font(Slurp *S)
{
	char *p, *cp;
	int i, n, err;
	char path[1024 + 1 + 3];

	cp = S->b;
	if (!getfontnum(cp, &cp)){	/* height */
		fprint(2, "%s:1 height\n", S->file);
		return 0;
	}
	if (!getfontnum(cp, &cp)){	/* ascent */
		fprint(2, "%s:1 ascent\n", S->file);
		return 0;
	}
	while(WHITESPACE(*cp))
		cp++;
	for (err = 0, i = 0; strchr(cp, '\n'); i++) {
		if (!getfontnum(cp, &cp)){	/* min */
			fprint(2, "%s:%d ascent\n", S->file, i+1);
			return 0;
		}
		if (!getfontnum(cp, &cp)){	/* max */
			fprint(2, "%s:%d ascent\n", S->file, i+1);
			return 0;
		}
		getfontnum(cp, &cp);	/* offset -- not required */
		while(SPACE(*cp))
			cp++;
		for(p = cp; !WHITESPACE(*cp); cp++)
			;
			/* construct a path name, if needed */
		n = 0;
		if (*p != '/' && S->slash) {
			n = S->slash-S->file+1;
			if (n < sizeof path)
				memcpy(path, S->file, n);
			else n = 0;
		}
		if (n+cp-p < sizeof path - sizeof ".00") {
			memcpy(path+n, p, cp-p);
			n += cp-p;
			path[n] = 0;
			if(faccess(path, AEXIST) < 0){
				fprint(2, "%s:%d (%s) %r\n", S->file, i+1, path);
				err++;
			}
		}
		while(WHITESPACE(*cp))
			cp++;
	}
	if(err)
		return 0;
	return i;
}

void
main(int argc, char **argv)
{
	int fd, err, n;

	ARGBEGIN{
	case 'f':
		fflag = 1;
		break;
	default:
		fprint(2, "usage: chkfont [-f] font\n");
		exits("usage");
	}ARGEND

	err = 0;
	if(argc>0)
		for(; *argv; argv++){
			fd = open(*argv, OREAD);
			n = -1;
			if(-1 == fd)
				fprint(2, "%s: %r\n", *argv);
			else
				n = slurp(*argv, fd, isp9font);
			close(fd);
			if(n < 1)
				err++;
		}
	else
		err = slurp("<stdin>", 0, isp9font);
	if(err)
		exits("bad");
	exits("");
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.