#include #include #include #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= 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 > Runemax) 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("", 0, isp9font); if(err) exits("bad"); exits(""); }