1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier #include <ctype.h> 5bd389b36SDavid du Colombier #include <mach.h> 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier /* 83e12c5d1SDavid du Colombier * file - determine type of file 93e12c5d1SDavid du Colombier */ 103e12c5d1SDavid du Colombier #define LENDIAN(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier uchar buf[6000]; 133e12c5d1SDavid du Colombier short cfreq[140]; 143e12c5d1SDavid du Colombier short wfreq[50]; 153e12c5d1SDavid du Colombier int nbuf; 163e12c5d1SDavid du Colombier Dir mbuf; 173e12c5d1SDavid du Colombier int fd; 183e12c5d1SDavid du Colombier char *fname; 193e12c5d1SDavid du Colombier char *slash; 203e12c5d1SDavid du Colombier 213e12c5d1SDavid du Colombier enum 223e12c5d1SDavid du Colombier { 233e12c5d1SDavid du Colombier Cword, 243e12c5d1SDavid du Colombier Fword, 253e12c5d1SDavid du Colombier Aword, 26*219b2ee8SDavid du Colombier Alword, 273e12c5d1SDavid du Colombier I1, 283e12c5d1SDavid du Colombier I2, 293e12c5d1SDavid du Colombier I3, 303e12c5d1SDavid du Colombier Clatin = 128, 313e12c5d1SDavid du Colombier Cbinary, 323e12c5d1SDavid du Colombier Cnull, 333e12c5d1SDavid du Colombier Ceascii, 343e12c5d1SDavid du Colombier Cutf, 353e12c5d1SDavid du Colombier }; 363e12c5d1SDavid du Colombier struct 373e12c5d1SDavid du Colombier { 383e12c5d1SDavid du Colombier char* word; 393e12c5d1SDavid du Colombier int class; 403e12c5d1SDavid du Colombier } dict[] = 413e12c5d1SDavid du Colombier { 42*219b2ee8SDavid du Colombier "TEXT", Aword, 43*219b2ee8SDavid du Colombier "adt", Alword, 44*219b2ee8SDavid du Colombier "aggr", Alword, 45*219b2ee8SDavid du Colombier "alef", Alword, 46*219b2ee8SDavid du Colombier "block", Fword, 47*219b2ee8SDavid du Colombier "chan", Alword, 48*219b2ee8SDavid du Colombier "char", Cword, 49*219b2ee8SDavid du Colombier "common", Fword, 50*219b2ee8SDavid du Colombier "data", Fword, 51*219b2ee8SDavid du Colombier "dimension", Fword, 52*219b2ee8SDavid du Colombier "double", Cword, 53*219b2ee8SDavid du Colombier "extern", Cword, 54*219b2ee8SDavid du Colombier "bio", I2, 55*219b2ee8SDavid du Colombier "float", Cword, 56*219b2ee8SDavid du Colombier "function", Fword, 57*219b2ee8SDavid du Colombier "h", I3, 58*219b2ee8SDavid du Colombier "include", I1, 59*219b2ee8SDavid du Colombier "int", Cword, 60*219b2ee8SDavid du Colombier "integer", Fword, 61*219b2ee8SDavid du Colombier "libc", I2, 62*219b2ee8SDavid du Colombier "long", Cword, 63*219b2ee8SDavid du Colombier "real", Fword, 64*219b2ee8SDavid du Colombier "register", Cword, 65*219b2ee8SDavid du Colombier "short", Cword, 66*219b2ee8SDavid du Colombier "static", Cword, 67*219b2ee8SDavid du Colombier "stdio", I2, 68*219b2ee8SDavid du Colombier "struct", Cword, 69*219b2ee8SDavid du Colombier "subroutine", Fword, 70*219b2ee8SDavid du Colombier "u", I2, 71*219b2ee8SDavid du Colombier "void", Cword, 72*219b2ee8SDavid du Colombier }; 73*219b2ee8SDavid du Colombier 74*219b2ee8SDavid du Colombier /* codes for 'mode' field in language structure */ 75*219b2ee8SDavid du Colombier enum { 76*219b2ee8SDavid du Colombier Normal = 0, 77*219b2ee8SDavid du Colombier First, /* first entry for language spanning several ranges */ 78*219b2ee8SDavid du Colombier Multi, /* later entries " " " ... */ 79*219b2ee8SDavid du Colombier Shared, /* codes used in several languages */ 803e12c5d1SDavid du Colombier }; 813e12c5d1SDavid du Colombier 823e12c5d1SDavid du Colombier struct 833e12c5d1SDavid du Colombier { 84*219b2ee8SDavid du Colombier int mode; /* see enum above */ 853e12c5d1SDavid du Colombier int count; 863e12c5d1SDavid du Colombier int low; 873e12c5d1SDavid du Colombier int high; 883e12c5d1SDavid du Colombier char *name; 893e12c5d1SDavid du Colombier 903e12c5d1SDavid du Colombier } language[] = 913e12c5d1SDavid du Colombier { 92*219b2ee8SDavid du Colombier Normal, 0, 0x0080, 0x0080, "Extended Latin", 93*219b2ee8SDavid du Colombier Normal, 0, 0x0100, 0x01FF, "Extended Latin", 94*219b2ee8SDavid du Colombier Normal, 0, 0x0370, 0x03FF, "Greek", 95*219b2ee8SDavid du Colombier Normal, 0, 0x0400, 0x04FF, "Cyrillic", 96*219b2ee8SDavid du Colombier Normal, 0, 0x0530, 0x058F, "Armenian", 97*219b2ee8SDavid du Colombier Normal, 0, 0x0590, 0x05FF, "Hebrew", 98*219b2ee8SDavid du Colombier Normal, 0, 0x0600, 0x06FF, "Arabic", 99*219b2ee8SDavid du Colombier Normal, 0, 0x0900, 0x097F, "Devanagari", 100*219b2ee8SDavid du Colombier Normal, 0, 0x0980, 0x09FF, "Bengali", 101*219b2ee8SDavid du Colombier Normal, 0, 0x0A00, 0x0A7F, "Gurmukhi", 102*219b2ee8SDavid du Colombier Normal, 0, 0x0A80, 0x0AFF, "Gujarati", 103*219b2ee8SDavid du Colombier Normal, 0, 0x0B00, 0x0B7F, "Oriya", 104*219b2ee8SDavid du Colombier Normal, 0, 0x0B80, 0x0BFF, "Tamil", 105*219b2ee8SDavid du Colombier Normal, 0, 0x0C00, 0x0C7F, "Telugu", 106*219b2ee8SDavid du Colombier Normal, 0, 0x0C80, 0x0CFF, "Kannada", 107*219b2ee8SDavid du Colombier Normal, 0, 0x0D00, 0x0D7F, "Malayalam", 108*219b2ee8SDavid du Colombier Normal, 0, 0x0E00, 0x0E7F, "Thai", 109*219b2ee8SDavid du Colombier Normal, 0, 0x0E80, 0x0EFF, "Lao", 110*219b2ee8SDavid du Colombier Normal, 0, 0x1000, 0x105F, "Tibetan", 111*219b2ee8SDavid du Colombier Normal, 0, 0x10A0, 0x10FF, "Georgian", 112*219b2ee8SDavid du Colombier Normal, 0, 0x3040, 0x30FF, "Japanese", 113*219b2ee8SDavid du Colombier Normal, 0, 0x3100, 0x312F, "Chinese", 114*219b2ee8SDavid du Colombier First, 0, 0x3130, 0x318F, "Korean", 115*219b2ee8SDavid du Colombier Multi, 0, 0x3400, 0x3D2F, "Korean", 116*219b2ee8SDavid du Colombier Shared, 0, 0x4e00, 0x9fff, "CJK", 117*219b2ee8SDavid du Colombier Normal, 0, 0, 0, 0, /* terminal entry */ 1183e12c5d1SDavid du Colombier }; 1193e12c5d1SDavid du Colombier 1203e12c5d1SDavid du Colombier 1213e12c5d1SDavid du Colombier enum 1223e12c5d1SDavid du Colombier { 1233e12c5d1SDavid du Colombier Fascii, /* printable ascii */ 1243e12c5d1SDavid du Colombier Flatin, /* latin 1*/ 1253e12c5d1SDavid du Colombier Futf, /* UTf character set */ 1263e12c5d1SDavid du Colombier Fbinary, /* binary */ 1273e12c5d1SDavid du Colombier Feascii, /* ASCII with control chars */ 1283e12c5d1SDavid du Colombier Fnull, /* NULL in file */ 1293e12c5d1SDavid du Colombier } guess; 1303e12c5d1SDavid du Colombier 1313e12c5d1SDavid du Colombier void bump_utf_count(Rune); 1323e12c5d1SDavid du Colombier void filetype(int); 1333e12c5d1SDavid du Colombier int getfontnum(uchar *, uchar **); 1343e12c5d1SDavid du Colombier int isas(void); 1353e12c5d1SDavid du Colombier int isc(void); 1363e12c5d1SDavid du Colombier int iscint(void); 1373e12c5d1SDavid du Colombier int isenglish(void); 1383e12c5d1SDavid du Colombier int ismung(void); 1393e12c5d1SDavid du Colombier int isp9bit(void); 1403e12c5d1SDavid du Colombier int isp9font(void); 1413e12c5d1SDavid du Colombier int istring(void); 1423e12c5d1SDavid du Colombier int long0(void); 1433e12c5d1SDavid du Colombier int p9bitnum(uchar *); 1443e12c5d1SDavid du Colombier int p9subfont(uchar *); 1453e12c5d1SDavid du Colombier void print_utf(void); 1463e12c5d1SDavid du Colombier int short0(void); 1473e12c5d1SDavid du Colombier void type(char*, int); 1483e12c5d1SDavid du Colombier int utf_count(void); 1493e12c5d1SDavid du Colombier void wordfreq(void); 1503e12c5d1SDavid du Colombier 1513e12c5d1SDavid du Colombier int (*call[])(void) = 1523e12c5d1SDavid du Colombier { 1533e12c5d1SDavid du Colombier long0, /* recognizable by first 4 bytes */ 1543e12c5d1SDavid du Colombier short0, /* recognizable by first 2 bytes */ 1553e12c5d1SDavid du Colombier istring, /* recognizable by first string */ 156*219b2ee8SDavid du Colombier iscint, /* compiler/assembler intermediate */ 157*219b2ee8SDavid du Colombier isc, /* c & alef compiler key words */ 1583e12c5d1SDavid du Colombier isas, /* assembler key words */ 1593e12c5d1SDavid du Colombier ismung, /* entropy compressed/encrypted */ 1603e12c5d1SDavid du Colombier isenglish, /* char frequency English */ 1613e12c5d1SDavid du Colombier isp9font, /* plan 9 font */ 1623e12c5d1SDavid du Colombier isp9bit, /* plan 9 bitmap (as from /dev/window) */ 1633e12c5d1SDavid du Colombier 0 1643e12c5d1SDavid du Colombier }; 1653e12c5d1SDavid du Colombier 1663e12c5d1SDavid du Colombier void 1673e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1683e12c5d1SDavid du Colombier { 1693e12c5d1SDavid du Colombier int i, j, maxlen; 1703e12c5d1SDavid du Colombier char *cp; 1713e12c5d1SDavid du Colombier Rune r; 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier maxlen = 0; 1743e12c5d1SDavid du Colombier for(i = 1; i < argc; i++) { 1753e12c5d1SDavid du Colombier for (j = 0, cp = argv[i]; *cp; j++, cp += chartorune(&r, cp)) 1763e12c5d1SDavid du Colombier ; 1773e12c5d1SDavid du Colombier if(j > maxlen) 1783e12c5d1SDavid du Colombier maxlen = j; 1793e12c5d1SDavid du Colombier } 1803e12c5d1SDavid du Colombier if (argc <= 1) { 1813e12c5d1SDavid du Colombier print ("stdin: "); 1823e12c5d1SDavid du Colombier filetype(0); 1833e12c5d1SDavid du Colombier } 1843e12c5d1SDavid du Colombier else { 1853e12c5d1SDavid du Colombier for(i = 1; i < argc; i++) 1863e12c5d1SDavid du Colombier type(argv[i], maxlen); 1873e12c5d1SDavid du Colombier } 1883e12c5d1SDavid du Colombier exits(0); 1893e12c5d1SDavid du Colombier } 1903e12c5d1SDavid du Colombier 1913e12c5d1SDavid du Colombier void 1923e12c5d1SDavid du Colombier type(char *file, int nlen) 1933e12c5d1SDavid du Colombier { 1943e12c5d1SDavid du Colombier Rune r; 1953e12c5d1SDavid du Colombier int i; 1963e12c5d1SDavid du Colombier char *p; 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier slash = 0; 1993e12c5d1SDavid du Colombier for (i = 0, p = file; *p; i++) { 2003e12c5d1SDavid du Colombier if (*p == '/') /* find rightmost slash */ 2013e12c5d1SDavid du Colombier slash = p; 2023e12c5d1SDavid du Colombier p += chartorune(&r, p); /* count runes */ 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier print("%s:%*s",file, nlen-i+1, ""); 2053e12c5d1SDavid du Colombier fname = file; 2063e12c5d1SDavid du Colombier if ((fd = open(file, OREAD)) < 0) { 2073e12c5d1SDavid du Colombier print("cannot open\n"); 2083e12c5d1SDavid du Colombier return; 2093e12c5d1SDavid du Colombier } 2103e12c5d1SDavid du Colombier filetype(fd); 2113e12c5d1SDavid du Colombier close(fd); 2123e12c5d1SDavid du Colombier } 2133e12c5d1SDavid du Colombier 2143e12c5d1SDavid du Colombier void 2153e12c5d1SDavid du Colombier filetype(int fd) 2163e12c5d1SDavid du Colombier { 2173e12c5d1SDavid du Colombier Rune r; 218*219b2ee8SDavid du Colombier int i, f, n; 219*219b2ee8SDavid du Colombier char *p, *eob; 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier if(dirfstat(fd, &mbuf) < 0) { 2223e12c5d1SDavid du Colombier print("cannot stat\n"); 2233e12c5d1SDavid du Colombier return; 2243e12c5d1SDavid du Colombier } 2253e12c5d1SDavid du Colombier if(mbuf.mode & CHDIR) { 2263e12c5d1SDavid du Colombier print("directory\n"); 2273e12c5d1SDavid du Colombier return; 2283e12c5d1SDavid du Colombier } 2293e12c5d1SDavid du Colombier if(mbuf.type != 'M' && mbuf.type != '|') { 2303e12c5d1SDavid du Colombier print("special file #%c\n", mbuf.type); 2313e12c5d1SDavid du Colombier return; 2323e12c5d1SDavid du Colombier } 2333e12c5d1SDavid du Colombier nbuf = read(fd, buf, sizeof(buf)); 2343e12c5d1SDavid du Colombier 2353e12c5d1SDavid du Colombier if(nbuf < 0) { 2363e12c5d1SDavid du Colombier print("cannot read\n"); 2373e12c5d1SDavid du Colombier return; 2383e12c5d1SDavid du Colombier } 2393e12c5d1SDavid du Colombier if(nbuf == 0) { 2403e12c5d1SDavid du Colombier print("empty\n"); 2413e12c5d1SDavid du Colombier return; 2423e12c5d1SDavid du Colombier } 2433e12c5d1SDavid du Colombier 2443e12c5d1SDavid du Colombier /* 2453e12c5d1SDavid du Colombier * build histogram table 2463e12c5d1SDavid du Colombier */ 2473e12c5d1SDavid du Colombier memset(cfreq, 0, sizeof(cfreq)); 2483e12c5d1SDavid du Colombier for (i = 0; language[i].name; i++) 2493e12c5d1SDavid du Colombier language[i].count = 0; 250*219b2ee8SDavid du Colombier eob = (char *)buf+nbuf; 251*219b2ee8SDavid du Colombier for(n = 0, p = (char *)buf; p < eob; n++) { 252*219b2ee8SDavid du Colombier if (!fullrune(p, eob-p) && eob-p < UTFmax) 253*219b2ee8SDavid du Colombier break; 2543e12c5d1SDavid du Colombier p += chartorune(&r, p); 2553e12c5d1SDavid du Colombier if (r == 0) 2563e12c5d1SDavid du Colombier f = Cnull; 2573e12c5d1SDavid du Colombier else if (r <= 0x7f) { 2583e12c5d1SDavid du Colombier if (!isprint(r) && !isspace(r)) 2593e12c5d1SDavid du Colombier f = Ceascii; /* ASCII control char */ 2603e12c5d1SDavid du Colombier else f = r; 261*219b2ee8SDavid du Colombier } else if (r == 0x080) { 262*219b2ee8SDavid du Colombier bump_utf_count(r); 263*219b2ee8SDavid du Colombier f = Cutf; 2643e12c5d1SDavid du Colombier } else if (r < 0xA0) 2653e12c5d1SDavid du Colombier f = Cbinary; /* Invalid Runes */ 2663e12c5d1SDavid du Colombier else if (r <= 0xff) 2673e12c5d1SDavid du Colombier f = Clatin; /* Latin 1 */ 2683e12c5d1SDavid du Colombier else { 2693e12c5d1SDavid du Colombier bump_utf_count(r); 2703e12c5d1SDavid du Colombier f = Cutf; /* UTF extension */ 2713e12c5d1SDavid du Colombier } 2723e12c5d1SDavid du Colombier cfreq[f]++; /* ASCII chars peg directly */ 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier /* 2753e12c5d1SDavid du Colombier * gross classify 2763e12c5d1SDavid du Colombier */ 2773e12c5d1SDavid du Colombier if (cfreq[Cbinary]) 2783e12c5d1SDavid du Colombier guess = Fbinary; 2793e12c5d1SDavid du Colombier else if (cfreq[Cutf]) 2803e12c5d1SDavid du Colombier guess = Futf; 2813e12c5d1SDavid du Colombier else if (cfreq[Clatin]) 2823e12c5d1SDavid du Colombier guess = Flatin; 2833e12c5d1SDavid du Colombier else if (cfreq[Ceascii]) 2843e12c5d1SDavid du Colombier guess = Feascii; 285*219b2ee8SDavid du Colombier else if (cfreq[Cnull] == n) { 286*219b2ee8SDavid du Colombier print("all null bytes\n"); 2873e12c5d1SDavid du Colombier return; 2883e12c5d1SDavid du Colombier } 2893e12c5d1SDavid du Colombier else guess = Fascii; 2903e12c5d1SDavid du Colombier /* 2913e12c5d1SDavid du Colombier * lookup dictionary words 2923e12c5d1SDavid du Colombier */ 293*219b2ee8SDavid du Colombier memset(wfreq, 0, sizeof(wfreq)); 294*219b2ee8SDavid du Colombier if(guess == Fascii || guess == Flatin) 2953e12c5d1SDavid du Colombier wordfreq(); 2963e12c5d1SDavid du Colombier /* 2973e12c5d1SDavid du Colombier * call individual classify routines 2983e12c5d1SDavid du Colombier */ 2993e12c5d1SDavid du Colombier for(i=0; call[i]; i++) 3003e12c5d1SDavid du Colombier if((*call[i])()) 3013e12c5d1SDavid du Colombier return; 3023e12c5d1SDavid du Colombier 3033e12c5d1SDavid du Colombier /* 3043e12c5d1SDavid du Colombier * if all else fails, 3053e12c5d1SDavid du Colombier * print out gross classification 3063e12c5d1SDavid du Colombier */ 3073e12c5d1SDavid du Colombier if (nbuf < 100) 3083e12c5d1SDavid du Colombier print("short "); 3093e12c5d1SDavid du Colombier if (guess == Fascii) 310*219b2ee8SDavid du Colombier print("Ascii\n"); 3113e12c5d1SDavid du Colombier else if (guess == Feascii) 3123e12c5d1SDavid du Colombier print("extended ascii\n"); 3133e12c5d1SDavid du Colombier else if (guess == Flatin) 3143e12c5d1SDavid du Colombier print("latin ascii\n"); 3153e12c5d1SDavid du Colombier else if (guess == Futf && utf_count() < 4) 3163e12c5d1SDavid du Colombier print_utf(); 3173e12c5d1SDavid du Colombier else print("binary\n"); 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier 3203e12c5d1SDavid du Colombier void 3213e12c5d1SDavid du Colombier bump_utf_count(Rune r) 3223e12c5d1SDavid du Colombier { 3233e12c5d1SDavid du Colombier int low, high, mid; 3243e12c5d1SDavid du Colombier 3253e12c5d1SDavid du Colombier high = sizeof(language)/sizeof(language[0])-1; 3263e12c5d1SDavid du Colombier for (low = 0; low < high;) { 3273e12c5d1SDavid du Colombier mid = (low+high)/2; 3283e12c5d1SDavid du Colombier if (r >=language[mid].low) { 3293e12c5d1SDavid du Colombier if (r <= language[mid].high) { 3303e12c5d1SDavid du Colombier language[mid].count++; 3313e12c5d1SDavid du Colombier break; 3323e12c5d1SDavid du Colombier } else low = mid+1; 3333e12c5d1SDavid du Colombier } else high = mid; 3343e12c5d1SDavid du Colombier } 3353e12c5d1SDavid du Colombier } 3363e12c5d1SDavid du Colombier 3373e12c5d1SDavid du Colombier int 3383e12c5d1SDavid du Colombier utf_count(void) 3393e12c5d1SDavid du Colombier { 3403e12c5d1SDavid du Colombier int i, count; 3413e12c5d1SDavid du Colombier 342*219b2ee8SDavid du Colombier count = 0; 343*219b2ee8SDavid du Colombier for (i = 0; language[i].name; i++) 3443e12c5d1SDavid du Colombier if (language[i].count > 0) 345*219b2ee8SDavid du Colombier switch (language[i].mode) { 346*219b2ee8SDavid du Colombier case Normal: 347*219b2ee8SDavid du Colombier case First: 3483e12c5d1SDavid du Colombier count++; 349*219b2ee8SDavid du Colombier break; 350*219b2ee8SDavid du Colombier default: 351*219b2ee8SDavid du Colombier break; 352*219b2ee8SDavid du Colombier } 3533e12c5d1SDavid du Colombier return count; 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier 356*219b2ee8SDavid du Colombier int 357*219b2ee8SDavid du Colombier chkascii(void) 358*219b2ee8SDavid du Colombier { 359*219b2ee8SDavid du Colombier int i; 360*219b2ee8SDavid du Colombier 361*219b2ee8SDavid du Colombier for (i = 'a'; i < 'z'; i++) 362*219b2ee8SDavid du Colombier if (cfreq[i]) 363*219b2ee8SDavid du Colombier return 1; 364*219b2ee8SDavid du Colombier for (i = 'A'; i < 'Z'; i++) 365*219b2ee8SDavid du Colombier if (cfreq[i]) 366*219b2ee8SDavid du Colombier return 1; 367*219b2ee8SDavid du Colombier return 0; 368*219b2ee8SDavid du Colombier } 369*219b2ee8SDavid du Colombier 370*219b2ee8SDavid du Colombier int 371*219b2ee8SDavid du Colombier find_first(char *name) 372*219b2ee8SDavid du Colombier { 373*219b2ee8SDavid du Colombier int i; 374*219b2ee8SDavid du Colombier 375*219b2ee8SDavid du Colombier for (i = 0; language[i].name != 0; i++) 376*219b2ee8SDavid du Colombier if (language[i].mode == First 377*219b2ee8SDavid du Colombier && strcmp(language[i].name, name) == 0) 378*219b2ee8SDavid du Colombier return i; 379*219b2ee8SDavid du Colombier return -1; 380*219b2ee8SDavid du Colombier } 381*219b2ee8SDavid du Colombier 3823e12c5d1SDavid du Colombier void 3833e12c5d1SDavid du Colombier print_utf(void) 3843e12c5d1SDavid du Colombier { 385*219b2ee8SDavid du Colombier int i, printed, j; 3863e12c5d1SDavid du Colombier 387*219b2ee8SDavid du Colombier if (chkascii()) { 388*219b2ee8SDavid du Colombier printed = 1; 389*219b2ee8SDavid du Colombier print("Ascii"); 390*219b2ee8SDavid du Colombier } else 391*219b2ee8SDavid du Colombier printed = 0; 392*219b2ee8SDavid du Colombier for (i = 0; language[i].name; i++) 3933e12c5d1SDavid du Colombier if (language[i].count) { 394*219b2ee8SDavid du Colombier switch(language[i].mode) { 395*219b2ee8SDavid du Colombier case Multi: 396*219b2ee8SDavid du Colombier j = find_first(language[i].name); 397*219b2ee8SDavid du Colombier if (j < 0) 398*219b2ee8SDavid du Colombier break; 399*219b2ee8SDavid du Colombier if (language[j].count > 0) 400*219b2ee8SDavid du Colombier break; 401*219b2ee8SDavid du Colombier /* Fall through */ 402*219b2ee8SDavid du Colombier case Normal: 403*219b2ee8SDavid du Colombier case First: 4043e12c5d1SDavid du Colombier if (printed) 4053e12c5d1SDavid du Colombier print(" & "); 4063e12c5d1SDavid du Colombier else printed = 1; 4073e12c5d1SDavid du Colombier print("%s", language[i].name); 408*219b2ee8SDavid du Colombier break; 409*219b2ee8SDavid du Colombier case Shared: 410*219b2ee8SDavid du Colombier default: 411*219b2ee8SDavid du Colombier break; 412*219b2ee8SDavid du Colombier } 4133e12c5d1SDavid du Colombier } 4143e12c5d1SDavid du Colombier if(!printed) 4153e12c5d1SDavid du Colombier print("UTF"); 4163e12c5d1SDavid du Colombier print(" text\n"); 4173e12c5d1SDavid du Colombier } 4183e12c5d1SDavid du Colombier 4193e12c5d1SDavid du Colombier void 4203e12c5d1SDavid du Colombier wordfreq(void) 4213e12c5d1SDavid du Colombier { 422*219b2ee8SDavid du Colombier int low, high, mid, r; 423*219b2ee8SDavid du Colombier uchar *p, *p2, c; 4243e12c5d1SDavid du Colombier 425*219b2ee8SDavid du Colombier p = buf; 426*219b2ee8SDavid du Colombier for(;;) { 427*219b2ee8SDavid du Colombier while (p < buf+nbuf && !isalpha(*p)) 428*219b2ee8SDavid du Colombier p++; 429*219b2ee8SDavid du Colombier if (p >= buf+nbuf) 430*219b2ee8SDavid du Colombier return; 431*219b2ee8SDavid du Colombier p2 = p; 432*219b2ee8SDavid du Colombier while(p < buf+nbuf && isalpha(*p)) 433*219b2ee8SDavid du Colombier p++; 434*219b2ee8SDavid du Colombier c = *p; 435*219b2ee8SDavid du Colombier *p = 0; 4363e12c5d1SDavid du Colombier high = sizeof(dict)/sizeof(dict[0]); 4373e12c5d1SDavid du Colombier for(low = 0;low < high;) { 4383e12c5d1SDavid du Colombier mid = (low+high)/2; 439*219b2ee8SDavid du Colombier r = strcmp(dict[mid].word, (char*)p2); 440*219b2ee8SDavid du Colombier if(r == 0) { 4413e12c5d1SDavid du Colombier wfreq[dict[mid].class]++; 4423e12c5d1SDavid du Colombier break; 4433e12c5d1SDavid du Colombier } 444*219b2ee8SDavid du Colombier if(r < 0) 4453e12c5d1SDavid du Colombier low = mid+1; 4463e12c5d1SDavid du Colombier else 4473e12c5d1SDavid du Colombier high = mid; 4483e12c5d1SDavid du Colombier } 449*219b2ee8SDavid du Colombier *p++ = c; 4503e12c5d1SDavid du Colombier } 4513e12c5d1SDavid du Colombier } 4523e12c5d1SDavid du Colombier 4533e12c5d1SDavid du Colombier int 4543e12c5d1SDavid du Colombier long0(void) 4553e12c5d1SDavid du Colombier { 4563e12c5d1SDavid du Colombier Fhdr f; 4573e12c5d1SDavid du Colombier 4583e12c5d1SDavid du Colombier seek(fd, 0, 0); /* reposition to start of file */ 4593e12c5d1SDavid du Colombier if (crackhdr(fd, &f)) { 4603e12c5d1SDavid du Colombier print("%s\n", f.name); 4613e12c5d1SDavid du Colombier return 1; 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier switch(LENDIAN(buf)) { 464*219b2ee8SDavid du Colombier case 0xf16df16d: 465*219b2ee8SDavid du Colombier print("pac1 audio file\n"); 466*219b2ee8SDavid du Colombier return 1; 467*219b2ee8SDavid du Colombier case 0x31636170: 468*219b2ee8SDavid du Colombier print("pac3 audio file\n"); 469*219b2ee8SDavid du Colombier return 1; 470*219b2ee8SDavid du Colombier case 0x32636170: 471*219b2ee8SDavid du Colombier print("pac4 audio file\n"); 4723e12c5d1SDavid du Colombier return 1; 4733e12c5d1SDavid du Colombier default: 4743e12c5d1SDavid du Colombier return 0; 4753e12c5d1SDavid du Colombier } 4763e12c5d1SDavid du Colombier return 1; 4773e12c5d1SDavid du Colombier } 4783e12c5d1SDavid du Colombier 4793e12c5d1SDavid du Colombier int 4803e12c5d1SDavid du Colombier short0(void) 4813e12c5d1SDavid du Colombier { 4823e12c5d1SDavid du Colombier 4833e12c5d1SDavid du Colombier switch(LENDIAN(buf) & 0xffff) { 4843e12c5d1SDavid du Colombier case 070707: 4853e12c5d1SDavid du Colombier print("cpio archive\n"); 4863e12c5d1SDavid du Colombier break; 4873e12c5d1SDavid du Colombier 4883e12c5d1SDavid du Colombier case 0x02f7: 4893e12c5d1SDavid du Colombier print("tex dvi\n"); 4903e12c5d1SDavid du Colombier break; 4913e12c5d1SDavid du Colombier default: 4923e12c5d1SDavid du Colombier return 0; 4933e12c5d1SDavid du Colombier } 4943e12c5d1SDavid du Colombier return 1; 4953e12c5d1SDavid du Colombier } 4963e12c5d1SDavid du Colombier 4973e12c5d1SDavid du Colombier /* 4983e12c5d1SDavid du Colombier * initial words to classify file 4993e12c5d1SDavid du Colombier */ 500*219b2ee8SDavid du Colombier struct FILE_STRING 501*219b2ee8SDavid du Colombier { 5023e12c5d1SDavid du Colombier char *key; 5033e12c5d1SDavid du Colombier char *filetype; 5043e12c5d1SDavid du Colombier int length; 5053e12c5d1SDavid du Colombier } file_string[] = 5063e12c5d1SDavid du Colombier { 5073e12c5d1SDavid du Colombier "!<arch>\n__.SYMDEF", "archive random library", 16, 5083e12c5d1SDavid du Colombier "!<arch>\n", "archive", 8, 5093e12c5d1SDavid du Colombier "070707", "cpio archive - ascii header", 6, 5103e12c5d1SDavid du Colombier "#!/bin/rc", "rc executable file", 9, 5113e12c5d1SDavid du Colombier "#!/bin/sh", "sh executable file", 9, 5123e12c5d1SDavid du Colombier "%!", "postscript", 2, 5133e12c5d1SDavid du Colombier "x T post", "troff output for post", 8, 5143e12c5d1SDavid du Colombier "x T Latin1", "troff output for Latin1", 10, 5153e12c5d1SDavid du Colombier "x T utf", "troff output for UTF", 7, 5163e12c5d1SDavid du Colombier "x T 202", "troff output for 202", 7, 5173e12c5d1SDavid du Colombier "x T aps", "troff output for aps", 7, 518*219b2ee8SDavid du Colombier "GIF", "GIF image", 3, 519*219b2ee8SDavid du Colombier "\0PC Research, Inc", "ghostscript fax file", 23, 5203e12c5d1SDavid du Colombier 0,0,0 5213e12c5d1SDavid du Colombier }; 5223e12c5d1SDavid du Colombier 5233e12c5d1SDavid du Colombier int 5243e12c5d1SDavid du Colombier istring(void) 5253e12c5d1SDavid du Colombier { 5263e12c5d1SDavid du Colombier int i; 5273e12c5d1SDavid du Colombier struct FILE_STRING *p; 5283e12c5d1SDavid du Colombier 5293e12c5d1SDavid du Colombier for(p = file_string; p->key; p++) { 530*219b2ee8SDavid du Colombier if(nbuf >= p->length && !memcmp(buf, p->key, p->length)) { 5313e12c5d1SDavid du Colombier print("%s\n", p->filetype); 5323e12c5d1SDavid du Colombier return 1; 5333e12c5d1SDavid du Colombier } 5343e12c5d1SDavid du Colombier } 5353e12c5d1SDavid du Colombier if(strncmp((char*)buf, "TYPE=", 5) == 0) { /* td */ 5363e12c5d1SDavid du Colombier for(i = 5; i < nbuf; i++) 5373e12c5d1SDavid du Colombier if(buf[i] == '\n') 5383e12c5d1SDavid du Colombier break; 5393e12c5d1SDavid du Colombier print("%.*s picture\n", i-5, buf+5); 5403e12c5d1SDavid du Colombier return 1; 5413e12c5d1SDavid du Colombier } 5423e12c5d1SDavid du Colombier return 0; 5433e12c5d1SDavid du Colombier } 5443e12c5d1SDavid du Colombier 5453e12c5d1SDavid du Colombier int 5463e12c5d1SDavid du Colombier iscint(void) 5473e12c5d1SDavid du Colombier { 548*219b2ee8SDavid du Colombier int type; 549*219b2ee8SDavid du Colombier char *name; 550*219b2ee8SDavid du Colombier Biobuf b; 5513e12c5d1SDavid du Colombier 552*219b2ee8SDavid du Colombier if(Binit(&b, fd, OREAD) == Beof) 5533e12c5d1SDavid du Colombier return 0; 554*219b2ee8SDavid du Colombier seek(fd, 0, 0); 555*219b2ee8SDavid du Colombier type = objtype(&b, &name); 556*219b2ee8SDavid du Colombier if(type < 0) 557*219b2ee8SDavid du Colombier return 0; 558*219b2ee8SDavid du Colombier print("%s intermediate\n", name); 559*219b2ee8SDavid du Colombier return 1; 5603e12c5d1SDavid du Colombier } 5613e12c5d1SDavid du Colombier 5623e12c5d1SDavid du Colombier int 5633e12c5d1SDavid du Colombier isc(void) 5643e12c5d1SDavid du Colombier { 5653e12c5d1SDavid du Colombier int n; 5663e12c5d1SDavid du Colombier 5673e12c5d1SDavid du Colombier n = wfreq[I1]; 5683e12c5d1SDavid du Colombier /* 5693e12c5d1SDavid du Colombier * includes 5703e12c5d1SDavid du Colombier */ 5713e12c5d1SDavid du Colombier if(n >= 2 && wfreq[I2] >= n && wfreq[I3] >= n && cfreq['.'] >= n) 5723e12c5d1SDavid du Colombier goto yes; 573*219b2ee8SDavid du Colombier if(n >= 1 && wfreq[Alword] >= n && wfreq[I3] >= n && cfreq['.'] >= n) 574*219b2ee8SDavid du Colombier goto yes; 5753e12c5d1SDavid du Colombier /* 5763e12c5d1SDavid du Colombier * declarations 5773e12c5d1SDavid du Colombier */ 5783e12c5d1SDavid du Colombier if(wfreq[Cword] >= 5 && cfreq[';'] >= 5) 5793e12c5d1SDavid du Colombier goto yes; 5803e12c5d1SDavid du Colombier /* 5813e12c5d1SDavid du Colombier * assignments 5823e12c5d1SDavid du Colombier */ 5833e12c5d1SDavid du Colombier if(cfreq[';'] >= 10 && cfreq['='] >= 10 && wfreq[Cword] >= 1) 5843e12c5d1SDavid du Colombier goto yes; 5853e12c5d1SDavid du Colombier return 0; 5863e12c5d1SDavid du Colombier 5873e12c5d1SDavid du Colombier yes: 588*219b2ee8SDavid du Colombier if(wfreq[Alword] > 0) 589*219b2ee8SDavid du Colombier print("alef program\n"); 590*219b2ee8SDavid du Colombier else 5913e12c5d1SDavid du Colombier print("c program\n"); 5923e12c5d1SDavid du Colombier return 1; 5933e12c5d1SDavid du Colombier } 5943e12c5d1SDavid du Colombier 5953e12c5d1SDavid du Colombier int 5963e12c5d1SDavid du Colombier isas(void) 5973e12c5d1SDavid du Colombier { 5983e12c5d1SDavid du Colombier 5993e12c5d1SDavid du Colombier /* 6003e12c5d1SDavid du Colombier * includes 6013e12c5d1SDavid du Colombier */ 6023e12c5d1SDavid du Colombier if(wfreq[Aword] < 2) 6033e12c5d1SDavid du Colombier return 0; 6043e12c5d1SDavid du Colombier print("as program\n"); 6053e12c5d1SDavid du Colombier return 1; 6063e12c5d1SDavid du Colombier } 6073e12c5d1SDavid du Colombier 6083e12c5d1SDavid du Colombier /* 6093e12c5d1SDavid du Colombier * low entropy means encrypted 6103e12c5d1SDavid du Colombier */ 6113e12c5d1SDavid du Colombier int 6123e12c5d1SDavid du Colombier ismung(void) 6133e12c5d1SDavid du Colombier { 6143e12c5d1SDavid du Colombier int i, bucket[8]; 6153e12c5d1SDavid du Colombier float cs; 6163e12c5d1SDavid du Colombier 6173e12c5d1SDavid du Colombier if(nbuf < 64) 6183e12c5d1SDavid du Colombier return 0; 6193e12c5d1SDavid du Colombier memset(bucket, 0, sizeof(bucket)); 6203e12c5d1SDavid du Colombier for(i=0; i<64; i++) 6213e12c5d1SDavid du Colombier bucket[(buf[i]>>5)&07] += 1; 6223e12c5d1SDavid du Colombier 6233e12c5d1SDavid du Colombier cs = 0.; 6243e12c5d1SDavid du Colombier for(i=0; i<8; i++) 6253e12c5d1SDavid du Colombier cs += (bucket[i]-8)*(bucket[i]-8); 6263e12c5d1SDavid du Colombier cs /= 8.; 6273e12c5d1SDavid du Colombier if(cs <= 24.322) { 6283e12c5d1SDavid du Colombier if(buf[0]==037 && buf[1]==0235) 6293e12c5d1SDavid du Colombier print("compressed\n"); 6303e12c5d1SDavid du Colombier else 6313e12c5d1SDavid du Colombier print("encrypted\n"); 6323e12c5d1SDavid du Colombier return 1; 6333e12c5d1SDavid du Colombier } 6343e12c5d1SDavid du Colombier return 0; 6353e12c5d1SDavid du Colombier } 6363e12c5d1SDavid du Colombier 6373e12c5d1SDavid du Colombier /* 6383e12c5d1SDavid du Colombier * english by punctuation and frequencies 6393e12c5d1SDavid du Colombier */ 6403e12c5d1SDavid du Colombier int 6413e12c5d1SDavid du Colombier isenglish(void) 6423e12c5d1SDavid du Colombier { 6433e12c5d1SDavid du Colombier int vow, comm, rare, badpun, punct; 6443e12c5d1SDavid du Colombier char *p; 6453e12c5d1SDavid du Colombier 6463e12c5d1SDavid du Colombier if(guess != Fascii && guess != Feascii) 6473e12c5d1SDavid du Colombier return 0; 6483e12c5d1SDavid du Colombier badpun = 0; 6493e12c5d1SDavid du Colombier punct = 0; 6503e12c5d1SDavid du Colombier for(p = (char *)buf; p < (char *)buf+nbuf-1; p++) 6513e12c5d1SDavid du Colombier switch(*p) { 6523e12c5d1SDavid du Colombier case '.': 6533e12c5d1SDavid du Colombier case ',': 6543e12c5d1SDavid du Colombier case ')': 6553e12c5d1SDavid du Colombier case '%': 6563e12c5d1SDavid du Colombier case ';': 6573e12c5d1SDavid du Colombier case ':': 6583e12c5d1SDavid du Colombier case '?': 6593e12c5d1SDavid du Colombier punct++; 6603e12c5d1SDavid du Colombier if(p[1] != ' ' && p[1] != '\n') 6613e12c5d1SDavid du Colombier badpun++; 6623e12c5d1SDavid du Colombier } 6633e12c5d1SDavid du Colombier if(badpun*5 > punct) 6643e12c5d1SDavid du Colombier return 0; 6653e12c5d1SDavid du Colombier if(cfreq['>']+cfreq['<']+cfreq['/'] > cfreq['e']) /* shell file test */ 6663e12c5d1SDavid du Colombier return 0; 6673e12c5d1SDavid du Colombier if(2*cfreq[';'] > cfreq['e']) 6683e12c5d1SDavid du Colombier return 0; 6693e12c5d1SDavid du Colombier 6703e12c5d1SDavid du Colombier vow = 0; 6713e12c5d1SDavid du Colombier for(p="AEIOU"; *p; p++) { 6723e12c5d1SDavid du Colombier vow += cfreq[*p]; 6733e12c5d1SDavid du Colombier vow += cfreq[tolower(*p)]; 6743e12c5d1SDavid du Colombier } 6753e12c5d1SDavid du Colombier comm = 0; 6763e12c5d1SDavid du Colombier for(p="ETAION"; *p; p++) { 6773e12c5d1SDavid du Colombier comm += cfreq[*p]; 6783e12c5d1SDavid du Colombier comm += cfreq[tolower(*p)]; 6793e12c5d1SDavid du Colombier } 6803e12c5d1SDavid du Colombier rare = 0; 6813e12c5d1SDavid du Colombier for(p="VJKQXZ"; *p; p++) { 6823e12c5d1SDavid du Colombier rare += cfreq[*p]; 6833e12c5d1SDavid du Colombier rare += cfreq[tolower(*p)]; 6843e12c5d1SDavid du Colombier } 6853e12c5d1SDavid du Colombier if(vow*5 >= nbuf-cfreq[' '] && comm >= 10*rare) { 6863e12c5d1SDavid du Colombier print("English text\n"); 6873e12c5d1SDavid du Colombier return 1; 6883e12c5d1SDavid du Colombier } 6893e12c5d1SDavid du Colombier return 0; 6903e12c5d1SDavid du Colombier } 6913e12c5d1SDavid du Colombier 6923e12c5d1SDavid du Colombier /* 6933e12c5d1SDavid du Colombier * pick up a number with 6943e12c5d1SDavid du Colombier * syntax _*[0-9]+_ 6953e12c5d1SDavid du Colombier */ 6963e12c5d1SDavid du Colombier #define P9BITLEN 12 6973e12c5d1SDavid du Colombier int 6983e12c5d1SDavid du Colombier p9bitnum(uchar *bp) 6993e12c5d1SDavid du Colombier { 7003e12c5d1SDavid du Colombier int n, c, len; 7013e12c5d1SDavid du Colombier 7023e12c5d1SDavid du Colombier len = P9BITLEN; 7033e12c5d1SDavid du Colombier while(*bp == ' ') { 7043e12c5d1SDavid du Colombier bp++; 7053e12c5d1SDavid du Colombier len--; 7063e12c5d1SDavid du Colombier if(len <= 0) 7073e12c5d1SDavid du Colombier return -1; 7083e12c5d1SDavid du Colombier } 7093e12c5d1SDavid du Colombier n = 0; 7103e12c5d1SDavid du Colombier while(len > 1) { 7113e12c5d1SDavid du Colombier c = *bp++; 7123e12c5d1SDavid du Colombier if(!isdigit(c)) 7133e12c5d1SDavid du Colombier return -1; 7143e12c5d1SDavid du Colombier n = n*10 + c-'0'; 7153e12c5d1SDavid du Colombier len--; 7163e12c5d1SDavid du Colombier } 7173e12c5d1SDavid du Colombier if(*bp != ' ') 7183e12c5d1SDavid du Colombier return -1; 7193e12c5d1SDavid du Colombier return n; 7203e12c5d1SDavid du Colombier } 7213e12c5d1SDavid du Colombier 7223e12c5d1SDavid du Colombier int 7233e12c5d1SDavid du Colombier isp9bit(void) 7243e12c5d1SDavid du Colombier { 725*219b2ee8SDavid du Colombier int ldep, lox, loy, hix, hiy, px; 726*219b2ee8SDavid du Colombier ulong t; 7273e12c5d1SDavid du Colombier long len; 7283e12c5d1SDavid du Colombier 7293e12c5d1SDavid du Colombier ldep = p9bitnum(buf + 0*P9BITLEN); 7303e12c5d1SDavid du Colombier lox = p9bitnum(buf + 1*P9BITLEN); 7313e12c5d1SDavid du Colombier loy = p9bitnum(buf + 2*P9BITLEN); 7323e12c5d1SDavid du Colombier hix = p9bitnum(buf + 3*P9BITLEN); 7333e12c5d1SDavid du Colombier hiy = p9bitnum(buf + 4*P9BITLEN); 7343e12c5d1SDavid du Colombier 7353e12c5d1SDavid du Colombier if(ldep < 0 || lox < 0 || loy < 0 || hix < 0 || hiy < 0) 7363e12c5d1SDavid du Colombier return 0; 7373e12c5d1SDavid du Colombier 738*219b2ee8SDavid du Colombier px = 1<<(3-ldep); /* pixels per byte */ 739*219b2ee8SDavid du Colombier /* set l to number of bytes of data per scan line */ 740*219b2ee8SDavid du Colombier if(lox >= 0) 741*219b2ee8SDavid du Colombier len = (hix+px-1)/px - lox/px; 742*219b2ee8SDavid du Colombier else{ /* make positive before divide */ 743*219b2ee8SDavid du Colombier t = (-lox)+px-1; 744*219b2ee8SDavid du Colombier t = (t/px)*px; 745*219b2ee8SDavid du Colombier len = (t+hix+px-1)/px; 746*219b2ee8SDavid du Colombier } 7473e12c5d1SDavid du Colombier len *= (hiy-loy); /* col length */ 7483e12c5d1SDavid du Colombier len += 5*P9BITLEN; /* size of initial ascii */ 7493e12c5d1SDavid du Colombier 7503e12c5d1SDavid du Colombier /* 7513e12c5d1SDavid du Colombier * for bitmap file, length is non-zero and must match calculation above 7523e12c5d1SDavid du Colombier * for /dev/window and /dev/screen the length is always zero 7533e12c5d1SDavid du Colombier * for subfont, the subfont header should follow immediately. 7543e12c5d1SDavid du Colombier */ 7553e12c5d1SDavid du Colombier if (mbuf.length == 0) 7563e12c5d1SDavid du Colombier return 0; 7573e12c5d1SDavid du Colombier if (mbuf.length == len) { 7583e12c5d1SDavid du Colombier print("plan 9 bitmap\n"); 7593e12c5d1SDavid du Colombier return 1; 7603e12c5d1SDavid du Colombier } 7613e12c5d1SDavid du Colombier if (p9subfont(buf+len)) { 7623e12c5d1SDavid du Colombier print("subfont file\n"); 7633e12c5d1SDavid du Colombier return 1; 7643e12c5d1SDavid du Colombier } 7653e12c5d1SDavid du Colombier return 0; 7663e12c5d1SDavid du Colombier } 7673e12c5d1SDavid du Colombier 7683e12c5d1SDavid du Colombier int 7693e12c5d1SDavid du Colombier p9subfont(uchar *p) 7703e12c5d1SDavid du Colombier { 7713e12c5d1SDavid du Colombier int n, h, a; 7723e12c5d1SDavid du Colombier 7733e12c5d1SDavid du Colombier /* if bitmap too big, assume it's a subfont */ 7743e12c5d1SDavid du Colombier if (p+3*P9BITLEN > buf+sizeof(buf)) 7753e12c5d1SDavid du Colombier return 1; 7763e12c5d1SDavid du Colombier 7773e12c5d1SDavid du Colombier n = p9bitnum(p + 0*P9BITLEN); /* char count */ 7783e12c5d1SDavid du Colombier if (n < 0) 7793e12c5d1SDavid du Colombier return 0; 7803e12c5d1SDavid du Colombier h = p9bitnum(p + 1*P9BITLEN); /* height */ 7813e12c5d1SDavid du Colombier if (h < 0) 7823e12c5d1SDavid du Colombier return 0; 7833e12c5d1SDavid du Colombier a = p9bitnum(p + 2*P9BITLEN); /* ascent */ 7843e12c5d1SDavid du Colombier if (a < 0) 7853e12c5d1SDavid du Colombier return 0; 7863e12c5d1SDavid du Colombier return 1; 7873e12c5d1SDavid du Colombier } 7883e12c5d1SDavid du Colombier 7893e12c5d1SDavid du Colombier #define WHITESPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 7903e12c5d1SDavid du Colombier 7913e12c5d1SDavid du Colombier int 7923e12c5d1SDavid du Colombier isp9font(void) 7933e12c5d1SDavid du Colombier { 7943e12c5d1SDavid du Colombier uchar *cp, *p; 7953e12c5d1SDavid du Colombier int i, n; 7963e12c5d1SDavid du Colombier char dbuf[DIRLEN]; 7973e12c5d1SDavid du Colombier char pathname[1024]; 7983e12c5d1SDavid du Colombier 7993e12c5d1SDavid du Colombier cp = buf; 8003e12c5d1SDavid du Colombier if (!getfontnum(cp, &cp)) /* height */ 8013e12c5d1SDavid du Colombier return 0; 8023e12c5d1SDavid du Colombier if (!getfontnum(cp, &cp)) /* ascent */ 8033e12c5d1SDavid du Colombier return 0; 8043e12c5d1SDavid du Colombier for (i = 0; 1; i++) { 8053e12c5d1SDavid du Colombier if (!getfontnum(cp, &cp)) /* min */ 8063e12c5d1SDavid du Colombier break; 8073e12c5d1SDavid du Colombier if (!getfontnum(cp, &cp)) /* max */ 8083e12c5d1SDavid du Colombier return 0; 8093e12c5d1SDavid du Colombier while (WHITESPACE(*cp)) 8103e12c5d1SDavid du Colombier cp++; 8113e12c5d1SDavid du Colombier for (p = cp; *cp && !WHITESPACE(*cp); cp++) 8123e12c5d1SDavid du Colombier ; 8133e12c5d1SDavid du Colombier /* construct a path name, if needed */ 8143e12c5d1SDavid du Colombier n = 0; 8153e12c5d1SDavid du Colombier if (*p != '/' && slash) { 8163e12c5d1SDavid du Colombier n = slash-fname+1; 8173e12c5d1SDavid du Colombier if (n < sizeof(pathname)) 8183e12c5d1SDavid du Colombier memcpy(pathname, fname, n); 8193e12c5d1SDavid du Colombier else n = 0; 8203e12c5d1SDavid du Colombier } 8213e12c5d1SDavid du Colombier if (n+cp-p < sizeof(pathname)) { 8223e12c5d1SDavid du Colombier memcpy(pathname+n, p, cp-p); 8233e12c5d1SDavid du Colombier n += cp-p; 8243e12c5d1SDavid du Colombier pathname[n] = 0; 8253e12c5d1SDavid du Colombier if (stat(pathname, dbuf) < 0) 8263e12c5d1SDavid du Colombier return 0; 8273e12c5d1SDavid du Colombier } 8283e12c5d1SDavid du Colombier } 8293e12c5d1SDavid du Colombier if (i) { 8303e12c5d1SDavid du Colombier print("font file\n"); 8313e12c5d1SDavid du Colombier return 1; 8323e12c5d1SDavid du Colombier } 8333e12c5d1SDavid du Colombier return 0; 8343e12c5d1SDavid du Colombier } 8353e12c5d1SDavid du Colombier 8363e12c5d1SDavid du Colombier int 8373e12c5d1SDavid du Colombier getfontnum(uchar *cp, uchar **rp) 8383e12c5d1SDavid du Colombier { 8393e12c5d1SDavid du Colombier while (WHITESPACE(*cp)) /* extract ulong delimited by whitespace */ 8403e12c5d1SDavid du Colombier cp++; 8413e12c5d1SDavid du Colombier if (*cp < '0' || *cp > '9') 8423e12c5d1SDavid du Colombier return 0; 8433e12c5d1SDavid du Colombier strtoul((char *)cp, (char **)rp, 0); 8443e12c5d1SDavid du Colombier if (!WHITESPACE(**rp)) 8453e12c5d1SDavid du Colombier return 0; 8463e12c5d1SDavid du Colombier return 1; 8473e12c5d1SDavid du Colombier } 848