Annotation of researchv10no/cmd/bcp/bcp.cpio, revision 1.1
1.1 ! root 1: 0707070035351137021006640007620000050000010260220476773366500001100000001573Bfeats.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 3: /* The copyright notice does not imply actual or intended publication. */
! 4: /* AUTHORS: */
! 5: /* H. S. Baird - ATT-BL MH - first versions */
! 6:
! 7: /* Bfeats.h - typedef, constants, and function declarations for Bfeats.
! 8: INCLUDES
! 9: Requires prior #include "BMask.h"
! 10: */
! 11:
! 12: typedef struct Bfeats {
! 13: BMask bm; /* bitmask (1 for each feature) */
! 14: unsigned short mny; /* number of feature indices in fa[] */
! 15: unsigned short *fa; /* fa[mny] of feature (ss) nos, no dups (malloc) */
! 16: } Bfeats;
! 17:
! 18: #define Init_Bfeats {Init_BMask,0,NULL}
! 19: #if MAIN
! 20: Bfeats empty_Bfeats = Init_Bfeats;
! 21: #else
! 22: extern Bfeats empty_Bfeats;
! 23: #endif
! 24:
! 25: Bfeats *alloc_bfeats();
! 26: free_bfeats();
! 27: char *bfeats_toa();
! 28: Bfeats *dup_bfeats();
! 29: 0707070035351137031006640007620000050000010260240476773366500001100000470007Bitmap.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 30: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 31: /* The copyright notice does not imply actual or intended publication. */
! 32: /* AUTHORS: */
! 33: /* H. S. Baird - ATT-BL MH - first versions */
! 34: /* Bitmap.h: 2-D fixed-sized bitmaps */
! 35:
! 36: /* BITMAP TEMPLATES: potentially MACHINE-DEPENDENT bit-packing */
! 37: #define Bm_h 54 /* height (no. bits) */
! 38: #define Bm_il 3 /* width (no. ints) */
! 39: #define Bm_ex_h 5 /* extra pixels allowed, top/bottom */
! 40: #define Bm_ex_w 16 /* extra pixels allowed, left/right */
! 41:
! 42: #define Bm_wi ((int)(8*sizeof(int))) /* width of an int in bits; sizeof() is
! 43: unsigned: must coerce to signed so can
! 44: compare correctly with negative ints */
! 45: typedef unsigned int Bm_l[Bm_il]; /* bitmap line */
! 46: #define Bm_w (Bm_wi*Bm_il) /* width of bitmap (<= # bits in a Bm_l) */
! 47: #define Bm_w_ok (Bm_w+2*Bm_ex_w) /* OK width (sides truncated to fit) */
! 48: #define Bm_h_ok (Bm_h+2*Bm_ex_h) /* OK height (top/bot truncated to fit) */
! 49: #define Bm_area (Bm_w*Bm_h) /* area of bitmap */
! 50: #define Bm_ni (Bm_il*Bm_h) /* no. ints in bitmap area */
! 51: #define Bm_ns (2*Bm_ni) /* no. of shorts in bitmap area */
! 52:
! 53: typedef union Bm { /* the rectangular array of bits */
! 54: Bm_l l[Bm_h];
! 55: int unsigned i[Bm_ni];
! 56: short unsigned s[Bm_ns];
! 57: } Bm;
! 58:
! 59: typedef struct Bm_consts {
! 60: unsigned int mask_all; /* all bitmap bits set */
! 61: unsigned int mask[Bm_wi]; /* constant mask bits (in int) */
! 62: unsigned char Rbits[256]; /* Bytes with bits reversed */
! 63: unsigned char Nbits[65536]; /* Nbits[i] = no. bits set in
! 64: (unsigned short) i */
! 65: } Bm_consts;
! 66:
! 67: /* The following 2076 lines are a static initialization for Bm_consts;
! 68: it is written by program `mkbmc' which runs function `fwra_bm_consts' */
! 69: #if MAIN
! 70: Bm_consts bm_consts = {
! 71: 0xffffffff,
! 72: { 0x1,0x2,0x4,0x8,
! 73: 0x10,0x20,0x40,0x80,
! 74: 0x100,0x200,0x400,0x800,
! 75: 0x1000,0x2000,0x4000,0x8000,
! 76: 0x10000,0x20000,0x40000,0x80000,
! 77: 0x100000,0x200000,0x400000,0x800000,
! 78: 0x1000000,0x2000000,0x4000000,0x8000000,
! 79: 0x10000000,0x20000000,0x40000000,0x80000000 },
! 80: { 00,0200,0100,0300,040,0240,0140,0340,020,0220,0120,0320,060,0260,0160,0360,
! 81: 010,0210,0110,0310,050,0250,0150,0350,030,0230,0130,0330,070,0270,0170,0370,
! 82: 04,0204,0104,0304,044,0244,0144,0344,024,0224,0124,0324,064,0264,0164,0364,
! 83: 014,0214,0114,0314,054,0254,0154,0354,034,0234,0134,0334,074,0274,0174,0374,
! 84: 02,0202,0102,0302,042,0242,0142,0342,022,0222,0122,0322,062,0262,0162,0362,
! 85: 012,0212,0112,0312,052,0252,0152,0352,032,0232,0132,0332,072,0272,0172,0372,
! 86: 06,0206,0106,0306,046,0246,0146,0346,026,0226,0126,0326,066,0266,0166,0366,
! 87: 016,0216,0116,0316,056,0256,0156,0356,036,0236,0136,0336,076,0276,0176,0376,
! 88: 01,0201,0101,0301,041,0241,0141,0341,021,0221,0121,0321,061,0261,0161,0361,
! 89: 011,0211,0111,0311,051,0251,0151,0351,031,0231,0131,0331,071,0271,0171,0371,
! 90: 05,0205,0105,0305,045,0245,0145,0345,025,0225,0125,0325,065,0265,0165,0365,
! 91: 015,0215,0115,0315,055,0255,0155,0355,035,0235,0135,0335,075,0275,0175,0375,
! 92: 03,0203,0103,0303,043,0243,0143,0343,023,0223,0123,0323,063,0263,0163,0363,
! 93: 013,0213,0113,0313,053,0253,0153,0353,033,0233,0133,0333,073,0273,0173,0373,
! 94: 07,0207,0107,0307,047,0247,0147,0347,027,0227,0127,0327,067,0267,0167,0367,
! 95: 017,0217,0117,0317,057,0257,0157,0357,037,0237,0137,0337,077,0277,0177,0377 },
! 96: { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
! 97: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 98: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 99: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 100: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 101: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 102: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 103: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 104: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 105: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 106: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 107: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 108: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 109: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 110: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 111: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 112: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 113: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 114: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 115: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 116: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 117: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 118: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 119: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 120: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 121: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 122: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 123: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 124: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 125: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 126: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 127: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 128: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 129: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 130: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 131: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 132: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 133: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 134: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 135: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 136: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 137: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 138: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 139: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 140: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 141: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 142: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 143: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 144: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 145: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 146: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 147: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 148: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 149: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 150: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 151: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 152: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 153: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 154: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 155: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 156: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 157: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 158: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 159: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 160: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 161: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 162: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 163: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 164: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 165: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 166: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 167: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 168: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 169: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 170: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 171: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 172: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 173: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 174: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 175: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 176: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 177: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 178: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 179: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 180: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 181: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 182: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 183: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 184: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 185: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 186: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 187: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 188: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 189: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 190: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 191: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 192: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 193: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 194: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 195: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 196: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 197: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 198: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 199: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 200: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 201: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 202: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 203: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 204: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 205: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 206: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 207: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 208: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 209: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 210: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 211: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 212: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 213: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 214: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 215: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 216: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 217: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 218: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 219: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 220: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 221: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 222: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 223: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 224: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 225: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 226: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 227: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 228: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 229: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 230: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 231: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 232: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 233: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 234: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 235: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 236: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 237: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 238: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 239: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 240: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 241: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 242: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 243: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 244: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 245: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 246: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 247: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 248: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 249: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 250: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 251: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 252: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 253: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 254: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 255: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 256: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 257: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 258: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 259: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 260: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 261: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 262: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 263: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 264: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 265: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 266: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 267: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 268: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 269: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 270: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 271: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 272: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 273: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 274: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 275: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 276: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 277: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 278: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 279: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 280: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 281: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 282: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 283: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 284: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 285: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 286: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 287: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 288: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 289: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 290: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 291: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 292: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 293: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 294: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 295: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 296: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 297: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 298: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 299: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 300: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 301: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 302: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 303: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 304: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 305: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 306: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 307: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 308: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 309: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 310: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 311: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 312: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 313: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 314: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 315: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 316: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 317: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 318: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 319: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 320: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 321: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 322: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 323: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 324: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 325: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 326: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 327: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 328: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 329: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 330: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 331: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 332: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 333: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 334: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 335: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 336: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 337: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 338: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 339: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 340: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 341: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 342: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 343: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 344: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 345: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 346: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 347: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 348: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 349: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 350: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 351: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 352: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 353: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 354: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 355: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 356: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 357: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 358: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 359: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 360: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 361: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 362: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 363: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 364: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 365: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 366: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 367: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 368: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 369: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 370: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 371: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 372: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 373: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 374: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 375: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 376: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 377: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 378: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 379: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 380: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 381: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 382: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 383: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 384: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 385: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 386: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 387: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 388: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 389: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 390: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 391: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 392: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 393: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 394: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 395: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 396: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 397: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 398: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 399: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 400: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 401: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 402: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 403: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 404: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 405: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 406: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 407: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 408: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 409: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 410: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 411: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 412: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 413: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 414: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 415: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 416: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 417: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 418: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 419: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 420: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 421: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 422: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 423: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 424: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 425: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 426: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 427: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 428: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 429: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 430: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 431: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 432: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 433: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 434: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 435: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 436: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 437: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 438: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 439: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 440: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 441: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 442: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 443: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 444: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 445: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 446: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 447: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 448: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 449: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 450: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 451: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 452: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 453: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 454: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 455: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 456: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 457: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 458: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 459: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 460: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 461: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 462: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 463: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 464: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 465: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 466: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 467: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 468: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 469: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 470: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 471: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 472: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 473: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 474: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 475: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 476: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 477: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 478: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 479: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 480: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 481: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 482: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 483: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 484: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 485: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 486: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 487: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 488: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 489: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 490: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 491: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 492: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 493: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 494: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 495: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 496: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 497: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 498: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 499: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 500: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 501: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 502: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 503: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 504: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 505: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 506: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 507: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 508: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 509: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 510: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 511: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 512: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 513: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 514: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 515: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 516: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 517: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 518: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 519: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 520: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 521: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 522: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 523: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 524: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 525: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 526: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 527: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 528: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 529: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 530: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 531: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 532: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 533: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 534: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 535: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 536: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 537: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 538: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 539: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 540: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 541: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 542: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 543: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 544: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 545: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 546: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 547: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 548: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 549: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 550: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 551: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 552: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 553: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 554: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 555: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 556: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 557: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 558: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 559: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 560: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 561: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 562: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 563: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 564: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 565: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 566: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 567: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 568: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 569: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 570: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 571: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 572: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 573: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 574: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 575: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 576: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 577: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 578: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 579: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 580: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 581: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 582: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 583: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 584: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 585: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 586: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 587: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 588: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 589: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 590: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 591: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 592: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 593: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 594: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 595: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 596: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 597: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 598: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 599: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 600: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 601: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 602: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 603: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 604: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 605: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 606: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 607: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 608: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 609: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 610: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 611: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 612: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 613: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 614: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 615: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 616: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 617: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 618: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 619: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 620: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 621: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 622: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 623: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 624: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 625: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 626: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 627: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 628: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 629: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 630: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 631: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 632: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 633: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 634: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 635: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 636: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 637: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 638: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 639: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 640: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 641: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 642: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 643: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 644: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 645: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 646: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 647: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 648: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 649: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 650: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 651: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 652: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 653: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 654: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 655: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 656: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 657: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 658: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 659: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 660: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 661: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 662: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 663: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 664: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 665: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 666: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 667: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 668: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 669: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 670: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 671: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 672: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 673: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 674: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 675: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 676: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 677: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 678: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 679: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 680: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 681: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 682: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 683: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 684: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 685: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 686: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 687: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 688: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 689: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 690: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 691: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 692: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 693: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 694: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 695: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 696: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 697: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 698: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 699: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 700: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 701: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 702: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 703: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 704: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 705: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 706: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 707: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 708: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 709: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 710: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 711: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 712: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 713: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 714: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 715: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 716: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 717: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 718: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 719: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 720: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 721: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 722: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 723: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 724: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 725: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 726: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 727: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 728: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 729: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 730: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 731: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 732: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 733: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 734: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 735: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 736: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 737: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 738: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 739: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 740: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 741: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 742: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 743: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 744: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 745: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 746: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 747: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 748: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 749: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 750: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 751: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 752: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 753: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 754: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 755: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 756: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 757: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 758: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 759: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 760: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 761: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 762: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 763: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 764: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 765: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 766: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 767: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 768: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 769: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 770: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 771: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 772: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 773: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 774: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 775: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 776: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 777: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 778: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 779: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 780: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 781: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 782: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 783: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 784: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 785: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 786: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 787: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 788: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 789: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 790: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 791: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 792: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 793: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 794: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 795: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 796: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 797: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 798: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 799: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 800: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 801: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 802: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 803: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 804: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 805: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 806: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 807: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 808: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 809: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 810: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 811: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 812: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 813: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 814: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 815: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 816: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 817: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 818: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 819: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 820: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 821: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 822: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 823: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 824: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 825: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 826: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 827: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 828: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 829: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 830: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 831: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 832: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 833: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 834: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 835: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 836: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 837: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 838: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 839: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 840: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 841: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 842: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 843: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 844: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 845: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 846: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 847: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 848: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 849: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 850: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 851: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 852: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 853: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 854: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 855: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 856: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 857: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 858: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 859: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 860: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 861: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 862: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 863: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 864: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 865: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 866: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 867: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 868: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 869: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 870: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 871: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 872: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 873: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 874: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 875: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 876: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 877: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 878: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 879: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 880: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 881: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 882: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 883: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 884: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 885: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 886: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 887: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 888: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 889: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 890: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 891: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 892: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 893: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 894: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 895: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 896: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 897: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 898: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 899: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 900: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 901: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 902: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 903: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 904: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 905: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 906: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 907: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 908: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 909: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 910: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 911: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 912: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 913: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 914: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 915: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 916: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 917: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 918: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 919: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 920: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 921: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 922: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 923: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 924: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 925: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 926: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 927: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 928: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 929: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 930: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 931: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 932: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 933: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 934: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 935: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 936: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 937: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 938: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 939: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 940: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 941: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 942: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 943: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 944: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 945: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 946: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 947: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 948: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 949: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 950: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 951: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 952: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 953: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 954: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 955: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 956: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 957: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 958: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 959: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 960: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 961: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 962: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 963: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 964: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 965: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 966: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 967: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 968: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 969: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 970: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 971: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 972: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 973: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 974: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 975: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 976: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 977: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 978: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 979: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 980: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 981: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 982: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 983: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 984: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 985: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 986: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 987: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 988: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 989: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 990: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 991: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 992: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 993: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 994: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 995: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 996: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 997: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 998: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 999: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1000: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1001: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1002: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1003: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1004: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1005: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1006: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1007: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1008: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1009: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1010: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1011: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1012: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1013: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1014: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1015: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1016: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1017: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1018: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1019: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1020: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1021: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1022: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1023: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1024: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1025: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1026: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1027: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1028: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1029: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1030: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1031: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1032: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1033: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1034: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1035: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1036: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1037: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1038: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1039: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1040: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1041: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1042: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1043: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1044: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1045: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1046: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1047: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1048: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1049: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1050: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1051: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1052: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1053: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1054: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1055: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1056: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1057: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1058: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1059: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1060: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1061: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1062: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1063: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1064: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1065: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1066: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1067: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1068: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1069: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1070: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1071: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1072: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1073: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1074: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1075: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1076: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1077: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1078: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1079: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1080: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1081: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1082: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1083: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1084: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1085: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1086: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1087: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1088: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1089: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1090: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1091: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1092: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1093: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1094: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1095: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1096: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1097: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1098: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1099: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1100: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1101: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1102: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1103: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1104: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1105: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1106: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1107: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1108: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1109: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1110: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1111: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1112: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1113: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1114: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1115: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1116: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1117: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1118: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1119: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 1120: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
! 1121: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1122: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1123: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1124: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1125: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1126: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1127: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1128: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1129: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1130: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1131: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1132: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1133: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1134: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1135: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1136: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1137: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1138: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1139: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1140: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1141: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1142: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1143: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1144: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1145: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1146: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1147: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1148: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1149: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1150: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1151: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1152: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1153: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1154: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1155: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1156: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1157: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1158: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1159: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1160: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1161: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1162: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1163: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1164: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1165: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1166: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1167: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1168: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1169: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1170: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1171: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1172: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1173: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1174: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1175: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1176: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1177: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1178: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1179: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1180: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1181: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1182: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1183: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1184: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1185: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1186: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1187: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1188: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1189: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1190: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1191: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1192: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1193: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1194: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1195: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1196: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1197: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1198: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1199: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1200: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1201: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1202: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1203: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1204: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1205: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1206: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1207: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1208: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1209: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1210: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1211: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1212: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1213: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1214: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1215: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1216: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1217: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1218: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1219: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1220: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1221: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1222: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1223: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1224: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1225: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1226: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1227: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1228: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1229: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1230: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1231: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1232: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1233: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1234: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1235: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1236: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1237: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1238: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1239: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1240: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1241: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1242: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1243: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1244: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1245: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1246: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1247: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1248: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1249: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1250: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1251: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1252: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1253: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1254: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1255: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1256: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1257: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1258: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1259: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1260: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1261: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1262: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1263: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1264: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1265: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1266: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1267: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1268: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1269: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1270: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1271: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1272: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1273: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1274: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1275: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1276: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1277: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1278: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1279: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1280: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1281: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1282: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1283: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1284: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1285: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1286: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1287: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1288: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1289: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1290: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1291: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1292: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1293: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1294: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1295: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1296: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1297: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1298: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1299: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1300: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1301: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1302: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1303: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1304: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1305: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1306: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1307: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1308: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1309: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1310: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1311: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1312: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1313: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1314: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1315: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1316: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1317: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1318: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1319: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1320: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1321: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1322: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1323: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1324: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1325: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1326: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1327: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1328: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1329: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1330: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1331: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1332: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1333: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1334: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1335: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1336: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1337: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1338: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1339: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1340: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1341: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1342: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1343: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1344: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1345: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1346: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1347: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1348: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1349: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1350: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1351: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1352: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1353: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1354: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1355: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1356: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1357: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1358: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1359: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1360: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1361: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1362: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1363: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1364: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1365: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1366: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1367: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1368: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1369: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1370: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1371: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1372: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1373: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1374: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1375: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1376: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1377: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1378: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1379: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1380: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1381: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1382: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1383: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1384: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1385: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1386: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1387: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1388: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1389: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1390: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1391: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1392: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1393: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1394: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1395: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1396: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1397: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1398: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1399: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1400: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1401: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1402: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1403: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1404: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1405: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1406: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1407: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1408: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1409: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1410: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1411: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1412: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1413: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1414: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1415: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1416: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1417: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1418: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1419: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1420: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1421: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1422: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1423: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1424: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1425: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1426: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1427: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1428: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1429: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1430: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1431: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1432: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1433: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1434: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1435: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1436: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1437: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1438: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1439: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1440: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1441: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1442: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1443: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1444: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1445: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1446: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1447: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1448: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1449: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1450: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1451: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1452: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1453: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1454: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1455: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1456: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1457: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1458: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1459: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1460: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1461: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1462: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1463: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1464: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1465: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1466: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1467: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1468: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1469: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1470: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1471: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1472: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1473: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1474: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1475: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1476: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1477: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1478: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1479: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1480: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1481: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1482: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1483: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1484: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1485: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1486: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1487: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1488: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1489: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1490: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1491: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1492: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1493: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1494: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1495: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1496: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1497: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1498: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1499: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1500: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1501: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1502: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1503: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1504: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1505: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1506: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1507: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1508: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1509: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1510: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1511: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1512: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1513: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1514: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1515: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1516: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1517: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1518: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1519: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1520: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1521: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1522: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1523: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1524: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1525: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1526: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1527: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1528: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1529: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1530: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1531: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1532: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1533: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1534: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1535: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1536: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1537: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1538: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1539: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1540: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1541: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1542: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1543: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1544: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1545: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1546: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1547: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1548: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1549: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1550: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1551: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1552: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1553: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1554: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1555: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1556: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1557: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1558: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1559: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1560: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1561: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1562: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1563: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1564: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1565: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1566: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1567: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1568: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1569: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1570: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1571: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1572: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1573: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1574: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1575: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1576: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1577: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1578: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1579: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1580: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1581: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1582: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1583: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1584: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1585: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1586: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1587: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1588: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1589: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1590: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1591: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1592: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1593: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1594: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1595: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1596: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1597: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1598: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1599: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1600: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1601: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1602: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1603: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1604: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1605: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1606: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1607: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1608: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1609: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1610: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1611: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1612: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1613: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1614: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1615: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1616: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1617: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1618: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1619: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1620: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1621: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1622: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1623: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1624: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1625: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1626: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1627: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1628: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1629: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1630: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1631: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 1632: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
! 1633: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1634: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1635: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1636: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1637: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1638: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1639: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1640: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1641: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1642: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1643: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1644: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1645: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1646: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1647: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1648: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1649: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1650: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1651: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1652: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1653: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1654: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1655: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1656: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1657: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1658: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1659: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1660: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1661: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1662: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1663: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1664: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1665: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1666: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1667: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1668: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1669: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1670: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1671: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1672: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1673: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1674: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1675: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1676: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1677: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1678: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1679: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1680: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1681: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1682: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1683: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1684: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1685: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1686: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1687: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1688: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1689: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1690: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1691: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1692: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1693: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1694: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1695: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1696: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1697: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1698: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1699: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1700: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1701: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1702: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1703: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1704: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1705: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1706: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1707: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1708: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1709: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1710: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1711: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1712: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1713: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1714: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1715: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1716: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1717: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1718: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1719: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1720: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1721: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1722: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1723: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1724: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1725: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1726: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1727: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1728: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1729: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1730: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1731: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1732: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1733: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1734: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1735: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1736: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1737: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1738: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1739: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1740: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1741: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1742: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1743: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1744: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1745: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1746: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1747: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1748: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1749: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1750: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1751: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1752: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1753: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1754: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1755: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1756: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1757: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1758: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1759: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1760: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1761: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1762: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1763: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1764: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1765: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1766: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1767: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1768: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1769: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1770: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1771: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1772: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1773: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1774: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1775: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1776: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1777: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1778: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1779: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1780: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1781: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1782: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1783: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1784: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1785: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1786: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1787: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1788: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1789: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1790: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1791: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1792: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1793: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1794: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1795: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1796: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1797: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1798: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1799: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1800: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1801: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1802: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1803: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1804: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1805: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1806: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1807: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1808: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1809: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1810: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1811: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1812: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1813: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1814: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1815: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1816: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1817: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1818: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1819: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1820: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1821: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1822: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1823: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1824: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1825: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1826: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1827: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1828: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1829: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1830: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1831: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1832: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1833: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1834: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1835: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1836: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1837: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1838: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1839: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1840: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1841: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1842: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1843: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1844: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1845: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1846: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1847: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1848: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1849: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1850: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1851: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1852: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1853: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1854: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1855: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1856: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1857: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1858: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1859: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1860: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1861: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1862: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1863: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1864: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1865: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1866: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1867: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1868: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1869: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1870: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1871: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1872: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1873: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1874: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1875: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1876: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1877: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1878: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1879: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1880: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1881: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1882: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1883: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1884: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1885: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1886: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1887: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 1888: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
! 1889: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1890: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1891: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1892: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1893: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1894: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1895: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1896: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1897: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1898: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1899: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1900: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1901: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1902: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1903: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1904: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1905: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1906: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1907: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1908: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1909: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1910: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1911: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1912: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1913: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1914: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1915: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1916: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1917: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1918: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1919: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1920: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1921: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1922: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1923: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1924: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1925: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1926: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1927: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1928: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1929: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1930: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1931: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1932: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1933: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1934: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1935: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1936: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1937: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1938: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1939: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1940: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1941: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1942: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1943: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1944: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1945: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1946: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1947: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1948: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1949: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1950: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1951: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1952: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 1953: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1954: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1955: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1956: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1957: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1958: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1959: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1960: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1961: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1962: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1963: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1964: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1965: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1966: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1967: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1968: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1969: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1970: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1971: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1972: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1973: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1974: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1975: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1976: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1977: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1978: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1979: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1980: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1981: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1982: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1983: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 1984: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 1985: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1986: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1987: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1988: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1989: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1990: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1991: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1992: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 1993: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1994: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1995: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1996: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 1997: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1998: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 1999: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2000: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2001: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2002: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2003: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2004: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2005: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2006: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2007: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2008: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2009: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2010: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2011: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2012: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2013: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2014: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2015: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2016: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
! 2017: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2018: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2019: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2020: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2021: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2022: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2023: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2024: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2025: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2026: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2027: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2028: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2029: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2030: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2031: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2032: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2033: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2034: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2035: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2036: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2037: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2038: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2039: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2040: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2041: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2042: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2043: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2044: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2045: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2046: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2047: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2048: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2049: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2050: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2051: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2052: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2053: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2054: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2055: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2056: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2057: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2058: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2059: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2060: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2061: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2062: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2063: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2064: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2065: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2066: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2067: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2068: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2069: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2070: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2071: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2072: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2073: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2074: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2075: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2076: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2077: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2078: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2079: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2080: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
! 2081: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2082: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2083: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2084: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2085: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2086: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2087: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2088: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2089: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2090: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2091: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2092: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2093: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2094: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2095: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2096: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2097: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2098: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2099: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2100: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2101: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2102: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2103: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2104: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2105: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2106: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2107: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2108: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2109: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2110: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2111: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2112: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
! 2113: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2114: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2115: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2116: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2117: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2118: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2119: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2120: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2121: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2122: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2123: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2124: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2125: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2126: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2127: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2128: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
! 2129: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2130: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2131: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2132: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2133: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2134: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2135: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2136: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
! 2137: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2138: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2139: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2140: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
! 2141: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2142: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
! 2143: 11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,12,13,13,14,13,14,14,15,13,14,14,15,14,15,15,16 }
! 2144: };
! 2145:
! 2146: #else
! 2147: extern Bm_consts bm_consts;
! 2148: #endif
! 2149:
! 2150: double Bm_match();
! 2151: char *BM_toa();
! 2152: 0707070035351137041006640007620000050000010260520476773366600001000000207047CCITT.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 2153: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 2154: /* The copyright notice does not imply actual or intended publication. */
! 2155: /* AUTHORS: */
! 2156: /* H. S. Baird - ATT-BL MH - first versions */
! 2157:
! 2158: /* CCITT.c - functions for CCITT compression/decompression of binary images.
! 2159: The following discussion is a summary of CCITT Recommendations T.4 and T.6
! 2160: on facsimile coding schemes and coding control functions for Group 3 and Group
! 2161: 4 facsimile apparatus (drafted at Malaga-Torremolinos, 1984). They describe
! 2162: algorithms for invertible (lossless) compression and decompression of bilevel
! 2163: (black-and-white, not grey) 2D rectangular images of arbitrary height and
! 2164: width. By convention the images are processed top-down, one horizontal scan
! 2165: line at a time. It is not strictly necessary to know the height of an image
! 2166: before starting compression or decompression. Width, however, must be known
! 2167: in advance in some cases (discussed below), and must remain constant for the
! 2168: whole image in all cases. There are three distinct but intimately related
! 2169: standards: Group 3 1-dimensional, Group 3 2-dimensional, and Group 4.
! 2170: VLSI hardware implementations always include all three. The Group 3 encodings
! 2171: are used in the vast installed base of FAX machines. Group 4 is not used
! 2172: in today's FAX machines, but seems to be the default standard in document image
! 2173: archiving applications.
! 2174: The CCITT Group 3 FAX standard permits either 1-D or 2-D encoding.
! 2175: It is not easy to tell from an encoding which was used. Both 1-D and 2-D
! 2176: assume fixed scanline length (in pixels), which must be known at encoding time.
! 2177: Group 3 1-D (g31) code uses fixed ``modified Huffman'' codes for
! 2178: run-lengths, with two different code tables for black and white runs. Each
! 2179: line is assumed to begin with a (possibly 0-length) white run. Of course,
! 2180: the colors strictly alternate. An empty (all-white) line is supposed to be
! 2181: spelled out with a full pixel count, although some decoders won't complain
! 2182: if just a 0-length count is used. There are provisions for fill bits at the
! 2183: end of lines to allow slow receiving equipment to keep up. Each line ends with
! 2184: an EOL code on which it may be possible to synchronize after transmission error.
! 2185: Group 3 2-D (g32) encoding tries to exploit the slowly-changing nature
! 2186: of artwork from line to line. It is a mixture of 1-D-coded lines and
! 2187: ``2-D''-coded lines describing small local changes relative to the immediately
! 2188: prior ``reference'' line. 1-D coding recurs every few (`k') lines, so that
! 2189: resynchronization is frequently possible. K is usually 2 or 4, but the
! 2190: standard permits any number, even infinity, since the coding method used on
! 2191: a line is specified by which of two special EOLx codes is used to end the
! 2192: prior line.
! 2193: CCITT Group 4 (g4) is like Group 3 2-D, but optimized to take advantage
! 2194: of a lossless communications channel or reliable storage medium (such as computer
! 2195: memory), where resynchronization is unnecessary. Thus the first line is 2-D
! 2196: encoded referenced to an imaginary initial blank line, k is always infinity,
! 2197: and EOL's are not used at all. It essential that the line-length be known in
! 2198: advance of both encoding and decoding, so that line-breaks can be triggered when
! 2199: that length is exceeded. End of FAX buffer (end of page) is signaled by a
! 2200: special EOFB code.
! 2201: On images of printed text and sparse line-graphics, g4-compressed files
! 2202: are often 15-40X smaller than bitmap (packed bits), 5X than bitfile(9.5),
! 2203: 2X than g31, and 2X than rle | pack.
! 2204: PERFORMANCE
! 2205: On 10 printed A4 pages (business letters, technical reports, etc),
! 2206: at a resolution of 400 dpi:
! 2207: binary: 2020 Kbytes CPU secs (to compress binary)
! 2208: pack: 200 - 380 17
! 2209: bitfile(9.5): 150 - 360 ?
! 2210: rle: 100 - 230 7.5
! 2211: compress: 90 - 155 14
! 2212: g31: 85 - 190 13
! 2213: g32: 55 - 110 13
! 2214: g4: 30 - 70 13
! 2215: G4-compressed files are 15-40X smaller than binary, 5X than bitfile(9.5),
! 2216: 3.5X than rle, 2X than g31, and 2X than rle | pack.
! 2217: */
! 2218:
! 2219: #include <stdio.h>
! 2220: #include <string.h>
! 2221: #include <ctype.h>
! 2222: #include "CPU.h"
! 2223: #include "stdocr.h"
! 2224: #include "rle.h"
! 2225: #include "bitio.h"
! 2226: #include "CCITT.h"
! 2227:
! 2228: #define DEBUG 0 /* 0 disables compilation of all debugging code;
! 2229: 1 compiles, but must enable particular parts below */
! 2230: #define NEW_TRAIL 1 /* enable new trailing-0 counts (has passed early tests) */
! 2231: #define dbg_trail 0
! 2232:
! 2233: DST_table *ccitt_table()
! 2234: { DST_context cx;
! 2235: if((cx.t = (DST_table *)malloc(sizeof(DST_table)))==NULL)
! 2236: abort("CCITT.c: build_tbl: can't alloc cx.t");
! 2237: /* All tables have e[DST_white], e[DST_black], & e[DST_2d] entries */
! 2238: cx.t->mny=3;
! 2239: if((cx.t->e=(DST_entry *)malloc(cx.t->mny*sizeof(DST_entry)))==NULL)
! 2240: abort("CCITT.c: build_tbl: can't alloc cx.t->e[%d]",cx.t->mny);
! 2241:
! 2242: cx.s = cx.c = DST_white;
! 2243: cx.l = 0;
! 2244: cx.t->e[cx.s].p[0] = '\0';
! 2245: cx.t->e[cx.s].l = 0;
! 2246: cx.t->e[cx.s].z = 0;
! 2247: build_transits(cx);
! 2248:
! 2249: cx.s = cx.c = DST_black;
! 2250: cx.l = 0;
! 2251: cx.t->e[cx.s].p[0] = '\0';
! 2252: cx.t->e[cx.s].l = 0;
! 2253: cx.t->e[cx.s].z = 0;
! 2254: build_transits(cx);
! 2255:
! 2256: cx.s = cx.c = DST_2d;
! 2257: cx.l = 0;
! 2258: cx.t->e[cx.s].p[0] = '\0';
! 2259: cx.t->e[cx.s].l = 0;
! 2260: cx.t->e[cx.s].z = 0;
! 2261: build_transits(cx);
! 2262:
! 2263: #if DEBUG
! 2264: if(F) ccitt_err_tbl(cx.t);
! 2265: #endif
! 2266: return(cx.t);
! 2267: }
! 2268:
! 2269: DST_state new_state(t)
! 2270: DST_table *t;
! 2271: { t->mny++;
! 2272: if((t->e=(DST_entry *)realloc(t->e,t->mny*sizeof(DST_entry)))==NULL)
! 2273: abort("can't realloc t->[%d]",t->mny);
! 2274: return(t->mny-1);
! 2275: }
! 2276:
! 2277: /* The entry described by `cx' exists in the table, and its prefix `p' is
! 2278: setup; create its transitions, and their next entries, recursively. */
! 2279: build_transits(cx)
! 2280: DST_context cx;
! 2281: #define entry cx.t->e[cx.s]
! 2282: #define transit entry.t[col]
! 2283: { DST_color col;
! 2284: DST_entry ne; /* next entry */
! 2285: DST_context ncx; /* next Context */
! 2286: char **s,**ss; /* for searching code */
! 2287: short *c,*cs;
! 2288: int si,matching,longer;
! 2289: char svch,col_str[2];
! 2290: switch(cx.c) {
! 2291: case DST_white:
! 2292: ss=codewht;
! 2293: cs=bitcwht;
! 2294: break;
! 2295: case DST_black:
! 2296: ss=codeblk;
! 2297: cs=bitcblk;
! 2298: break;
! 2299: case DST_2d:
! 2300: ss=code2d;
! 2301: cs=bitc2d;
! 2302: break;
! 2303: };
! 2304: for(col=0;col<=1;col++) {
! 2305: sprintf(col_str,"%1d",col);
! 2306: ncx = cx; ncx.l++;
! 2307: /* build a transition */
! 2308: strcpy(ne.p,entry.p); strcat(ne.p,col_str);
! 2309: ne.l = ncx.l;
! 2310: if(col==0) ne.z = entry.z+1; else ne.z = 0;
! 2311: /* count those that match new prefix */
! 2312: longer=matching=0;
! 2313: for(s=ss,c=cs,si=0; (*s)!=NULL; s++,c++,si++) {
! 2314: if(*c==ncx.l) {
! 2315: if(strcmp(*s,ne.p)==0) {
! 2316: matching++;
! 2317: switch(cx.c) {
! 2318: case DST_white:
! 2319: case DST_black:
! 2320: transit.a = itor(si);
! 2321: break;
! 2322: case DST_2d:
! 2323: transit.a = si;
! 2324: break;
! 2325: };
! 2326: };
! 2327: }
! 2328: else if(*c>ncx.l) {
! 2329: svch=(*s)[ncx.l]; (*s)[ncx.l] = '\0';
! 2330: if(strcmp(*s,ne.p)==0) {
! 2331: longer++;
! 2332: };
! 2333: (*s)[ncx.l]=svch;
! 2334: };
! 2335: };
! 2336: /* analyze results */
! 2337: if(matching==0&&longer>0) {
! 2338: /* no match yet; go deeper */
! 2339: transit.a = DST_action_NULL;
! 2340: ncx.s = transit.s = new_state(cx.t);
! 2341: strcpy(cx.t->e[ncx.s].p,ne.p);
! 2342: cx.t->e[ncx.s].l = ne.l;
! 2343: cx.t->e[ncx.s].z = ne.z;
! 2344: build_transits(ncx);
! 2345: }
! 2346: else if(matching==1&&longer==0) {
! 2347: /* unique leaf: good */
! 2348: /* picked up action earlier */
! 2349: switch(cx.c) {
! 2350: case DST_white:
! 2351: case DST_black:
! 2352: if(transit.a<=63) /* termination code */
! 2353: transit.s = flip_color(cx.c);
! 2354: else /* makeup code */
! 2355: transit.s = cx.c;
! 2356: break;
! 2357: case DST_2d:
! 2358: /* legal end of code */
! 2359: transit.s = DST_state_NULL;
! 2360: break;
! 2361: };
! 2362: }
! 2363: else { /* illegal transition */
! 2364: transit.a = DST_action_ERROR;
! 2365: transit.s = DST_state_NULL;
! 2366: };
! 2367: };
! 2368: }
! 2369:
! 2370: ccitt_err_tbl(t)
! 2371: DST_table *t;
! 2372: { int d;
! 2373: ccitt_err_state(DST_white,t);
! 2374: ccitt_err_state(DST_black,t);
! 2375: ccitt_err_state(DST_2d,t);
! 2376: }
! 2377:
! 2378: ccitt_err_state(s,t)
! 2379: DST_state s;
! 2380: DST_table *t;
! 2381: { err("%03d %s %2d %2d%*s %d %03d,%-4d %d %03d,%-4d",
! 2382: s,t->e[s].p,t->e[s].l,t->e[s].z,14-strlen(t->e[s].p)," ",
! 2383: 0,t->e[s].t[0].s,t->e[s].t[0].a,
! 2384: 1,t->e[s].t[1].s,t->e[s].t[1].a
! 2385: );
! 2386: if(t->e[s].t[0].s>1) ccitt_err_state(t->e[s].t[0].s,t);
! 2387: if(t->e[s].t[1].s>1) ccitt_err_state(t->e[s].t[1].s,t);
! 2388: }
! 2389:
! 2390: /* Translate a stream of bits in CCITT FAX Group 3 (1-D) compression format
! 2391: into a sequence of RLE_Lines. Returns one (RLE_Line *) on each call (or NULL
! 2392: if EOF or error). The first pixel (black or white) in each g31 line is
! 2393: assigned run index 0. */
! 2394: RLE_Line *g31_to_rlel(t,f,bof)
! 2395: DST_table *t;
! 2396: BITFILE *f;
! 2397: boolean bof; /* beginning of file */
! 2398: #define dbg_g31r_r (0) /* trace each run/EOL/ERR_SYN */
! 2399: #define dbg_g31r_c (0) /* trace each Huffman code (or, fill+EOL)*/
! 2400: #define dbg_g31r_t (0) /* trace each state-transition */
! 2401: { static DST_context cx;
! 2402: static RLE_Line rl;
! 2403: static RLE_Run *r; /* prior, current runs */
! 2404: int run,biti,sync,si,bitv;
! 2405: boolean fill;
! 2406: /* color of 1st run in each line */
! 2407: #define g31_first_color DST_white
! 2408: /* reverse Black/White in output image */
! 2409: #define g31_negative 0
! 2410: if(bof){if(T) { /* sync by skipping initial FILL & EOL code */
! 2411: sync=0; while((bitv=getb(f))==0) sync++;
! 2412: if(bitv!=1||sync<11) {
! 2413: #if DEBUG
! 2414: if(dbg_g31r_c) {
! 2415: fprintf(stderr,"BOF_ERR ");
! 2416: for(si=0;si<sync;si++) fprintf(stderr,"0");
! 2417: if(bitv==1) fprintf(stderr,"1\n");
! 2418: else fprintf(stderr,"?\n");
! 2419: };
! 2420: #endif
! 2421: return(NULL);
! 2422: }
! 2423: #if DEBUG
! 2424: else if(dbg_g31r_c){
! 2425: fprintf(stderr,"BOF_EOL ");
! 2426: for(si=0;si<sync;si++) fprintf(stderr,"0");
! 2427: fprintf(stderr,"1\n");
! 2428: };
! 2429: #endif
! 2430: };
! 2431: /* start file expecting a run-code of a fixed color */
! 2432: cx.s = cx.c = g31_first_color;
! 2433: rl.y = -1; /* assume first line is y==0 */
! 2434: };
! 2435: rl.y++; rl.runs=0; r = rl.r; biti=run=0;
! 2436: while(T) switch(getb(f)) {
! 2437: case 0 : /* next bit is 0 */
! 2438: switch(t->e[cx.s].t[0].a) {
! 2439: case DST_action_ERROR:
! 2440: /* bad code: try to resynchronize */
! 2441: #if DEBUG
! 2442: if(dbg_g31r_t){
! 2443: fprintf(stderr,"%s %04d %s0?...\n",
! 2444: (cx.c==DST_white)? "W": "B",
! 2445: t->e[cx.s].t[0].s,
! 2446: t->e[cx.s].p);
! 2447: };
! 2448: #endif
! 2449: /* count trailing 0's so far (should be in table) */
! 2450: #if !NEW_TRAIL
! 2451: sync=1;
! 2452: si=strlen(t->e[cx.s].p)-1;
! 2453: while(si>=0&&t->e[cx.s].p[si]=='0') {sync++; si--;};
! 2454: fill = (si<0); /* all 0's: may be fill bits */
! 2455: #else
! 2456: sync=t->e[cx.s].z+1;
! 2457: fill = (sync>t->e[cx.s].l); /* all 0's: maybe fill bits */
! 2458: #endif
! 2459: #if DEBUG
! 2460: if(dbg_trail) err("sync %d fill %d",sync,fill);
! 2461: if(dbg_g31r_c)fprintf(stderr,"ERR_SYN %s0?",t->e[cx.s].p);
! 2462: #endif
! 2463: while(sync<11) {
! 2464: switch(bitv=getb(f)) {
! 2465: case 0: sync++;
! 2466: #if DEBUG
! 2467: if(dbg_g31r_c) fprintf(stderr,"0");
! 2468: #endif
! 2469: break;
! 2470: case 1: sync=0; fill=F;
! 2471: #if DEBUG
! 2472: if(dbg_g31r_c) fprintf(stderr,"1");
! 2473: #endif
! 2474: break;
! 2475: case EOF:
! 2476: #if DEBUG
! 2477: if(dbg_g31r_c) fprintf(stderr,"<EOF>\n");
! 2478: #endif
! 2479: return(NULL); break;
! 2480: };
! 2481: };
! 2482: /* next `1' will synchronize */
! 2483: do { switch(bitv=getb(f)) {
! 2484: case 0:
! 2485: #if DEBUG
! 2486: if(dbg_g31r_c) fprintf(stderr,"0");
! 2487: #endif
! 2488: break;
! 2489: case 1:
! 2490: #if DEBUG
! 2491: if(dbg_g31r_c) fprintf(stderr,"1");
! 2492: #endif
! 2493: break;
! 2494: case EOF:
! 2495: #if DEBUG
! 2496: if(dbg_g31r_c) fprintf(stderr,"<EOF>\n");
! 2497: #endif
! 2498: return(NULL); break;
! 2499: };
! 2500: }
! 2501: while(bitv!=1);
! 2502: #if DEBUG
! 2503: if(dbg_g31r_c) fprintf(stderr,"\n");
! 2504: if(dbg_g31r_r) {
! 2505: if(fill) fprintf(stderr,"FILL_EOL\n");
! 2506: else fprintf(stderr,"ERR_SYN_EOL\n");
! 2507: };
! 2508: #endif
! 2509: /* start next line expecting a run-code of a fixed color */
! 2510: cx.s = cx.c = g31_first_color;
! 2511: return(&rl);
! 2512: break;
! 2513: case DST_action_NULL:
! 2514: #if DEBUG
! 2515: if(dbg_g31r_t)fprintf(stderr,"%s %04d %s0\n",
! 2516: (cx.c==DST_white)? "W": "B",
! 2517: t->e[cx.s].t[0].s,
! 2518: t->e[cx.s].p);
! 2519: #endif
! 2520: cx.s = t->e[cx.s].t[0].s;
! 2521: break;
! 2522: case DST_EOL:
! 2523: #if DEBUG
! 2524: if(dbg_g31r_c)fprintf(stderr,"EOL %s0\n",
! 2525: t->e[cx.s].p);
! 2526: if(dbg_g31r_r)fprintf(stderr,"EOL\n");
! 2527: #endif
! 2528: /* start next line expecting a run-code of a fixed color */
! 2529: cx.s = cx.c = g31_first_color;
! 2530: return(&rl);
! 2531: break;
! 2532: default:
! 2533: #if DEBUG
! 2534: if(dbg_g31r_c)fprintf(stderr,"%s%6d %s0\n",
! 2535: (cx.c==DST_white)? "W": "B",
! 2536: t->e[cx.s].t[0].a,
! 2537: t->e[cx.s].p);
! 2538: #endif
! 2539: if(t->e[cx.s].t[0].a<=63) {
! 2540: run += t->e[cx.s].t[0].a;
! 2541: #if DEBUG
! 2542: if(dbg_g31r_r)fprintf(stderr,"%s%6d\n",
! 2543: (cx.c==DST_white)? "W": "B",
! 2544: run);
! 2545: #endif
! 2546: biti += run;
! 2547: if(cx.c==DST_black^g31_negative) {
! 2548: /* end of black run */
! 2549: r->xe = biti-1;
! 2550: r++; rl.runs++;
! 2551: }
! 2552: else { /* end of white run */
! 2553: r->xs = biti;
! 2554: };
! 2555: cx.c = flip_color(cx.c);
! 2556: run = 0;
! 2557: }
! 2558: else run += t->e[cx.s].t[0].a;
! 2559: cx.s = t->e[cx.s].t[0].s;
! 2560: break;
! 2561: };
! 2562: break;
! 2563: case 1: /* next bit is 1 */
! 2564: switch(t->e[cx.s].t[1].a) {
! 2565: case DST_action_ERROR:
! 2566: /* bad code: try to resynchronize */
! 2567: #if DEBUG
! 2568: if(dbg_g31r_t){
! 2569: fprintf(stderr,"%s %04d %s1?...\n",
! 2570: (cx.c==DST_white)? "W": "B",
! 2571: t->e[cx.s].t[1].s,
! 2572: t->e[cx.s].p);
! 2573: };
! 2574: if(dbg_g31r_c)fprintf(stderr,"ERR_SYN %s1?",t->e[cx.s].p);
! 2575: #endif
! 2576: /* no trailing 0's; can't be fill bits */
! 2577: sync=0;
! 2578: while(sync<11) {
! 2579: switch(bitv=getb(f)) {
! 2580: case 0: sync++;
! 2581: #if DEBUG
! 2582: if(dbg_g31r_c) fprintf(stderr,"0");
! 2583: #endif
! 2584: break;
! 2585: case 1: sync=0;
! 2586: #if DEBUG
! 2587: if(dbg_g31r_c) fprintf(stderr,"1");
! 2588: #endif
! 2589: break;
! 2590: case EOF:
! 2591: #if DEBUG
! 2592: if(dbg_g31r_c)
! 2593: fprintf(stderr,"<EOF>\n");
! 2594: #endif
! 2595: return(NULL); break;
! 2596: };
! 2597: };
! 2598: /* next `1' will synchronize */
! 2599: do { switch(bitv=getb(f)) {
! 2600: case 0:
! 2601: #if DEBUG
! 2602: if(dbg_g31r_c) fprintf(stderr,"0");
! 2603: #endif
! 2604: break;
! 2605: case 1:
! 2606: #if DEBUG
! 2607: if(dbg_g31r_c) fprintf(stderr,"1");
! 2608: #endif
! 2609: break;
! 2610: case EOF:
! 2611: #if DEBUG
! 2612: if(dbg_g31r_c)
! 2613: fprintf(stderr,"<EOF>\n");
! 2614: #endif
! 2615: return(NULL); break;
! 2616: };
! 2617: }
! 2618: while(bitv!=1);
! 2619: #if DEBUG
! 2620: if(dbg_g31r_c) fprintf(stderr,"\n");
! 2621: if(dbg_g31r_r) fprintf(stderr,"ERR_SYN_EOL\n");
! 2622: #endif
! 2623: /* start next line expecting a run-code of a fixed color */
! 2624: cx.s = cx.c = g31_first_color;
! 2625: return(&rl);
! 2626: break;
! 2627: case DST_action_NULL:
! 2628: #if DEBUG
! 2629: if(dbg_g31r_t)fprintf(stderr,"%s %04d %s1\n",
! 2630: (cx.c==DST_white)? "W": "B",
! 2631: t->e[cx.s].t[1].s,
! 2632: t->e[cx.s].p);
! 2633: #endif
! 2634: cx.s = t->e[cx.s].t[1].s;
! 2635: break;
! 2636: case DST_EOL:
! 2637: #if DEBUG
! 2638: if(dbg_g31r_c)fprintf(stderr,"EOL %s1\n",
! 2639: t->e[cx.s].p);
! 2640: if(dbg_g31r_r)fprintf(stderr,"EOL\n");
! 2641: #endif
! 2642: /* start next line expecting a run-code of a fixed color */
! 2643: cx.s = cx.c = g31_first_color;
! 2644: return(&rl);
! 2645: break;
! 2646: default:
! 2647: #if DEBUG
! 2648: if(dbg_g31r_c)fprintf(stderr,"%s%6d %s1\n",
! 2649: (cx.c==DST_white)? "W": "B",
! 2650: t->e[cx.s].t[1].a,
! 2651: t->e[cx.s].p);
! 2652: #endif
! 2653: if(t->e[cx.s].t[1].a<=63) {
! 2654: run += t->e[cx.s].t[1].a;
! 2655: #if DEBUG
! 2656: if(dbg_g31r_r)fprintf(stderr,"%s%6d\n",
! 2657: (cx.c==DST_white)? "W": "B",
! 2658: run);
! 2659: #endif
! 2660: biti += run;
! 2661: if(cx.c==DST_black^g31_negative) {
! 2662: /* end of black run */
! 2663: r->xe = biti-1;
! 2664: r++; rl.runs++;
! 2665: }
! 2666: else { /* end of white run */
! 2667: r->xs = biti;
! 2668: };
! 2669: cx.c = flip_color(cx.c);
! 2670: run = 0;
! 2671: }
! 2672: else run += t->e[cx.s].t[1].a;
! 2673: cx.s = t->e[cx.s].t[1].s;
! 2674: break;
! 2675: };
! 2676: break;
! 2677: case EOF:
! 2678: return(NULL);
! 2679: break;
! 2680: default:
! 2681: return(NULL);
! 2682: break;
! 2683: };
! 2684: /* never come here: return() variously from cases above */
! 2685: }
! 2686:
! 2687: /* Translate a sequence of RLE_Line's (describing a binary image)
! 2688: into a file (a stream of bits) in CCITT FAX Group 3 (1-D) compression format.
! 2689: BOF_to_g31() must be called first; then call rlel_to_g31() for each line
! 2690: (including blank lines); finally, EOF_to_g31() must be called. Each line's
! 2691: EOL and the RTC's first EOL are padded so they end on a byte boundary.
! 2692: */
! 2693: /* debugging flags: trace to stderr */
! 2694: #define dbg_rg31_e (0) /* entry */
! 2695: #define dbg_rg31_r (0) /* runs */
! 2696: #define dbg_rg31_s (0) /* bitstrings */
! 2697:
! 2698: #if DEBUG
! 2699: #define bits_g31(bits) { \
! 2700: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
! 2701: if(dbg_rg31_s) fprintf(stderr,"%s",(bits)); \
! 2702: if(dbg_rg31_r) fprintf(stderr," "); \
! 2703: }
! 2704: #define EOL_g31 { \
! 2705: if(dbg_rg31_r) fprintf(stderr,"EOL "); \
! 2706: bits_g31(EOLSTRING); \
! 2707: if(dbg_rg31_r) fprintf(stderr,"\n"); \
! 2708: }
! 2709: #else
! 2710: #define bits_g31(bits) { \
! 2711: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
! 2712: }
! 2713: #define EOL_g31 { \
! 2714: bits_g31(EOLSTRING); \
! 2715: }
! 2716: #endif
! 2717:
! 2718: BOF_to_g31(f)
! 2719: BITFILE *f; /* state of output bitfile */
! 2720: { char *cs;
! 2721: EOL_g31;
! 2722: }
! 2723:
! 2724: rlel_to_g31(rl,wid,f)
! 2725: RLE_Line *rl; /* line of runs: if NULL, then blank */
! 2726: int wid; /* width of an output line in pixels */
! 2727: BITFILE *f; /* state of output bitfile */
! 2728: { int pi; /* input pixel index on line */
! 2729: RLE_Run *rp,*pp,*sp;
! 2730: int runl,codi;
! 2731: char *cs,*p01;
! 2732: #if DEBUG
! 2733: #define Wrun_g31(rn) { \
! 2734: runl=(rn); \
! 2735: if(dbg_rg31_r) fprintf(stderr,"W %5d ",runl); \
! 2736: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
! 2737: p01=codewht[codi=rtoi(runl)]; bits_g31(p01); \
! 2738: if(codi>=64) {p01=codewht[runl%64]; bits_g31(p01);}; \
! 2739: if(dbg_rg31_r) fprintf(stderr,"\n"); \
! 2740: }
! 2741: #else
! 2742: #define Wrun_g31(rn) { \
! 2743: runl=(rn); \
! 2744: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
! 2745: p01=codewht[codi=rtoi(runl)]; bits_g31(p01); \
! 2746: if(codi>=64) {p01=codewht[runl%64]; bits_g31(p01);}; \
! 2747: }
! 2748: #endif
! 2749: #if DEBUG
! 2750: #define Brun_g31(rn) { \
! 2751: runl=(rn); \
! 2752: if(dbg_rg31_r) fprintf(stderr,"B %5d ",runl); \
! 2753: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
! 2754: p01=codeblk[codi=rtoi(runl)]; bits_g31(p01); \
! 2755: if(codi>=64) {p01=codeblk[runl%64]; bits_g31(p01);}; \
! 2756: if(dbg_rg31_r) fprintf(stderr,"\n"); \
! 2757: }
! 2758:
! 2759: #else
! 2760: #define Brun_g31(rn) { \
! 2761: runl=(rn); \
! 2762: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
! 2763: p01=codeblk[codi=rtoi(runl)]; bits_g31(p01); \
! 2764: if(codi>=64) {p01=codeblk[runl%64]; bits_g31(p01);}; \
! 2765: }
! 2766: #endif
! 2767: #if DEBUG
! 2768: if(dbg_rg31_e) err("rlel_to_g31(rl[y%d,r%d])",rl->y,rl->runs);
! 2769: #endif
! 2770: if(rl!=NULL&&rl->runs>0) {
! 2771: pi=0; /* bit to write next */
! 2772: #if DEBUG
! 2773: if(dbg_rg31_e) err("rlel_to_g31(rl[y%d,r%d])",rl->y,rl->runs);
! 2774: #endif
! 2775: for(sp=(rp=rl->r)+rl->runs; rp<sp; rp++) {
! 2776: Wrun_g31(rp->xs-pi); pi=rp->xs;
! 2777: Brun_g31(rp->xe-pi+1); pi=rp->xe+1;
! 2778: };
! 2779: if((--rp)->xe+1<wid) Wrun_g31(wid-rp->xe-1);
! 2780: }
! 2781: else {
! 2782: #if DEBUG
! 2783: if(dbg_rg31_e) err("rlel_to_g31(rl[y?,r0])");
! 2784: #endif
! 2785: Wrun_g31(wid); /* blank (all-white) scanline */
! 2786: };
! 2787: /* fill so that EOL ends on byte boundary */
! 2788: padb(f,0,8,EOLLENGTH);
! 2789: #if DEBUG
! 2790: if(dbg_rg31_s) fprintf(stderr,"+0?");
! 2791: #endif
! 2792: EOL_g31;
! 2793: }
! 2794:
! 2795: EOF_to_g31(f)
! 2796: BITFILE *f;
! 2797: { char *cs;
! 2798: /* fill so that EOL ends on byte boundary */
! 2799: padb(f,0,8,EOLLENGTH);
! 2800: #if DEBUG
! 2801: if(dbg_rg31_s) fprintf(stderr,"+0?");
! 2802: #endif
! 2803: /* write RTC */
! 2804: EOL_g31;
! 2805: EOL_g31;
! 2806: EOL_g31;
! 2807: EOL_g31;
! 2808: EOL_g31;
! 2809: EOL_g31;
! 2810: }
! 2811:
! 2812: /* Macro for use within g32_to_rlel, to read one 1-D Modified Huffman coded
! 2813: run-length of a given color, placing the result in a given variable.
! 2814: Exceptionally, goto trap_eol, trap_eof, or trap_code_err.
! 2815: */
! 2816: #if DEBUG
! 2817: #define g32_1d_run(C,V) { \
! 2818: run = 0; \
! 2819: do { cx.tr.s = (C); \
! 2820: do { px = cx; \
! 2821: switch(bitv=getb(f)) { \
! 2822: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
! 2823: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
! 2824: case EOF : goto trap_eof; break; \
! 2825: }; \
! 2826: } \
! 2827: while(cx.tr.a==DST_action_NULL); \
! 2828: switch(cx.tr.a) { \
! 2829: case DST_EOL : \
! 2830: if(dbg_g32r_c)fprintf(stderr,"EOL %s\n",EOLSTRING); \
! 2831: goto trap_eol; \
! 2832: break; \
! 2833: case DST_action_ERROR : goto trap_code_err; break; \
! 2834: default : \
! 2835: if(dbg_g32r_c)fprintf(stderr,"%s%6d %s%d\n", \
! 2836: ((C)==DST_white)? "W": "B", \
! 2837: cx.tr.a, \
! 2838: t->e[px.tr.s].p, \
! 2839: bitv); \
! 2840: run += cx.tr.a; \
! 2841: break; \
! 2842: }; \
! 2843: } \
! 2844: while(cx.tr.a>63); \
! 2845: (V) = run; \
! 2846: }
! 2847: #else
! 2848: #define g32_1d_run(C,V) { \
! 2849: run = 0; \
! 2850: do { cx.tr.s = (C); \
! 2851: do { px = cx; \
! 2852: switch(bitv=getb(f)) { \
! 2853: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
! 2854: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
! 2855: case EOF : goto trap_eof; break; \
! 2856: }; \
! 2857: } \
! 2858: while(cx.tr.a==DST_action_NULL); \
! 2859: switch(cx.tr.a) { \
! 2860: case DST_EOL : \
! 2861: goto trap_eol; \
! 2862: break; \
! 2863: case DST_action_ERROR : goto trap_code_err; break; \
! 2864: default : \
! 2865: run += cx.tr.a; \
! 2866: break; \
! 2867: }; \
! 2868: } \
! 2869: while(cx.tr.a>63); \
! 2870: (V) = run; \
! 2871: }
! 2872: #endif
! 2873:
! 2874: /* Translate a stream of bits in CCITT FAX Group 3 (2-D) compression format
! 2875: into a sequence of RLE_Lines. Returns one (RLE_Line *) on each call (or NULL
! 2876: if EOF or error). The first pixel (black or white) in each g32 line is
! 2877: assigned run index 0. */
! 2878: RLE_Line *g32_to_rlel(t,f,bof)
! 2879: DST_table *t;
! 2880: BITFILE *f;
! 2881: boolean bof; /* beginning of file */
! 2882: #define dbg_g32r_e (0) /* entry/exit */
! 2883: #define dbg_g32r_r (0) /* trace each run/EOL/ERR_SYN */
! 2884: #define dbg_g32r_c (0) /* trace each Huffman code (or, fill+EOL)*/
! 2885: #define dbg_g32r_t (0) /* trace each state-transition */
! 2886: #define g32r_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
! 2887: { static RLE_Line rl0,rl1,*prl,*crl; /* prior, current run-lines */
! 2888: RLE_Line *swrl;
! 2889: int bitv; /* the last-read bit value */
! 2890: DST_context cx,px; /* the current/prior decoding context */
! 2891: RLE_Run *cr,*pr,*pre; /* into current/prior rle lines */
! 2892: RLE_Run *pra0; /* rightmost in prior line with xe<=a0 (if none: prl->r) */
! 2893: int run,sync,si,rtc_eols;
! 2894: boolean fill;
! 2895: /* pixel indices (0,1,...): current-line a*; prior-line b*.
! 2896: a0 is the index of the most recently completely encoded bit */
! 2897: int a0,a1,a2,b1,b2;
! 2898: DST_color a0_color; /* a0's color: same as a2 & b2, opposite of a1 & b1 */
! 2899: int a01,a12; /* lengths of runs a0-a1 & a1-a2 */
! 2900: #define g32_first_color DST_white /* color of 1st run in each line */
! 2901: #define g32_negative (0) /* if 1, invert Black/White on output */
! 2902: #define swap_rl(f,b) {swrl=(f); (f)=(b); (b)=swrl;}
! 2903: /* detect b1 & b2: sensitive to a0, a0_color, and prior runs *pr *(pr+1) */
! 2904: #define g32r_find_Bb1Wb2 { \
! 2905: /* find 1st black changing pel>a0 */ \
! 2906: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
! 2907: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
! 2908: /* look beyond pra0 */ \
! 2909: pr=pra0; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
! 2910: /* move b2 to 1st changing white pel > b1 */ \
! 2911: if(pr<pre) b2=pr->xe+1; \
! 2912: else b1=b2=prl->len; \
! 2913: }
! 2914: #define g32r_find_Wb1Bb2 { \
! 2915: /* find 1st white changing pel>a0 */ \
! 2916: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
! 2917: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
! 2918: /* look beyond pra0 */ \
! 2919: pr=pra0; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
! 2920: /* move b2 to 1st changing black pel > b1 */ \
! 2921: if(pr<pre) { \
! 2922: if((pr+1)<pre) b2=(pr+1)->xs; \
! 2923: else b2=prl->len; \
! 2924: } \
! 2925: else b1=b2=prl->len; \
! 2926: }
! 2927: #define g32r_find_b1b2 {if(a0_color==DST_white) g32r_find_Bb1Wb2 else g32r_find_Wb1Bb2;}
! 2928:
! 2929: #if DEBUG
! 2930: if(dbg_g32r_e) fprintf(stderr,"g32_to_rlel(t,bf,bof%d)\n",bof);
! 2931: #endif
! 2932: if(bof){crl= &rl0; crl->y= -1; crl->len=0; crl->runs=0;
! 2933: prl= &rl1; prl->y= -1; prl->len=0; prl->runs=0;
! 2934: /* sync by skipping initial FILL & EOL code */
! 2935: sync=0; while((bitv=getb(f))==0) sync++;
! 2936: if(bitv!=1||sync<11) {
! 2937: #if DEBUG
! 2938: if(dbg_g32r_c) {
! 2939: fprintf(stderr,"BOF_ERR ");
! 2940: for(si=0;si<sync;si++) fprintf(stderr,"0");
! 2941: if(bitv==1) fprintf(stderr,"1\n");
! 2942: else fprintf(stderr,"?\n");
! 2943: };
! 2944: #endif
! 2945: return(NULL);
! 2946: }
! 2947: #if DEBUG
! 2948: else if(dbg_g32r_c){
! 2949: fprintf(stderr,"BOF_EOL ");
! 2950: for(si=0;si<sync;si++) fprintf(stderr,"0");
! 2951: fprintf(stderr,"1\n");
! 2952: };
! 2953: #else
! 2954: ;
! 2955: #endif
! 2956: prl->y = -1; crl->y = 0;
! 2957: }
! 2958: else crl->y = prl->y + 1;
! 2959:
! 2960: pre = (pra0=pr=prl->r) + prl->runs; /* prior line */
! 2961: crl->runs=0; cr=crl->r-1; /* current line */
! 2962: /* start on an imaginary white pixel just to left of margin */
! 2963: a0= -1; a0_color = DST_white;
! 2964:
! 2965: /* check 1-D / 2-D bit immediately after prior EOL */
! 2966: switch(bitv=getb(f)) {
! 2967: case 0 : /* 2-dimensionally encoded line */
! 2968: #if DEBUG
! 2969: if(dbg_g32r_c) fprintf(stderr,"2D_LINE 0\n");
! 2970: #endif
! 2971: /* start b1/b2 on prior line's first black pixel, etc;
! 2972: if none, then place off end of line */
! 2973: if(pr<pre) {b1=pr->xs; b2=pr->xe+1;} else b1=b2=prl->len;
! 2974: /* parse a sequence of 2D codes... */
! 2975: while(T/* exited only via goto trap_* and return */) {
! 2976: cx.tr.s = DST_2d; cx.tr.a = DST_action_NULL;
! 2977: #if DEBUG
! 2978: if(dbg_g32r_t)fprintf(stderr,"(%d,%d)\n",cx.tr.s,cx.tr.a);
! 2979: #endif
! 2980: do { switch(bitv=getb(f)) {
! 2981: case 0 :
! 2982: case 1 :
! 2983: cx.tr=t->e[cx.tr.s].t[bitv];
! 2984: break;
! 2985: case EOF: goto trap_eof; break;
! 2986: };
! 2987: #if DEBUG
! 2988: if(dbg_g32r_t)fprintf(stderr,"%d->(%d,%d)\n",
! 2989: bitv,cx.tr.s,cx.tr.a);
! 2990: #endif
! 2991: }
! 2992: while(cx.tr.a==DST_action_NULL);
! 2993: #if DEBUG
! 2994: if(dbg_g32r_t)fprintf(stderr,"%s %04d %s0\n",
! 2995: (cx.c==DST_white)? "W": "B",
! 2996: cx.tr.s,
! 2997: t->e[cx.tr.s].p);
! 2998: #endif
! 2999: switch(cx.tr.a) {
! 3000: case i2D_V0:
! 3001: #if DEBUG
! 3002: if(dbg_g32r_c)
! 3003: fprintf(stderr,"V0 %s\n",code2d[cx.tr.a]);
! 3004: #endif
! 3005: a1=b1;
! 3006: /* encode a0 to a1-1 */
! 3007: if(a0_color==DST_black) cr->xe=a1-1;
! 3008: /* move a0 to a1 */
! 3009: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3010: a0_color = flip_color(a0_color);
! 3011: /* encode a0 */
! 3012: if(a0_color==DST_black)
! 3013: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3014: #if g32r_strict
! 3015: if(a0==prl->len-1)
! 3016: { a0++; goto trap_expecting_eol; };
! 3017: #endif
! 3018: g32r_find_b1b2;
! 3019: break;
! 3020: case i2D_VR1:
! 3021: #if DEBUG
! 3022: if(dbg_g32r_c)
! 3023: fprintf(stderr,"VR1 %s\n",code2d[cx.tr.a]);
! 3024: #endif
! 3025: a1=b1+1;
! 3026: /* encode a0 to a1-1 */
! 3027: if(a0_color==DST_black) cr->xe=a1-1;
! 3028: /* move a0 to a1 */
! 3029: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3030: a0_color = flip_color(a0_color);
! 3031: /* encode a0 */
! 3032: if(a0_color==DST_black)
! 3033: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3034: #if !g32r_strict
! 3035: if(a0==prl->len-1)
! 3036: { a0++; goto trap_expecting_eol; };
! 3037: #endif
! 3038: g32r_find_b1b2;
! 3039: break;
! 3040: case i2D_VR2:
! 3041: #if DEBUG
! 3042: if(dbg_g32r_c)
! 3043: fprintf(stderr,"VR2 %s\n",code2d[cx.tr.a]);
! 3044: #endif
! 3045: a1=b1+2;
! 3046: /* encode a0 to a1-1 */
! 3047: if(a0_color==DST_black) cr->xe=a1-1;
! 3048: /* move a0 to a1 */
! 3049: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3050: a0_color = flip_color(a0_color);
! 3051: /* encode a0 */
! 3052: if(a0_color==DST_black)
! 3053: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3054: #if !g32r_strict
! 3055: if(a0==prl->len-1)
! 3056: { a0++; goto trap_expecting_eol; };
! 3057: #endif
! 3058: g32r_find_b1b2;
! 3059: break;
! 3060: case i2D_VR3:
! 3061: #if DEBUG
! 3062: if(dbg_g32r_c)
! 3063: fprintf(stderr,"VR3 %s\n",code2d[cx.tr.a]);
! 3064: #endif
! 3065: a1=b1+3;
! 3066: /* encode a0 to a1-1 */
! 3067: if(a0_color==DST_black) cr->xe=a1-1;
! 3068: /* move a0 to a1 */
! 3069: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3070: a0_color = flip_color(a0_color);
! 3071: /* encode a0 */
! 3072: if(a0_color==DST_black)
! 3073: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3074: #if !g32r_strict
! 3075: if(a0==prl->len-1)
! 3076: { a0++; goto trap_expecting_eol; };
! 3077: #endif
! 3078: g32r_find_b1b2;
! 3079: break;
! 3080: case i2D_VL1:
! 3081: #if DEBUG
! 3082: if(dbg_g32r_c)
! 3083: fprintf(stderr,"VL1 %s\n",code2d[cx.tr.a]);
! 3084: #endif
! 3085: if((a1=b1-1)<0) err("g32_to_rlel: VL1 backs up to %d",a1);
! 3086: /* encode a0 to a1-1 */
! 3087: if(a0_color==DST_black) cr->xe=a1-1;
! 3088: /* move a0 to a1 */
! 3089: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3090: a0_color = flip_color(a0_color);
! 3091: /* encode a0 */
! 3092: if(a0_color==DST_black)
! 3093: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3094: #if !g32_strict
! 3095: if(a0==prl->len-1)
! 3096: { a0++; goto trap_expecting_eol; };
! 3097: #endif
! 3098: g32r_find_b1b2;
! 3099: break;
! 3100: case i2D_VL2:
! 3101: #if DEBUG
! 3102: if(dbg_g32r_c)
! 3103: fprintf(stderr,"VL2 %s\n",code2d[cx.tr.a]);
! 3104: #endif
! 3105: if((a1=b1-2)<0) err("g32_to_rlel: VL2 backs up to %d",a1);
! 3106: /* encode a0 to a1-1 */
! 3107: if(a0_color==DST_black) cr->xe=a1-1;
! 3108: /* move a0 to a1 */
! 3109: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3110: a0_color = flip_color(a0_color);
! 3111: /* encode a0 */
! 3112: if(a0_color==DST_black)
! 3113: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3114: #if !g32r_strict
! 3115: if(a0==prl->len-1)
! 3116: { a0++; goto trap_expecting_eol; };
! 3117: #endif
! 3118: g32r_find_b1b2;
! 3119: break;
! 3120: case i2D_VL3:
! 3121: #if DEBUG
! 3122: if(dbg_g32r_c)
! 3123: fprintf(stderr,"VL3 %s\n",code2d[cx.tr.a]);
! 3124: #endif
! 3125: if((a1=b1-3)<0) err("g32_to_rlel: VL3 backs up to %d",a1);
! 3126: /* encode a0 to a1-1 */
! 3127: if(a0_color==DST_black) cr->xe=a1-1;
! 3128: /* move a0 to a1 */
! 3129: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3130: a0_color = flip_color(a0_color);
! 3131: /* encode a0 */
! 3132: if(a0_color==DST_black)
! 3133: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
! 3134: #if !g32r_strict
! 3135: if(a0==prl->len-1)
! 3136: { a0++; goto trap_expecting_eol; };
! 3137: #endif
! 3138: g32r_find_b1b2;
! 3139: break;
! 3140: case i2D_PASS:
! 3141: #if DEBUG
! 3142: if(dbg_g32r_c)
! 3143: fprintf(stderr,"PASS %s\n",code2d[cx.tr.a]);
! 3144: #endif
! 3145: /* move a0 to b2; no change of color */
! 3146: a0=b2; if(a0>=prl->len) goto trap_expecting_eol;
! 3147: if(a0_color==DST_black) cr->xe = a0;
! 3148: #if !g32r_strict
! 3149: if(a0==prl->len-1)
! 3150: { a0++; goto trap_expecting_eol; };
! 3151: #endif
! 3152: g32r_find_b1b2;
! 3153: break;
! 3154: case i2D_HORIZ:
! 3155: #if DEBUG
! 3156: if(dbg_g32r_c)
! 3157: fprintf(stderr,"HORIZ %s\n",code2d[cx.tr.a]);
! 3158: #endif
! 3159: if(a0_color==DST_white) {
! 3160: if(a0<0) a0=0; /* first run in line starts at 0 */
! 3161: g32_1d_run(DST_white,a01); a1 = a0 + a01;
! 3162: g32_1d_run(DST_black,a12); a2 = a1 + a12;
! 3163: if(a12>0) /* Black run of >0 length */ {
! 3164: crl->runs++;
! 3165: (++cr)->xs = a1;
! 3166: cr->xe = a2-1;
! 3167: };
! 3168: a0 = a2; /* still white */
! 3169: if(a0>=prl->len) goto trap_expecting_eol;
! 3170: /* encode a0 */
! 3171: #if !g32r_strict
! 3172: if(a0==prl->len-1)
! 3173: { a0++; goto trap_expecting_eol; };
! 3174: #endif
! 3175: g32r_find_Bb1Wb2;
! 3176: }
! 3177: else { g32_1d_run(DST_black,a01); a1 = a0 + a01;
! 3178: g32_1d_run(DST_white,a12); a2 = a1 + a12;
! 3179: if(a01>0) /* Black run of >0 length */ {
! 3180: cr->xe = a1 - 1;
! 3181: }
! 3182: else { /* 0-length: very peculiar: ignore */
! 3183: fprintf(stderr,
! 3184: "g32_to_rlel: HORIZ B%d! W%d - ignore\n",
! 3185: a01,a12);
! 3186: cr--; crl->runs--;
! 3187: };
! 3188: a0 = a2; /* still black */
! 3189: if(a0>=prl->len) goto trap_expecting_eol;
! 3190: /* encode a0 */
! 3191: crl->runs++; (++cr)->xs = a0;
! 3192: #if !g32r_strict
! 3193: if(a0==prl->len-1) {
! 3194: cr->xe = a0;
! 3195: a0++;
! 3196: goto trap_expecting_eol;
! 3197: };
! 3198: #endif
! 3199: g32r_find_Wb1Bb2;
! 3200: };
! 3201: break;
! 3202: case i2D_EOL:
! 3203: #if DEBUG
! 3204: if(dbg_g32r_c)
! 3205: fprintf(stderr,"EOL %s\n",code2d[cx.tr.a]);
! 3206: #endif
! 3207: goto trap_eol;
! 3208: break;
! 3209: case DST_action_ERROR: goto trap_code_err; break;
! 3210: };
! 3211: };
! 3212: break;
! 3213: case 1 : /* 1-dimensionally encoded line */
! 3214: #if DEBUG
! 3215: if(dbg_g32r_c) fprintf(stderr,"1D_LINE 1\n");
! 3216: #endif
! 3217: /* read a sequence of 1-D runcodes... */
! 3218: while(T/* exit only via goto trap_X */) {
! 3219: g32_1d_run(a0_color,a01);
! 3220: a1 = ((a0>=0)? a0 : 0) + a01;
! 3221: if(a01>0) {
! 3222: /* encode a0 through a1-1 */
! 3223: if(a0_color==DST_black^g32_negative) {
! 3224: /* output-black run */
! 3225: crl->runs++;
! 3226: (++cr)->xs=((a0>=0)? a0 : 0);
! 3227: cr->xe=a1-1;
! 3228: };
! 3229: };
! 3230: a0=a1;
! 3231: a0_color=flip_color(a0_color);
! 3232: if(prl->len>0 && a0>=prl->len) goto trap_expecting_eol;
! 3233: };
! 3234: break;
! 3235: case EOF : goto trap_eof; break;
! 3236: };
! 3237:
! 3238: /* come here via goto's: all these traps return() */
! 3239:
! 3240: trap_expecting_eol: /* come here expecting to see EOL or FILL+EOL */
! 3241: sync=0; while((bitv=getb(f))==0) sync++;
! 3242: switch(bitv) {
! 3243: case 1:
! 3244: if(sync==11) {
! 3245: #if DEBUG
! 3246: if(dbg_g32r_c){
! 3247: fprintf(stderr,"EOL %s\n",EOLSTRING);
! 3248: };
! 3249: #endif
! 3250: goto trap_eol;
! 3251: }
! 3252: else if(sync>11) {
! 3253: #if DEBUG
! 3254: if(dbg_g32r_c){
! 3255: fprintf(stderr,"FILLEOL ");
! 3256: for(si=0;si<sync-11;si++) fprintf(stderr,"0");
! 3257: fprintf(stderr,"+");
! 3258: fprintf(stderr,"%s\n",EOLSTRING);
! 3259: };
! 3260: #endif
! 3261: goto trap_eol;
! 3262: }
! 3263: else {
! 3264: #if DEBUG
! 3265: if(dbg_g32r_c){
! 3266: fprintf(stderr,"NOT EOL ");
! 3267: for(si=0;si<sync;si++) fprintf(stderr,"0");
! 3268: fprintf(stderr,"1?");
! 3269: };
! 3270: #endif
! 3271: sync=0;
! 3272: goto trap_eol_err;
! 3273: };
! 3274: break;
! 3275: case EOF: goto trap_eof; break;
! 3276: };
! 3277: goto trap_eol;
! 3278:
! 3279: trap_code_err:
! 3280: /* unexpected coding sequence:
! 3281: 'px' holds last decoding context & 'bitv' latest bit value;
! 3282: will attempt to resynchronize on next EOL */
! 3283: #if DEBUG
! 3284: if(dbg_g32r_c)fprintf(stderr,"CODERR %s%d?",
! 3285: t->e[px.tr.s].p,bitv);
! 3286: #endif
! 3287: /* count trailing 0's so far (should be in table) */
! 3288: #if !NEW_TRAIL
! 3289: if(bitv==0) sync=1; else sync=0;
! 3290: si=strlen(t->e[px.tr.s].p)-1;
! 3291: while(si>=0&&t->e[px.tr.s].p[si]=='0') {sync++; si--;};
! 3292: fill = (si<0); /* all 0's: may be fill bits */
! 3293: #else
! 3294: if(bitv==0) sync=t->e[px.tr.s].z+1; else sync=t->e[px.tr.s].z;
! 3295: fill = (sync>t->e[px.tr.s].l); /* all 0's: maybe fill bits */
! 3296: #endif
! 3297: #if DEBUG
! 3298: if(dbg_trail)err("sync %d fill %d",sync,fill);
! 3299: #endif
! 3300: trap_eol_err:
! 3301: while(sync<11) {
! 3302: switch(bitv=getb(f)) {
! 3303: case 0: sync++;
! 3304: #if DEBUG
! 3305: if(dbg_g32r_c) fprintf(stderr,"0");
! 3306: #endif
! 3307: break;
! 3308: case 1: sync=0;
! 3309: #if DEBUG
! 3310: if(dbg_g32r_c) fprintf(stderr,"1");
! 3311: #endif
! 3312: break;
! 3313: case EOF: goto trap_eof; break;
! 3314: };
! 3315: };
! 3316: /* next `1' will synchronize */
! 3317: do { switch(bitv=getb(f)) {
! 3318: case 0:
! 3319: #if DEBUG
! 3320: if(dbg_g32r_c) fprintf(stderr,"0");
! 3321: #endif
! 3322: break;
! 3323: case 1:
! 3324: #if DEBUG
! 3325: if(dbg_g32r_c) fprintf(stderr,"1");
! 3326: #endif
! 3327: break;
! 3328: case EOF: goto trap_eof; break;
! 3329: };
! 3330: }
! 3331: while(bitv!=1);
! 3332: #if DEBUG
! 3333: if(dbg_g32r_c) fprintf(stderr," EOL\n");
! 3334: #endif
! 3335: goto trap_eol;
! 3336:
! 3337: trap_eol: /* come here having seen (and reported) EOL */
! 3338: /* learn/check line-length */
! 3339: if(a0>=0) crl->len=a0; else crl->len=0;
! 3340: if(crl->len==0) {
! 3341: /* no pixels coded -- may be the 1st of 6 RTC EOLs */
! 3342: /* check suffix 1 bit */
! 3343: if((bitv=getb(f))!=1) goto trap_eol_err;
! 3344: rtc_eols=1;
! 3345: #if DEBUG
! 3346: if(dbg_g32r_c)fprintf(stderr,"RTC_EOL +1 (%d)\n",rtc_eols);
! 3347: #endif
! 3348: do { sync=0; while((bitv=getb(f))==0) sync++;
! 3349: switch(bitv) {
! 3350: case 1:
! 3351: if(sync<11) {
! 3352: #if DEBUG
! 3353: if(dbg_g32r_c){
! 3354: fprintf(stderr,"NOT RTC ");
! 3355: for(si=0;si<sync;si++)
! 3356: fprintf(stderr,"0");
! 3357: fprintf(stderr,"1?\n");
! 3358: };
! 3359: #endif
! 3360: sync=0;
! 3361: goto trap_eol_err;
! 3362: };
! 3363: break;
! 3364: case EOF: goto trap_eof; break;
! 3365: };
! 3366: /* check suffix 1 bit */
! 3367: if((bitv=getb(f))!=1) goto trap_eol_err;
! 3368: rtc_eols++;
! 3369: #if DEBUG
! 3370: if(dbg_g32r_c) {
! 3371: fprintf(stderr,"RTC_EOL ");
! 3372: for(si=0;si<sync;si++) fprintf(stderr,"0");
! 3373: fprintf(stderr,"1+1 (%d)\n",rtc_eols);
! 3374: };
! 3375: #endif
! 3376: }
! 3377: while(rtc_eols<6);
! 3378: /* normal RTC */
! 3379: #if DEBUG
! 3380: if(dbg_g32r_c)fprintf(stderr,"RTC\n");
! 3381: #endif
! 3382: return(NULL);
! 3383: }
! 3384: else if(prl->len==0) {
! 3385: #if DEBUG
! 3386: if(dbg_g32r_c)fprintf(stderr,"LINELEN %d\n",crl->len);
! 3387: #endif
! 3388: }
! 3389: else if(crl->len!=prl->len) {
! 3390: err("g32_to_rlel: y%d: LINELEN changes c%d != p%d ? (force to %d)",
! 3391: crl->y,crl->len,prl->len,prl->len);
! 3392: crl->len = prl->len;
! 3393: };
! 3394: swap_rl(crl,prl);
! 3395: return(prl);
! 3396:
! 3397: trap_eof:
! 3398: #if DEBUG
! 3399: if(dbg_g32r_c) fprintf(stderr,"<EOF>\n");
! 3400: #endif
! 3401: return(NULL);
! 3402:
! 3403: }
! 3404:
! 3405: /* Translate a sequence of RLE_Line's (describing a binary image)
! 3406: into a file (a stream of bits) in CCITT FAX Group 3 (2-D) compression format.
! 3407: BOF_to_g32() must be called first; then call rlel_to_g32() for each line
! 3408: (including blank lines); finally, EOF_to_g32() must be called. Each line's
! 3409: EOL and the RTC's first EOL will be padded so they end on a byte boundary.
! 3410: */
! 3411: /* debugging flags: trace to stderr */
! 3412: #define dbg_rg32_e (0) /* entry */
! 3413: #define dbg_rg32_r (0) /* runs */
! 3414: #define dbg_rg32_s (0) /* bitstrings */
! 3415: #define rg32_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
! 3416:
! 3417: #if DEBUG
! 3418: #define bits_g32(bits) { \
! 3419: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
! 3420: if(dbg_rg32_s) fprintf(stderr,"%s",(bits)); \
! 3421: if(dbg_rg32_r) fprintf(stderr," "); \
! 3422: }
! 3423: #else
! 3424: #define bits_g32(bits) { \
! 3425: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
! 3426: }
! 3427: #endif
! 3428: #if DEBUG
! 3429: #define EOL_g32 { \
! 3430: if(dbg_rg32_r) fprintf(stderr,"EOL "); \
! 3431: bits_g32(EOLSTRING); \
! 3432: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3433: }
! 3434: #else
! 3435: #define EOL_g32 { \
! 3436: bits_g32(EOLSTRING); \
! 3437: }
! 3438: #endif
! 3439:
! 3440: BOF_to_g32(f)
! 3441: BITFILE *f;
! 3442: { char *cs;
! 3443: /* a NOP: no header for Group 3 (2-D) */
! 3444: #if DEBUG
! 3445: if(dbg_rg32_e) fprintf(stderr,"BOF\n");
! 3446: #endif
! 3447: };
! 3448:
! 3449: rlel_to_g32(pl,cl,wid,f)
! 3450: RLE_Line *pl; /* prior "reference" line: if NULL, use 1-D coding on cl */
! 3451: RLE_Line *cl; /* current "coding" line: if NULL, is blank (all white) */
! 3452: int wid; /* width of an output line in pixels */
! 3453: BITFILE *f;
! 3454: { int runl,codi;
! 3455: char *cs,*p01;
! 3456: #if DEBUG
! 3457: #define Wrun_g32(rn) { \
! 3458: runl=(rn); \
! 3459: if(dbg_rg32_r) fprintf(stderr,"W %5d ",runl); \
! 3460: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
! 3461: p01=codewht[codi=rtoi(runl)]; bits_g32(p01); \
! 3462: if(codi>=64) {p01=codewht[runl%64]; bits_g32(p01);}; \
! 3463: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3464: }
! 3465: #else
! 3466: #define Wrun_g32(rn) { \
! 3467: runl=(rn); \
! 3468: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
! 3469: p01=codewht[codi=rtoi(runl)]; bits_g32(p01); \
! 3470: if(codi>=64) {p01=codewht[runl%64]; bits_g32(p01);}; \
! 3471: }
! 3472: #endif
! 3473: #if DEBUG
! 3474: #define Brun_g32(rn) { \
! 3475: runl=(rn); \
! 3476: if(dbg_rg32_r) fprintf(stderr,"B %5d ",runl); \
! 3477: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
! 3478: p01=codeblk[codi=rtoi(runl)]; bits_g32(p01); \
! 3479: if(codi>=64) {p01=codeblk[runl%64]; bits_g32(p01);}; \
! 3480: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3481: }
! 3482: #else
! 3483: #define Brun_g32(rn) { \
! 3484: runl=(rn); \
! 3485: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
! 3486: p01=codeblk[codi=rtoi(runl)]; bits_g32(p01); \
! 3487: if(codi>=64) {p01=codeblk[runl%64]; bits_g32(p01);}; \
! 3488: }
! 3489: #endif
! 3490: #if DEBUG
! 3491: #define V0_g32 { \
! 3492: if(dbg_rg32_r) fprintf(stderr,"V0 "); \
! 3493: bits_g32(code2d[i2D_V0]); \
! 3494: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3495: }
! 3496: #else
! 3497: #define V0_g32 { \
! 3498: bits_g32(code2d[i2D_V0]); \
! 3499: }
! 3500: #endif
! 3501: #if DEBUG
! 3502: #define VR1_g32 { \
! 3503: if(dbg_rg32_r) fprintf(stderr,"VR1 "); \
! 3504: bits_g32(code2d[i2D_VR1]); \
! 3505: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3506: }
! 3507: #else
! 3508: #define VR1_g32 { \
! 3509: bits_g32(code2d[i2D_VR1]); \
! 3510: }
! 3511: #endif
! 3512: #if DEBUG
! 3513: #define VR2_g32 { \
! 3514: if(dbg_rg32_r) fprintf(stderr,"VR2 "); \
! 3515: bits_g32(code2d[i2D_VR2]); \
! 3516: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3517: }
! 3518: #else
! 3519: #define VR2_g32 { \
! 3520: bits_g32(code2d[i2D_VR2]); \
! 3521: }
! 3522: #endif
! 3523: #if DEBUG
! 3524: #define VR3_g32 { \
! 3525: if(dbg_rg32_r) fprintf(stderr,"VR3 "); \
! 3526: bits_g32(code2d[i2D_VR3]); \
! 3527: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3528: }
! 3529: #else
! 3530: #define VR3_g32 { \
! 3531: bits_g32(code2d[i2D_VR3]); \
! 3532: }
! 3533: #endif
! 3534: #if DEBUG
! 3535: #define VL1_g32 { \
! 3536: if(dbg_rg32_r) fprintf(stderr,"VL1 "); \
! 3537: bits_g32(code2d[i2D_VL1]); \
! 3538: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3539: }
! 3540: #else
! 3541: #define VL1_g32 { \
! 3542: bits_g32(code2d[i2D_VL1]); \
! 3543: }
! 3544: #endif
! 3545: #if DEBUG
! 3546: #define VL2_g32 { \
! 3547: if(dbg_rg32_r) fprintf(stderr,"VL2 "); \
! 3548: bits_g32(code2d[i2D_VL2]); \
! 3549: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3550: }
! 3551: #else
! 3552: #define VL2_g32 { \
! 3553: bits_g32(code2d[i2D_VL2]); \
! 3554: }
! 3555: #endif
! 3556: #if DEBUG
! 3557: #define VL3_g32 { \
! 3558: if(dbg_rg32_r) fprintf(stderr,"VL3 "); \
! 3559: bits_g32(code2d[i2D_VL3]); \
! 3560: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3561: }
! 3562: #else
! 3563: #define VL3_g32 { \
! 3564: bits_g32(code2d[i2D_VL3]); \
! 3565: }
! 3566: #endif
! 3567: #if DEBUG
! 3568: #define PASS_g32 { \
! 3569: if(dbg_rg32_r) fprintf(stderr,"PASS "); \
! 3570: bits_g32(code2d[i2D_PASS]); \
! 3571: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3572: }
! 3573: #else
! 3574: #define PASS_g32 { \
! 3575: bits_g32(code2d[i2D_PASS]); \
! 3576: }
! 3577: #endif
! 3578: #if DEBUG
! 3579: #define HORIZ_g32 { \
! 3580: if(dbg_rg32_r) fprintf(stderr,"HORIZ "); \
! 3581: bits_g32(code2d[i2D_HORIZ]); \
! 3582: if(dbg_rg32_r) fprintf(stderr,"\n"); \
! 3583: }
! 3584: #else
! 3585: #define HORIZ_g32 { \
! 3586: bits_g32(code2d[i2D_HORIZ]); \
! 3587: }
! 3588: #endif
! 3589: #define detect_a1a2_BW { \
! 3590: /* find leftmost black changing pel > a0 */ \
! 3591: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
! 3592: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
! 3593: /* look beyond cra, until cr->xs>a0 */ \
! 3594: cr=cra; while(cr<cre && (a1=cr->xs)<=a0) cr++; \
! 3595: if(cr<cre) a2=cr->xe+1; \
! 3596: else a1=a2=wid; \
! 3597: }
! 3598: #define detect_a1a2_WB { \
! 3599: /* find leftmost white changing pel > a0 */ \
! 3600: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
! 3601: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
! 3602: /* look beyond cra, until cr->xe+1>a0 */ \
! 3603: cr=cra; while(cr<cre && (a1=cr->xe+1)<=a0) cr++; \
! 3604: if(cr<cre) { \
! 3605: if((cr+1)<cre) a2=(cr+1)->xs; \
! 3606: else a2=wid; \
! 3607: } \
! 3608: else a1=a2=wid; \
! 3609: }
! 3610: #define detect_a1a2 {if(a0_color==DST_white) detect_a1a2_BW else detect_a1a2_WB;}
! 3611: #define detect_b1b2_BW {\
! 3612: /* find leftmost black changing pel > a0 */ \
! 3613: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
! 3614: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
! 3615: /* look beyond pra */ \
! 3616: pr=pra; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
! 3617: /* move b2 to 1st changing white pel > b1 */ \
! 3618: if(pr<pre) b2=pr->xe+1; \
! 3619: else b1=b2=wid; \
! 3620: }
! 3621: #define detect_b1b2_WB {\
! 3622: /* find leftmost white changing pel > a0 */ \
! 3623: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
! 3624: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
! 3625: /* look beyond pra */ \
! 3626: pr=pra; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
! 3627: /* move b2 to 1st changing black pel > b1 */ \
! 3628: if(pr<pre) { \
! 3629: if((pr+1)<pre) b2=(pr+1)->xs; \
! 3630: else b2=wid; \
! 3631: } \
! 3632: else b1=b2=wid; \
! 3633: }
! 3634: #define detect_b1b2 {if(a0_color==DST_white) detect_b1b2_BW else detect_b1b2_WB;}
! 3635:
! 3636: #if DEBUG
! 3637: if(dbg_rg32_e) err("rlel_to_g32(pl[%d],cl[%d],w%d)",
! 3638: (pl==NULL)? -1: pl->runs,
! 3639: (cl==NULL)? -1: cl->runs,
! 3640: wid);
! 3641: #endif
! 3642: /* fill so that EOL ends on byte boundary */
! 3643: padb(f,0,8,EOLLENGTH);
! 3644: #if DEBUG
! 3645: if(dbg_rg32_s) fprintf(stderr,"FILL +0?");
! 3646: #endif
! 3647: EOL_g32; /* begin with EOL (sic) */
! 3648: if(pl==NULL) /* use 1-D coding for *cl */ {
! 3649: int pi; /* input pixel index on line */
! 3650: RLE_Run *rp,*pp,*sp;
! 3651: putb(1,f);
! 3652: #if DEBUG
! 3653: if(dbg_rg32_r) fprintf(stderr,"1D_LINE 1\n");
! 3654: #endif
! 3655: if(cl!=NULL&&cl->runs>0) {
! 3656: pi=0; /* bit to write next */
! 3657: for(sp=(rp=cl->r)+cl->runs; rp<sp; rp++) {
! 3658: Wrun_g32(rp->xs-pi); pi=rp->xs;
! 3659: Brun_g32(rp->xe-pi+1); pi=rp->xe+1;
! 3660: };
! 3661: if((--rp)->xe+1<wid) Wrun_g32(wid-rp->xe-1);
! 3662: }
! 3663: else Wrun_g32(wid); /* blank scanline */
! 3664: }
! 3665: else /* use 2-D coding for *cl */ {
! 3666: RLE_Run *cr,*cre,*pr,*pre; /* into current/prior rle lines */
! 3667: int a0,a1,a2,b1,b2; /* indices {0,1,...} of pixels */
! 3668: DST_color a0_color; /* a0's color: same as a2 & b2, opp of a1 & b1 */
! 3669: RLE_Run *cra; /* rightmost in current st xe<=a0 (none: ==cl->r) */
! 3670: RLE_Run *pra; /* rightmost in prior st xe<=a0 (none: ==pl->r) */
! 3671: int a01,a12,a1b1; /* lengths of runs a0-a1 a1-a2 a1-b1 */
! 3672: putb(0,f);
! 3673: #if DEBUG
! 3674: if(dbg_rg32_r) fprintf(stderr,"2D_LINE 0\n");
! 3675: #endif
! 3676: /* start on an imaginary white pixel just to left of margin */
! 3677: a0= -1; a0_color = DST_white;
! 3678: pre = (pra=pl->r) + pl->runs; /* prior line's runs */
! 3679: /* start b1/b2 on prior line's first black pixel, etc;
! 3680: if none, then place off end of line */
! 3681: if(pra<pre) {b1=pra->xs; b2=pra->xe+1;} else b1=b2=wid;
! 3682: if(cl!=NULL&&cl->runs>0) {
! 3683: cre = (cra=cl->r) + cl->runs;
! 3684: a1=cra->xs; a2=cra->xe+1;
! 3685: #if rg32_strict
! 3686: while(a0 < wid) {
! 3687: #else
! 3688: while(a0 < wid-1) {
! 3689: #endif
! 3690: /* a0, a1, a2, b1, b2 are as in CCITT Rec T.4 */
! 3691: #if DEBUG
! 3692: if(dbg_rg32_r)
! 3693: fprintf(stderr,"f%d(%d,%d,%d) b%d(%d,%d)\n",
! 3694: cra-(cl->r),a0,a1,a2,pra-(pl->r),b1,b2);
! 3695: #endif
! 3696: if(b2<a1) /* PASS mode */ {
! 3697: PASS_g32;
! 3698: a0=b2;
! 3699: /* a0-color, a1, & a2 are unchanged */
! 3700: detect_b1b2;
! 3701: }
! 3702: else if((a1b1=(a1-b1))<=3 && a1b1>= -3) {
! 3703: /* VERTICAL mode */
! 3704: switch(a1b1) {
! 3705: case -3: VL3_g32; break;
! 3706: case -2: VL2_g32; break;
! 3707: case -1: VL1_g32; break;
! 3708: case 0: V0_g32; break;
! 3709: case 1: VR1_g32; break;
! 3710: case 2: VR2_g32; break;
! 3711: case 3: VR3_g32; break;
! 3712: };
! 3713: a0=a1; a0_color=flip_color(a0_color);
! 3714: detect_a1a2;
! 3715: detect_b1b2;
! 3716: }
! 3717: else { /* HORIZONTAL mode */
! 3718: HORIZ_g32;
! 3719: a01=a1-a0; if(a0== -1) a01--;
! 3720: a12=a2-a1;
! 3721: if(a0_color==DST_white) {
! 3722: Wrun_g32(a01);
! 3723: Brun_g32(a12);
! 3724: }
! 3725: else { Brun_g32(a01);
! 3726: Wrun_g32(a12);
! 3727: };
! 3728: a0=a2;
! 3729: /* a0_color is unchanged */
! 3730: detect_a1a2;
! 3731: detect_b1b2;
! 3732: };
! 3733: };
! 3734: }
! 3735: else /* current line is blank */ {
! 3736: a1=a2=wid;
! 3737: #if rg32_strict
! 3738: while(a0 < wid) {
! 3739: #else
! 3740: while(a0 < wid-1) {
! 3741: #endif
! 3742: /* a0, a1, a2, b1, b2 are as in CCITT Rec. T.4 */
! 3743: #if DEBUG
! 3744: if(dbg_rg32_r)
! 3745: fprintf(stderr,"f(%d,%d,%d) b%d(%d,%d)\n",
! 3746: a0,a1,a2,pra-(pl->r),b1,b2);
! 3747: #endif
! 3748: if(b2<a1) /* PASS mode */ {
! 3749: PASS_g32;
! 3750: a0=b2;
! 3751: /* a0-color, a1, & a2 are unchanged */
! 3752: detect_b1b2;
! 3753: }
! 3754: else if((a1b1=a1-b1)<=3 && a1b1>= -3) {
! 3755: /* VERTICAL mode */
! 3756: switch(a1b1) {
! 3757: case -3: VL3_g32; break;
! 3758: case -2: VL2_g32; break;
! 3759: case -1: VL1_g32; break;
! 3760: case 0: V0_g32; break;
! 3761: case 1: VR1_g32; break;
! 3762: case 2: VR2_g32; break;
! 3763: case 3: VR3_g32; break;
! 3764: };
! 3765: a0=a1; a0_color=flip_color(a0_color);
! 3766: /* a1, & a2 are unchanged */
! 3767: detect_b1b2;
! 3768: }
! 3769: else { /* HORIZONTAL mode */
! 3770: HORIZ_g32;
! 3771: a01=a1-a0; if(a0== -1) a01--;
! 3772: a12=a2-a1;
! 3773: if(a0_color==DST_white) {
! 3774: Wrun_g32(a01);
! 3775: Brun_g32(a12);
! 3776: }
! 3777: else { Brun_g32(a01);
! 3778: Wrun_g32(a12);
! 3779: };
! 3780: a0=a2;
! 3781: /* a0_color, a1, & a2 are unchanged */
! 3782: detect_b1b2;
! 3783: };
! 3784: };
! 3785: };
! 3786: };
! 3787: }
! 3788:
! 3789: EOF_to_g32(f)
! 3790: BITFILE *f;
! 3791: { char *cs;
! 3792: padb(f,0,8,EOLLENGTH); /* fill so that EOL ends on byte boundary */
! 3793: #if DEBUG
! 3794: if(dbg_rg32_s) fprintf(stderr,"FILL +0?");
! 3795: #endif
! 3796: /* write RTC */
! 3797: EOL_g32;
! 3798: EOL_g32;
! 3799: EOL_g32;
! 3800: EOL_g32;
! 3801: EOL_g32;
! 3802: EOL_g32;
! 3803: #if DEBUG
! 3804: if(dbg_rg32_e) fprintf(stderr,"EOF\n");
! 3805: #endif
! 3806: }
! 3807:
! 3808: /* Macro for use within g4_to_rlel, to read one 1-D Modified Huffman coded
! 3809: run-length of color C, placing the result in variable V.
! 3810: Exceptionally, goto trap_eol, trap_eof, or trap_code_err.
! 3811: */
! 3812: #if DEBUG
! 3813: #define g4_1d_run(C,V) { \
! 3814: run = 0; \
! 3815: do { cx.tr.s = (C); \
! 3816: do { px = cx; \
! 3817: switch(bitv=getb(f)) { \
! 3818: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
! 3819: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
! 3820: case EOF : goto trap_eof; break; \
! 3821: }; \
! 3822: } \
! 3823: while(cx.tr.a==DST_action_NULL); \
! 3824: switch(cx.tr.a) { \
! 3825: case DST_EOL : \
! 3826: if(dbg_g4r_c)fprintf(stderr,"EOL %s\n",EOLSTRING); \
! 3827: goto trap_eol; \
! 3828: break; \
! 3829: case DST_action_ERROR : goto trap_code_err; break; \
! 3830: default : \
! 3831: if(dbg_g4r_c)fprintf(stderr,"%s%6d %s%d\n", \
! 3832: ((C)==DST_white)? "W": "B", \
! 3833: cx.tr.a, \
! 3834: t->e[px.tr.s].p, \
! 3835: bitv); \
! 3836: run += cx.tr.a; \
! 3837: break; \
! 3838: }; \
! 3839: } \
! 3840: while(cx.tr.a>63); \
! 3841: (V) = run; \
! 3842: }
! 3843: #else
! 3844: #define g4_1d_run(C,V) { \
! 3845: run = 0; \
! 3846: do { cx.tr.s = (C); \
! 3847: do { px = cx; \
! 3848: switch(bitv=getb(f)) { \
! 3849: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
! 3850: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
! 3851: case EOF : goto trap_eof; break; \
! 3852: }; \
! 3853: } \
! 3854: while(cx.tr.a==DST_action_NULL); \
! 3855: switch(cx.tr.a) { \
! 3856: case DST_EOL : \
! 3857: goto trap_eol; \
! 3858: break; \
! 3859: case DST_action_ERROR : goto trap_code_err; break; \
! 3860: default : \
! 3861: run += cx.tr.a; \
! 3862: break; \
! 3863: }; \
! 3864: } \
! 3865: while(cx.tr.a>63); \
! 3866: (V) = run; \
! 3867: }
! 3868: #endif
! 3869:
! 3870: /* Translate a stream of bits in CCITT FAX Group 4 compression format, of known
! 3871: fixed line-length, into a sequence of RLE_Lines. Returns one (RLE_Line *)
! 3872: on each call (or NULL if EOF or error). The first pixel (black or white)
! 3873: in each g4 line is assigned run index 0.
! 3874: WARNING: the RLE_Line returned must NOT be modified by the caller, since
! 3875: it is used to decode the next line. */
! 3876: RLE_Line *g4_to_rlel(t,f,bof,len)
! 3877: DST_table *t;
! 3878: BITFILE *f;
! 3879: boolean bof; /* beginning of file */
! 3880: int len; /* line-length in pixels (used only on bof) */
! 3881: #define dbg_g4r_e (0) /* trace entry-to / exit-from function */
! 3882: #define dbg_g4r_r (0) /* trace each run/EOL/ERR_SYN */
! 3883: #define dbg_g4r_c (0) /* trace each Huffman code (or, fill+EOL)*/
! 3884: #define dbg_g4r_t (0) /* trace each state-transition */
! 3885: #define g4r_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
! 3886: { static RLE_Line rl0,rl1,*prl,*crl; /* prior, current run-lines */
! 3887: RLE_Line *swrl;
! 3888: int bitv; /* the last-read bit value */
! 3889: DST_context cx,px; /* the current/prior decoding context */
! 3890: RLE_Run *cr,*pr,*pre; /* into current/prior rle lines */
! 3891: RLE_Run *pra0; /* rightmost in prior line with xe<=a0
! 3892: (if none: prl->r) */
! 3893: int run,sync,si,rtc_eols;
! 3894: /* pixel indices (0,1,...): current-line a*; prior-line b*.
! 3895: a0 is the index of the most recently completely encoded bit */
! 3896: int a0,a1,a2,b1,b2;
! 3897: DST_color a0_color; /* a0's color: same as a2 & b2, opposite of a1 & b1 */
! 3898: int a01,a12; /* lengths of runs a0-a1 & a1-a2 */
! 3899: #define g4_first_color (DST_white) /* color of 1st run in each line */
! 3900: #define g4_negative (0) /* if 1, invert Black/White on output */
! 3901: #define swap_rl(f,b) {swrl=(f); (f)=(b); (b)=swrl;}
! 3902: /* detect b1 & b2: sensitive to a0, a0_color, and prior runs *pr *(pr+1) */
! 3903: #define g4r_find_Bb1Wb2 { \
! 3904: /* find 1st black changing pel>a0 */ \
! 3905: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
! 3906: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
! 3907: /* look beyond pra0 */ \
! 3908: pr=pra0; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
! 3909: /* move b2 to 1st changing white pel > b1 */ \
! 3910: if(pr<pre) b2=pr->xe+1; \
! 3911: else b1=b2=prl->len; \
! 3912: }
! 3913: #define g4r_find_Wb1Bb2 { \
! 3914: /* find 1st white changing pel>a0 */ \
! 3915: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
! 3916: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
! 3917: /* look beyond pra0 */ \
! 3918: pr=pra0; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
! 3919: /* move b2 to 1st changing black pel > b1 */ \
! 3920: if(pr<pre) { \
! 3921: if((pr+1)<pre) b2=(pr+1)->xs; \
! 3922: else b2=prl->len; \
! 3923: } \
! 3924: else b1=b2=prl->len; \
! 3925: }
! 3926: #define g4r_find_b1b2 { \
! 3927: if(a0_color==DST_white) g4r_find_Bb1Wb2 else g4r_find_Wb1Bb2; \
! 3928: if(b1<=a0) err("g4_to_rlel: y%d: b1 %d <= a0 %d ?",crl->y,a0,b1); \
! 3929: }
! 3930:
! 3931: if(bof){/* initial reference line is all white, of known length */
! 3932: prl= &rl0; prl->y= -1; prl->len=len; prl->runs=0;
! 3933: /* initial coding line has y-coordinate 0 */
! 3934: crl= &rl1; crl->y=0; crl->len=0; crl->runs=0;
! 3935: }
! 3936: else crl->y = prl->y + 1;
! 3937: #if DEBUG
! 3938: if(dbg_g4r_e)
! 3939: fprintf(stderr,
! 3940: "g4_to_rlel(t,f,bof%d,len%d) y%d,l%d\n",
! 3941: bof,len,prl->y,prl->len);
! 3942: #endif
! 3943:
! 3944: pre = (pra0=pr=prl->r) + prl->runs; /* prior line */
! 3945: crl->runs=0; cr=crl->r-1; /* current line */
! 3946: /* start on an imaginary white pixel just to left of margin */
! 3947: a0= -1; a0_color = DST_white;
! 3948: #if DEBUG
! 3949: a1=a2=b1=b2=0; /* immaterial; looks better when debugging */
! 3950: #endif
! 3951:
! 3952: /* start b1/b2 on prior line's first black pixel, etc;
! 3953: if none, then place off end of line */
! 3954: if(pr<pre) {b1=pr->xs; b2=pr->xe+1;} else b1=b2=prl->len;
! 3955: /* parse a sequence of 2D codes... */
! 3956: while(T/* exit only via 'goto trap_X' */) {
! 3957: /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
! 3958: #if DEBUG
! 3959: if(dbg_g4r_r)
! 3960: fprintf(stderr,"a(%d,%d,%d) b(%d,%d)\n",a0,a1,a2,b1,b2);
! 3961: #endif
! 3962: cx.tr.s = DST_2d; cx.tr.a = DST_action_NULL;
! 3963: #if DEBUG
! 3964: if(dbg_g4r_t)fprintf(stderr,"(%d,%d)\n",cx.tr.s,cx.tr.a);
! 3965: #endif
! 3966: do { switch(bitv=getb(f)) {
! 3967: case 0 :
! 3968: case 1 :
! 3969: cx.tr=t->e[cx.tr.s].t[bitv];
! 3970: break;
! 3971: case EOF: goto trap_eof; break;
! 3972: };
! 3973: #if DEBUG
! 3974: if(dbg_g4r_t)fprintf(stderr,"%d->(%d,%d)\n",
! 3975: bitv,cx.tr.s,cx.tr.a);
! 3976: #endif
! 3977: }
! 3978: while(cx.tr.a==DST_action_NULL);
! 3979: #if DEBUG
! 3980: if(dbg_g4r_t)fprintf(stderr,"%s %04d %s0\n",
! 3981: (cx.c==DST_white)? "W": "B",
! 3982: cx.tr.s,
! 3983: t->e[cx.tr.s].p);
! 3984: #endif
! 3985: switch(cx.tr.a) {
! 3986: case i2D_V0:
! 3987: #if DEBUG
! 3988: if(dbg_g4r_c)
! 3989: fprintf(stderr,"V0 %s\n",code2d[cx.tr.a]);
! 3990: #endif
! 3991: a1=b1;
! 3992: /* interpret (a0,a1-1] */
! 3993: if(a0_color==DST_black) cr->xe=a1-1;
! 3994: /* move a0 to a1 */
! 3995: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 3996: a0_color = flip_color(a0_color);
! 3997: /* interpret a0 */
! 3998: if(a0_color==DST_black) {
! 3999: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4000: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4001: crl->y,crl->runs,cr->xs,cr->xe);
! 4002: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4003: };
! 4004: #if !g4r_strict
! 4005: if(a0==prl->len-1)
! 4006: { a0++; goto trap_expecting_eol; };
! 4007: #endif
! 4008: g4r_find_b1b2;
! 4009: break;
! 4010: case i2D_VR1:
! 4011: #if DEBUG
! 4012: if(dbg_g4r_c)
! 4013: fprintf(stderr,"VR1 %s\n",code2d[cx.tr.a]);
! 4014: #endif
! 4015: a1=b1+1;
! 4016: /* encode a0 to a1-1 */
! 4017: if(a0_color==DST_black) cr->xe=a1-1;
! 4018: /* move a0 to a1 */
! 4019: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 4020: a0_color = flip_color(a0_color);
! 4021: /* encode a0 */
! 4022: if(a0_color==DST_black) {
! 4023: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4024: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4025: crl->y,crl->runs,cr->xs,cr->xe);
! 4026: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4027: };
! 4028: #if !g4r_strict
! 4029: if(a0==prl->len-1)
! 4030: { a0++; goto trap_expecting_eol; };
! 4031: #endif
! 4032: g4r_find_b1b2;
! 4033: break;
! 4034: case i2D_VR2:
! 4035: #if DEBUG
! 4036: if(dbg_g4r_c)
! 4037: fprintf(stderr,"VR2 %s\n",code2d[cx.tr.a]);
! 4038: #endif
! 4039: a1=b1+2;
! 4040: /* encode a0 to a1-1 */
! 4041: if(a0_color==DST_black) cr->xe=a1-1;
! 4042: /* move a0 to a1 */
! 4043: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 4044: a0_color = flip_color(a0_color);
! 4045: /* encode a0 */
! 4046: if(a0_color==DST_black) {
! 4047: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4048: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4049: crl->y,crl->runs,cr->xs,cr->xe);
! 4050: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4051: };
! 4052: #if !g4r_strict
! 4053: if(a0==prl->len-1)
! 4054: { a0++; goto trap_expecting_eol; };
! 4055: #endif
! 4056: g4r_find_b1b2;
! 4057: break;
! 4058: case i2D_VR3:
! 4059: #if DEBUG
! 4060: if(dbg_g4r_c)
! 4061: fprintf(stderr,"VR3 %s\n",code2d[cx.tr.a]);
! 4062: #endif
! 4063: a1=b1+3;
! 4064: /* encode a0 to a1-1 */
! 4065: if(a0_color==DST_black) cr->xe=a1-1;
! 4066: /* move a0 to a1 */
! 4067: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 4068: a0_color = flip_color(a0_color);
! 4069: /* encode a0 */
! 4070: if(a0_color==DST_black) {
! 4071: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4072: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4073: crl->y,crl->runs,cr->xs,cr->xe);
! 4074: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4075: };
! 4076: #if !g4r_strict
! 4077: if(a0==prl->len-1)
! 4078: { a0++; goto trap_expecting_eol; };
! 4079: #endif
! 4080: g4r_find_b1b2;
! 4081: break;
! 4082: case i2D_VL1:
! 4083: #if DEBUG
! 4084: if(dbg_g4r_c)
! 4085: fprintf(stderr,"VL1 %s\n",code2d[cx.tr.a]);
! 4086: #endif
! 4087: if((a1=b1-1)<=a0)
! 4088: err("g4_to_rlel: y%d: VL1 a1 %d <= a0 %d ?",
! 4089: crl->y,a1,a0);
! 4090: /* encode a0 to a1-1 */
! 4091: if(a0_color==DST_black) cr->xe=a1-1;
! 4092: /* move a0 to a1 */
! 4093: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 4094: a0_color = flip_color(a0_color);
! 4095: /* encode a0 */
! 4096: if(a0_color==DST_black) {
! 4097: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4098: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4099: crl->y,crl->runs,cr->xs,cr->xe);
! 4100: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4101: };
! 4102: #if !g4r_strict
! 4103: if(a0==prl->len-1)
! 4104: { a0++; goto trap_expecting_eol; };
! 4105: #endif
! 4106: g4r_find_b1b2;
! 4107: break;
! 4108: case i2D_VL2:
! 4109: #if DEBUG
! 4110: if(dbg_g4r_c)
! 4111: fprintf(stderr,"VL2 %s\n",code2d[cx.tr.a]);
! 4112: #endif
! 4113: if((a1=b1-2)<=a0)
! 4114: err("g4_to_rlel: y%d: VL2 a1 %d <= a0 %d ?",
! 4115: crl->y,a1,a0);
! 4116: /* encode a0 to a1-1 */
! 4117: if(a0_color==DST_black) cr->xe=a1-1;
! 4118: /* move a0 to a1 */
! 4119: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 4120: a0_color = flip_color(a0_color);
! 4121: /* encode a0 */
! 4122: if(a0_color==DST_black) {
! 4123: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4124: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4125: crl->y,crl->runs,cr->xs,cr->xe);
! 4126: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4127: };
! 4128: #if !g4r_strict
! 4129: if(a0==prl->len-1)
! 4130: { a0++; goto trap_expecting_eol; };
! 4131: #endif
! 4132: g4r_find_b1b2;
! 4133: break;
! 4134: case i2D_VL3:
! 4135: #if DEBUG
! 4136: if(dbg_g4r_c)
! 4137: fprintf(stderr,"VL3 %s\n",code2d[cx.tr.a]);
! 4138: #endif
! 4139: if((a1=b1-3)<=a0)
! 4140: err("g4_to_rlel: y%d: VL3 a1 %d <= a0 %d ?",
! 4141: crl->y,a1,a0);
! 4142: /* encode a0 to a1-1 */
! 4143: if(a0_color==DST_black) cr->xe=a1-1;
! 4144: /* move a0 to a1 */
! 4145: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
! 4146: a0_color = flip_color(a0_color);
! 4147: /* encode a0 */
! 4148: if(a0_color==DST_black) {
! 4149: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4150: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4151: crl->y,crl->runs,cr->xs,cr->xe);
! 4152: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
! 4153: };
! 4154: #if !g4r_strict
! 4155: if(a0==prl->len-1)
! 4156: { a0++; goto trap_expecting_eol; };
! 4157: #endif
! 4158: g4r_find_b1b2;
! 4159: break;
! 4160: case i2D_PASS:
! 4161: #if DEBUG
! 4162: if(dbg_g4r_c)
! 4163: fprintf(stderr,"PASS %s\n",code2d[cx.tr.a]);
! 4164: #endif
! 4165: /* move a0 to b2; no change of color */
! 4166: a0=b2; if(a0>=prl->len) goto trap_expecting_eol;
! 4167: if(a0_color==DST_black) cr->xe = a0;
! 4168: #if !g4r_strict
! 4169: if(a0==prl->len-1)
! 4170: { a0++; goto trap_expecting_eol; };
! 4171: #endif
! 4172: g4r_find_b1b2;
! 4173: break;
! 4174: case i2D_HORIZ:
! 4175: #if DEBUG
! 4176: if(dbg_g4r_c)
! 4177: fprintf(stderr,"HORIZ %s\n",code2d[cx.tr.a]);
! 4178: #endif
! 4179: if(a0_color==DST_white) {
! 4180: if(a0<0) a0=0; /* first run in line starts at 0 */
! 4181: g4_1d_run(DST_white,a01); a1 = a0 + a01;
! 4182: g4_1d_run(DST_black,a12); a2 = a1 + a12;
! 4183: if(a12>0) /* Black run of >0 length */ {
! 4184: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
! 4185: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
! 4186: crl->y,crl->runs,cr->xs,cr->xe);
! 4187: crl->runs++; (++cr)->xs = a1; cr->xe = a2-1;
! 4188: };
! 4189: a0 = a2; /* still white */
! 4190: if(a0>=prl->len) goto trap_expecting_eol;
! 4191: /* encode a0 */
! 4192: #if !g4r_strict
! 4193: if(a0==prl->len-1)
! 4194: { a0++; goto trap_expecting_eol; };
! 4195: #endif
! 4196: g4r_find_Bb1Wb2;
! 4197: }
! 4198: else { g4_1d_run(DST_black,a01); a1 = a0 + a01;
! 4199: g4_1d_run(DST_white,a12); a2 = a1 + a12;
! 4200: if(a01>0) /* Black run of >0 length */ {
! 4201: cr->xe = a1 - 1;
! 4202: }
! 4203: else { /* 0-length: very peculiar: ignore */
! 4204: fprintf(stderr,
! 4205: "g4_to_rlel: HORIZ B%d! W%d - ignore\n",
! 4206: a01,a12);
! 4207: cr--; crl->runs--;
! 4208: };
! 4209: a0 = a2; /* still black */
! 4210: if(a0>=prl->len) goto trap_expecting_eol;
! 4211: /* encode a0 */
! 4212: crl->runs++; (++cr)->xs = a0;
! 4213: #if !g4r_strict
! 4214: if(a0==prl->len-1) {
! 4215: cr->xe = a0;
! 4216: a0++;
! 4217: goto trap_expecting_eol;
! 4218: };
! 4219: #endif
! 4220: g4r_find_Wb1Bb2;
! 4221: };
! 4222: break;
! 4223: case i2D_EOL:
! 4224: #if DEBUG
! 4225: if(dbg_g4r_c)
! 4226: fprintf(stderr,"EOL %s\n",code2d[cx.tr.a]);
! 4227: #endif
! 4228: goto trap_eol;
! 4229: break;
! 4230: case DST_action_ERROR: goto trap_code_err; break;
! 4231: };
! 4232: };
! 4233:
! 4234: /* come here via goto's: all these traps return() */
! 4235:
! 4236: trap_expecting_eol: /* come here having detected (computed) end-of-line */
! 4237: /* learn/check/correct line-length */
! 4238: crl->len = (a0>0)? a0 : 0;
! 4239: if(crl->len!=prl->len) {
! 4240: err("g4_to_rlel: y%d: LINELEN changes c%d != p%d ? (force to %d)",
! 4241: crl->y,crl->len,prl->len,prl->len);
! 4242: crl->len = prl->len;
! 4243: };
! 4244: swap_rl(crl,prl);
! 4245: #if DEBUG
! 4246: if(dbg_g4r_e)
! 4247: fprintf(stderr,
! 4248: "exit g4_to_rlel: expg_eol y%d,l%d\n",
! 4249: prl->y,prl->len);
! 4250: #endif
! 4251: return(prl);
! 4252:
! 4253: trap_eol: /* come here having seen an EOL code (rare in Group 4) */
! 4254: /* It must be the first of two EOL codes making up the EOB signal */
! 4255: /* look for 2nd EOL */
! 4256: sync=0; while((bitv=getb(f))==0) sync++;
! 4257: switch(bitv) {
! 4258: case 1:
! 4259: if(sync==11) {
! 4260: #if DEBUG
! 4261: if(dbg_g4r_c) {
! 4262: fprintf(stderr,"EOB_EOL %s\n",EOLSTRING);
! 4263: fprintf(stderr,"EOB\n");
! 4264: };
! 4265: #endif
! 4266: }
! 4267: else {
! 4268: #if DEBUG
! 4269: if(dbg_g4r_c){
! 4270: fprintf(stderr,"NOT EOB ");
! 4271: for(si=0;si<sync;si++)
! 4272: fprintf(stderr,"0");
! 4273: fprintf(stderr,"1?\n");
! 4274: fprintf(stderr,"ABORT\n");
! 4275: };
! 4276: #endif
! 4277: };
! 4278: break;
! 4279: case EOF: goto trap_eof; break;
! 4280: };
! 4281: #if DEBUG
! 4282: if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: eol\n");
! 4283: #endif
! 4284: return(NULL);
! 4285:
! 4286: trap_code_err:
! 4287: /* unexpected coding sequence:
! 4288: 'px' holds last decoding context & 'bitv' latest bit value;
! 4289: will attempt to resynchronize on next EOL */
! 4290: #if DEBUG
! 4291: if(dbg_g4r_c)fprintf(stderr,"CODERR %s%d? (px.tr.s=%d)\n",
! 4292: t->e[px.tr.s].p,bitv,px.tr.s);
! 4293: #endif
! 4294: err("g4_to_rlel: code error");
! 4295: #if DEBUG
! 4296: if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: code_err\n");
! 4297: #endif
! 4298: return(NULL);
! 4299:
! 4300: trap_eof:
! 4301: #if DEBUG
! 4302: if(dbg_g4r_c) fprintf(stderr,"<EOF>\n");
! 4303: if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: eof\n");
! 4304: #endif
! 4305: return(NULL);
! 4306:
! 4307: }
! 4308:
! 4309: /* Translate a sequence of RLE_Line's (describing a binary image)
! 4310: into a file (a stream of bits) in CCITT FAX Group 4 compression format.
! 4311: BOF_to_g4() must be called first; then call rlel_to_g4() for each line
! 4312: (including blank lines); finally, EOF_to_g4() must be called. The EOFB
! 4313: is padded (suffixed) with 0's to a byte boundary if necessary; no other
! 4314: filling or padding is performed.
! 4315: */
! 4316: /* debugging flags: trace to stderr */
! 4317: #define dbg_rg4_e (0) /* entry */
! 4318: #define dbg_rg4_r (0) /* runs */
! 4319: #define dbg_rg4_c (0) /* codes (bitstrings) */
! 4320: #define rg4_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
! 4321:
! 4322: #if DEBUG
! 4323: #define bits_g4(bits) { \
! 4324: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
! 4325: if(dbg_rg4_c) fprintf(stderr,"%s",(bits)); \
! 4326: if(dbg_rg4_r) fprintf(stderr," "); \
! 4327: }
! 4328: #else
! 4329: #define bits_g4(bits) { \
! 4330: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
! 4331: }
! 4332: #endif
! 4333: #if DEBUG
! 4334: #define EOFB_g4 { \
! 4335: if(dbg_rg4_r) fprintf(stderr,"EOFB "); \
! 4336: bits_g4(EOFB); \
! 4337: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4338: }
! 4339: #else
! 4340: #define EOFB_g4 { \
! 4341: bits_g4(EOFB); \
! 4342: }
! 4343: #endif
! 4344:
! 4345: BOF_to_g4(f)
! 4346: BITFILE *f;
! 4347: { char *cs;
! 4348: /* a NOP: no header for Group 4 */
! 4349: #if DEBUG
! 4350: if(dbg_rg4_e) fprintf(stderr,"BOF\n");
! 4351: #endif
! 4352: };
! 4353:
! 4354: rlel_to_g4(pl,cl,wid,f)
! 4355: RLE_Line *pl; /* prior "reference" line */
! 4356: RLE_Line *cl; /* current "coding" line: if NULL, is blank (all white) */
! 4357: int wid; /* width of an output line in pixels */
! 4358: BITFILE *f;
! 4359: { int runl,codi;
! 4360: char *cs,*p01;
! 4361: #if DEBUG
! 4362: #define Wrun_g4(rn) { \
! 4363: runl=(rn); \
! 4364: if(dbg_rg4_r) fprintf(stderr,"W %5d ",runl); \
! 4365: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
! 4366: p01=codewht[codi=rtoi(runl)]; bits_g4(p01); \
! 4367: if(codi>=64) {p01=codewht[runl%64]; bits_g4(p01);}; \
! 4368: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4369: }
! 4370: #else
! 4371: #define Wrun_g4(rn) { \
! 4372: runl=(rn); \
! 4373: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
! 4374: p01=codewht[codi=rtoi(runl)]; bits_g4(p01); \
! 4375: if(codi>=64) {p01=codewht[runl%64]; bits_g4(p01);}; \
! 4376: }
! 4377: #endif
! 4378: #if DEBUG
! 4379: #define Brun_g4(rn) { \
! 4380: runl=(rn); \
! 4381: if(dbg_rg4_r) fprintf(stderr,"B %5d ",runl); \
! 4382: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
! 4383: p01=codeblk[codi=rtoi(runl)]; bits_g4(p01); \
! 4384: if(codi>=64) {p01=codeblk[runl%64]; bits_g4(p01);}; \
! 4385: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4386: }
! 4387: #else
! 4388: #define Brun_g4(rn) { \
! 4389: runl=(rn); \
! 4390: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
! 4391: p01=codeblk[codi=rtoi(runl)]; bits_g4(p01); \
! 4392: if(codi>=64) {p01=codeblk[runl%64]; bits_g4(p01);}; \
! 4393: }
! 4394: #endif
! 4395: #if DEBUG
! 4396: #define V0_g4 { \
! 4397: if(dbg_rg4_r) fprintf(stderr,"V0 "); \
! 4398: bits_g4(code2d[i2D_V0]); \
! 4399: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4400: }
! 4401: #else
! 4402: #define V0_g4 { \
! 4403: bits_g4(code2d[i2D_V0]); \
! 4404: }
! 4405: #endif
! 4406: #if DEBUG
! 4407: #define VR1_g4 { \
! 4408: if(dbg_rg4_r) fprintf(stderr,"VR1 "); \
! 4409: bits_g4(code2d[i2D_VR1]); \
! 4410: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4411: }
! 4412: #else
! 4413: #define VR1_g4 { \
! 4414: bits_g4(code2d[i2D_VR1]); \
! 4415: }
! 4416: #endif
! 4417: #if DEBUG
! 4418: #define VR2_g4 { \
! 4419: if(dbg_rg4_r) fprintf(stderr,"VR2 "); \
! 4420: bits_g4(code2d[i2D_VR2]); \
! 4421: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4422: }
! 4423: #else
! 4424: #define VR2_g4 { \
! 4425: bits_g4(code2d[i2D_VR2]); \
! 4426: }
! 4427: #endif
! 4428: #if DEBUG
! 4429: #define VR3_g4 { \
! 4430: if(dbg_rg4_r) fprintf(stderr,"VR3 "); \
! 4431: bits_g4(code2d[i2D_VR3]); \
! 4432: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4433: }
! 4434: #else
! 4435: #define VR3_g4 { \
! 4436: bits_g4(code2d[i2D_VR3]); \
! 4437: }
! 4438: #endif
! 4439: #if DEBUG
! 4440: #define VL1_g4 { \
! 4441: if(dbg_rg4_r) fprintf(stderr,"VL1 "); \
! 4442: bits_g4(code2d[i2D_VL1]); \
! 4443: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4444: }
! 4445: #else
! 4446: #define VL1_g4 { \
! 4447: bits_g4(code2d[i2D_VL1]); \
! 4448: }
! 4449: #endif
! 4450: #if DEBUG
! 4451: #define VL2_g4 { \
! 4452: if(dbg_rg4_r) fprintf(stderr,"VL2 "); \
! 4453: bits_g4(code2d[i2D_VL2]); \
! 4454: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4455: }
! 4456: #else
! 4457: #define VL2_g4 { \
! 4458: bits_g4(code2d[i2D_VL2]); \
! 4459: }
! 4460: #endif
! 4461: #if DEBUG
! 4462: #define VL3_g4 { \
! 4463: if(dbg_rg4_r) fprintf(stderr,"VL3 "); \
! 4464: bits_g4(code2d[i2D_VL3]); \
! 4465: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4466: }
! 4467: #else
! 4468: #define VL3_g4 { \
! 4469: bits_g4(code2d[i2D_VL3]); \
! 4470: }
! 4471: #endif
! 4472: #if DEBUG
! 4473: #define PASS_g4 { \
! 4474: if(dbg_rg4_r) fprintf(stderr,"PASS "); \
! 4475: bits_g4(code2d[i2D_PASS]); \
! 4476: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4477: }
! 4478: #else
! 4479: #define PASS_g4 { \
! 4480: bits_g4(code2d[i2D_PASS]); \
! 4481: }
! 4482: #endif
! 4483: #if DEBUG
! 4484: #define HORIZ_g4 { \
! 4485: if(dbg_rg4_r) fprintf(stderr,"HORIZ "); \
! 4486: bits_g4(code2d[i2D_HORIZ]); \
! 4487: if(dbg_rg4_r) fprintf(stderr,"\n"); \
! 4488: }
! 4489: #else
! 4490: #define HORIZ_g4 { \
! 4491: bits_g4(code2d[i2D_HORIZ]); \
! 4492: }
! 4493: #endif
! 4494: #define detect_a1a2_BW { \
! 4495: /* find leftmost black changing pel > a0 */ \
! 4496: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
! 4497: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
! 4498: /* look beyond cra, until cr->xs>a0 */ \
! 4499: cr=cra; while(cr<cre && (a1=cr->xs)<=a0) cr++; \
! 4500: if(cr<cre) a2=cr->xe+1; \
! 4501: else a1=a2=wid; \
! 4502: }
! 4503: #define detect_a1a2_WB { \
! 4504: /* find leftmost white changing pel > a0 */ \
! 4505: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
! 4506: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
! 4507: /* look beyond cra, until cr->xe+1>a0 */ \
! 4508: cr=cra; while(cr<cre && (a1=cr->xe+1)<=a0) cr++; \
! 4509: if(cr<cre) { \
! 4510: if((cr+1)<cre) a2=(cr+1)->xs; \
! 4511: else a2=wid; \
! 4512: } \
! 4513: else a1=a2=wid; \
! 4514: }
! 4515: #define detect_a1a2 {if(a0_color==DST_white) detect_a1a2_BW else detect_a1a2_WB;}
! 4516: #define detect_b1b2_BW {\
! 4517: /* find leftmost black changing pel > a0 */ \
! 4518: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
! 4519: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
! 4520: /* look beyond pra */ \
! 4521: pr=pra; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
! 4522: /* move b2 to 1st changing white pel > b1 */ \
! 4523: if(pr<pre) b2=pr->xe+1; \
! 4524: else b1=b2=wid; \
! 4525: }
! 4526: #define detect_b1b2_WB {\
! 4527: /* find leftmost white changing pel > a0 */ \
! 4528: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
! 4529: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
! 4530: /* look beyond pra */ \
! 4531: pr=pra; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
! 4532: /* move b2 to 1st changing black pel > b1 */ \
! 4533: if(pr<pre) { \
! 4534: if((pr+1)<pre) b2=(pr+1)->xs; \
! 4535: else b2=wid; \
! 4536: } \
! 4537: else b1=b2=wid; \
! 4538: }
! 4539: #define detect_b1b2 {if(a0_color==DST_white) detect_b1b2_BW else detect_b1b2_WB;}
! 4540:
! 4541: RLE_Run *cr,*cre,*pr,*pre; /* into current/prior rle lines */
! 4542: int a0,a1,a2,b1,b2; /* indices {0,1,...} of pixels */
! 4543: DST_color a0_color; /* a0's color: same as a2 & b2, opp of a1 & b1 */
! 4544: RLE_Run *cra; /* rightmost in current st xe<=a0 (none: ==cl->r) */
! 4545: RLE_Run *pra; /* rightmost in prior st xe<=a0 (none: ==pl->r) */
! 4546: int a01,a12,a1b1; /* lengths of runs a0-a1 a1-a2 a1-b1 */
! 4547: #if DEBUG
! 4548: if(dbg_rg4_e) err("rlel_to_g4(pl[%d],cl[%d],w%d)",
! 4549: (pl==NULL)? -1: pl->runs,
! 4550: (cl==NULL)? -1: cl->runs,
! 4551: wid);
! 4552: #endif
! 4553: /* start on an imaginary white pixel just to left of margin */
! 4554: a0= -1; a0_color = DST_white;
! 4555: pre = (pra=pl->r) + pl->runs; /* prior line's runs */
! 4556: /* start b1/b2 on prior line's first black pixel, etc;
! 4557: if none, then place off end of line */
! 4558: if(pra<pre) {b1=pra->xs; b2=pra->xe+1;} else b1=b2=wid;
! 4559: if(cl!=NULL&&cl->runs>0) {
! 4560: cre = (cra=cl->r) + cl->runs;
! 4561: a1=cra->xs; a2=cra->xe+1;
! 4562: #if rg4_strict
! 4563: while( a0 < wid ) {
! 4564: #else
! 4565: while( a0 < wid-1 ) {
! 4566: #endif
! 4567: /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
! 4568: #if DEBUG
! 4569: if(dbg_rg4_r)
! 4570: fprintf(stderr,"f%d(%d,%d,%d) b%d(%d,%d)\n",
! 4571: cra-(cl->r),a0,a1,a2,pra-(pl->r),b1,b2);
! 4572: #endif
! 4573: if(b2<a1) /* PASS mode */ {
! 4574: PASS_g4;
! 4575: a0=b2;
! 4576: /* a0-color, a1, & a2 are unchanged */
! 4577: detect_b1b2;
! 4578: }
! 4579: else if((a1b1=(a1-b1))<=3 && a1b1>= -3) {
! 4580: /* VERTICAL mode */
! 4581: switch(a1b1) {
! 4582: case -3: VL3_g4; break;
! 4583: case -2: VL2_g4; break;
! 4584: case -1: VL1_g4; break;
! 4585: case 0: V0_g4; break;
! 4586: case 1: VR1_g4; break;
! 4587: case 2: VR2_g4; break;
! 4588: case 3: VR3_g4; break;
! 4589: };
! 4590: a0=a1; a0_color=flip_color(a0_color);
! 4591: detect_a1a2;
! 4592: detect_b1b2;
! 4593: }
! 4594: else { /* HORIZONTAL mode */
! 4595: HORIZ_g4;
! 4596: a01=a1-a0; if(a0== -1) a01--;
! 4597: a12=a2-a1;
! 4598: if(a0_color==DST_white) {
! 4599: Wrun_g4(a01);
! 4600: Brun_g4(a12);
! 4601: }
! 4602: else { Brun_g4(a01);
! 4603: Wrun_g4(a12);
! 4604: };
! 4605: a0=a2;
! 4606: /* a0_color is unchanged */
! 4607: detect_a1a2;
! 4608: detect_b1b2;
! 4609: };
! 4610: };
! 4611: }
! 4612: else /* current line is blank */ {
! 4613: a1=a2=wid;
! 4614: #if rg4_strict
! 4615: while( a0 < wid ) {
! 4616: #else
! 4617: while( a0 < wid-1 ) {
! 4618: #endif
! 4619: /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
! 4620: #if DEBUG
! 4621: if(dbg_rg4_r)
! 4622: fprintf(stderr,"f(%d,%d,%d) b%d(%d,%d)\n",
! 4623: a0,a1,a2,pra-(pl->r),b1,b2);
! 4624: #endif
! 4625: if(b2<a1) /* PASS mode */ {
! 4626: PASS_g4;
! 4627: a0=b2;
! 4628: /* a0-color, a1, & a2 are unchanged */
! 4629: detect_b1b2;
! 4630: }
! 4631: else if((a1b1=a1-b1)<=3 && a1b1>= -3) {
! 4632: /* VERTICAL mode */
! 4633: switch(a1b1) {
! 4634: case -3: VL3_g4; break;
! 4635: case -2: VL2_g4; break;
! 4636: case -1: VL1_g4; break;
! 4637: case 0: V0_g4; break;
! 4638: case 1: VR1_g4; break;
! 4639: case 2: VR2_g4; break;
! 4640: case 3: VR3_g4; break;
! 4641: };
! 4642: a0=a1; a0_color=flip_color(a0_color);
! 4643: /* a1, & a2 are unchanged */
! 4644: detect_b1b2;
! 4645: }
! 4646: else { /* HORIZONTAL mode */
! 4647: HORIZ_g4;
! 4648: a01=a1-a0; if(a0== -1) a01--;
! 4649: a12=a2-a1;
! 4650: if(a0_color==DST_white) {
! 4651: Wrun_g4(a01);
! 4652: Brun_g4(a12);
! 4653: }
! 4654: else { Brun_g4(a01);
! 4655: Wrun_g4(a12);
! 4656: };
! 4657: a0=a2;
! 4658: /* a0_color, a1, & a2 are unchanged */
! 4659: detect_b1b2;
! 4660: };
! 4661: };
! 4662: };
! 4663: }
! 4664:
! 4665: EOF_to_g4(f)
! 4666: BITFILE *f;
! 4667: { char *cs;
! 4668: /* write EOFB */
! 4669: EOFB_g4;
! 4670: #if DEBUG
! 4671: if(dbg_rg4_e) fprintf(stderr,"EOF\n");
! 4672: #endif
! 4673: }
! 4674:
! 4675: 0707070035351137051006640007620000050000010261160476773366600001000000024315CCITT.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 4676: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 4677: /* The copyright notice does not imply actual or intended publication. */
! 4678: /* AUTHORS: */
! 4679: /* H. S. Baird - ATT-BL MH - first versions */
! 4680: /* CCITT Group 3 FAX compression codes */
! 4681: #define EOLSTRING "000000000001"
! 4682: #define EOLLENGTH 12 /* length of EOLSTRING */
! 4683: #define MAXCODELEN 24
! 4684:
! 4685: #define DST_EOL -3
! 4686:
! 4687: /* translate a runlength value <=2560 to an index into the Huffman code table;
! 4688: if the index is >=64, then must repeat for (r%64) */
! 4689: #define rtoi(r) (((r)<64)? (r): 64+((r)/64))
! 4690: /* translate an index into the Huffman code table to a runlength value */
! 4691: #define itor(i) (((i)<64)? (i): (((i)>64)? (((i)-64)*64): DST_EOL))
! 4692:
! 4693: /* Black run code table */
! 4694: static char *codeblk[] = {
! 4695: /* code run-length value */
! 4696: "0000110111", /* 0, */
! 4697: "010", /* 1, */
! 4698: "11", /* 2, */
! 4699: "10", /* 3, */
! 4700: "011", /* 4, */
! 4701: "0011", /* 5, */
! 4702: "0010", /* 6, */
! 4703: "00011", /* 7, */
! 4704: "000101", /* 8, */
! 4705: "000100", /* 9, */
! 4706: "0000100", /* 10, */
! 4707: "0000101", /* 11, */
! 4708: "0000111", /* 12, */
! 4709: "00000100", /* 13, */
! 4710: "00000111", /* 14, */
! 4711: "000011000", /* 15, */
! 4712: "0000010111", /* 16, */
! 4713: "0000011000", /* 17, */
! 4714: "0000001000", /* 18, */
! 4715: "00001100111", /* 19, */
! 4716: "00001101000", /* 20, */
! 4717: "00001101100", /* 21, */
! 4718: "00000110111", /* 22, */
! 4719: "00000101000", /* 23, */
! 4720: "00000010111", /* 24, */
! 4721: "00000011000", /* 25, */
! 4722: "000011001010", /* 26, */
! 4723: "000011001011", /* 27, */
! 4724: "000011001100", /* 28, */
! 4725: "000011001101", /* 29, */
! 4726: "000001101000", /* 30, */
! 4727: "000001101001", /* 31, */
! 4728: "000001101010", /* 32, */
! 4729: "000001101011", /* 33, */
! 4730: "000011010010", /* 34, */
! 4731: "000011010011", /* 35, */
! 4732: "000011010100", /* 36, */
! 4733: "000011010101", /* 37, */
! 4734: "000011010110", /* 38, */
! 4735: "000011010111", /* 39, */
! 4736: "000001101100", /* 40, */
! 4737: "000001101101", /* 41, */
! 4738: "000011011010", /* 42, */
! 4739: "000011011011", /* 43, */
! 4740: "000001010100", /* 44, */
! 4741: "000001010101", /* 45, */
! 4742: "000001010110", /* 46, */
! 4743: "000001010111", /* 47, */
! 4744: "000001100100", /* 48, */
! 4745: "000001100101", /* 49, */
! 4746: "000001010010", /* 50, */
! 4747: "000001010011", /* 51, */
! 4748: "000000100100", /* 52, */
! 4749: "000000110111", /* 53, */
! 4750: "000000111000", /* 54, */
! 4751: "000000100111", /* 55, */
! 4752: "000000101000", /* 56, */
! 4753: "000001011000", /* 57, */
! 4754: "000001011001", /* 58, */
! 4755: "000000101011", /* 59, */
! 4756: "000000101100", /* 60, */
! 4757: "000001011010", /* 61, */
! 4758: "000001100110", /* 62, */
! 4759: "000001100111", /* 63 */
! 4760: EOLSTRING, /* EOL */
! 4761: "0000001111", /* 64, */
! 4762: "000011001000", /* 128, */
! 4763: "000011001001", /* 192, */
! 4764: "000001011011", /* 256, */
! 4765: "000000110011", /* 320, */
! 4766: "000000110100", /* 384, */
! 4767: "000000110101", /* 448, */
! 4768: "0000001101100", /* 512, */
! 4769: "0000001101101", /* 576, */
! 4770: "0000001001010", /* 640, */
! 4771: "0000001001011", /* 704, */
! 4772: "0000001001100", /* 768, */
! 4773: "0000001001101", /* 832, */
! 4774: "0000001110010", /* 896, */
! 4775: "0000001110011", /* 960, */
! 4776: "0000001110100", /* 1024, */
! 4777: "0000001110101", /* 1088, */
! 4778: "0000001110110", /* 1152, */
! 4779: "0000001110111", /* 1216, */
! 4780: "0000001010010", /* 1280, */
! 4781: "0000001010011", /* 1344, */
! 4782: "0000001010100", /* 1408, */
! 4783: "0000001010101", /* 1472, */
! 4784: "0000001011010", /* 1536, */
! 4785: "0000001011011", /* 1600, */
! 4786: "0000001100100", /* 1664, */
! 4787: "0000001100101", /* 1728 */
! 4788: /* extended length: */
! 4789: "00000001000", /* 1792, */
! 4790: "00000001100", /* 1856, */
! 4791: "00000001101", /* 1920, */
! 4792: "000000010010", /* 1984, */
! 4793: "000000010011", /* 2048, */
! 4794: "000000010100", /* 2112, */
! 4795: "000000010101", /* 2176, */
! 4796: "000000010110", /* 2240, */
! 4797: "000000010111", /* 2304, */
! 4798: "000000011100", /* 2368, */
! 4799: "000000011101", /* 2432, */
! 4800: "000000011110", /* 2496, */
! 4801: "000000011111", /* 2560 */
! 4802: NULL /* are there codes beyond 2560? */
! 4803: };
! 4804: /* No. bits in the codes in the above table */
! 4805: static short bitcblk[] = {
! 4806: 10,3,2,2,3,4,4,5,6,6, /* 0 - 9 */
! 4807: 7,7,7,8,8,9,10,10,10,11, /* 10 - 19 */
! 4808: 11,11,11,11,11,11,12,12,12,12, /* 20 - 29 */
! 4809: 12,12,12,12,12,12,12,12,12,12, /* 30 - 39 */
! 4810: 12,12,12,12,12,12,12,12,12,12, /* 40 - 49 */
! 4811: 12,12,12,12,12,12,12,12,12,12, /* 50 - 59 */
! 4812: 12,12,12,12, /* 60 - 63 */
! 4813: 12, /* EOL */
! 4814: 10, /* 64 */
! 4815: 12,12,12,12,12,12, /* 128 - 448 */
! 4816: 13,13,13,13,13,13,13,13,13, /* 512 - */
! 4817: 13,13,13,13,13,13,13,13,13,
! 4818: 13,13, /* - 1728 */
! 4819: 11,11,11, /* 1792 - 1920 */
! 4820: 12,12,12,12,12,12,12,12,12,12, /* 1984 - 2560 */
! 4821: /* for codes over 2560 */
! 4822: 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
! 4823: -1
! 4824: };
! 4825:
! 4826: /* White run code table */
! 4827: static char *codewht[] = {
! 4828: /* code run-length value */
! 4829: "00110101", /* 0, */
! 4830: "000111", /* 1, */
! 4831: "0111", /* 2, */
! 4832: "1000", /* 3, */
! 4833: "1011", /* 4, */
! 4834: "1100", /* 5, */
! 4835: "1110", /* 6, */
! 4836: "1111", /* 7, */
! 4837: "10011", /* 8, */
! 4838: "10100", /* 9, */
! 4839: "00111", /* 10, */
! 4840: "01000", /* 11, */
! 4841: "001000", /* 12, */
! 4842: "000011", /* 13, */
! 4843: "110100", /* 14, */
! 4844: "110101", /* 15, */
! 4845: "101010", /* 16, */
! 4846: "101011", /* 17, */
! 4847: "0100111", /* 18, */
! 4848: "0001100", /* 19, */
! 4849: "0001000", /* 20, */
! 4850: "0010111", /* 21, */
! 4851: "0000011", /* 22, */
! 4852: "0000100", /* 23, */
! 4853: "0101000", /* 24, */
! 4854: "0101011", /* 25, */
! 4855: "0010011", /* 26, */
! 4856: "0100100", /* 27, */
! 4857: "0011000", /* 28, */
! 4858: "00000010", /* 29, */
! 4859: "00000011", /* 30, */
! 4860: "00011010", /* 31, */
! 4861: "00011011", /* 32, */
! 4862: "00010010", /* 33, */
! 4863: "00010011", /* 34, */
! 4864: "00010100", /* 35, */
! 4865: "00010101", /* 36, */
! 4866: "00010110", /* 37, */
! 4867: "00010111", /* 38, */
! 4868: "00101000", /* 39, */
! 4869: "00101001", /* 40, */
! 4870: "00101010", /* 41, */
! 4871: "00101011", /* 42, */
! 4872: "00101100", /* 43, */
! 4873: "00101101", /* 44, */
! 4874: "00000100", /* 45, */
! 4875: "00000101", /* 46, */
! 4876: "00001010", /* 47, */
! 4877: "00001011", /* 48, */
! 4878: "01010010", /* 49, */
! 4879: "01010011", /* 50, */
! 4880: "01010100", /* 51, */
! 4881: "01010101", /* 52, */
! 4882: "00100100", /* 53, */
! 4883: "00100101", /* 54, */
! 4884: "01011000", /* 55, */
! 4885: "01011001", /* 56, */
! 4886: "01011010", /* 57, */
! 4887: "01011011", /* 58, */
! 4888: "01001010", /* 59, */
! 4889: "01001011", /* 60, */
! 4890: "00110010", /* 61, */
! 4891: "00110011", /* 62, */
! 4892: "00110100", /* 63 */
! 4893: EOLSTRING, /* EOL */
! 4894: "11011", /* 64, */
! 4895: "10010", /* 128, */
! 4896: "010111", /* 192, */
! 4897: "0110111", /* 256, */
! 4898: "00110110", /* 320, */
! 4899: "00110111", /* 384, */
! 4900: "01100100", /* 448, */
! 4901: "01100101", /* 512, */
! 4902: "01101000", /* 576, */
! 4903: "01100111", /* 640, */
! 4904: "011001100", /* 704, */
! 4905: "011001101", /* 768, */
! 4906: "011010010", /* 832, */
! 4907: "011010011", /* 896, */
! 4908: "011010100", /* 960, */
! 4909: "011010101", /* 1024, */
! 4910: "011010110", /* 1088, */
! 4911: "011010111", /* 1152, */
! 4912: "011011000", /* 1216, */
! 4913: "011011001", /* 1280, */
! 4914: "011011010", /* 1344, */
! 4915: "011011011", /* 1408, */
! 4916: "010011000", /* 1472, */
! 4917: "010011001", /* 1536, */
! 4918: "010011010", /* 1600, */
! 4919: "011000", /* 1664, */
! 4920: "010011011", /* 1728 */
! 4921: /* extended length: */
! 4922: "00000001000", /* 1792, */
! 4923: "00000001100", /* 1856, */
! 4924: "00000001101", /* 1920, */
! 4925: "000000010010", /* 1984, */
! 4926: "000000010011", /* 2048, */
! 4927: "000000010100", /* 2112, */
! 4928: "000000010101", /* 2176, */
! 4929: "000000010110", /* 2240, */
! 4930: "000000010111", /* 2304, */
! 4931: "000000011100", /* 2368, */
! 4932: "000000011101", /* 2432, */
! 4933: "000000011110", /* 2496, */
! 4934: "000000011111", /* 2560 */
! 4935: NULL /* are there codes beyond 2560? */
! 4936: };
! 4937: /* no. bits in the codes in the above table */
! 4938: static short bitcwht[] = {
! 4939: 8,6,4,4,4,4,4,4,5,5, /* 0 - 9 */
! 4940: 5,5,6,6,6,6,6,6,7,7, /* 10 - 19 */
! 4941: 7,7,7,7,7,7,7,7,7,8, /* 20 - 29 */
! 4942: 8,8,8,8,8,8,8,8,8,8, /* 30 - 39 */
! 4943: 8,8,8,8,8,8,8,8,8,8, /* 40 - 49 */
! 4944: 8,8,8,8,8,8,8,8,8,8, /* 50 - 59 */
! 4945: 8,8,8,8, /* 60 - 63 */
! 4946: 12, /* EOL */
! 4947: 5,5, /* 64,128 */
! 4948: 6, /* 192 */
! 4949: 7, /* 256 */
! 4950: 8,8,8,8,8,8, /* 320 - 640 */
! 4951: 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, /* 704 - 1600 */
! 4952: 6, /* 1664 */
! 4953: 9, /* 1728 */
! 4954: 11,11,11, /* 1792,1856,1920 */
! 4955: 12,12,12,12,12,12,12,12,12,12, /* 1984 - 2560 */
! 4956: /* for codes over 2560 */
! 4957: 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
! 4958: -1
! 4959: };
! 4960:
! 4961: /* 2-D codes (indices into code2d[] table) */
! 4962: #define i2D_V0 0
! 4963: #define i2D_VR1 1
! 4964: #define i2D_VR2 2
! 4965: #define i2D_VR3 3
! 4966: #define i2D_VL1 4
! 4967: #define i2D_VL2 5
! 4968: #define i2D_VL3 6
! 4969: #define i2D_PASS 7
! 4970: #define i2D_HORIZ 8
! 4971: #define i2D_EOL 9
! 4972:
! 4973: static char *code2d[] = {
! 4974: "1", /* V0 */
! 4975: "011", /* VR1 */
! 4976: "000011", /* VR2 */
! 4977: "0000011", /* VR3 */
! 4978: "010", /* VL1 */
! 4979: "000010", /* VL2 */
! 4980: "0000010", /* VL3 */
! 4981: "0001", /* PASS */
! 4982: "001", /* HORIZ */
! 4983: EOLSTRING, /* EOL */
! 4984: NULL };
! 4985: static short bitc2d[] = { 1,3,6,7,3,6,7,4,3,12 };
! 4986:
! 4987: #define EOL0STRING "0000000000010"
! 4988: #define EOL1STRING "0000000000011"
! 4989: #define EOFB "000000000001000000000001"
! 4990:
! 4991: static char *spare1d[] = {
! 4992: "000000001", /* 0, */
! 4993: "0000000001", /* 0, */
! 4994: "00000000001", /* 0 */
! 4995: NULL };
! 4996: static char *spare2d[] = {
! 4997: "0000001", /* 0, */
! 4998: "00000001", /* 0, */
! 4999: "000000001", /* 0, */
! 5000: "0000000001", /* 0, */
! 5001: "00000000001", /* 0 */
! 5002: NULL };
! 5003:
! 5004: /* State-transition table for decoding CCITT G3-1 */
! 5005:
! 5006: /* bit colors; also, starting index in table of 1-D codes*/
! 5007: #define DST_color short
! 5008: #define DST_white 0
! 5009: #define DST_black 1
! 5010:
! 5011: #define flip_color(c) ((c)? 0: 1)
! 5012:
! 5013: #define DST_2d 2 /* starting index in table of 2-D codes */
! 5014:
! 5015: #define DST_state short /* state-id: index into DST_tbl.e[] */
! 5016: #define DST_state_NULL (-1)
! 5017: #define DST_state_ERROR (-2)
! 5018:
! 5019: #define DST_action int
! 5020: #define DST_action_NULL (-1)
! 5021: #define DST_action_ERROR (-2)
! 5022:
! 5023: /* transition in finite-state machine */
! 5024: typedef struct DST_transit {
! 5025: DST_action a; /* action to perform */
! 5026: DST_state s; /* next state */
! 5027: } DST_transit;
! 5028: typedef struct DST_entry {
! 5029: char p[MAXCODELEN+1]; /* code prefix so far (in ASCII) */
! 5030: short l; /* strlen(.p) */
! 5031: short z; /* no. of trailing "0"'s in .p */
! 5032: DST_transit t[2]; /* two transitions: on 0 & 1 */
! 5033: } DST_entry;
! 5034: typedef struct DST_table {
! 5035: int mny; /* no. entries so far */
! 5036: DST_entry *e; /* array in malloc space:
! 5037: e[DST_white] starts white 1-D codes;
! 5038: e[DST_black] starts black 1-D codes;
! 5039: e[DST_2d] starts 2-D codes */
! 5040: } DST_table;
! 5041: typedef struct DST_context {
! 5042: DST_color c; /* current run-color */
! 5043: int l; /* length of current code in bits: 0..(len-1) */
! 5044: DST_table *t; /* table */
! 5045: DST_state s; /* current state */
! 5046: DST_transit tr; /* current state/action */
! 5047: } DST_context;
! 5048:
! 5049:
! 5050: DST_table *ccitt_table();
! 5051: RLE_Line *g31_to_rlel();
! 5052: int rlel_to_g31();
! 5053: RLE_Line *g32_to_rlel();
! 5054: int rlel_to_g32();
! 5055: RLE_Line *g4_to_rlel();
! 5056: int rlel_to_g4();
! 5057: 0707070035351137061006640007620000050000010261170476773366600000600000010272CPU.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 5058: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 5059: /* The copyright notice does not imply actual or intended publication. */
! 5060: /* AUTHORS: */
! 5061: /* H. S. Baird - ATT-BL MH - first versions */
! 5062: /* T. Thompson - ATT-BL HO - portable versions */
! 5063: /* C. Macey - ATT-DSG LZ - portable versions */
! 5064:
! 5065: /* Specify the environment: CPU, OS, graphics, etc.
! 5066: This is an attempt to maintain a single master source tailorable at compile
! 5067: time, while encapsulating as many as possible of the required #if's and
! 5068: #ifdef's in this one file.
! 5069: OS-dependent #includes are triggered by these prior statements:
! 5070: #define LIBC_INCL 1 -- strcpy(), etc
! 5071: #define VALUES_INCL 1 -- math constants (PI etc)
! 5072: #define FILE_TREE_INCL 1 -- UNIX file-tree walking
! 5073: */
! 5074:
! 5075: /* CPUs with some support: */
! 5076: #define VAX 0
! 5077: #define CRAY 1
! 5078: #define SUN 2 /* including SPARC */
! 5079: #define ATT3B 3
! 5080: #define I386 4
! 5081: #define MIPS 5 /* including SGI */
! 5082:
! 5083: /*** Select CPU here: */
! 5084: #define CPU VAX
! 5085:
! 5086:
! 5087: /* Operating systems with some support: */
! 5088: #define V9_OS 1 /* ATT-BL research UNIX, 9th edition */
! 5089: #define SV_OS 2 /* ATT UNIX System V */
! 5090: #define SUN_OS 3 /* Sun OS 4.x */
! 5091:
! 5092: /*** Select OS here: */
! 5093: #define OS V9_OS
! 5094:
! 5095:
! 5096: /* Graphics display environments with some support: */
! 5097: #define NO_GRAPHICS 0 /* defeat all graphics */
! 5098: #define Y_GRAPHICS 1 /* the Y graphics interface (used in 1127 for Metheus) */
! 5099: #define SUN_GRAPHICS 2 /* Tim Thompson's Sun interface */
! 5100: #define X_GRAPHICS 3 /* Mark Tuomenoksa's X interface */
! 5101:
! 5102: /*** Select graphics environment here: */
! 5103: #define GRAPHICS Y_GRAPHICS
! 5104:
! 5105:
! 5106: /* OCR installation directory */
! 5107: #ifndef OCRDIR
! 5108: #define OCRDIR "/usr/ocr"
! 5109: #endif
! 5110:
! 5111: /*** Miscellaneous arcane options: best left alone **/
! 5112:
! 5113: #define FILE_TREE (1) /* set to zero to defeat UNIX file tree code */
! 5114:
! 5115:
! 5116: /*** END OF SELECTIONS ** The rest of this file merely implements their effects */
! 5117:
! 5118: /* define byte ordering in CPU */
! 5119:
! 5120: #if CPU == SUN || CPU == MIPS
! 5121: #define BIG_ENDIAN 1
! 5122: #endif
! 5123:
! 5124: /* deal with compilers that don't like (void *) */
! 5125:
! 5126: #if CPU == MIPS
! 5127: #define VOID char
! 5128: #else
! 5129: #define VOID void
! 5130: #endif
! 5131:
! 5132: /* include libc functions defs, if necessary */
! 5133:
! 5134: #if LIBC_INCL
! 5135:
! 5136: #if OS == V9_OS || CPU == CRAY
! 5137: #include <libc.h>
! 5138: #else
! 5139: #if OS == SV_OS || OS == SUN_OS || CPU == MIPS
! 5140: #include <string.h>
! 5141: #endif
! 5142: #endif
! 5143:
! 5144: #endif
! 5145:
! 5146: /* include values */
! 5147:
! 5148: #if VALUES_INCL
! 5149: #include <values.h>
! 5150: #endif
! 5151:
! 5152: /* UNIX file-tree-walk includes */
! 5153:
! 5154: #if FILE_TREE_INCL
! 5155:
! 5156: #if CPU==VAX || CPU==CRAY || CPU==MIPS
! 5157: #include <sys/types.h>
! 5158: #include <sys/stat.h>
! 5159: #include <ftw.h>
! 5160: #else
! 5161: #if CPU==SUN || CPU==I386
! 5162: #include <sys/types.h>
! 5163: #include <sys/stat.h>
! 5164: #include "myftw.h" /* T. Thompson's version */
! 5165: #endif
! 5166: #endif
! 5167:
! 5168: #endif
! 5169:
! 5170: #if CPU==SUN||CPU==ATT3B||CPU==MIPS||CPU==I386
! 5171: #define sgn(V) (((V)>0)? 1: (((V)<0)? -1: 0))
! 5172: #endif
! 5173:
! 5174: #if CPU==SUN||CPU==ATT3B||CPU==MIPS
! 5175: /* These are all big-endian machines */
! 5176: #define swapshortin(x) (((x)<<8)&0xff00)|(((x)>>8)&0xff)
! 5177: #define swapintin(x) \
! 5178: ((((x)<<24)&0xff000000)| \
! 5179: (((x)<<8) &0x00ff0000)| \
! 5180: (((x)>>8) &0x0000ff00)| \
! 5181: (((x)>>24)&0x000000ff))
! 5182: /* The order of bytes in an int */
! 5183: #define INDEX0 3
! 5184: #define INDEX1 2
! 5185: #define INDEX2 1
! 5186: #define INDEX3 0
! 5187: /* disable fast trick for picking out a short from an int */
! 5188: #define USESHIFT /* cf. skewlib.c */
! 5189: #else
! 5190: #define swapshortin(x) (x)
! 5191: #define swapintin(x) (x)
! 5192: #define INDEX0 0
! 5193: #define INDEX1 1
! 5194: #define INDEX2 2
! 5195: #define INDEX3 3
! 5196: #endif
! 5197:
! 5198: /* global max no. classes -- gradually being made dynamic everywhere */
! 5199: #if CPU==SUN
! 5200: #define MAX_CL 128
! 5201: #else
! 5202: #define MAX_CL 3200 /* adequate for JIS Level 1 */
! 5203: #endif
! 5204:
! 5205: /* include char types (is this really necessary?) */
! 5206:
! 5207: #if CTYPE_INCL
! 5208:
! 5209: #if CPU == SUN
! 5210: #include <string.h>
! 5211: #else
! 5212: #include <ctype.h>
! 5213: #endif
! 5214:
! 5215: #endif
! 5216:
! 5217: /* includes for atan2 special configurations */
! 5218:
! 5219: #if ATAN_INCL
! 5220:
! 5221: #if CPU == CRAY
! 5222: #define use_fast_atan2 F
! 5223: #include "CRAY.h"
! 5224: #else
! 5225: #define use_fast_atan2 T
! 5226: #endif
! 5227:
! 5228: #endif
! 5229:
! 5230: /* regular expression includes (fix to use standard regexp?) */
! 5231:
! 5232: #if REGEXP_INCL
! 5233:
! 5234: #if OS == V9_OS
! 5235: #include <regexp.h>
! 5236: #else
! 5237: #include "regexp.h"
! 5238: #endif
! 5239:
! 5240: #endif
! 5241:
! 5242: /* Use of the graphics display */
! 5243:
! 5244: #if CPU != CRAY
! 5245: #define SHOW_GRAPHICS 1
! 5246: #endif
! 5247:
! 5248: #ifndef PI
! 5249: #define PI 3.14159265358979323846
! 5250: #endif
! 5251: 0707070035351137071006640007620000050000010261230476773366600001000000027244Coord.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 5252: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 5253: /* The copyright notice does not imply actual or intended publication. */
! 5254: /* AUTHORS: */
! 5255: /* H. S. Baird - ATT-BL MH - first versions */
! 5256: /* T. J. Thompson - ATT-BL HO - improvements */
! 5257:
! 5258: /* Coord.c - function bodies for basic Coordinate geometry.
! 5259: See Coord.h for associated defines, typedefs, etc.
! 5260: */
! 5261:
! 5262: #include <stdio.h>
! 5263: #include <math.h>
! 5264: #include <string.h>
! 5265: #define ATAN_INCL 1
! 5266: #include "CPU.h"
! 5267: #include "boole.h"
! 5268: #include "Units.h"
! 5269: #include "Coord.h"
! 5270:
! 5271: /* Added by Tim Thompson ... */
! 5272: int Readvax = 0;
! 5273:
! 5274: VOID
! 5275: setreadvax()
! 5276: {
! 5277: char *getenv();
! 5278: char *p = getenv("READVAX");
! 5279: /* any non-null value of READVAX will set it */
! 5280: if ( p!=NULL && strlen(p)>0 )
! 5281: Readvax = 1;
! 5282: }
! 5283:
! 5284: /* ... */
! 5285:
! 5286: /* Convert a real value, a units specification, and a resolution
! 5287: into a value in scanner coordinates. */
! 5288: int vto_scoor(v,u,r)
! 5289: double v; /* value in special units */
! 5290: char u; /* units: one of UNITS (see ric.h) */
! 5291: int r; /* resolution in pixels/inch */
! 5292: { int c;
! 5293: switch(u) {
! 5294: case 'i': /* inches */
! 5295: c = (int)(v*r + 0.5);
! 5296: break;
! 5297: case 'c': /* cm */
! 5298: c = (int)((v*r/2.54) + 0.5);
! 5299: break;
! 5300: case 'p': /* points */
! 5301: c = (int)((v*INCHES_PER_POINT*r) + 0.5);
! 5302: break;
! 5303: case 'P': /* picas */
! 5304: c = (int)((v*12.0*INCHES_PER_POINT*r) + 0.5);
! 5305: break;
! 5306: case 's': /* scanner pixel (Scoor) */
! 5307: case 'u': /* basic unit */
! 5308: c = (int)(v + 0.5);
! 5309: break;
! 5310: default:
! 5311: c = (int)(v + 0.5);
! 5312: break;
! 5313: };
! 5314: return(c);
! 5315: }
! 5316:
! 5317: /* Return pointer to empty Sp from malloc space */
! 5318: Sp *alloc_sp()
! 5319: { Sp *spp;
! 5320: if((spp=(Sp *)malloc(sizeof(Sp)))==NULL)
! 5321: abort("alloc_sp: can't");
! 5322: *spp = zero_Sp;
! 5323: return(spp);
! 5324: }
! 5325:
! 5326: /* Free Sp from malloc space */
! 5327: free_sp(spp)
! 5328: Sp *spp;
! 5329: { free(spp);
! 5330: }
! 5331:
! 5332: Sp *ato_sp(s)
! 5333: char *s;
! 5334: { char *d;
! 5335: static Sp p;
! 5336: char *p_x,*p_y;
! 5337: #define SP_DELIM "(), "
! 5338: d = strdup(s);
! 5339: p_x = strtok(d,SP_DELIM);
! 5340: p_y = strtok((char *)0,SP_DELIM);
! 5341: if(p_x==NULL||p_y==NULL)
! 5342: {free(d); return(NULL);};
! 5343: p.x = atoi(p_x);
! 5344: p.y = atoi(p_y);
! 5345: free(d);
! 5346: return(&p);
! 5347: }
! 5348:
! 5349: char *sp_toa(sp)
! 5350: Sp *sp;
! 5351: #define sp_toa_distinct (5)
! 5352: { static char s[sp_toa_distinct][40];
! 5353: static int sp_toa_cur = -1;
! 5354: sp_toa_cur = (sp_toa_cur+1)%sp_toa_distinct;
! 5355: sprintf(s[sp_toa_cur],"(%d,%d)",sp->x,sp->y);
! 5356: return(s[sp_toa_cur]);
! 5357: }
! 5358:
! 5359: /* Read a list of Sp's (in ascii) from file *fp, into set *spsp */
! 5360: frda_sps(fp,spsp)
! 5361: FILE *fp;
! 5362: Sps *spsp;
! 5363: #define MAX_SPS_LINE (80)
! 5364: { Sp *spp,**bb;
! 5365: long seek;
! 5366: char line[MAX_SPS_LINE+1];
! 5367: *spsp = empty_Sps;
! 5368: seek = ftell(fp);
! 5369: /* count all points quickly, in advance */
! 5370: while(!feof(fp)) {
! 5371: line[0] = '\0';
! 5372: fgets(line,MAX_SPS_LINE,fp);
! 5373: if(strlen(line)>0) {
! 5374: spsp->mny++;
! 5375: };
! 5376: };
! 5377: if((spsp->pa=(Sp **)malloc((spsp->mny+1)*sizeof(Sp *)))==NULL)
! 5378: abort("frda_sps: can't alloc spsp->pa[%d]",spsp->mny+1);
! 5379: /* next, reread points */
! 5380: fseek(fp,(long)seek,0);
! 5381: bb=spsp->pa;
! 5382: while(!feof(fp)) {
! 5383: line[0] = '\0';
! 5384: fgets(line,MAX_SPS_LINE,fp);
! 5385: if(strlen(line)>0) {
! 5386: *(spp = alloc_sp()) = *ato_sp(line);
! 5387: *(bb++) = spp;
! 5388: };
! 5389: };
! 5390: *bb = NULL;
! 5391: }
! 5392:
! 5393: err_sps(p)
! 5394: Sps *p;
! 5395: { int i;
! 5396: Sp **s;
! 5397: fprintf(stderr,"Sps: %d points: ",p->mny);
! 5398: if(p->mny>0) for(s=p->pa; (*s)!=NULL; s++) {
! 5399: fprintf(stderr,"%s ",sp_toa(*s));
! 5400: };
! 5401: fprintf(stderr,"\n");
! 5402: }
! 5403:
! 5404: Sp *append_sp_sps(sp,sps)
! 5405: Sp *sp;
! 5406: Sps *sps;
! 5407: { if(sps->mny>0) {
! 5408: if((sps->pa=(Sp **)realloc(sps->pa,(sps->mny+2)*sizeof(Sp *)))==NULL)
! 5409: abort("append_sp_sps: can't realloc sps->pa[%d]",sps->mny+2);
! 5410: }
! 5411: else { sps->mny=0;
! 5412: if((sps->pa=(Sp **)malloc((sps->mny+2)*sizeof(Sp *)))==NULL)
! 5413: abort("append_sp_sps: can't alloc sps->pa[%d]",sps->mny+2);
! 5414: };
! 5415: sps->pa[sps->mny++] = sp;
! 5416: sps->pa[sps->mny] = NULL;
! 5417: }
! 5418:
! 5419: /* Return pointer to local static Sps which holds a duplicate of the
! 5420: given Sps (all contents are freshly malloc'ed) */
! 5421: Sps *dup_sps(old)
! 5422: Sps *old;
! 5423: { static Sps new;
! 5424: Sp **o,**n;
! 5425: if(old->mny>0) {
! 5426: new.mny = old->mny;
! 5427: if((new.pa=(Sp **)malloc((new.mny+1)*sizeof(Sp *)))==NULL)
! 5428: abort("dup_sps: can't alloc new.pa[%d]",new.mny+1);
! 5429: for(o=old->pa,n=new.pa; *o!=NULL; o++,n++) {
! 5430: *(*n = alloc_sp()) = **o;
! 5431: };
! 5432: *n = NULL;
! 5433: }
! 5434: else new = empty_Sps;
! 5435: return(&new);
! 5436: }
! 5437:
! 5438: free_sps(p)
! 5439: Sps *p;
! 5440: { if(p->pa!=NULL) free(p->pa);
! 5441: *p = empty_Sps;
! 5442: }
! 5443:
! 5444: Sp *append_sp_spa(sp,spa)
! 5445: Sp *sp;
! 5446: Spa *spa;
! 5447: { if(spa->mny>0) {
! 5448: if((spa->a=(Sp *)realloc(spa->a,(spa->mny+1)*sizeof(Sp)))==NULL)
! 5449: abort("append_sp_spa: can't alloc spa->a[%d]",spa->mny+1);
! 5450: }
! 5451: else { spa->mny=0;
! 5452: if((spa->a=(Sp *)malloc((spa->mny+1)*sizeof(Sp)))==NULL)
! 5453: abort("append_sp_spa: can't alloc spa->a[%d]",spa->mny+1);
! 5454: };
! 5455: spa->a[spa->mny++] = *sp;
! 5456: }
! 5457:
! 5458: err_spa(p)
! 5459: Spa *p;
! 5460: { int i;
! 5461: Sp *sp;
! 5462: fprintf(stderr,"Spa: %d points: ",p->mny);
! 5463: for(i=0,sp=p->a;i<p->mny;i++,sp++) {
! 5464: fprintf(stderr,"%s ",sp_toa(sp));
! 5465: };
! 5466: fprintf(stderr,"\n");
! 5467: }
! 5468:
! 5469: free_spa(p)
! 5470: Spa *p;
! 5471: { if(p->a!=NULL) free(p->a);
! 5472: *p = empty_Spa;
! 5473: }
! 5474:
! 5475: /* Rotate the Scanner point `(x,y') about origin `*orp' by angle `ang',
! 5476: and return pointer to the result. This is slow, but no matter. */
! 5477: Sp *rotate_Sp(ang,orp,x,y)
! 5478: double ang;
! 5479: Sp *orp;
! 5480: int x,y;
! 5481: { static Sp res;
! 5482: Sp of;
! 5483: of.x = x - orp->x; of.y = y - orp->y;
! 5484: res.x = (short)(((cos(ang)*of.x - sin(ang)*of.y)) + orp->x + 0.5);
! 5485: res.y = (short)(((sin(ang)*of.x + cos(ang)*of.y)) + orp->y + 0.5);
! 5486: return(&res);
! 5487: }
! 5488:
! 5489: /* Horizontally shear the Scanner point `(x,y') about origin `*orp' by shear
! 5490: angle `ang', and return pointer to the result. `Ang' is close to 90 degrees.
! 5491: This is slow, but no matter. */
! 5492: Sp *hshear_Sp(ang,orp,x,y)
! 5493: double ang;
! 5494: Sp *orp;
! 5495: int x,y;
! 5496: { static Sp res;
! 5497: Scoor of_y,tr_x;
! 5498: res.x = (short)(orp->x - (y - orp->y)*tan(ang-(90.0*DtoR)) + 0.5);
! 5499: res.y = orp->y;
! 5500: return(&res);
! 5501: }
! 5502:
! 5503: /* Return pointer to initialized Edge from malloc space */
! 5504: Edge *alloc_edge()
! 5505: { Edge *ep;
! 5506: if((ep=(Edge *)malloc(sizeof(Edge)))==NULL)
! 5507: abort("alloc_edge: can't");
! 5508: *ep = empty_Edge;
! 5509: return(ep);
! 5510: }
! 5511:
! 5512: /* Free Edge from malloc space */
! 5513: free_edge(ep)
! 5514: Edge *ep;
! 5515: { free(ep);
! 5516: }
! 5517:
! 5518: char *edge_toa(ep)
! 5519: Edge *ep;
! 5520: { static char s[40];
! 5521: strcpy(s,sp_toa(&(ep->a)));
! 5522: strcat(s,"-");
! 5523: strcat(s,sp_toa(&(ep->b)));
! 5524: return(s);
! 5525: }
! 5526:
! 5527: Edge *ato_edge(s)
! 5528: char *s;
! 5529: { char *d;
! 5530: static Edge e;
! 5531: char *a_x,*a_y,*b_x,*b_y;
! 5532: #define EDGE_DELIM "(),- "
! 5533: d = strdup(s);
! 5534: a_x = strtok(d,EDGE_DELIM);
! 5535: a_y = strtok((char *)0,EDGE_DELIM);
! 5536: b_x = strtok((char *)0,EDGE_DELIM);
! 5537: b_y = strtok((char *)0,EDGE_DELIM);
! 5538: if(a_x==NULL||a_y==NULL||b_x==NULL||b_y==NULL)
! 5539: {free(d); return(NULL);};
! 5540: e.a.x = atoi(a_x);
! 5541: e.a.y = atoi(a_y);
! 5542: e.b.x = atoi(b_x);
! 5543: e.b.y = atoi(b_y);
! 5544: free(d);
! 5545: return(&e);
! 5546: }
! 5547:
! 5548: /* Return pointer to empty Bbx from malloc space */
! 5549: Bbx *alloc_bbx()
! 5550: { Bbx *bxp;
! 5551: if((bxp=(Bbx *)malloc(sizeof(Bbx)))==NULL)
! 5552: abort("alloc_bbx: can't");
! 5553: *bxp = empty_Bbx;
! 5554: return(bxp);
! 5555: }
! 5556:
! 5557: /* Free Bbx from malloc space */
! 5558: free_bbx(bxp)
! 5559: Bbx *bxp;
! 5560: { free(bxp);
! 5561: }
! 5562:
! 5563: char *bbx_toa(bxp)
! 5564: Bbx *bxp;
! 5565: { static char s[40];
! 5566: strcpy(s,sp_toa(&(bxp->a)));
! 5567: strcat(s,sp_toa(&(bxp->b)));
! 5568: return(s);
! 5569: }
! 5570:
! 5571: Bbx *ato_bbx(s)
! 5572: char *s;
! 5573: { char *d;
! 5574: static Bbx bx;
! 5575: char *a_x,*a_y,*b_x,*b_y;
! 5576: #define BBX_DELIM "(), "
! 5577: d = strdup(s);
! 5578: a_x = strtok(d,BBX_DELIM);
! 5579: a_y = strtok((char *)0,BBX_DELIM);
! 5580: b_x = strtok((char *)0,BBX_DELIM);
! 5581: b_y = strtok((char *)0,BBX_DELIM);
! 5582: if(a_x==NULL||a_y==NULL||b_x==NULL||b_y==NULL)
! 5583: {free(d); return(NULL);};
! 5584: bx.a.x = atoi(a_x);
! 5585: bx.a.y = atoi(a_y);
! 5586: bx.b.x = atoi(b_x);
! 5587: bx.b.y = atoi(b_y);
! 5588: free(d);
! 5589: return(&bx);
! 5590: }
! 5591:
! 5592: Bbx *expand_bbx(bxp,X)
! 5593: Bbx *bxp;
! 5594: int X; /* expansion code */
! 5595: { static Bbx xbx;
! 5596: xbx = *bxp;
! 5597: switch(X) {
! 5598: case -3:
! 5599: xbx.a.x += 2;
! 5600: xbx.a.y += 2;
! 5601: xbx.b.x -= 1;
! 5602: xbx.b.y -= 1;
! 5603: break;
! 5604: case -2:
! 5605: xbx.a.x += 1;
! 5606: xbx.a.y += 1;
! 5607: xbx.b.x -= 1;
! 5608: xbx.b.y -= 1;
! 5609: break;
! 5610: case -1:
! 5611: xbx.a.x += 1;
! 5612: xbx.a.y += 1;
! 5613: break;
! 5614: case 0:
! 5615: break;
! 5616: case 1:
! 5617: xbx.b.x += 1;
! 5618: xbx.b.y += 1;
! 5619: break;
! 5620: case 2:
! 5621: xbx.a.x -= 1;
! 5622: xbx.a.y -= 1;
! 5623: xbx.b.x += 1;
! 5624: xbx.b.y += 1;
! 5625: break;
! 5626: case 3:
! 5627: xbx.a.x -= 1;
! 5628: xbx.a.y -= 1;
! 5629: xbx.b.x += 2;
! 5630: xbx.b.y += 2;
! 5631: break;
! 5632: default:
! 5633: break;
! 5634: };
! 5635: return(&xbx);
! 5636: }
! 5637:
! 5638: /* Predicate: Is most of Bbx 1 inside Bbx 2? ``Most'' is defined
! 5639: as more than half of the first Bbx's area inside BBx 2.*/
! 5640: boolean bbx_inside_most(b1,b2)
! 5641: Bbx *b1,*b2;
! 5642: { struct { /* overlap between blob box and selection box */
! 5643: Bbx bx; /* Bbx of intersection */
! 5644: Sp sd; /* side-lengths of overlap box, >=0 */
! 5645: long area; /* area is square pixels, >=0 */
! 5646: } ov;
! 5647: if(!bbx_inside_any(b1,b2)) return(F);
! 5648: else if(bbx_inside_all(b1,b2)) return(T);
! 5649: else { /* compute overlap box */
! 5650: ov.bx.a.x = ((b1)->a.x>(b2)->a.x)? (b1)->a.x: (b2)->a.x;
! 5651: ov.bx.a.y = ((b1)->a.y>(b2)->a.y)? (b1)->a.y: (b2)->a.y;
! 5652: ov.bx.b.x = ((b1)->b.x<(b2)->b.x)? (b1)->b.x: (b2)->b.x;
! 5653: ov.bx.b.y = ((b1)->b.y<(b2)->b.y)? (b1)->b.y: (b2)->b.y;
! 5654: ov.sd.x = bbx_wid(&ov.bx); if(ov.sd.x<0) ov.sd.x=0;
! 5655: ov.sd.y = bbx_hgt(&ov.bx); if(ov.sd.y<0) ov.sd.y=0;
! 5656: ov.area = ov.sd.x*ov.sd.y;
! 5657: return( (ov.area>0) && ( 2*ov.area > bbx_area(b1) ) );
! 5658: };
! 5659: }
! 5660:
! 5661: Bbx *translate_bbx(bxp,off)
! 5662: Bbx *bxp;
! 5663: Sp off;
! 5664: { static Bbx res;
! 5665: res.a.x = bxp->a.x + off.x;
! 5666: res.a.y = bxp->a.y + off.y;
! 5667: res.b.x = bxp->b.x + off.x;
! 5668: res.b.y = bxp->b.y + off.y;
! 5669: return(&res);
! 5670: }
! 5671:
! 5672: /* Free Bbxs (but not the contents) */
! 5673: free_bbxs(bxsp)
! 5674: Bbxs *bxsp;
! 5675: { Bbx **b;
! 5676: if(bxsp->mny>0) {
! 5677: if(bxsp->pa!=NULL) free(bxsp->pa);
! 5678: };
! 5679: *bxsp = empty_Bbxs;
! 5680: }
! 5681:
! 5682: /* Free Bbxs (and the individually-malloc'ed contents) */
! 5683: free_bbxs_etc(bxsp)
! 5684: Bbxs *bxsp;
! 5685: { Bbx **b;
! 5686: if(bxsp->mny>0) {
! 5687: for(b=bxsp->pa; (*b)!=NULL; b++) free(*b);
! 5688: if(bxsp->pa!=NULL) free(bxsp->pa);
! 5689: };
! 5690: *bxsp = empty_Bbxs;
! 5691: }
! 5692:
! 5693: /* Return pointer to local static Bbxs which holds a duplicate of the
! 5694: given Bbxs (all contents are freshly malloc'ed) */
! 5695: Bbxs *dup_bbxs(old)
! 5696: Bbxs *old;
! 5697: { static Bbxs new;
! 5698: Bbx **o,**n;
! 5699: if(old->mny>0) {
! 5700: new.mny = old->mny;
! 5701: new.alloc = old->alloc;
! 5702: new.incr = old->incr;
! 5703: if((new.pa=(Bbx **)malloc((new.alloc)*sizeof(Bbx *)))==NULL)
! 5704: abort("dup_bbxs: can't alloc new.pa[%d]",new.alloc);
! 5705: for(o=old->pa,n=new.pa; *o!=NULL; o++,n++) {
! 5706: *(*n = alloc_bbx()) = **o;
! 5707: };
! 5708: *n = NULL;
! 5709: }
! 5710: else new = empty_Bbxs;
! 5711: return(&new);
! 5712: }
! 5713:
! 5714: Bbx *append_bbx(bxp,bxsp)
! 5715: Bbx *bxp;
! 5716: Bbxs *bxsp;
! 5717: { if(bxsp->mny>0) {
! 5718: if((bxsp->mny+2)>bxsp->alloc) {
! 5719: bxsp->alloc += bxsp->incr;
! 5720: if( ( bxsp->pa =
! 5721: (Bbx **)realloc(bxsp->pa,bxsp->alloc*sizeof(Bbx *)) )
! 5722: ==NULL )
! 5723: abort("append_bbx: can't alloc bxsp->pa[%d]",bxsp->alloc);
! 5724: };
! 5725: }
! 5726: else { bxsp->mny=0;
! 5727: if(bxsp->pa!=NULL) free(bxsp->pa);
! 5728: bxsp->alloc=0;
! 5729: while((bxsp->mny+2)>bxsp->alloc) bxsp->alloc += bxsp->incr;
! 5730: if((bxsp->pa=(Bbx **)malloc(bxsp->alloc*sizeof(Bbx *)))==NULL)
! 5731: abort("append_bbx: can't alloc bxsp->a[%d]",bxsp->alloc);
! 5732: };
! 5733: bxsp->pa[bxsp->mny++] = bxp;
! 5734: bxsp->pa[bxsp->mny] = NULL;
! 5735: }
! 5736:
! 5737: frda_bbxs(fp,bxsp)
! 5738: FILE *fp;
! 5739: Bbxs *bxsp;
! 5740: #define MAX_BBX_LINE (80)
! 5741: { Bbx *bxp,**bb;
! 5742: long seek;
! 5743: char line[MAX_BBX_LINE+1];
! 5744: *bxsp = empty_Bbxs;
! 5745: seek = ftell(fp);
! 5746: /* count all boxes quickly, in advance */
! 5747: while(!feof(fp)) {
! 5748: line[0] = '\0';
! 5749: fgets(line,MAX_BBX_LINE,fp);
! 5750: if(strlen(line)>0) {
! 5751: bxsp->mny++;
! 5752: };
! 5753: };
! 5754: if((bxsp->pa=(Bbx **)malloc((bxsp->mny+1)*sizeof(Bbx *)))==NULL)
! 5755: abort("frda_bbxs: can't alloc bxsp->pa[%d]",bxsp->mny+1);
! 5756: bxsp->alloc = bxsp->mny+1;
! 5757: /* next, reread boxes */
! 5758: fseek(fp,(long)seek,0);
! 5759: bb=bxsp->pa;
! 5760: while(!feof(fp)) {
! 5761: line[0] = '\0';
! 5762: fgets(line,MAX_BBX_LINE,fp);
! 5763: if(strlen(line)>0) {
! 5764: *(bxp = alloc_bbx()) = *ato_bbx(line);
! 5765: *(bb++) = bxp;
! 5766: };
! 5767: };
! 5768: *bb = NULL;
! 5769: }
! 5770:
! 5771: fwra_bbxs(fp,bxsp)
! 5772: FILE *fp;
! 5773: Bbxs *bxsp;
! 5774: { Bbx **b;
! 5775: if(bxsp->mny>0) for(b=bxsp->pa; *b!=NULL; b++) {
! 5776: fputs(bbx_toa(*b),fp);
! 5777: fputs("\n",fp);
! 5778: };
! 5779: fflush(fp);
! 5780: }
! 5781: 0707070035351137101006640007620000050000010261240476773366600001000000017772Coord.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 5782: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 5783: /* The copyright notice does not imply actual or intended publication. */
! 5784: /* AUTHORS: */
! 5785: /* H. S. Baird - ATT-BL MH - first versions */
! 5786: /* Coord.h - defines, typedefs, Inits, empties, and function declarations
! 5787: for basic Coordinate geometry data items.
! 5788: See Coord.c for associated functions.
! 5789: */
! 5790:
! 5791: /* Round signed floating-pt no. F:
! 5792: (a) ROUND - to nearest integer;
! 5793: (b) ROUND_UP - up to next int;
! 5794: (c) ROUND_DN - down to prior int.
! 5795: Evaluates the argument exactly once. */
! 5796: static double _round,_round_up,_round_dn;
! 5797: #define ROUND(F) ((int)(((_round=(F))>=0.0)? _round+0.5: _round-0.5))
! 5798: #define ROUND_UP(F) ((int)(((_round_up=(F))>=0.0)? _round_up+0.999999: _round_up))
! 5799: #define ROUND_DN(F) ((int)(((_round_dn=(F))>=0.0)? _round_dn: _round_dn-0.999999))
! 5800:
! 5801: /* The basic unit is the scanner pixel, located in the X,Y plane. As in many
! 5802: graphics coordinate systems, X increases left-to-right, while Y increases
! 5803: top-down. Pixel coordinates are usually integer values. The physical extent
! 5804: of integer coordinate `x' along the real X-axis is the half-open interval
! 5805: [x,x+1), and similarly for Y. The actual digitizing resolution (e.g.
! 5806: pixels/inch) represented can vary from document to document, and is almost
! 5807: always known to the algorithms. X & Y resolution can be different, though
! 5808: for simplicity of discussion we will usually assume that they are equal,
! 5809: i.e. that pixels are square. Thus pixel (x,y) may be thought of as the region
! 5810: [x,x+1)X[y,y+1) in the real plane.
! 5811: Half-pixel resolution is also supported, with its own data types for
! 5812: clarity. However, to avoid distracting struggles with the type system, they
! 5813: are for the most part #defined to be identical to ordinary coordinates. The
! 5814: principle effect is that the limits of scanner coordinates have been halved
! 5815: to allow for safe use of half-pixels everywhere. (This still permits images
! 5816: 80 inches square at 400 pixels/inch, assuming `short' is at least 16-bit 2's
! 5817: complement.)
! 5818: Half-pixel coordinates can also be used to describe boundaries of regions,
! 5819: as a set of ideal point locations at the corners and edge midpoints of pixels.
! 5820: The half-pixel data type is used; boundary points are identified by flags
! 5821: in the Bdy "boundary" structure, and may be displayed differently. */
! 5822:
! 5823: #define Scoor short /* Scanner pixel coordinate value */
! 5824: #define Hcoor Scoor /* Half-pixel coordinate value */
! 5825: #define Bcoor Hcoor /* Half-pixel boundary coordinate value */
! 5826:
! 5827: /* Each Scoor value `v' is associated of course with two Hcoor values `a' < `b'.
! 5828: Conventionally, the physical extent of the `a' half-coordinate is the real
! 5829: interval [v,v+0.5), and `b' is [v+0.5,v+1). */
! 5830: #define StoHa(S) ((S)*2)
! 5831: #define StoHb(S) ((S)*2+1)
! 5832: #define HtoS(H) ((H)/2)
! 5833:
! 5834: /* The 3 half-pixel boundary points of a pixel coordinate `C' are: */
! 5835: #define StoBa(S) (StoHa((S))) /* minimum of interval */
! 5836: #define StoBb(S) (StoHb((S))) /* midpoint of interval */
! 5837: #define StoBc(S) (StoHa((S)+1)) /* maximum of interval */
! 5838:
! 5839: #define Scoor_MIN (SHRT_MIN/2) /* minimum possible value */
! 5840: #define Scoor_MAX (SHRT_MAX/2) /* maximum possible value */
! 5841:
! 5842: #define Hcoor_MIN (SHRT_MIN) /* minimum possible value */
! 5843: #define Hcoor_MAX (SHRT_MAX) /* maximum possible value */
! 5844:
! 5845: #define fwri_Scoor(F,V) fwri_int2((F),(V))
! 5846: #define frdi_Scoor(F) frdi_int2(F)
! 5847:
! 5848: #define fwri_Hcoor(F,V) fwri_int2((F),(V))
! 5849: #define frdi_Hcoor(F) frdi_int2(F)
! 5850:
! 5851: #define fwri_Bcoor(F,V) fwri_int2((F),(V))
! 5852: #define frdi_Bcoor(F) frdi_int2(F)
! 5853:
! 5854: typedef struct Sp { /* point: pixel address */
! 5855: Scoor x; /* increases left-to-right: Scoor_MIN is left of image */
! 5856: Scoor y; /* increases down: Scoor_MIN is top of image */
! 5857: } Sp;
! 5858: #define Hp Sp /* Half-pixel point */
! 5859:
! 5860: #define Init_Zero_Sp {0,0}
! 5861: #define Init_Min_Sp {Scoor_MIN,Scoor_MIN}
! 5862: #define Init_Max_Sp {Scoor_MAX,Scoor_MAX}
! 5863:
! 5864: #if MAIN
! 5865: Sp zero_Sp = Init_Zero_Sp;
! 5866: #else
! 5867: extern Sp zero_Sp;
! 5868: #endif
! 5869:
! 5870: #define fwri_Sp(F,P) { fwri_Scoor((F),(P)->x); fwri_Scoor((F),(P)->y); }
! 5871: #define frdi_Sp(F,P) (feof(F)? 0: ( \
! 5872: (P)->x=frdi_Scoor(F), \
! 5873: (P)->y=frdi_Scoor(F), \
! 5874: (ferror(F)? -errno: 1) ) )
! 5875:
! 5876: /* Is Sp *p1 exactly equal to Sp *p2? */
! 5877: #define sp_eq(p1,p2) ( \
! 5878: ((p1)->x == (p2)->x) \
! 5879: && ((p1)->y == (p2)->y) \
! 5880: )
! 5881:
! 5882: typedef struct Sps { /* Set of Points */
! 5883: int mny; /* no. points (mny==0 ==> pa==NULL) */
! 5884: Sp **pa; /* NULL-terminated Sp *pa[mny+1] (malloc space)*/
! 5885: } Sps;
! 5886:
! 5887: #define Init_Sps {0,NULL}
! 5888: #if MAIN
! 5889: Sps empty_Sps = Init_Sps;
! 5890: #else
! 5891: extern Sps empty_Sps;
! 5892: #endif
! 5893:
! 5894: typedef struct Spa { /* array of Points */
! 5895: int mny; /* no. points in array */
! 5896: Sp *a; /* Sp a[mny] (malloc space)*/
! 5897: } Spa;
! 5898: /** #define Pointa Spa **/ /* OBSOLESCENT */
! 5899:
! 5900: #define Init_Spa {0,NULL}
! 5901: #if MAIN
! 5902: Spa empty_Spa = Init_Spa;
! 5903: #else
! 5904: extern Spa empty_Spa;
! 5905: #endif
! 5906:
! 5907: /* An edge is an ordered pair of vertices. */
! 5908: typedef struct Edge {
! 5909: Sp a,b; /* endpoints */
! 5910: } Edge;
! 5911:
! 5912: #define Init_Edge {Init_Zero_Sp,Init_Zero_Sp}
! 5913: #if MAIN
! 5914: Edge empty_Edge = Init_Edge;
! 5915: #else
! 5916: extern Edge empty_Edge;
! 5917: #endif
! 5918:
! 5919: #define fwri_Edge(F,P) { fwri_Sp((F),&((P)->a)); fwri_Sp((F),&((P)->b)); }
! 5920: #define frdi_Edge(F,P) ( feof(F)? 0: ( \
! 5921: frdi_Sp(F,&((P)->a)), \
! 5922: frdi_Sp(F,&((P)->b)), \
! 5923: (ferror(F)? -errno: 1) ) )
! 5924:
! 5925: /* A bounding box is a rectangle */
! 5926: typedef struct { /* bounding box: inclusive of boundary values */
! 5927: Sp a; /* top-left corner */
! 5928: Sp b; /* bottom-right corner */
! 5929: } Bbx;
! 5930:
! 5931: typedef struct DSp { /* point: pixel address */
! 5932: double x; /* increases down the page, MinScoor at top */
! 5933: double y; /* increases across the page, MinScoor at left */
! 5934: } DSp;
! 5935:
! 5936: #define Init_Bbx {Init_Max_Sp,Init_Min_Sp}
! 5937: #define Init_Max_Bbx {Init_Min_Sp,Init_Max_Sp}
! 5938: #if MAIN
! 5939: Bbx empty_Bbx = Init_Bbx;
! 5940: Bbx max_Bbx = Init_Max_Bbx;
! 5941: #else
! 5942: extern Bbx empty_Bbx;
! 5943: extern Bbx max_Bbx;
! 5944: #endif
! 5945:
! 5946: #define fwri_Bbx(F,P) { fwri_Sp((F),&((P)->a)); fwri_Sp((F),&((P)->b)); }
! 5947: #define frdi_Bbx(F,P) ( feof(F)? 0: ( \
! 5948: frdi_Sp(F,&((P)->a)), \
! 5949: frdi_Sp(F,&((P)->b)), \
! 5950: (ferror(F)? -errno: 1) ) )
! 5951:
! 5952: /* OBSOLESCENT: */
! 5953: #if MAIN
! 5954: Bbx null_Bbx = {Init_Max_Sp,Init_Min_Sp};
! 5955: #else
! 5956: extern Bbx null_Bbx;
! 5957: #endif
! 5958:
! 5959: /* height, width, area of Bbx in pixels */
! 5960: #define bbx_hgt(bxp) ((bxp)->b.y-(bxp)->a.y+1)
! 5961: #define bbx_wid(bxp) ((bxp)->b.x-(bxp)->a.x+1)
! 5962: #define bbx_area(bxp) (bbx_hgt((bxp))*bbx_wid((bxp)))
! 5963:
! 5964: /* Is Bbx *b1 exactly equal to Bbx *b2? */
! 5965: #define bbx_eq(b1,b2) ( \
! 5966: ((b1)->a.x == (b2)->a.x) \
! 5967: && ((b1)->a.y == (b2)->a.y) \
! 5968: && ((b1)->b.x == (b2)->b.x) \
! 5969: && ((b1)->b.y == (b2)->b.y) \
! 5970: )
! 5971:
! 5972: /* Is Bbx *b1 wholly inside Bbx *b2? */
! 5973: #define bbx_inside_all(b1,b2) ( \
! 5974: ((b1)->a.x >= (b2)->a.x) \
! 5975: && ((b1)->a.y >= (b2)->a.y) \
! 5976: && ((b1)->b.x <= (b2)->b.x) \
! 5977: && ((b1)->b.y <= (b2)->b.y) \
! 5978: )
! 5979:
! 5980: /* Is any of Bbx *b1 inside Bbx *b2? */
! 5981: #define bbx_inside_any(b1,b2) ( \
! 5982: ((b1)->a.x <= (b2)->b.x) \
! 5983: && ((b1)->a.y <= (b2)->b.y) \
! 5984: && ((b1)->b.x >= (b2)->a.x) \
! 5985: && ((b1)->b.y >= (b2)->a.y) \
! 5986: )
! 5987:
! 5988: typedef struct Bbxs { /* A set of Bbxs */
! 5989: int mny; /* if mny==0, then pa==NULL */
! 5990: Bbx **pa; /* NULL-terminated array (in malloc space) of `mny+1'
! 5991: pointers to Bbxs (in malloc space) */
! 5992: int alloc; /* no. slots in pa[] actually allocated (>=mny+1) */
! 5993: int incr; /* no. slots in pa[] to reallocate at a time */
! 5994: } Bbxs;
! 5995:
! 5996: #define Init_Bbxs {0,NULL,0,512}
! 5997: #if MAIN
! 5998: Bbxs empty_Bbxs = Init_Bbxs;
! 5999: #else
! 6000: extern Bbxs empty_Bbxs;
! 6001: #endif
! 6002:
! 6003: Sp *alloc_sp();
! 6004: free_sp();
! 6005: char *sp_toa(); /* Sp to ascii printable string */
! 6006: Sp *ato_sp(); /* Sp from ascii printable string */
! 6007: frda_sps();
! 6008: Sps *dup_sps();
! 6009: Sp *append_sp_sps();
! 6010: Sp *append_sp_spa();
! 6011: Sp *rotate_Sp(); /* rotate Sp about given fixed-point */
! 6012: Sp *hshear_Sp(); /* horiz-shear Sp about given fixed-point */
! 6013: Edge *alloc_edge();
! 6014: free_edge();
! 6015: char *edge_toa(); /* Edge to ascii printable string */
! 6016: Edge *ato_edge(); /* Edge from ascii printable string */
! 6017: Bbx *alloc_bbx();
! 6018: Bbx *append_bbx();
! 6019: Bbxs *dup_bbxs();
! 6020: char *bbx_toa(); /* Bbx to ascii printable string */
! 6021: Bbx *ato_bbx(); /* Bbx from ascii printable string */
! 6022: Bbx *translate_bbx();
! 6023: boolean bbx_inside_most(); /* Is Bbx 1 mostly inside Bbx 2? */
! 6024: Bbx *expand_bbx();
! 6025: 0707070035351137111006640007620000050000010261300476773366600000700000016417Path.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 6026: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 6027: /* The copyright notice does not imply actual or intended publication. */
! 6028: /* AUTHORS: */
! 6029: /* H. S. Baird - ATT-BL MH - first versions */
! 6030: /* Path.c - Path functions */
! 6031:
! 6032: #include <errno.h>
! 6033: #include <stdio.h>
! 6034: #include <string.h>
! 6035: #define FILE_TREE_INCL 1
! 6036: #include "CPU.h"
! 6037: #include "Path.h"
! 6038:
! 6039: #define dbg_FTW (0)
! 6040:
! 6041: /* Return full path string in Path *pp, starting at level `sl';
! 6042: if the level is too deep or the name at level `sl' is null, return null string.
! 6043: */
! 6044: char *path_toa(pp,sl)
! 6045: Path *pp;
! 6046: int sl; /* starting level: 0 is first */
! 6047: { int len,lvl;
! 6048: static char s[MAX_PATH_DEPTH*(32)];
! 6049: s[0] = '\0';
! 6050: if( sl<=pp->level && pp->name[sl]!=NULL && pp->name[sl][0]!='\0' ) {
! 6051: for(lvl=sl; lvl<=pp->level; lvl++) {
! 6052: strcat(s,pp->name[lvl]);
! 6053: strcat(s,"/");
! 6054: };
! 6055: };
! 6056: if((len=strlen(s))>0) s[len-1] = '\0';
! 6057: return(s);
! 6058: }
! 6059:
! 6060: /* no. slashes in a name */
! 6061: int slashes(n)
! 6062: char *n;
! 6063: { register int res;
! 6064: register char *c;
! 6065: res=0;
! 6066: c=n;
! 6067: while(*c!='\0') {
! 6068: if(*c=='/') res++;
! 6069: c++;
! 6070: };
! 6071: return(res);
! 6072: }
! 6073:
! 6074: /* basename */
! 6075: char *bname(n)
! 6076: char *n;
! 6077: { register char *res,*c;
! 6078: res=n-1;
! 6079: c=n;
! 6080: while(*c!='\0') {
! 6081: if(*c=='/') res=c;
! 6082: c++;
! 6083: };
! 6084: return(res+1);
! 6085: }
! 6086:
! 6087: #if CPU==VAX || CPU==CRAY
! 6088:
! 6089: int process_file_tree_node(n,s,code,S)
! 6090: char *n;
! 6091: struct stat *s;
! 6092: int code;
! 6093: struct FTW *S;
! 6094: /* Uses global `path_process' structure */
! 6095: { char *out_n;
! 6096: int persist;
! 6097: struct stat sbuf;
! 6098: switch(code) {
! 6099: case FTW_F: if(dbg_FTW)err("visit file %s %s %d",n,n+(S->base),S->level);
! 6100: if(S->level>0) {
! 6101: if(path_process.path.name[S->level]!=NULL)
! 6102: free(path_process.path.name[S->level]);
! 6103: path_process.path.name[S->level]=strdup(n+(S->base));
! 6104: };
! 6105: path_process.path.level = S->level;
! 6106: out_n = strdup(path_toa(&path_process.path,0));
! 6107: if(dbg_FTW)err("file: %s ==> %s",n,out_n);
! 6108: (*path_process.process)(n,out_n,path_process.arg);
! 6109: if(out_n!=NULL) free(out_n);
! 6110: break;
! 6111: case FTW_SL: if(dbg_FTW)err("visit link %s %s %d",n,n+(S->base),S->level);
! 6112: S->quit = FTW_FOLLOW; /* follow symbolic link */
! 6113: break;
! 6114: case FTW_D: /* pre-visit of directory */
! 6115: if(dbg_FTW)err("visit dir %s %s %d",n,n+(S->base),S->level);
! 6116: if(S->level>0) {
! 6117: if(path_process.path.name[S->level]!=NULL)
! 6118: free(path_process.path.name[S->level]);
! 6119: path_process.path.name[S->level]=strdup(n+(S->base));
! 6120: };
! 6121: path_process.path.level = S->level;
! 6122: out_n = path_toa(&path_process.path,0);
! 6123: if(dbg_FTW)err("dir: %s --> %s",n,out_n);
! 6124: if(out_n[0]=='\0') /* no output name */ break;
! 6125: /* ensure directory named out_n exists */
! 6126: if(stat(out_n,&sbuf)==0) {
! 6127: /* file exists */
! 6128: if(!(sbuf.st_mode&S_IFDIR)) {
! 6129: /* not a directory - try to remove */
! 6130: if(unlink(out_n)==0) {
! 6131: if(mkdir(out_n,0777)!=0) {
! 6132: /* irrecoverable mkdir */
! 6133: abort("can't mkdir %s",
! 6134: out_n);
! 6135: };
! 6136: }
! 6137: else { /* irrecoverable unlink */
! 6138: abort("can't unlink %s",out_n);
! 6139: };
! 6140: };
! 6141: }
! 6142: else if(errno==ENOENT) {
! 6143: /* file doesn't exist */
! 6144: if(mkdir(out_n,0777)!=0) {
! 6145: /* irrecoverable mkdir */
! 6146: abort("can't mkdir %s",out_n);
! 6147: };
! 6148: }
! 6149: else { /* irrecoverable stat */
! 6150: abort("can't stat %s",out_n);
! 6151: };
! 6152: break;
! 6153: case FTW_DP: /* post-visit of directory: ignore it*/
! 6154: break;
! 6155: case FTW_DNR:
! 6156: err("can't read dir %s (FTW_DNR) - ignore it",n);
! 6157: break;
! 6158: case FTW_NS:
! 6159: err("can't stat %s (FTW_NS) - ignore it",n);
! 6160: break;
! 6161: case FTW_NSL:
! 6162: if(0) /* happens if file is missing */
! 6163: err("can't stat symbolic link %s (FTW_NSL) - ignore it",n);
! 6164: break;
! 6165: default:
! 6166: err("unexpected FTW code %d - ignore it",code);
! 6167: break;
! 6168: };
! 6169: return(0);
! 6170: }
! 6171:
! 6172: #else
! 6173: #if CPU==MIPS
! 6174: int process_file_tree_node(n,s,code)
! 6175: char *n; /* name of the object */
! 6176: struct stat *s; /* info. about object */
! 6177: int code;
! 6178: /* Uses global `path_process' structure */
! 6179: #define lvl path_process.path.level
! 6180: { char *out_n;
! 6181: int persist;
! 6182: struct stat sbuf;
! 6183: char *bn;
! 6184: lvl = slashes(n) - path_process.sl0;
! 6185: bn = bname(n);
! 6186: switch(code) {
! 6187: case FTW_F: if(dbg_FTW) err("visit file %s, bn %s, lvl %d",n,bn,lvl);
! 6188: if(lvl>0) {
! 6189: if(path_process.path.name[lvl]!=NULL)
! 6190: free(path_process.path.name[lvl]);
! 6191: path_process.path.name[lvl]=strdup(bn);
! 6192: };
! 6193: out_n = strdup(path_toa(&path_process.path,0));
! 6194: if(dbg_FTW)err("file: %s ==> %s",n,out_n);
! 6195: (*path_process.process)(n,out_n,path_process.arg);
! 6196: if(out_n!=NULL) free(out_n);
! 6197: break;
! 6198: case FTW_D: /* pre-visit of directory */
! 6199: if(dbg_FTW) err("visit dir %s, bn %s, lvl %d",n,bn,lvl);
! 6200: if(lvl>0) {
! 6201: if(path_process.path.name[lvl]!=NULL)
! 6202: free(path_process.path.name[lvl]);
! 6203: path_process.path.name[lvl]=strdup(bn);
! 6204: };
! 6205: out_n = path_toa(&path_process.path,0);
! 6206: if(dbg_FTW)err("dir: %s --> %s",n,out_n);
! 6207: if(out_n[0]=='\0') /* no output name */ break;
! 6208: /* ensure directory named out_n exists */
! 6209: if(stat(out_n,&sbuf)==0) {
! 6210: /* file exists */
! 6211: if(!(sbuf.st_mode&S_IFDIR)) {
! 6212: /* not a directory - try to remove */
! 6213: if(unlink(out_n)==0) {
! 6214: if(mkdir(out_n,0777)!=0) {
! 6215: /* irrecoverable mkdir */
! 6216: abort("can't mkdir %s",
! 6217: out_n);
! 6218: };
! 6219: }
! 6220: else { /* irrecoverable unlink */
! 6221: abort("can't unlink %s",out_n);
! 6222: };
! 6223: };
! 6224: }
! 6225: else if(errno==ENOENT) {
! 6226: /* file doesn't exist */
! 6227: if(mkdir(out_n,0777)!=0) {
! 6228: /* irrecoverable mkdir */
! 6229: abort("can't mkdir %s",out_n);
! 6230: };
! 6231: }
! 6232: else { /* irrecoverable stat */
! 6233: abort("can't stat %s",out_n);
! 6234: };
! 6235: break;
! 6236: case FTW_DNR:
! 6237: err("can't read dir %s (FTW_DNR) - ignore it",n);
! 6238: break;
! 6239: case FTW_NS:
! 6240: err("can't stat %s (FTW_NS) - ignore it",n);
! 6241: break;
! 6242: default:
! 6243: err("unexpected FTW code %d - ignore it",code);
! 6244: break;
! 6245: };
! 6246: return(0);
! 6247: }
! 6248:
! 6249: #endif
! 6250: #endif
! 6251:
! 6252: /* Process every leaf file (non-directory) in the file-tree rooted at `in_ftn'.
! 6253: If `in_ftn' is itself a leaf, then only it is processed. If it is a directory,
! 6254: then a corresponding file-tree is built, rooted at `out_ftn', and paths
! 6255: to its leaves created by `mkdir's as required; for each pair of corresponding
! 6256: leaf filenames, `process' is called. The filenames have not yet been opened.
! 6257: If `out_ftn' is the empty string, then no output file-tree will be generated
! 6258: and the corresponding output filenames will all be null. If `in_ftn' is the
! 6259: empty string, then `process' is called only once, with the input filename
! 6260: empty. Pass 'arg' to 'process' as third argument. */
! 6261: process_file_trees(process,in_ftn,out_ftn,arg)
! 6262: VOID (*process)();
! 6263: char *in_ftn; /* may be empty */
! 6264: char *out_ftn; /* may be empty */
! 6265: VOID *arg; /* passed to '(*process)()' as 3rd argument */
! 6266: /* Uses global `path_process' structure */
! 6267: { int level;
! 6268: if(in_ftn[0]=='\0') (*process)(in_ftn,out_ftn,arg);
! 6269: else { if(dbg_FTW) err("process_file_trees(%s,%s)",in_ftn,out_ftn);
! 6270: path_process.path.level = 0;
! 6271: path_process.path.name[0] = out_ftn;
! 6272: path_process.sl0 = slashes(in_ftn);
! 6273: for(level=1; level<MAX_PATH_DEPTH; level++)
! 6274: path_process.path.name[level] = NULL;
! 6275: path_process.process = process;
! 6276: path_process.arg = arg;
! 6277: if(ftw(in_ftn,process_file_tree_node,MAX_PATH_DEPTH)<0)
! 6278: err("ftw error: errno %d",errno);
! 6279: };
! 6280: }
! 6281: 0707070035351137121006640007620000050000010261310476773366700000700000001611Path.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 6282: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 6283: /* The copyright notice does not imply actual or intended publication. */
! 6284: /* AUTHORS: */
! 6285: /* H. S. Baird - ATT-BL MH - first versions */
! 6286:
! 6287: /* Path.h - Path names */
! 6288:
! 6289: #define MAX_PATH_DEPTH (16) /* maximum expected names in path */
! 6290:
! 6291: typedef struct Path {
! 6292: int level; /* current level */
! 6293: char *name[MAX_PATH_DEPTH]; /* name[0] is output root name;
! 6294: the rest are basenames (both input
! 6295: and output) */
! 6296: } Path;
! 6297:
! 6298: typedef struct Path_process {
! 6299: int sl0; /* no. slashes in input root name */
! 6300: Path path;
! 6301: VOID (*process)();
! 6302: VOID *arg; /* passed as 3rd arg to (*process)() */
! 6303: } Path_process;
! 6304:
! 6305: Path_process path_process; /* controls file-tree processing */
! 6306:
! 6307: char *path_toa(); /* see Path.c */
! 6308: 0707070035351137131006640007620000050000010261330476773367000000700000404335Text.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 6309: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 6310: /* The copyright notice does not imply actual or intended publication. */
! 6311: /* AUTHORS: */
! 6312: /* H. S. Baird - ATT-BL MH - first versions */
! 6313:
! 6314: /* Text.c - functions for Document-image file ("dim" file) handling
! 6315:
! 6316: General Introduction
! 6317: --------------------
! 6318:
! 6319: Dim files describe a document as a collection of records of these types:
! 6320: Page full page
! 6321: Block block (often a column) of text
! 6322: Txtln line of text
! 6323: Word word
! 6324: Char character, isolated symbol, `graph'
! 6325: Interp interpretation of a character (result of classification)
! 6326: Sfeats scalar features of a character
! 6327: Shapes local shape features of a character
! 6328: Bfeats binary indicator features of a character
! 6329: Blob connected component (maximal subset of 8-connected black pixels)
! 6330: Lag line-adjacency graph of runs
! 6331: Run horizontal run of black pixels
! 6332: Pixel bilevel (black/white) picture element (symbols are expected to
! 6333: be black against a white background); usually square
! 6334:
! 6335: They may be organized hierarchically --
! 6336: a Page may own : Blocks, Txtlns, Words, Chars, & Blobs
! 6337: a Block may own : Blocks, Txtlns, Words, Chars, & Blobs
! 6338: a Txtln may own : Txtlns, Words, Chars, & Blobs
! 6339: a Word may own : Words, Chars & Blobs
! 6340: a Char may own : Blobs, Interps, Sfeats, Shapes, & Bfeats
! 6341: a Blob may own : Runs (variously represented)
! 6342: a Run owns : black Pixels
! 6343: Note that the hierarchy is strict except that Blocks, Txtlns, & Words may
! 6344: own records of their own type. This serves several functions:
! 6345: -- a Block may own other Blocks, conventionally nested within it, to
! 6346: represent a physical or logical page layout decomposition;
! 6347: -- a Txtln may have alternative interpretations & segmentations into Words;
! 6348: -- a Word may have alternative segmentations into Chars.
! 6349:
! 6350: For each record type R, there should exist these data-structures:
! 6351: R struct
! 6352: Init_R #define'd initialization string
! 6353: empty_R an extern ``empty'' (initialized) instance of R
! 6354: Also there are library functions (in which _R is spelled in lower-case):
! 6355: R *alloc_R() allocate memory and initialize to ``empty''
! 6356: free_R(R *) free memory (only of record R, not what it owns)
! 6357: free_R_etc(R *,ids) free R and what it owns (as specified by `ids')
! 6358: R *dup_R(R *) return distinct copy, with duplicated contents
! 6359: R *dup_R_etc(R *,ids) return distinct copy, duplicated contents & parts
! 6360: char *R_toa(R *) convert to printable ASCII string
! 6361: frdb_R(FILE *, R *) fread R (binary) from file thru pointer
! 6362: frdb_R_etc(",",ids) fread R (binary) and what it owns (as specified)
! 6363: fwrb_R(FILE *, R *) fwrite R (binary) to file thru pointer
! 6364: fwrb_R_etc(",",ids) fwrite R (binary) and what it owns (as specified)
! 6365: (some of these may be unimplemented if they haven't yet been needed)
! 6366:
! 6367: I/O conventions:
! 6368: -- frd?_... return one of:
! 6369: 1 normal & successful
! 6370: 0 EOF
! 6371: <0 I/O errors
! 6372: Quite a few functions don't obey this rule yet.
! 6373: Many intermediate fns that don't directly perform I/O
! 6374: don't bother passing back status from fns they call.
! 6375: Those that perform I/O directly often complain to stderr and exit(2).
! 6376: The situation is fairly chaotic, and has already caused bugs.
! 6377:
! 6378: Generally:
! 6379: -- An `etc' argument is a set of Ident bits specifying a set of record types;
! 6380: it is passed along unchanged in calls to other _etc functions.
! 6381: -- `fwrb_R_etc' fns obey the `etc' instructions carefully, writing only those
! 6382: record types specified
! 6383: -- `frdb_R_etc' fns mostly ignore `etc', blindly reading everything they
! 6384: see (since they aren't clever enough to skip past yet); however, the
! 6385: Blob-reading fns look at the Runs_?? bits to select a main memory
! 6386: format for Runs
! 6387: -- `frdb_R_etc' uses alloc_Y to allocate all new Y
! 6388: -- `fwrb_R_etc', however, does NOT free anything: this must be done explicitly
! 6389: afterwards.
! 6390:
! 6391: Ownership of a set of records is implemented by two fields in the owner record:
! 6392: (1) a count of the number of members, and (2) either a ``set'' or a ``list''
! 6393: pointer:
! 6394: set: to a NULL-terminated array of pointers to records
! 6395: list: to the first in a singly-linked, NULL-terminated, chain
! 6396: sets are used for sets of Blocks, Txtlns, Words, Chars, and Blobs
! 6397: lists are used for Interpl, and for Blobs owned by Chars, since they tend
! 6398: to be fewer
! 6399:
! 6400: Blobs and Runs are treated more elaborately than other records. Blobs are
! 6401: collected in lists when owned by Chars, but in sets otherwise --
! 6402: the motivation was that the Char lists are usually very short, and the malloc
! 6403: overhead of creating them might be unpleasant -- however, maintaining two
! 6404: kinds of sets has caused other headaches; it might be good someday to
! 6405: abolish lists in favor of sets throughout.
! 6406: Runs can often be compressed to about half the usual size by using char
! 6407: fields instead of shorts, and this is done automatically when writing to files. There is both a set and a list form of Run.
! 6408:
! 6409: The peripheral file format is:
! 6410: - deliberately decoupled from the internal (main memory) format: i.e.
! 6411: the main memory structs can be (and are) changed frequently for
! 6412: purposes of experimentation without forcing frequent reformatting
! 6413: of the (by now large) backlog of archived files (particularly the
! 6414: character image databases). To bring such files up-to-date, the program
! 6415: `renew' should be used: it must be edited to reflect changes since
! 6416: the last overhaul of the file format.
! 6417: - designed to be ``scannable'': that is, one can skip rapidly from record
! 6418: to record (using the Ident headers) without minding the hierarchy.
! 6419: This is most useful for the graphics editor "met", where it permits
! 6420: quick response at the outset. It is also used widely in the
! 6421: off-line training programs, where main memory is at a premium.
! 6422: - machine-independent: floating-point representations are forced to
! 6423: fixed point and scaled to integer; all integer representations are
! 6424: written as a sequence of bytes in a fixed order, via putc()/getc().
! 6425: fwrite()/fread() are never used for binary I/O. This seems to work
! 6426: on virtually all UNIX machines. See fioi.h.
! 6427:
! 6428: CCITT Group 4 encodings have been implemented and are available
! 6429: as a peripheral file format for Blobs. They offer a large compression
! 6430: factor (x8) over RunF and RunFS records, and the CPU overhead is not
! 6431: excessive. It turns out that the connectivity information represented
! 6432: explicitly in Run records but lost in ccitt-g4 can be recovered in linear
! 6433: time and space (see fix_lag()); in practice the extra recovery time is
! 6434: negligible and the extra space is 0. This is possible because Blobs are
! 6435: known to be connected: if not, then (I suspect that) superlinear time is
! 6436: required in general to recover the lag.
! 6437:
! 6438: */
! 6439:
! 6440: #include <stdio.h>
! 6441: #include <math.h>
! 6442: #define LIBC_INCL 1
! 6443: #include "CPU.h"
! 6444: #include "stdocr.h"
! 6445: #include "rle.h"
! 6446: #include "Text.h"
! 6447: #include "bitio.h"
! 6448: #include "CCITT.h"
! 6449:
! 6450: long fseek(),lseek();
! 6451:
! 6452: #define dbg_fwrb T /* failsafe consistency checking */
! 6453: #define dbg_frdb T /* failsafe consistency checking */
! 6454: #define dbg_fwrb_runs F /* announce no. bytes used to write each Blob's Runs */
! 6455: #define dbg_frdb_runs F /* announce no. bytes used to write each Blob's Runs */
! 6456:
! 6457: /* return ASCII string describing ident bits */
! 6458: char *ident_toa(id)
! 6459: Ident id;
! 6460: { static char s[80];
! 6461: s[0]='\0';
! 6462: if((id&IsALL)==IsALL) strcat(s,"ALL");
! 6463: else {
! 6464: if(id&IsPage) {
! 6465: strcat(s,"PG");
! 6466: if(id&(Page_label)) {
! 6467: strcat(s,".");
! 6468: if(id&Page_label) strcat(s,"l");
! 6469: };
! 6470: }
! 6471: if(id&IsBlock) {
! 6472: strcat(s,"BK");
! 6473: if(id&(Block_wst|Block_label)) {
! 6474: strcat(s,".");
! 6475: if(id&Block_wst) strcat(s,"w");
! 6476: if(id&Block_label) strcat(s,"l");
! 6477: };
! 6478: };
! 6479: if(id&IsTxtln) {
! 6480: strcat(s,"TL");
! 6481: if(id&(Txtln_basl|Txtln_size|Txtln_label)) {
! 6482: strcat(s,".");
! 6483: if(id&Txtln_basl) strcat(s,"b");
! 6484: if(id&Txtln_size) strcat(s,"s");
! 6485: if(id&Txtln_label) strcat(s,"l");
! 6486: };
! 6487: };
! 6488: if(id&IsWord) {
! 6489: strcat(s,"WD");
! 6490: if(id&(Word_spelled|Word_label)) {
! 6491: strcat(s,".");
! 6492: if(id&Word_spelled) strcat(s,"s");
! 6493: if(id&Word_label) strcat(s,"l");
! 6494: };
! 6495: };
! 6496: if(id&IsWordInterp) {
! 6497: strcat(s,"WI");
! 6498: if(id&(Word_spelled|Word_numeric|Word_initcap|Word_allcaps|Word_hyphens|Word_slashes|Word_termhyp|Word_endsent)) {
! 6499: strcat(s,".");
! 6500: if(id&Word_spelled) strcat(s,"s");
! 6501: if(id&Word_numeric) strcat(s,"n");
! 6502: if(id&Word_initcap) strcat(s,"i");
! 6503: if(id&Word_allcaps) strcat(s,"a");
! 6504: if(id&Word_hyphens) strcat(s,"-");
! 6505: if(id&Word_slashes) strcat(s,"/");
! 6506: if(id&Word_termhyp) strcat(s,"h");
! 6507: if(id&Word_endsent) strcat(s,".");
! 6508: };
! 6509: };
! 6510: if(id&IsChar) {
! 6511: strcat(s,"CH");
! 6512: if(id&(Char_spelled|Char_confused|Char_termhyp|Char_omit|Char_label|Char_ranparms)) {
! 6513: strcat(s,".");
! 6514: if(id&Char_spelled) strcat(s,"s");
! 6515: if(id&Char_confused) strcat(s,"c");
! 6516: if(id&Char_termhyp) strcat(s,"h");
! 6517: if(id&Char_omit) strcat(s,"o");
! 6518: if(id&Char_label) strcat(s,"l");
! 6519: if(id&Char_ranparms) strcat(s,"r");
! 6520: if(id&Char_split) strcat(s,"S");
! 6521: if(id&Char_merged) strcat(s,"M");
! 6522: };
! 6523: };
! 6524: if(id&IsInterp) {
! 6525: strcat(s,"IN");
! 6526: if(id&Interp_spelled) {
! 6527: strcat(s,".s");
! 6528: };
! 6529: };
! 6530: if(id&IsBlob) {
! 6531: strcat(s,"BB");
! 6532: if( id&(Blob_lm|Blob_rm|Blob_tm|Blob_bm
! 6533: |Blob_chopt|Blob_chopb|Blob_chopl|Blob_chopr
! 6534: |Blob_small|Blob_local)
! 6535: ) {
! 6536: strcat(s,".");
! 6537: if(id&(Blob_tm|Blob_bm|Blob_lm|Blob_rm)) {
! 6538: if(id&Blob_lm) strcat(s,"l");
! 6539: if(id&Blob_rm) strcat(s,"r");
! 6540: if(id&Blob_tm) strcat(s,"t");
! 6541: if(id&Blob_bm) strcat(s,"b");
! 6542: };
! 6543: if(id&(Blob_chopt|Blob_chopb|Blob_chopl|Blob_chopr)) {
! 6544: if(id&Blob_chopl) strcat(s,"L");
! 6545: if(id&Blob_chopr) strcat(s,"R");
! 6546: if(id&Blob_chopt) strcat(s,"T");
! 6547: if(id&Blob_chopb) strcat(s,"B");
! 6548: };
! 6549: if(id&Blob_small) strcat(s,"s");
! 6550: if(id&Blob_local) strcat(s,"o");
! 6551: };
! 6552: }
! 6553: };
! 6554: return(s);
! 6555: }
! 6556:
! 6557: /* convert a conventional character-code to a record type */
! 6558: Ident cto_ident(c)
! 6559: char c;
! 6560: { Ident type;
! 6561: switch(c) {
! 6562: case 'b':
! 6563: type=IsBlob; break;
! 6564: case 'B': case 'k':
! 6565: type=IsBlock; break;
! 6566: case 'c':
! 6567: type=IsChar; break;
! 6568: case 'i':
! 6569: type=IsInterp; break;
! 6570: case 'p': case 'P':
! 6571: type=IsPage; break;
! 6572: case 'r':
! 6573: type=IsRun; break;
! 6574: case 't': case 'l':
! 6575: type=IsTxtln; break;
! 6576: case 'w':
! 6577: type=IsWord; break;
! 6578: case 'y':
! 6579: type=IsBdy; break;
! 6580: };
! 6581: return(type);
! 6582: }
! 6583:
! 6584: Ident cto_flag(c,type)
! 6585: char c;
! 6586: Ident type;
! 6587: { Ident flag;
! 6588: flag = IsNONE;
! 6589: if(type&IsPage) {
! 6590: switch(c) {
! 6591: case 'l': flag |= Page_label; break;
! 6592: };
! 6593: }
! 6594: else if(type&IsBlock) {
! 6595: switch(c) {
! 6596: case 'w': flag |= Block_wst; break;
! 6597: case 'l': flag |= Block_label; break;
! 6598: };
! 6599: }
! 6600: else if(type&IsTxtln) {
! 6601: switch(c) {
! 6602: case 'b': flag |= Txtln_basl; break;
! 6603: case 's': flag |= Txtln_size; break;
! 6604: case 'l': flag |= Txtln_label; break;
! 6605: };
! 6606: }
! 6607: else if(type&IsWord) {
! 6608: switch(c) {
! 6609: case 's': flag |= Word_spelled; break;
! 6610: case 'n': flag |= Word_numeric; break;
! 6611: case 'i': flag |= Word_initcap; break;
! 6612: case 'a': flag |= Word_allcaps; break;
! 6613: case '-': flag |= Word_hyphens; break;
! 6614: case '/': flag |= Word_slashes; break;
! 6615: case 'h': flag |= Word_termhyp; break;
! 6616: case '.': flag |= Word_endsent; break;
! 6617: case 'l': flag |= Word_label; break;
! 6618: };
! 6619: }
! 6620: else if(type&IsChar) {
! 6621: switch(c) {
! 6622: case 's': flag |= Char_spelled; break;
! 6623: case 'c': flag |= Char_confused; break;
! 6624: case 'h': flag |= Char_termhyp; break;
! 6625: case 'o': flag |= Char_omit; break;
! 6626: case 'l': flag |= Char_label; break;
! 6627: case 'r': flag |= Char_ranparms; break;
! 6628: case 'S': flag |= Char_split; break;
! 6629: case 'M': flag |= Char_merged; break;
! 6630: };
! 6631: }
! 6632: else if(type&IsBlob) {
! 6633: switch(c) {
! 6634: case 'B': flag |= Blob_chopb; break;
! 6635: case 'L': flag |= Blob_chopl; break;
! 6636: case 'R': flag |= Blob_chopr; break;
! 6637: case 'T': flag |= Blob_chopt; break;
! 6638: case 'b': flag |= Blob_bm; break;
! 6639: case 'l': flag |= Blob_lm; break;
! 6640: case 'o': flag |= Blob_local; break;
! 6641: case 'r': flag |= Blob_rm; break;
! 6642: case 's': flag |= Blob_small; break;
! 6643: case 't': flag |= Blob_tm; break;
! 6644: };
! 6645: }
! 6646: else if(type&IsInterp) {
! 6647: switch(c) {
! 6648: case 's': flag |= Interp_spelled; break;
! 6649: };
! 6650: };
! 6651: return(flag);
! 6652: }
! 6653:
! 6654: #if FRDI
! 6655: /* read only the Ident of the next record; if EOF, return 0 */
! 6656: Ident frdb_ident(fp)
! 6657: FILE *fp;
! 6658: { Ident ident;
! 6659: ident = frdi_Ident(fp);
! 6660: #if dbg_frdb_toa
! 6661: err("frdb_ident: %s",ident_toa(ident));
! 6662: #endif
! 6663: if(feof(fp)) return(0);
! 6664: else return(ident);
! 6665: }
! 6666: #else
! 6667: /* read only the Ident of the next record; return 0 iff EOF */
! 6668: Ident frdb_ident(fp)
! 6669: FILE *fp;
! 6670: { Ident ident;
! 6671: int stat;
! 6672: if((stat=fread(&ident,sizeof(Ident),1,fp))!=1) {
! 6673: if(stat==0) return(0);
! 6674: else abort("frdb_ident: can't fread, status %d",stat);
! 6675: };
! 6676: if( Readvax ) ident = swapintin(ident);
! 6677: #if dbg_frdb_toa
! 6678: err("frdb_ident: %s",ident_toa(ident));
! 6679: #endif
! 6680: if(feof(fp)) return(0);
! 6681: else return(ident);
! 6682: }
! 6683: #endif
! 6684:
! 6685: #if FRDI
! 6686: /* read label into malloc space */
! 6687: char *frdb_label(f)
! 6688: FILE *f;
! 6689: { register char *res;
! 6690: res=frdi_str(f);
! 6691: #if dbg_frdb_toa
! 6692: err("frdb_label: \"%s\"",res);
! 6693: #endif
! 6694: return(res);
! 6695: }
! 6696: #else
! 6697: /* read label into malloc space */
! 6698: char *frdb_label(fp)
! 6699: FILE *fp;
! 6700: { static char s[MAX_LABEL_LEN];
! 6701: char *c,*ce,*l;
! 6702: int ch;
! 6703: ce=(c=s)+MAX_LABEL_LEN-1;
! 6704: while((c<ce)&&((ch=getc(fp))!=EOF)&&(ch!='\0')) *(c++) = ch;
! 6705: *c='\0';
! 6706: if(c==ce) {
! 6707: /* label is truncated; find end of it */
! 6708: while(((ch=getc(fp))!=EOF)&&(ch!='\0')) ;
! 6709: };
! 6710: if((l=strdup(s))==NULL)
! 6711: abort("frdb_label: can't dup char *s[%d]",strlen(s));
! 6712: #if dbg_frdb_toa
! 6713: err("frdb_label: \"%s\"",l);
! 6714: #endif
! 6715: return(l);
! 6716: }
! 6717: #endif
! 6718:
! 6719: /* skip label */
! 6720: fskb_label(fp)
! 6721: FILE *fp;
! 6722: { int ch;
! 6723: while(((ch=getc(fp))!=EOF)&&(ch!='\0')&&(ch!='\n')) ;
! 6724: if(ch==EOF) return(0); else return(1);
! 6725: }
! 6726:
! 6727: /* Skip the REST of this record (the Ident is assumed to have been read),
! 6728: and return the Ident of the next record in the file;
! 6729: else return:
! 6730: 0 EOF
! 6731: -1 I/O error
! 6732: -2 not one of: Page, Block, Txtln, Char, Interp
! 6733: */
! 6734: char *pp_toa(ppp)
! 6735: Pp *ppp;
! 6736: { static char s[30];
! 6737: sprintf(s,"(%0.2f,%0.2f)",ppp->x,ppp->y);
! 6738: return(s);
! 6739: }
! 6740:
! 6741: /* return integer string in the range 00-99 */
! 6742: char *merit_toa(m)
! 6743: Merit m;
! 6744: { static char s[3];
! 6745: int im;
! 6746: im = (int)(m * 100);
! 6747: if(im>99) im=99; else if(im<0) im=0;
! 6748: if(im<10) {
! 6749: s[0] = '0';
! 6750: sprintf(s+1,"%d",im);
! 6751: }
! 6752: else sprintf(s,"%2d",im);
! 6753: s[3] = '\0';
! 6754: return(s);
! 6755: }
! 6756:
! 6757: char *pts_toa(p)
! 6758: Pts p;
! 6759: { static char s[10];
! 6760: sprintf(s,"%g",((int)((p*10.0)+0.5))/10.0);
! 6761: return(s);
! 6762: }
! 6763:
! 6764: Bdy *alloc_bdy()
! 6765: { Bdy *p;
! 6766: if((p=(Bdy *)malloc(sizeof(Bdy)))==NULL)
! 6767: abort("alloc_bdy: can't malloc");
! 6768: else { *p = empty_Bdy;
! 6769: return(p);
! 6770: };
! 6771: }
! 6772:
! 6773: Bdys *alloc_bdys()
! 6774: { Bdys *p;
! 6775: if((p=(Bdys *)malloc(sizeof(Bdys)))==NULL)
! 6776: abort("alloc_bdys: can't malloc");
! 6777: else { *p = empty_Bdys;
! 6778: return(p);
! 6779: };
! 6780: }
! 6781:
! 6782: char *bdyedge_toa(bep)
! 6783: BdyEdge *bep;
! 6784: { static char s[80];
! 6785: char aps[20];
! 6786: strcpy(aps,sp_toa(bep->ap));
! 6787: sprintf(s,"%s,%s p%d c%s a%0.2f",
! 6788: aps, sp_toa(bep->bp),
! 6789: bep->per,
! 6790: pp_toa(&(bep->ctr)),
! 6791: (bep->ang/PI)*180.0);
! 6792: return(s);
! 6793: }
! 6794:
! 6795: free_bdyedges(besp)
! 6796: BdyEdges *besp;
! 6797: { register BdyEdge *bep,**bepp;
! 6798: if(besp->pa!=NULL) {
! 6799: if(besp->mny>0) {
! 6800: for(bep= *(bepp=besp->pa); bep!=NULL; bep= *(++bepp))
! 6801: free(bep);
! 6802: };
! 6803: free(besp->pa);
! 6804: };
! 6805: *besp = empty_BdyEdges;
! 6806: }
! 6807:
! 6808: /* Skip past the "TYPE=document-image\n\n" (or "TYPE=dim\n\n") ASCII header from
! 6809: file *fp, read and check the Doc record, and, if all's well, return 1.
! 6810: If an immediate EOF, return 0. If not EOF, and no "TYPE=" header,
! 6811: leave fp as it was, and return -1. If a malformed "TYPE=" header, leave fp
! 6812: as it was, and return -2. */
! 6813: int skip_type(fp)
! 6814: FILE *fp;
! 6815: { int ich,stat;
! 6816: long seek;
! 6817: #define MAX_TYPE_HDR_LEN (100)
! 6818: char type_eq[MAX_TYPE_HDR_LEN+1];
! 6819: register char *pcp,*ccp,*ecp;
! 6820: int version;
! 6821:
! 6822: seek = ftell(fp);
! 6823: /* test for EOF */
! 6824: if(feof(fp) || (ich=getc(fp))==EOF)
! 6825: /* premature EOF*/ return(0);
! 6826: if((type_eq[0]=ich)!='T') {
! 6827: /* no "TYPE=" header */
! 6828: ungetc(ich,fp); /* fast, guaranteed push-back */
! 6829: return(-1);
! 6830: };
! 6831: /* try to read the rest of "TYPE=" */
! 6832: for(ecp=(ccp=type_eq+1)+4; ccp<ecp; ccp++) {
! 6833: if(feof(fp) || (ich=getc(fp))==EOF) {
! 6834: /* no "TYPE=" header */
! 6835: fseek(fp,seek,0);
! 6836: return(-1);
! 6837: }
! 6838: else *ccp=ich;
! 6839: }
! 6840: *ccp='\0';
! 6841: /* check for "TYPE=" so far */
! 6842: if(strcmp(type_eq,"TYPE=")==0) {
! 6843: /* read rest of ASCII header */
! 6844: ccp=(pcp=type_eq+3)+1; ecp=type_eq+MAX_TYPE_HDR_LEN;
! 6845: do { ccp++; pcp++;
! 6846: if((ich=getc(fp))==EOF) {
! 6847: /* malformed "TYPE=" header */
! 6848: fseek(fp,seek,0);
! 6849: return(-2);
! 6850: }
! 6851: else *ccp=ich;
! 6852: }
! 6853: while(ccp<ecp && (*ccp!='\n'||*pcp!='\n'));
! 6854: if(ccp==ecp) {
! 6855: /* malformed "TYPE=" header */
! 6856: fseek(fp,seek,0);
! 6857: return(-2);
! 6858: };
! 6859: *pcp='\0';
! 6860: /* check that it is "TYPE=document-image\n\n" or "TYPE=dim\n\n" */
! 6861: if(strcmp(type_eq,"TYPE=document-image")!=0
! 6862: && strcmp(type_eq,"TYPE=dim")!=0) {
! 6863: /* malformed "TYPE=" header */
! 6864: fseek(fp,seek,0);
! 6865: return(-2);
! 6866: };
! 6867: #if dbg_frdb_toa
! 6868: err("skip_type: \"%s\\n\\n\"",type_eq);
! 6869: #endif
! 6870: return(1); /* normal and successful TYPE= header */
! 6871: }
! 6872: else { /* no "TYPE=" header */
! 6873: fseek(fp,seek,0);
! 6874: return(-1);
! 6875: };
! 6876: }
! 6877:
! 6878: Doc *alloc_doc()
! 6879: { Doc *p;
! 6880: if((p=(Doc *)malloc(sizeof(Doc)))==NULL)
! 6881: abort("alloc_doc: can't malloc");
! 6882: else { *p = empty_Doc;
! 6883: return(p);
! 6884: };
! 6885: }
! 6886:
! 6887: char *doc_toa(p)
! 6888: Doc *p;
! 6889: { static char s[80];
! 6890: sprintf(s,"Doc v%d p%d l%s",
! 6891: p->version,
! 6892: p->ps.mny,
! 6893: (p->l!=NULL)? p->l: "");
! 6894: return(s);
! 6895: }
! 6896:
! 6897: #if FWRI
! 6898: /* write the given doc (record only) */
! 6899: fwrb_doc(f,p)
! 6900: FILE *f;
! 6901: Doc *p;
! 6902: { int stat;
! 6903: fwri_uint1(f,p->version);
! 6904: fwri_uint2(f,p->ps.mny);
! 6905: #if dbg_fwrb_toa
! 6906: err("fwrb_doc: %s",doc_toa(p));
! 6907: #endif
! 6908: if(p->l!=NULL) {
! 6909: fwri_ch(f,'l');
! 6910: fwrb_label(f,p->l);
! 6911: }
! 6912: else fwri_ch(f,'\0');
! 6913: }
! 6914: #else
! 6915: fwrb_doc(f,p)
! 6916: FILE *f;
! 6917: Doc *p;
! 6918: {}
! 6919: #endif
! 6920:
! 6921: #if FRDI
! 6922: /* read a Doc record (only) - it must be next in the file;
! 6923: don't immediately read its parts; return 0 iff immediate EOF.
! 6924: Check for correct version no: if fails, abort. */
! 6925: int frdb_doc(f,p)
! 6926: FILE *f;
! 6927: Doc *p;
! 6928: { char qlabel;
! 6929: *p = empty_Doc;
! 6930: if(feof(f))
! 6931: return(0);
! 6932: p->version=frdi_uint1(f);
! 6933: p->ps.mny=frdi_uint2(f);
! 6934: if((qlabel=frdi_ch(f))=='l')
! 6935: p->l=frdb_label(f);
! 6936: #if dbg_frdb_toa
! 6937: err("frdb_doc: %s",doc_toa(p));
! 6938: #endif
! 6939: if(ferror(f)) return(-errno); else return(1);
! 6940: }
! 6941: #else
! 6942: int frdb_doc(f,p)
! 6943: FILE *f;
! 6944: Doc *p;
! 6945: { return(1);
! 6946: }
! 6947: #endif
! 6948:
! 6949: #if FWRI
! 6950: /* Write the initial Doc record */
! 6951: put_doc(f)
! 6952: FILE *f;
! 6953: { Doc doc;
! 6954: doc = empty_Doc;
! 6955: doc.version = DIM_VERSION;
! 6956: doc.ps.mny = 1;
! 6957: fwrb_doc(f,&doc);
! 6958: }
! 6959: #else
! 6960: put_doc(f)
! 6961: FILE *f;
! 6962: {}
! 6963: #endif
! 6964:
! 6965: #if FRDI
! 6966: /* read, check, discard, and skip past the Doc record */
! 6967: int skip_doc(f)
! 6968: FILE *f;
! 6969: { Doc doc;
! 6970: frdb_doc(f,&doc);
! 6971: if(doc.version!=DIM_VERSION)
! 6972: abort("skip_doc: version %d != DIM_VERSION %d",
! 6973: doc.version,DIM_VERSION);
! 6974: if(doc.l!=NULL) free(doc.l);
! 6975: return(1);
! 6976: }
! 6977: #else
! 6978: int skip_doc(f)
! 6979: FILE *f;
! 6980: { Doc doc;
! 6981: return(1);
! 6982: }
! 6983: #endif
! 6984:
! 6985: Page *alloc_page()
! 6986: { Page *p;
! 6987: if((p=(Page *)malloc(sizeof(Page)))==NULL)
! 6988: abort("alloc_page: can't malloc");
! 6989: alloc_census(Page,1);
! 6990: *p = empty_Page;
! 6991: return(p);
! 6992: }
! 6993:
! 6994: char *page_toa(p)
! 6995: Page *p;
! 6996: { static char s[80];
! 6997: sprintf(s,"%s bx%s res%d,%d sk%0.2f,sh%0.2f bk%d l%d c%d b%d",
! 6998: ident_toa(p->ident),
! 6999: bbx_toa(&(p->bx)),
! 7000: p->res_x,p->res_y,
! 7001: (p->skew/PI)*180.0,
! 7002: (p->shear/PI)*180.0,
! 7003: p->bks.mny,p->ls.mny,p->cs.mny,p->bs.mny,
! 7004: (p->l!=NULL)? p->l: "");
! 7005: return(s);
! 7006: }
! 7007:
! 7008: #if FWRI
! 7009: /* write the given page (record only) */
! 7010: fwrb_page(f,p)
! 7011: FILE *f;
! 7012: Page *p;
! 7013: { int stat;
! 7014: #if dbg_fwrb
! 7015: if(f==stdout||f==stderr||ftell(f)<=0L) {
! 7016: fprintf(f,"TYPE=dim\n\n");
! 7017: #if dbg_fwrb_toa
! 7018: err("fwrb_page: \"TYPE=dim\\n\\n\"");
! 7019: #endif
! 7020: put_doc(f);
! 7021: };
! 7022: if((!(p->ident&IsPage))||(p->ident&(IsALL&(~IsPage))))
! 7023: err("fwrb_page: %s",page_toa(p));
! 7024: if(p->ident&Page_label && p->l==NULL) {
! 7025: err("fwrb_page: Page_label set but .l==NULL");
! 7026: p->ident &= ~Page_label;
! 7027: };
! 7028: #endif
! 7029: fwri_Ident(f,p->ident);
! 7030: fwri_Bbx(f,&(p->bx));
! 7031: fwri_int2(f,p->res_x);
! 7032: fwri_int2(f,p->res_y);
! 7033: fwri_Radians(f,p->skew);
! 7034: fwri_Radians(f,p->shear);
! 7035: fwri_uint2(f,p->bks.mny);
! 7036: fwri_uint2(f,p->ls.mny);
! 7037: fwri_uint2(f,p->ws.mny);
! 7038: fwri_uint2(f,p->cs.mny);
! 7039: fwri_uint3(f,p->bs.mny);
! 7040: #if dbg_fwrb_toa
! 7041: err("fwrb_page: %s",page_toa(p));
! 7042: #endif
! 7043: if(p->ident&Page_label) fwrb_label(f,p->l);
! 7044: }
! 7045: #else
! 7046: /* write the given page (record only) */
! 7047: fwrb_page(fp,pp)
! 7048: FILE *fp;
! 7049: Page *pp;
! 7050: { PageF pf;
! 7051: int stat;
! 7052: #if dbg_fwrb
! 7053: if((!(pp->ident&IsPage))||(pp->ident&(IsALL&(~IsPage))))
! 7054: err("fwrb_page: %s",page_toa(pp));
! 7055: #endif
! 7056: memset(&pf,'\0',sizeof(pf));
! 7057: pf.ident = pp->ident;
! 7058: pf.res_x=pp->res_x;
! 7059: pf.res_y=pp->res_y;
! 7060: pf.bx=pp->bx;
! 7061: pf.skew=pp->skew;
! 7062: pf.shear=pp->shear;
! 7063: pf.bkmny=pp->bks.mny;
! 7064: pf.lmny=pp->ls.mny;
! 7065: pf.wmny=pp->ws.mny;
! 7066: pf.cmny=pp->cs.mny;
! 7067: pf.bmny=pp->bs.mny;
! 7068: if(fp==stdout||fp==stderr||ftell(fp)<=0L) {
! 7069: fprintf(fp,"TYPE=document-image\n\n");
! 7070: #if dbg_fwrb_toa
! 7071: err("fwrb_page: \"TYPE=document-image\\n\\n\"");
! 7072: #endif
! 7073: };
! 7074: if((stat=fwrite(&pf,sizeof(PageF),1,fp))!=1)
! 7075: abort("fwrb_page: can't fwrite - status %d",stat);
! 7076: #if dbg_fwrb_toa
! 7077: err("fwrb_page: %s",page_toa(pp));
! 7078: #endif
! 7079: if(pf.ident&Page_label) fwrb_label(fp,pp->l);
! 7080: }
! 7081: #endif
! 7082:
! 7083: /* write a page and its specified parts */
! 7084: fwrb_page_etc(fp,pp,etc)
! 7085: FILE *fp;
! 7086: Page *pp;
! 7087: Ident etc;
! 7088: { static Ident parts = (IsBlock|IsTxtln|IsWord|IsChar|IsBlob);
! 7089: Page pg;
! 7090: if((etc&parts)!=parts) /* write selected parts */ {
! 7091: pg = *pp;
! 7092: if(!(etc&IsBlock)) pg.bks.mny=0;
! 7093: if(!(etc&IsTxtln)) pg.ls.mny=0;
! 7094: if(!(etc&IsWord)) pg.ws.mny=0;
! 7095: if(!(etc&IsChar)) pg.cs.mny=0;
! 7096: if(!(etc&IsBlob)) pg.bs.mny=0;
! 7097: pp = &pg; /* write modified record */
! 7098: };
! 7099: fwrb_page(fp,pp);
! 7100: fwrb_blocks_etc(fp,pp->bks,etc);
! 7101: fwrb_txtlns_etc(fp,pp->ls,etc);
! 7102: fwrb_words_etc(fp,pp->ws,etc);
! 7103: fwrb_chars_etc(fp,pp->cs,etc);
! 7104: fwrb_blobs_etc(fp,pp->bs,etc);
! 7105: }
! 7106:
! 7107: /* write a page and its specified parts, ASCII (INCOMPLETE) */
! 7108: fwra_page_etc(fp,pp,etc)
! 7109: FILE *fp;
! 7110: Page *pp;
! 7111: Ident etc;
! 7112: { static Ident parts = (IsBlock|IsTxtln|IsWord|IsChar|IsBlob);
! 7113: Page pg;
! 7114: if((etc&parts)!=parts) /* write selected parts */ {
! 7115: pg = *pp;
! 7116: if(!(etc&IsBlock)) pg.bks.mny=0;
! 7117: if(!(etc&IsTxtln)) pg.ls.mny=0;
! 7118: if(!(etc&IsWord)) pg.ws.mny=0;
! 7119: if(!(etc&IsChar)) pg.cs.mny=0;
! 7120: if(!(etc&IsBlob)) pg.bs.mny=0;
! 7121: pp = &pg; /* write modified record */
! 7122: };
! 7123: if(etc&IsPage) fwrb_page(fp,pp);
! 7124: fwrb_blocks_etc(fp,pp->bks,etc);
! 7125: fwrb_txtlns_etc(fp,pp->ls,etc);
! 7126: fwrb_words_etc(fp,pp->ws,etc);
! 7127: fwrb_chars_etc(fp,pp->cs,etc);
! 7128: fwrb_blobs_etc(fp,pp->bs,etc);
! 7129: }
! 7130:
! 7131: #if FRDI
! 7132: /* read a Page record (only) - it must be next in the file;
! 7133: don't immediately read its parts; return 0 iff immediate EOF */
! 7134: int frdb_page(f,p)
! 7135: FILE *f;
! 7136: Page *p;
! 7137: { char *pfc; /* for debugging */
! 7138: int stat;
! 7139: switch(skip_type(f)) {
! 7140: case 1: /* "TYPE=" header */
! 7141: skip_doc(f);
! 7142: break;
! 7143: case 0: /* immediate EOF */
! 7144: return(0);
! 7145: break;
! 7146: case -1: /* no "TYPE=" header */
! 7147: break;
! 7148: case -2: /* garbled "TYPE=" header */
! 7149: abort("frdb_page: garbled \"TYPE=\" header");
! 7150: break;
! 7151: };
! 7152: *p = empty_Page;
! 7153: if(feof(f))
! 7154: return(0);
! 7155: p->ident=frdi_Ident(f);
! 7156: frdi_Bbx(f,&(p->bx));
! 7157: p->res_x=frdi_int2(f);
! 7158: p->res_y=frdi_int2(f);
! 7159: p->skew=frdi_Radians(f);
! 7160: p->shear=frdi_Radians(f);
! 7161: p->bks.mny=frdi_uint2(f);
! 7162: p->ls.mny=frdi_uint2(f);
! 7163: p->ws.mny=frdi_uint2(f);
! 7164: p->cs.mny=frdi_uint2(f);
! 7165: p->bs.mny=frdi_uint3(f);
! 7166: #if dbg_frdb
! 7167: if((!(p->ident&IsPage))||(p->ident&(IsALL&(~IsPage))))
! 7168: err("frdb_page: %s",page_toa(p));
! 7169: #endif
! 7170: #if dbg_frdb_toa
! 7171: err("frdb_page: %s",page_toa(p));
! 7172: #endif
! 7173: if(p->ident&Page_label) p->l = frdb_label(f);
! 7174: if(ferror(f)) return(-errno); else return(1);
! 7175: }
! 7176: #else
! 7177: /* read a Page record (only) - it must be next in the file;
! 7178: don't immediately read its parts; return T iff not early EOF */
! 7179: int frdb_page(fp,pp)
! 7180: FILE *fp;
! 7181: Page *pp;
! 7182: { PageF pf;
! 7183: char *pfc; /* for debugging */
! 7184: int stat;
! 7185: if((stat=skip_type(fp))!=1 /* "TYPE=" header */
! 7186: && stat!=-1 /* no "TYPE=" header */ ) {
! 7187: /* premature EOF or error */ return(stat);
! 7188: };
! 7189: if((stat=fread(&pf,sizeof(PageF),1,fp))!=1)
! 7190: /* premature EOF*/ return(stat);
! 7191: pfc = (char *)&pf;
! 7192: *pp = empty_Page;
! 7193: pp->ident=pf.ident;
! 7194: pp->res_x=pf.res_x;
! 7195: pp->res_y=pf.res_y;
! 7196: pp->bx=pf.bx;
! 7197: pp->skew=pf.skew;
! 7198: pp->shear=pf.shear;
! 7199: pp->bks.mny = pf.bkmny; pp->bks.bpa=NULL;
! 7200: pp->ls.mny = pf.lmny; pp->ls.lpa=NULL;
! 7201: pp->ws.mny = pf.wmny; pp->ws.wpa=NULL;
! 7202: pp->cs.mny = pf.cmny; pp->cs.cpa=NULL;
! 7203: pp->bs.mny = pf.bmny; pp->bs.bpa=NULL;
! 7204: #if dbg_frdb_toa
! 7205: err("frdb_page: %s",page_toa(pp));
! 7206: #endif
! 7207: if(pp->ident&Page_label) pp->l = frdb_label(fp);
! 7208: #if dbg_frdb
! 7209: if((!(pp->ident&IsPage))||(pp->ident&(IsALL&(~IsPage))))
! 7210: err("frdb_page: %s",page_toa(pp));
! 7211: #endif
! 7212: return(stat);
! 7213: }
! 7214: #endif
! 7215:
! 7216: /* Read a page and selected parts */
! 7217: int frdb_page_etc(fp,pp,etc)
! 7218: FILE *fp;
! 7219: Page *pp;
! 7220: Ident etc;
! 7221: { int stat;
! 7222: if((etc&IsALL)==IsALL) {
! 7223: long here;
! 7224: /* In order to minimize malloc time to read an often huge file,
! 7225: malloc and then free storage roughly equal to what's needed */
! 7226: if( /* DEFEATED */ F && (here=ftell(fp))>=0 && fseek(fp,0,2)>=0 ) {
! 7227: /* *fp is connected to a file, not a pipe */
! 7228: free(malloc(ftell(fp)));
! 7229: fseek(fp,here,0);
! 7230: };
! 7231: };
! 7232: if((stat=frdb_page(fp,pp))!=1) return(stat);
! 7233: if(etc&IsBlock && pp->bks.mny>0)
! 7234: frdb_blocks_etc(fp,&(pp->bks),etc);
! 7235: else pp->bks = empty_Blocks;
! 7236: if(etc&IsTxtln && pp->ls.mny>0)
! 7237: frdb_txtlns_etc(fp,&(pp->ls),etc);
! 7238: else pp->ls = empty_Txtlns;
! 7239: if(etc&IsWord && pp->ws.mny>0)
! 7240: frdb_words_etc(fp,&(pp->ws),etc);
! 7241: else pp->ws = empty_Words;
! 7242: if(etc&IsChar && pp->cs.mny>0)
! 7243: frdb_chars_etc(fp,&(pp->cs),etc);
! 7244: else pp->cs = empty_Chars;
! 7245: if(etc&IsBlob && pp->bs.mny>0)
! 7246: frdb_blobs_etc(fp,&(pp->bs),etc);
! 7247: else pp->bs = empty_Blobs;
! 7248: return(1/*normal return*/);
! 7249: }
! 7250:
! 7251: free_page_etc(p,etc)
! 7252: Page *p;
! 7253: Ident etc;
! 7254: { free_blocks_etc(&(p->bks),etc);
! 7255: free_txtlns_etc(&(p->ls),etc);
! 7256: free_words_etc(&(p->ws),etc);
! 7257: free_chars_etc(&(p->cs),etc);
! 7258: free_blobs_etc(&(p->bs),etc);
! 7259: if(p->ident&Page_label && p->l!=NULL) {
! 7260: free(p->l); p->l=NULL; p->ident &= ~Page_label;
! 7261: };
! 7262: if(etc&IsPage) {
! 7263: free(p);
! 7264: free_census(Page,1);
! 7265: };
! 7266: }
! 7267:
! 7268: /* return a pointer to a distinct and duplicate copy of record Page *p,
! 7269: created out of malloc space */
! 7270: Page *dup_page(p)
! 7271: Page *p;
! 7272: { Page *dup;
! 7273: dup=alloc_page(); *dup = *p; return(dup);
! 7274: }
! 7275:
! 7276: /* Return a pointer to a distinct and duplicate copy of Page *p, and its parts
! 7277: as specified by `etc', created out of malloc space. */
! 7278: Page *dup_page_etc(p,etc)
! 7279: Page *p;
! 7280: Ident etc;
! 7281: { Page *dup;
! 7282: dup = dup_page(p);
! 7283: if(etc&IsBlob&&dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(p->bs),etc);
! 7284: else dup->bs = empty_Blobs;
! 7285: if(etc&IsChar&&dup->cs.mny>0) dup->cs = *dup_chars_etc(&(p->cs),etc);
! 7286: else dup->cs = empty_Chars;
! 7287: if(etc&IsWord&&dup->ws.mny>0) dup->ws = *dup_words_etc(&(p->ws),etc);
! 7288: else dup->ws = empty_Words;
! 7289: if(etc&IsTxtln&&dup->ls.mny>0) dup->ls = *dup_txtlns_etc(&(p->ls),etc);
! 7290: else dup->ls = empty_Txtlns;
! 7291: if(etc&IsBlock&&dup->bks.mny>0) dup->bks = *dup_blocks_etc(&(p->bks),etc);
! 7292: else dup->bks = empty_Blocks;
! 7293: return(dup);
! 7294: }
! 7295:
! 7296: Block *alloc_block()
! 7297: { Block *p;
! 7298: if((p=(Block *)malloc(sizeof(Block)))==NULL)
! 7299: abort("alloc_block: can't malloc");
! 7300: alloc_census(Block,1);
! 7301: *p = empty_Block;
! 7302: return(p);
! 7303: }
! 7304:
! 7305: char *block_toa(p)
! 7306: Block *p;
! 7307: { static char s[80];
! 7308: sprintf(s,"%s bx%s sk%0.2f,sh%0.2f wst%0.2f m%s bk%d l%d w%d c%d b%d",
! 7309: ident_toa(p->ident),
! 7310: bbx_toa(&(p->bx)),
! 7311: p->skew/DtoR,
! 7312: p->shear/DtoR,
! 7313: p->wst,
! 7314: merit_toa(p->m),
! 7315: p->bks.mny,p->ls.mny,p->ws.mny,p->cs.mny,p->bs.mny,
! 7316: (p->l!=NULL)? p->l: "");
! 7317: return(s);
! 7318: }
! 7319:
! 7320: #if FWRI
! 7321: fwrb_block(f,p)
! 7322: FILE *f;
! 7323: Block *p;
! 7324: { int stat;
! 7325: #if dbg_fwrb
! 7326: if((!(p->ident&IsBlock))||(p->ident&(IsALL&(~IsBlock))))
! 7327: err("fwrb_block: %s",block_toa(p));
! 7328: if(p->ident&Block_label && p->l==NULL) {
! 7329: err("fwrb_page: Block_label set but .l==NULL");
! 7330: p->ident &= ~Block_label;
! 7331: };
! 7332: #endif
! 7333: fwri_Ident(f,p->ident);
! 7334: fwri_Bbx(f,&(p->bx));
! 7335: fwri_Radians(f,p->skew);
! 7336: fwri_Radians(f,p->shear);
! 7337: fwri_Ems(f,p->wst);
! 7338: fwri_Merit(f,p->m);
! 7339: fwri_uint2(f,p->bks.mny);
! 7340: fwri_uint2(f,p->ls.mny);
! 7341: fwri_uint2(f,p->ws.mny);
! 7342: fwri_uint2(f,p->cs.mny);
! 7343: fwri_uint3(f,p->bs.mny);
! 7344: #if dbg_fwrb_toa
! 7345: err("fwrb_block: %s",block_toa(p));
! 7346: #endif
! 7347: if(p->ident&Block_label) fwrb_label(f,p->l);
! 7348: }
! 7349: #else
! 7350: fwrb_block(fp,bkp)
! 7351: FILE *fp;
! 7352: Block *bkp;
! 7353: { BlockF bf;
! 7354: int stat;
! 7355: #if dbg_fwrb
! 7356: if((!(bkp->ident&IsBlock))||(bkp->ident&(IsALL&(~IsBlock))))
! 7357: err("fwrb_block: %s",block_toa(bkp));
! 7358: #endif
! 7359: memset(&bf,'\0',sizeof(bf));
! 7360: bf.ident = bkp->ident;
! 7361: bf.bx = bkp->bx;
! 7362: bf.wst = bkp->wst;
! 7363: bf.skew = bkp->skew;
! 7364: bf.shear = bkp->shear;
! 7365: bf.lmny = bkp->ls.mny;
! 7366: bf.wmny = bkp->ws.mny;
! 7367: bf.cmny = bkp->cs.mny;
! 7368: bf.bmny = bkp->bs.mny;
! 7369: #if dbg_fwrb_toa
! 7370: err("fwrb_block: %s",block_toa(bkp));
! 7371: #endif
! 7372: if((stat=fwrite(&bf,sizeof(BlockF),1,fp))!=1)
! 7373: abort("fwrb_block: can't fwrite - status %d",stat);
! 7374: }
! 7375: #endif
! 7376:
! 7377: fwrb_blocks_etc(fp,bks,etc)
! 7378: FILE *fp;
! 7379: Blocks bks;
! 7380: Ident etc;
! 7381: { register Block *bkp,**bkpp;
! 7382: if(bks.mny>0) for(bkp= *(bkpp=bks.bpa); bkp!=NULL; bkp= *(++bkpp))
! 7383: fwrb_block_etc(fp,bkp,etc);
! 7384: }
! 7385:
! 7386: fwrb_block_etc(fp,bkp,etc)
! 7387: FILE *fp;
! 7388: Block *bkp;
! 7389: Ident etc;
! 7390: { static Ident parts = (IsTxtln|IsWord|IsChar|IsBlob);
! 7391: Block bk;
! 7392: if((etc&parts)!=parts) /* write selected parts */ {
! 7393: bk = *bkp;
! 7394: if(!(etc&IsTxtln)) bk.ls.mny=0;
! 7395: if(!(etc&IsWord)) bk.ws.mny=0;
! 7396: if(!(etc&IsChar)) bk.cs.mny=0;
! 7397: if(!(etc&IsBlob)) bk.bs.mny=0;
! 7398: bkp = &bk; /* write modified record */
! 7399: };
! 7400: fwrb_block(fp,bkp);
! 7401: fwrb_txtlns_etc(fp,bkp->ls,etc);
! 7402: fwrb_words_etc(fp,bkp->ws,etc);
! 7403: fwrb_chars_etc(fp,bkp->cs,etc);
! 7404: fwrb_blobs_etc(fp,bkp->bs,etc);
! 7405: }
! 7406:
! 7407: #if FRDI
! 7408: int frdb_block(f,p)
! 7409: FILE *f;
! 7410: Block *p;
! 7411: { *p = empty_Block;
! 7412: if(feof(f))
! 7413: return(0);
! 7414: p->ident=frdi_Ident(f);
! 7415: frdi_Bbx(f,&(p->bx));
! 7416: p->skew=frdi_Radians(f);
! 7417: p->shear=frdi_Radians(f);
! 7418: p->wst=frdi_Ems(f);
! 7419: p->m=frdi_Merit(f);
! 7420: p->bks.mny=frdi_uint2(f);
! 7421: p->ls.mny=frdi_uint2(f);
! 7422: p->ws.mny=frdi_uint2(f);
! 7423: p->cs.mny=frdi_uint2(f);
! 7424: p->bs.mny=frdi_uint3(f);
! 7425: #if dbg_frdb_toa
! 7426: err("frdb_block: %s",block_toa(p));
! 7427: #endif
! 7428: #if dbg_frdb
! 7429: if((!(p->ident&IsBlock))||(p->ident&(IsALL&(~IsBlock))))
! 7430: err("frdb_block: %s",block_toa(p));
! 7431: #endif
! 7432: if(p->ident&Block_label) p->l = frdb_label(f);
! 7433: if(ferror(f)) return(-errno); else return(1);
! 7434: }
! 7435: #else
! 7436: int frdb_block(fp,bkp)
! 7437: FILE *fp;
! 7438: Block *bkp;
! 7439: { BlockF bf;
! 7440: int stat;
! 7441: if((stat=fread(&bf,sizeof(BlockF),1,fp))!=1)
! 7442: abort("frdb_block: can't fread - status %d",stat);
! 7443: *bkp = empty_Block;
! 7444: bkp->ident = bf.ident;
! 7445: bkp->bx = bf.bx;
! 7446: bkp->skew = bf.skew;
! 7447: bkp->shear = bf.shear;
! 7448: bkp->wst = bf.wst;
! 7449: bkp->ls.mny = bf.lmny;
! 7450: bkp->ws.mny = bf.wmny;
! 7451: bkp->cs.mny = bf.cmny;
! 7452: bkp->bs.mny = bf.bmny;
! 7453: #if dbg_frdb
! 7454: if((!(bkp->ident&IsBlock))||(bkp->ident&(IsALL&(~IsBlock))))
! 7455: err("frdb_block: %s",block_toa(bkp));
! 7456: #endif
! 7457: #if dbg_frdb_toa
! 7458: err("frdb_block: %s",block_toa(bkp));
! 7459: #endif
! 7460: if(bkp->ident&Block_label) bkp->l = frdb_label(fp);
! 7461: if(ferror(fp)) return(-errno); else return(1);
! 7462: }
! 7463: #endif
! 7464:
! 7465: frdb_block_etc(fp,bkp,etc)
! 7466: FILE *fp;
! 7467: Block *bkp;
! 7468: Ident etc;
! 7469: { BlockF bf;
! 7470: int stat;
! 7471: frdb_block(fp,bkp);
! 7472: if(etc&IsTxtln && bkp->ls.mny>0)
! 7473: frdb_txtlns_etc(fp,&(bkp->ls),etc);
! 7474: else bkp->ls = empty_Txtlns;
! 7475: if(etc&IsWord && bkp->ws.mny>0)
! 7476: frdb_words_etc(fp,&(bkp->ws),etc);
! 7477: else bkp->ws = empty_Words;
! 7478: if(etc&IsChar && bkp->cs.mny>0)
! 7479: frdb_chars_etc(fp,&(bkp->cs),etc);
! 7480: else bkp->cs = empty_Chars;
! 7481: if(etc&IsBlob && bkp->bs.mny>0)
! 7482: frdb_blobs_etc(fp,&(bkp->bs),etc);
! 7483: else bkp->bs = empty_Blobs;
! 7484: if(ferror(fp)) return(-errno); else return(1);
! 7485: }
! 7486:
! 7487: /* read number of blocks, and their parts */
! 7488: frdb_blocks_etc(fp,bksp,etc)
! 7489: FILE *fp;
! 7490: Blocks *bksp;
! 7491: Ident etc;
! 7492: { int bi;
! 7493: register Block *bkp,**bkpp;
! 7494: if(bksp->mny<=0) {
! 7495: *bksp = empty_Blocks;
! 7496: return(1);
! 7497: };
! 7498:
! 7499: if((bkpp=bksp->bpa=(Block **)malloc((bksp->mny+1)*sizeof(Block *)))==NULL)
! 7500: abort("can't alloc Blocks.bpa array");
! 7501: for(bi=0; bi<bksp->mny; bi++) {
! 7502: *(bkpp++) = bkp = alloc_block();
! 7503: frdb_block_etc(fp,bkp,etc);
! 7504: };
! 7505: *bkpp = NULL;
! 7506: if(ferror(fp)) return(-errno); else return(1);
! 7507: }
! 7508:
! 7509: free_block_etc(p,etc)
! 7510: Block *p;
! 7511: Ident etc;
! 7512: { free_txtlns_etc(&(p->ls),etc);
! 7513: free_words_etc(&(p->ws),etc);
! 7514: free_chars_etc(&(p->cs),etc);
! 7515: free_blobs_etc(&(p->bs),etc);
! 7516: if(p->ident&Block_label && p->l!=NULL) {
! 7517: free(p->l); p->l=NULL; p->ident &= ~Block_label;
! 7518: };
! 7519: if(etc&IsBlock) {
! 7520: free(p);
! 7521: free_census(Block,1);
! 7522: };
! 7523: }
! 7524:
! 7525: /* Unconditionally free the malloc-space array of pointers, and empty the set.
! 7526: Don't free the records that it owned.
! 7527: */
! 7528: free_blocks(p)
! 7529: Blocks *p;
! 7530: { if(p->bpa!=NULL) { free(p->bpa); p->bpa = NULL; }
! 7531: p->mny = 0;
! 7532: }
! 7533:
! 7534: free_blocks_etc(p,etc)
! 7535: Blocks *p;
! 7536: Ident etc;
! 7537: { register Block *bkp,**bkpp;
! 7538: if(p->mny>0&&(etc&IsBlock))
! 7539: for(bkp= *(bkpp=p->bpa); bkp!=NULL; bkp= *(++bkpp))
! 7540: free_block_etc(bkp,etc);
! 7541: free_blocks(p);
! 7542: }
! 7543:
! 7544: /* return a pointer to a distinct and duplicate copy of *bkp,
! 7545: created out of malloc space */
! 7546: Block *dup_block(bkp)
! 7547: Block *bkp;
! 7548: { Block *dup;
! 7549: dup=alloc_block();
! 7550: *dup = *bkp;
! 7551: return(dup);
! 7552: }
! 7553:
! 7554: /* Return a pointer to a distinct and duplicate copy of *bkp, and its parts
! 7555: as specified by `etc', created out of malloc space. */
! 7556: Block *dup_block_etc(bkp,etc)
! 7557: Block *bkp;
! 7558: Ident etc;
! 7559: { Block *dup;
! 7560: dup = dup_block(bkp);
! 7561: if(etc&IsBlob&&dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(bkp->bs),etc);
! 7562: else dup->bs = empty_Blobs;
! 7563: if(etc&IsChar&&dup->cs.mny>0) dup->cs = *dup_chars_etc(&(bkp->cs),etc);
! 7564: else dup->cs = empty_Chars;
! 7565: if(etc&IsWord&&dup->ws.mny>0) dup->ws = *dup_words_etc(&(bkp->ws),etc);
! 7566: else dup->ws = empty_Words;
! 7567: if(etc&IsTxtln&&dup->ls.mny>0) dup->ls = *dup_txtlns_etc(&(bkp->ls),etc);
! 7568: else dup->ls = empty_Txtlns;
! 7569: return(dup);
! 7570: }
! 7571:
! 7572: /* Return a pointer to a distinct local static duplicate of non-empty *bksp.
! 7573: Its bkpa array is created newly out of malloc space.
! 7574: If etc&IsBlock, all its Blocks are also duplicated,
! 7575: else the contents of bkpa point to the old unduplicated Blocks.
! 7576: */
! 7577: Blocks *dup_blocks_etc(bksp,etc)
! 7578: Blocks *bksp;
! 7579: Ident etc; /* parts to duplicate */
! 7580: { static Blocks dup;
! 7581: register Block **bkpp,**dpp;
! 7582: if((dup.mny = bksp->mny)<=0) dup = empty_Blocks;
! 7583: else { if((dup.bpa=(Block **)malloc((dup.mny+1)*sizeof(Block *)))==NULL)
! 7584: abort("can't dup bks.bpa");
! 7585: for(bkpp=bksp->bpa,dpp=dup.bpa; *bkpp!=NULL; bkpp++,dpp++) {
! 7586: if(etc&IsBlock) *dpp = dup_block_etc(*bkpp,etc);
! 7587: else *dpp = *bkpp;
! 7588: };
! 7589: *dpp = NULL;
! 7590: };
! 7591: return(&dup);
! 7592: }
! 7593:
! 7594: /* Append a block to the end of a blocks set.
! 7595: Return appended Block *. */
! 7596: Block *append_block(bkp,bksp)
! 7597: Block *bkp;
! 7598: Blocks *bksp;
! 7599: { register Block *rp,**rpp,**npp;
! 7600: if(bksp->mny==0) {
! 7601: if((bksp->bpa=(Block **)malloc(2*sizeof(Block *)))==NULL)
! 7602: abort("append_block: can't malloc bksp->bpa");
! 7603: }
! 7604: else { if((bksp->bpa=(Block **)realloc(
! 7605: bksp->bpa,
! 7606: (bksp->mny+2)*sizeof(Block *))
! 7607: )==NULL)
! 7608: abort("append_block: can't realloc bksp->bpa");
! 7609: };
! 7610: bksp->bpa[bksp->mny] = bkp;
! 7611: bksp->bpa[++bksp->mny] = NULL;
! 7612: return(bkp);
! 7613: }
! 7614:
! 7615: /* remove a block from a blocks set */
! 7616: remove_block(bkp,bksp)
! 7617: Block *bkp;
! 7618: Blocks *bksp;
! 7619: { register Block *rp,**rpp,**npp;
! 7620: if(bksp->mny==0) err("can't remove Block - Blocks empty");
! 7621: else { for(rp= *(rpp=bksp->bpa); rp!=NULL; rp= *(++rpp)) if(rp==bkp) break;
! 7622: if(rp==NULL) err("can't remove Block - not found");
! 7623: else { /* move later entries up */
! 7624: npp=rpp+1;
! 7625: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
! 7626: if((--(bksp->mny))==0) {free(bksp->bpa); bksp->bpa=NULL;};
! 7627: /* don't bother to realloc downwards */
! 7628: };
! 7629: };
! 7630: }
! 7631:
! 7632: ConstPitch *alloc_constpitch()
! 7633: { ConstPitch *p;
! 7634: if((p=(ConstPitch *)malloc(sizeof(ConstPitch)))==NULL)
! 7635: abort("can't alloc ConstPitch");
! 7636: else { *p = empty_ConstPitch;
! 7637: return(p);
! 7638: };
! 7639: }
! 7640:
! 7641: char *constpitch_toa(p)
! 7642: ConstPitch *p;
! 7643: { static char s[80];
! 7644: sprintf(s,"{w%.3f,o%d,r%.1f}",
! 7645: p->w,p->o,p->r);
! 7646: return(s);
! 7647: }
! 7648:
! 7649: free_constpitch(p)
! 7650: ConstPitch *p;
! 7651: { free(p);
! 7652: }
! 7653:
! 7654: Txtln *alloc_txtln()
! 7655: { Txtln *p;
! 7656: if((p=(Txtln *)malloc(sizeof(Txtln)))==NULL)
! 7657: abort("can't alloc Txtln");
! 7658: alloc_census(Txtln,1);
! 7659: *p = empty_Txtln;
! 7660: return(p);
! 7661: }
! 7662:
! 7663: char *txtln_toa(p)
! 7664: Txtln *p;
! 7665: { static char s[80];
! 7666: sprintf(s,"%s bx%s sz%s ba%d cw%s m%s l%d w%d c%d b%d %s",
! 7667: ident_toa(p->ident),
! 7668: bbx_toa(&(p->bx)),
! 7669: pts_toa(p->size),
! 7670: p->basl,
! 7671: /** proj omitted **/
! 7672: ((p->cp!=NULL)? constpitch_toa(p->cp): "0"),
! 7673: merit_toa(p->m),
! 7674: p->ls.mny,p->ws.mny,p->cs.mny,p->bs.mny,
! 7675: (p->l!=NULL)? p->l: "");
! 7676: return(s);
! 7677: }
! 7678:
! 7679: #if FWRI
! 7680: fwrb_txtln(f,p)
! 7681: FILE *f;
! 7682: Txtln *p;
! 7683: {
! 7684: #if dbg_fwrb
! 7685: if((!(p->ident&IsTxtln))||(p->ident&(IsALL&(~IsTxtln))))
! 7686: err("fwrb_txtln: %s",txtln_toa(p));
! 7687: if(p->ident&Txtln_label && p->l==NULL) {
! 7688: err("fwrb_page: Txtln_label set but .l==NULL");
! 7689: p->ident &= ~Txtln_label;
! 7690: };
! 7691: #endif
! 7692: fwri_Ident(f,p->ident);
! 7693: fwri_Bbx(f,&(p->bx));
! 7694: fwri_Pts(f,p->size);
! 7695: fwri_Scoor(f,p->basl);
! 7696: /* fwri_?(f,p->proj); */
! 7697: /* fwri_ConstPitch(f,p->cp); */
! 7698: fwri_Merit(f,p->m);
! 7699: fwri_uint2(f,p->ls.mny);
! 7700: fwri_uint2(f,p->ws.mny);
! 7701: fwri_uint2(f,p->cs.mny);
! 7702: fwri_uint3(f,p->bs.mny);
! 7703: #if dbg_fwrb_toa
! 7704: err("fwrb_txtln: %s",txtln_toa(p));
! 7705: #endif
! 7706: if(p->ident&Txtln_label) fwrb_label(f,p->l);
! 7707: }
! 7708: #else
! 7709: fwrb_txtln(fp,lp)
! 7710: FILE *fp;
! 7711: Txtln *lp;
! 7712: { TxtlnF lf;
! 7713: int stat;
! 7714: #if dbg_fwrb
! 7715: if((!(lp->ident&IsTxtln))||(lp->ident&(IsALL&(~IsTxtln))))
! 7716: err("fwrb_txtln: %s",txtln_toa(lp));
! 7717: #endif
! 7718: memset(&lf,'\0',sizeof(lf));
! 7719: lf.ident = lp->ident;
! 7720: lf.bx = lp->bx;
! 7721: lf.basl = lp->basl;
! 7722: lf.size = lp->size;
! 7723: if(lp->proj!=NULL) lf.pmny = lp->bx.b.y - lp->bx.a.y + 1;
! 7724: else lf.pmny = 0;
! 7725: /* ignore lp->cp for now */
! 7726: lf.wmny = lp->ws.mny;
! 7727: lf.cmny = lp->cs.mny;
! 7728: lf.bmny = lp->bs.mny;
! 7729: if((stat=fwrite(&lf,sizeof(TxtlnF),1,fp))!=1)
! 7730: abort("can't write TxtlnF, status %d",stat);
! 7731: #if dbg_fwrb_toa
! 7732: err("fwrb_txtln: %s",txtln_toa(lp));
! 7733: #endif
! 7734: if(lf.ident&Txtln_label) fwrb_label(fp,lp->l);
! 7735: }
! 7736: #endif
! 7737:
! 7738: fwrb_txtlns_etc(fp,ls,etc)
! 7739: FILE *fp;
! 7740: Txtlns ls;
! 7741: Ident etc;
! 7742: { register Txtln *lp,**lpp;
! 7743: if(ls.mny>0) for(lp= *(lpp=ls.lpa); lp!=NULL; lp= *(++lpp))
! 7744: fwrb_txtln_etc(fp,lp,etc);
! 7745: }
! 7746:
! 7747: fwrb_txtln_etc(fp,lp,etc)
! 7748: FILE *fp;
! 7749: Txtln *lp;
! 7750: Ident etc;
! 7751: { static Ident parts = (IsWord|IsChar|IsBlob);
! 7752: Txtln tl;
! 7753: if((etc&parts)!=parts) /* write selected parts */ {
! 7754: tl = *lp;
! 7755: if(!(etc&IsWord)) tl.ws.mny=0;
! 7756: if(!(etc&IsChar)) tl.cs.mny=0;
! 7757: if(!(etc&IsBlob)) tl.bs.mny=0;
! 7758: lp = &tl; /* write modified record */
! 7759: };
! 7760: fwrb_txtln(fp,lp);
! 7761: if(lp->proj!=NULL) {/* write projection array someday */};
! 7762: fwrb_words_etc(fp,lp->ws,etc);
! 7763: fwrb_chars_etc(fp,lp->cs,etc);
! 7764: fwrb_blobs_etc(fp,lp->bs,etc);
! 7765: }
! 7766:
! 7767: #if FRDI
! 7768: int frdb_txtln(f,p)
! 7769: FILE *f;
! 7770: Txtln *p;
! 7771: { *p = empty_Txtln;
! 7772: if(feof(f))
! 7773: return(0);
! 7774: p->ident=frdi_Ident(f);
! 7775: frdi_Bbx(f,&(p->bx));
! 7776: p->size=frdi_Pts(f);
! 7777: p->basl=frdi_Scoor(f);
! 7778: /* p->proj=frdi_?(f); */
! 7779: /* p->cp=frdi_ConstPitch(f); */
! 7780: p->m=frdi_Merit(f);
! 7781: p->ls.mny=frdi_uint2(f);
! 7782: p->ws.mny=frdi_uint2(f);
! 7783: p->cs.mny=frdi_uint2(f);
! 7784: p->bs.mny=frdi_uint3(f);
! 7785: #if dbg_frdb
! 7786: if((!(p->ident&IsTxtln))||(p->ident&(IsALL&(~IsTxtln))))
! 7787: err("frdb_txtln: %s",txtln_toa(p));
! 7788: #endif
! 7789: #if dbg_frdb_toa
! 7790: err("frdb_txtln: %s",txtln_toa(p));
! 7791: #endif
! 7792: if(p->ident&Txtln_label) p->l = frdb_label(f);
! 7793: if(ferror(f)) return(-errno); else return(1);
! 7794: }
! 7795: #else
! 7796: int frdb_txtln(fp,lp)
! 7797: FILE *fp;
! 7798: Txtln *lp;
! 7799: { TxtlnF lf;
! 7800: int stat;
! 7801: if((stat=fread(&lf,sizeof(TxtlnF),1,fp))!=1)
! 7802: abort("can't read TxtlnF, status %d",stat);
! 7803: *lp = empty_Txtln;
! 7804: lp->ident = lf.ident;
! 7805: lp->bx = lf.bx;
! 7806: lp->basl = lf.basl;
! 7807: lp->size = lf.size;
! 7808: if(lf.pmny>0) lp->proj=(short *)malloc(lf.pmny);
! 7809: else lp->proj = NULL;
! 7810: lp->cp = NULL;
! 7811: lp->ws.mny = lf.wmny;
! 7812: lp->cs.mny = lf.cmny;
! 7813: lp->bs.mny = lf.bmny;
! 7814: #if dbg_frdb
! 7815: if((!(lp->ident&IsTxtln))||(lp->ident&(IsALL&(~IsTxtln))))
! 7816: err("frdb_txtln: %s",txtln_toa(lp));
! 7817: #endif
! 7818: #if dbg_frdb_toa
! 7819: err("frdb_txtln: %s",txtln_toa(lp));
! 7820: #endif
! 7821: if(lp->ident&Txtln_label) lp->l = frdb_label(fp);
! 7822: if(ferror(fp)) return(-errno); else return(1);
! 7823: }
! 7824: #endif
! 7825:
! 7826: frdb_txtln_etc(fp,lp,etc)
! 7827: FILE *fp;
! 7828: Txtln *lp;
! 7829: Ident etc;
! 7830: { TxtlnF lf;
! 7831: int stat;
! 7832: frdb_txtln(fp,lp);
! 7833: if(lp->proj!=NULL) {/* read projection array someday */};
! 7834: if(etc&IsWord && lp->ws.mny>0)
! 7835: frdb_words_etc(fp,&(lp->ws),etc);
! 7836: else lp->ws = empty_Words;
! 7837: if(etc&IsChar && lp->cs.mny>0)
! 7838: frdb_chars_etc(fp,&(lp->cs),etc);
! 7839: else lp->cs = empty_Chars;
! 7840: if(etc&IsBlob && lp->bs.mny>0)
! 7841: frdb_blobs_etc(fp,&(lp->bs),etc);
! 7842: else lp->bs = empty_Blobs;
! 7843: if(ferror(fp)) return(-errno); else return(1);
! 7844: }
! 7845:
! 7846: /* read number of txtlns, and parts */
! 7847: frdb_txtlns_etc(fp,lsp,etc)
! 7848: FILE *fp;
! 7849: Txtlns *lsp;
! 7850: Ident etc;
! 7851: { int li;
! 7852: register Txtln *lp,**lpp;
! 7853: if(lsp->mny<=0) {
! 7854: *lsp = empty_Txtlns;
! 7855: return(1);
! 7856: };
! 7857: if((lpp=lsp->lpa=(Txtln **)malloc((lsp->mny+1)*sizeof(Txtln *)))==NULL)
! 7858: abort("can't alloc Txtlns.lpa array");
! 7859: for(li=0; li<lsp->mny; li++) {
! 7860: *(lpp++) = lp = alloc_txtln();
! 7861: frdb_txtln_etc(fp,lp,etc);
! 7862: };
! 7863: *lpp = NULL;
! 7864: if(ferror(fp)) return(-errno); else return(1);
! 7865: }
! 7866:
! 7867: /* Append a txtln to the end of a txtlns set.
! 7868: Do NOT maintain Txtlns in order sorted ascending on Txtln.bx.a.y.
! 7869: Return appended Txtln *. */
! 7870: Txtln *append_txtln(lp,lsp)
! 7871: Txtln *lp;
! 7872: Txtlns *lsp;
! 7873: { register Txtln *rp,**rpp,**npp;
! 7874: if(lsp->mny==0) {
! 7875: if((lsp->lpa=(Txtln **)malloc(2*sizeof(Txtln *)))==NULL)
! 7876: abort("append_txtln: can't malloc lsp->lpa");
! 7877: }
! 7878: else { if((lsp->lpa=(Txtln **)realloc(
! 7879: lsp->lpa,
! 7880: (lsp->mny+2)*sizeof(Txtln *))
! 7881: )==NULL)
! 7882: abort("append_txtln: can't realloc lsp->lpa");
! 7883: };
! 7884: lsp->lpa[lsp->mny] = lp;
! 7885: lsp->lpa[++lsp->mny] = NULL;
! 7886: return(lp);
! 7887: }
! 7888:
! 7889: /* remove a txtln from a txtlns set */
! 7890: remove_txtln(lp,lsp)
! 7891: Txtln *lp;
! 7892: Txtlns *lsp;
! 7893: { register Txtln *rp,**rpp,**npp;
! 7894: if(lsp->mny==0) err("can't remove Txtln - Txtlns empty");
! 7895: else { for(rp= *(rpp=lsp->lpa); rp!=NULL; rp= *(++rpp)) if(rp==lp) break;
! 7896: if(rp==NULL) err("can't remove Txtln - not found");
! 7897: else { /* move later entries up */
! 7898: npp=rpp+1;
! 7899: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
! 7900: if((--(lsp->mny))==0) {free(lsp->lpa); lsp->lpa=NULL;};
! 7901: /* don't bother to realloc downwards */
! 7902: };
! 7903: };
! 7904: }
! 7905:
! 7906: free_txtln_etc(p,etc)
! 7907: Txtln *p;
! 7908: Ident etc;
! 7909: { free_words_etc(&(p->ws),etc);
! 7910: free_chars_etc(&(p->cs),etc);
! 7911: free_blobs_etc(&(p->bs),etc);
! 7912: if(p->ident&Txtln_label && p->l!=NULL) {
! 7913: free(p->l); p->l=NULL; p->ident &= ~Txtln_label;
! 7914: };
! 7915: if(etc&IsTxtln) {
! 7916: if(p->l!=NULL) free(p->l);
! 7917: free(p);
! 7918: free_census(Txtln,1);
! 7919: };
! 7920: }
! 7921:
! 7922: /* Unconditionally free the malloc-space array of pointers, and empty the set.
! 7923: Don't free the records that it owned.
! 7924: */
! 7925: free_txtlns(lsp)
! 7926: Txtlns *lsp;
! 7927: { if(lsp->lpa!=NULL) { free(lsp->lpa); lsp->lpa = NULL; }
! 7928: lsp->mny = 0;
! 7929: }
! 7930:
! 7931: free_txtlns_etc(lsp,etc)
! 7932: Txtlns *lsp;
! 7933: Ident etc;
! 7934: { register Txtln *lp,**lpp;
! 7935: if(lsp->mny>0&&(etc&IsTxtln))
! 7936: for(lp= *(lpp=lsp->lpa); lp!=NULL; lp= *(++lpp))
! 7937: free_txtln_etc(lp,etc);
! 7938: free_txtlns(lsp);
! 7939: }
! 7940:
! 7941: /* return a pointer to a distinct and duplicate copy of *lp,
! 7942: created out of malloc space */
! 7943: Txtln *dup_txtln(lp)
! 7944: Txtln *lp;
! 7945: { Txtln *dup;
! 7946: if((dup=(Txtln *)malloc(sizeof(Txtln)))==NULL)
! 7947: abort("can't dup Txtln");
! 7948: alloc_census(Txtln,1);
! 7949: *dup = *lp;
! 7950: return(dup);
! 7951: }
! 7952:
! 7953: /* Return a pointer to a distinct and duplicate copy of *lp, and its parts
! 7954: as specified by `etc', created out of malloc space. */
! 7955: Txtln *dup_txtln_etc(lp,etc)
! 7956: Txtln *lp;
! 7957: Ident etc;
! 7958: { Txtln *dup;
! 7959: dup = dup_txtln(lp);
! 7960: if(etc&IsBlob&&dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(lp->bs),etc);
! 7961: else dup->bs = empty_Blobs;
! 7962: if(etc&IsChar&&dup->cs.mny>0) dup->cs = *dup_chars_etc(&(lp->cs),etc);
! 7963: else dup->cs = empty_Chars;
! 7964: if(etc&IsWord&&dup->ws.mny>0) dup->ws = *dup_words_etc(&(lp->ws),etc);
! 7965: else dup->ws = empty_Words;
! 7966: return(dup);
! 7967: }
! 7968:
! 7969: /* Return a pointer to a distinct local static duplicate of non-empty *lsp.
! 7970: Its lpa array is created newly out of malloc space.
! 7971: If etc&IsTxtln, all its Txtlns are also duplicated,
! 7972: else the contents of lpa point to the old unduplicated Txtlns.
! 7973: */
! 7974: Txtlns *dup_txtlns_etc(lsp,etc)
! 7975: Txtlns *lsp;
! 7976: Ident etc; /* parts to duplicate */
! 7977: { static Txtlns dup;
! 7978: register Txtln **lpp,**dpp;
! 7979: if((dup.mny = lsp->mny)<=0) dup = empty_Txtlns;
! 7980: else { if((dup.lpa=(Txtln **)malloc((dup.mny+1)*sizeof(Txtln *)))==NULL)
! 7981: abort("can't dup ls.lpa");
! 7982: for(lpp=lsp->lpa,dpp=dup.lpa; *lpp!=NULL; lpp++,dpp++) {
! 7983: if(etc&IsTxtln) *dpp = dup_txtln_etc(*lpp,etc);
! 7984: else *dpp = *lpp;
! 7985: };
! 7986: *dpp = NULL;
! 7987: };
! 7988: return(&dup);
! 7989: }
! 7990:
! 7991: Word *alloc_word()
! 7992: { Word *p;
! 7993: if((p=(Word *)malloc(sizeof(Word)))==NULL)
! 7994: abort("can't alloc Word");
! 7995: alloc_census(Word,1);
! 7996: *p = empty_Word;
! 7997: return(p);
! 7998: }
! 7999:
! 8000: char *word_toa(p)
! 8001: Word *p;
! 8002: { static char s[80];
! 8003: sprintf(s,"%s bx%s ws%0.2f c%d b%d m%s w%d",
! 8004: ident_toa(p->ident),
! 8005: bbx_toa(&(p->bx)),
! 8006: p->wsp,
! 8007: p->cs.mny,p->bs.mny,merit_toa(p->m),p->ws.mny);
! 8008: return(s);
! 8009: }
! 8010:
! 8011: /* Are two Words identical? A not quite exhaustively-detailed test. */
! 8012: boolean eq_word(w1,w2)
! 8013: Word *w1,*w2;
! 8014: { register Char **c1,**c2;
! 8015: if(w1->cs.mny!=w2->cs.mny) return(F);
! 8016: for(c1=w1->cs.cpa,c2=w2->cs.cpa; *c1!=NULL; c1++,c2++) {
! 8017: if((*c1)->area!=(*c2)->area) return(F);
! 8018: if(!bbx_eq(&((*c1)->bx),&((*c2)->bx))) return(F);
! 8019: if((*c1)->bmny!=(*c2)->bmny) return(F);
! 8020: };
! 8021: /* don't bother to compare Blob lists in detail (they aren't
! 8022: in any particular order). */
! 8023: return(T);
! 8024: }
! 8025:
! 8026: /* Compute a hash key for this Word that is likely to indicate whether or
! 8027: not it is geometrically identical to another Word. */
! 8028: int hash_word(w)
! 8029: Word *w;
! 8030: { register int k;
! 8031: register Char **c;
! 8032: if(w->cs.mny==0) return(0);
! 8033: k = w->bx.a.x * w->bx.a.y * w->bx.b.x * w->bx.b.y;
! 8034: for(c=w->cs.cpa; (*c)!=NULL; c++) {
! 8035: k += (*c)->bx.a.x * (*c)->bx.a.y * (*c)->bx.b.x
! 8036: * (*c)->bx.b.y * (*c)->bmny * (*c)->area;
! 8037: };
! 8038: return(k);
! 8039: }
! 8040:
! 8041: #if FWRI
! 8042: fwrb_word(f,p)
! 8043: FILE *f;
! 8044: Word *p;
! 8045: {
! 8046: #if dbg_fwrb
! 8047: if((!(p->ident&IsWord))||(p->ident&(IsALL&(~IsWord))))
! 8048: err("fwrb_word: %s",word_toa(p));
! 8049: if(p->ident&Word_label && p->l==NULL) {
! 8050: err("fwrb_page: Word_label set but .l==NULL");
! 8051: p->ident &= ~Word_label;
! 8052: };
! 8053: #endif
! 8054: fwri_Ident(f,p->ident);
! 8055: fwri_Bbx(f,&(p->bx));
! 8056: fwri_int2(f,p->wsp*UCHAR_MAX);
! 8057: fwri_Merit(f,p->m);
! 8058: fwri_Prob(f,p->p);
! 8059: fwri_uint2(f,p->ws.mny);
! 8060: fwri_uint2(f,p->cs.mny);
! 8061: fwri_uint3(f,p->bs.mny);
! 8062: /* fwri_int4(f,p->hash); */
! 8063: #if dbg_fwrb_toa
! 8064: err("fwrb_word: %s",word_toa(p));
! 8065: #endif
! 8066: if(p->ident&Word_label) fwrb_label(f,p->l);
! 8067: }
! 8068: #else
! 8069: fwrb_word(fp,wp)
! 8070: FILE *fp;
! 8071: Word *wp;
! 8072: { WordF wf;
! 8073: int stat;
! 8074: #if dbg_fwrb
! 8075: if((!(wp->ident&IsWord))||(wp->ident&(IsALL&(~IsWord))))
! 8076: err("fwrb_word: %s",word_toa(wp));
! 8077: #endif
! 8078: memset(&wf,'\0',sizeof(wf));
! 8079: wf.ident = wp->ident;
! 8080: wf.bx = wp->bx;
! 8081: wf.wsp = wp->wsp;
! 8082: wf.m = wp->m;
! 8083: wf.wmny = wp->ws.mny;
! 8084: wf.cmny = wp->cs.mny;
! 8085: wf.bmny = wp->bs.mny;
! 8086: if((stat=fwrite(&wf,sizeof(WordF),1,fp))!=1)
! 8087: abort("can't write WordF, status %d",stat);
! 8088: #if dbg_fwrb_toa
! 8089: err("fwrb_word: %s",word_toa(wp));
! 8090: #endif
! 8091: if(wf.ident&Word_label) fwrb_label(fp,wp->l);
! 8092: }
! 8093: #endif
! 8094:
! 8095: fwrb_words_etc(fp,ws,etc)
! 8096: FILE *fp;
! 8097: Words ws;
! 8098: Ident etc;
! 8099: { register Word *wp,**wpp;
! 8100: if(ws.mny>0) for(wp= *(wpp=ws.wpa); wp!=NULL; wp= *(++wpp))
! 8101: fwrb_word_etc(fp,wp,etc);
! 8102: }
! 8103:
! 8104: fwrb_word_etc(fp,wp,etc)
! 8105: FILE *fp;
! 8106: Word *wp;
! 8107: Ident etc;
! 8108: { static Ident parts = (IsWord|IsChar|IsBlob);
! 8109: Word wd;
! 8110: if((etc&parts)!=parts) /* write selected parts */ {
! 8111: wd = *wp;
! 8112: if(!(etc&IsWord)) wd.ws.mny=0;
! 8113: if(!(etc&IsChar)) wd.cs.mny=0;
! 8114: if(!(etc&IsBlob)) wd.bs.mny=0;
! 8115: wp = &wd; /* write modified record */
! 8116: };
! 8117: fwrb_word(fp,wp);
! 8118: if(etc&IsWord) fwrb_words_etc(fp,wp->ws,IsALL);
! 8119: fwrb_chars_etc(fp,wp->cs,etc);
! 8120: fwrb_blobs_etc(fp,wp->bs,etc);
! 8121: }
! 8122:
! 8123: #if FRDI
! 8124: int frdb_word(f,p)
! 8125: FILE *f;
! 8126: Word *p;
! 8127: { *p = empty_Word;
! 8128: if(feof(f))
! 8129: return(0);
! 8130: p->ident=frdi_Ident(f);
! 8131: frdi_Bbx(f,&(p->bx));
! 8132: p->wsp=frdi_int2(f)/(float)UCHAR_MAX;
! 8133: p->m=frdi_Merit(f);
! 8134: p->p=frdi_Prob(f);
! 8135: p->ws.mny=frdi_uint2(f);
! 8136: p->cs.mny=frdi_uint2(f);
! 8137: p->bs.mny=frdi_uint3(f);
! 8138: /* p->hash=frdi_int4(f); */
! 8139: #if dbg_frdb
! 8140: if((!(p->ident&IsWord))||(p->ident&(IsALL&(~IsWord))))
! 8141: err("frdb_word: %s",word_toa(p));
! 8142: #endif
! 8143: #if dbg_frdb_toa
! 8144: err("frdb_word: %s",word_toa(p));
! 8145: #endif
! 8146: if(p->ident&Word_label) p->l = frdb_label(f);
! 8147: if(ferror(f)) return(-errno); else return(1);
! 8148: }
! 8149: #else
! 8150: int frdb_word(fp,wp)
! 8151: FILE *fp;
! 8152: Word *wp;
! 8153: { WordF wf;
! 8154: int stat;
! 8155: if((stat=fread(&wf,sizeof(WordF),1,fp))!=1)
! 8156: abort("can't read WordF, status %d",stat);
! 8157: *wp = empty_Word;
! 8158: wp->ident = wf.ident;
! 8159: wp->bx = wf.bx;
! 8160: wp->wsp = wf.wsp;
! 8161: wp->m = wf.m;
! 8162: wp->ws.mny = wf.wmny;
! 8163: wp->cs.mny = wf.cmny;
! 8164: wp->bs.mny = wf.bmny;
! 8165: #if dbg_frdb
! 8166: if((!(wp->ident&IsWord))||(wp->ident&(IsALL&(~IsWord))))
! 8167: err("frdb_word: %s",word_toa(wp));
! 8168: #endif
! 8169: #if dbg_frdb_toa
! 8170: err("frdb_word: %s",word_toa(wp));
! 8171: #endif
! 8172: if(wp->ident&Word_label) wp->l = frdb_label(fp);
! 8173: if(ferror(fp)) return(-errno); else return(1);
! 8174: }
! 8175: #endif
! 8176:
! 8177: frdb_word_etc(fp,wp,etc)
! 8178: FILE *fp;
! 8179: Word *wp;
! 8180: Ident etc;
! 8181: { WordF cf;
! 8182: int stat;
! 8183: frdb_word(fp,wp);
! 8184: frdb_words_etc(fp,&(wp->ws),IsALL); /* rd alternatives entirely, if any */
! 8185: if(etc&IsChar && wp->cs.mny>0)
! 8186: frdb_chars_etc(fp,&(wp->cs),etc);
! 8187: else wp->cs = empty_Chars;
! 8188: if(etc&IsBlob && wp->bs.mny>0)
! 8189: frdb_blobs_etc(fp,&(wp->bs),etc);
! 8190: else wp->bs = empty_Blobs;
! 8191: if(ferror(fp)) return(-errno); else return(1);
! 8192: }
! 8193:
! 8194: /* read words, and their parts */
! 8195: frdb_words_etc(fp,wsp,etc)
! 8196: FILE *fp;
! 8197: Words *wsp;
! 8198: Ident etc;
! 8199: { int wi;
! 8200: register Word *wp,**wpp;
! 8201: if(wsp->mny<=0) {
! 8202: *wsp = empty_Words;
! 8203: return(1);
! 8204: };
! 8205: if((wpp=wsp->wpa=(Word **)malloc((wsp->mny+1)*sizeof(Word *)))==NULL)
! 8206: abort("can't alloc Words.wpa array");
! 8207: for(wi=0; wi<wsp->mny; wi++) {
! 8208: *(wpp++) = wp = alloc_word();
! 8209: frdb_word_etc(fp,wp,etc);
! 8210: };
! 8211: *wpp = NULL;
! 8212: if(ferror(fp)) return(-errno); else return(1);
! 8213: }
! 8214:
! 8215: /* remove a word from a words set */
! 8216: remove_word(wp,wsp)
! 8217: Word *wp;
! 8218: Words *wsp;
! 8219: { register Word *rp,**rpp,**npp;
! 8220: if(wsp->mny==0) err("can't remove Word - Words empty");
! 8221: else { for(rp= *(rpp=wsp->wpa); rp!=NULL; rp= *(++rpp)) if(rp==wp) break;
! 8222: if(rp==NULL) err("can't remove Word - not found");
! 8223: else { /* move later entries up */
! 8224: npp=rpp+1;
! 8225: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
! 8226: if((--(wsp->mny))==0) {free(wsp->wpa); wsp->wpa=NULL;};
! 8227: /* don't bother to realloc downwards */
! 8228: };
! 8229: };
! 8230: }
! 8231:
! 8232: /* Remove a Word from a Txtln's Words set.
! 8233: Shrink the Txtln's Bbx if the Word abuts it on the left or right.
! 8234: Ensure that the first Word in the line has wsp==0.0
! 8235: BUG: doesn't update wsp of trailing Word */
! 8236: remove_word_txtln(wp,lp)
! 8237: Word *wp;
! 8238: Txtln *lp;
! 8239: { register Word *cwp,**wpp;
! 8240: remove_word(wp,&(lp->ws));
! 8241: if(lp->ws.mny>0) {
! 8242: if(wp->bx.a.x==lp->bx.a.x || wp->bx.b.x==lp->bx.b.x) {
! 8243: /* recompute possibly shrunken bx */
! 8244: lp->bx=empty_Bbx;
! 8245: for(cwp= *(wpp=lp->ws.wpa); cwp!=NULL; cwp= *(++wpp))
! 8246: merge_bbx(&(cwp->bx),&(lp->bx));
! 8247: };
! 8248: (lp->ws.wpa[0])->wsp=0.0;
! 8249: };
! 8250: }
! 8251:
! 8252: /* Append a word to the end of a words set.
! 8253: Do NOT maintain set in order ascending on Word.bx.a.x.
! 8254: Return the appended Word. */
! 8255: Word *append_word(wp,wsp)
! 8256: Word *wp;
! 8257: Words *wsp;
! 8258: { if(wsp->mny==0) {
! 8259: if((wsp->wpa=(Word **)malloc(2*sizeof(Word *)))==NULL)
! 8260: abort("append_word: can't malloc wsp->wpa");
! 8261: }
! 8262: else { if((wsp->wpa=(Word **)realloc(
! 8263: wsp->wpa,
! 8264: (wsp->mny+2)*sizeof(Word *))
! 8265: )==NULL)
! 8266: abort("append_word: can't realloc wsp->wpa");
! 8267: };
! 8268: wsp->wpa[wsp->mny++] = wp;
! 8269: wsp->wpa[wsp->mny] = NULL;
! 8270: return(wp);
! 8271: }
! 8272:
! 8273: /* Insert a Word into a Words set. Words is assumed to be sorted ascending
! 8274: on Word.bx.a.x, and this order is maintained.
! 8275: Words with equal Word.bx.a.x are stored in the order that they were
! 8276: inserted: so that the first one inserted remains the first among equals
! 8277: (this feature is important for certain WordSet applications).
! 8278: Return inserted (Word *) */
! 8279: Word *insert_word(wp,wsp)
! 8280: Word *wp;
! 8281: Words *wsp;
! 8282: { register Word **wpp,*nwp,*pwp;
! 8283: if(wsp->mny==0) {
! 8284: if((wsp->wpa=(Word **)malloc(2*sizeof(Word *)))==NULL)
! 8285: abort("insert_word: can't malloc wsp->wpa");
! 8286: wsp->wpa[wsp->mny] = wp;
! 8287: }
! 8288: else { if((wpp=wsp->wpa=(Word **)realloc(
! 8289: wsp->wpa,
! 8290: (wsp->mny+2)*sizeof(Word *))
! 8291: )==NULL)
! 8292: abort("insert_word: can't realloc wsp->wpa");
! 8293: while(((*wpp)!=NULL)&&(*wpp)->bx.a.x<=wp->bx.a.x) wpp++;
! 8294: /* **wpp is now 1st entry > *wp in sorted order; insert
! 8295: new word just before it */
! 8296: pwp=wp;
! 8297: do { nwp= *wpp;
! 8298: *(wpp++)=pwp;
! 8299: pwp=nwp;
! 8300: }
! 8301: while(pwp!=NULL);
! 8302: };
! 8303: wsp->wpa[++wsp->mny] = NULL;
! 8304: return(wp);
! 8305: }
! 8306:
! 8307: /* Insert a Word into the Words owned by a given Txtln,
! 8308: maintaining the Txtln's Bbx and sorted order in the Words set.
! 8309: Return the inserted Word * */
! 8310: Word *insert_word_txtln(wp,lp)
! 8311: Word *wp;
! 8312: Txtln *lp;
! 8313: { merge_bbx(&(wp->bx),&(lp->bx));
! 8314: return(insert_word(wp,&(lp->ws)));
! 8315: }
! 8316:
! 8317: /* Free wordinterp and its parts as specified in etc.
! 8318: Always free its strings (if any).
! 8319: If etc&IsWordInterp, free the record itself also.
! 8320: */
! 8321: free_wordinterp_etc(p,etc)
! 8322: WordInterp *p;
! 8323: Ident etc;
! 8324: { if(p->s!=NULL) { free(p->s); p->s=NULL; };
! 8325: if(p->pp!=NULL) { free(p->pp); p->pp=NULL; };
! 8326: if(p->by!=NULL) { free(p->by); p->by=NULL; };
! 8327: if(p->po!=NULL) { free(p->po); p->po=NULL; };
! 8328: if(p->ps!=NULL) { free(p->ps); p->ps=NULL; };
! 8329: if(etc&IsWordInterp) free(p);
! 8330: }
! 8331:
! 8332: /* Duplicate (return ptr to local static copy of) a WordInterp.
! 8333: Always free its strings (if any).
! 8334: 'etc' is ignored.
! 8335: */
! 8336: WordInterp *dup_wordinterp_etc(p,etc)
! 8337: WordInterp *p;
! 8338: Ident etc;
! 8339: { static WordInterp d;
! 8340: d = *p;
! 8341: if(p->s!=NULL) d.s = strdup(p->s);
! 8342: if(p->pp!=NULL) d.pp = strdup(p->pp);
! 8343: if(p->by!=NULL) d.by = strdup(p->by);
! 8344: if(p->po!=NULL) d.po = strdup(p->po);
! 8345: if(p->ps!=NULL) d.ps = strdup(p->ps);
! 8346: return(&d);
! 8347: }
! 8348:
! 8349: /* Unconditionally free the malloc-space array of pointers, and empty the set.
! 8350: Don't free the records that it owned.
! 8351: */
! 8352: free_words(wsp)
! 8353: Words *wsp;
! 8354: { if(wsp->wpa!=NULL) { free(wsp->wpa); wsp->wpa = NULL; }
! 8355: wsp->mny = 0;
! 8356: }
! 8357:
! 8358: free_words_etc(wsp,etc)
! 8359: Words *wsp;
! 8360: Ident etc;
! 8361: { register Word *wp,**wpp;
! 8362: int wi;
! 8363: if(wsp->mny>0&&(etc&IsWord))
! 8364: for(wp= *(wpp=wsp->wpa); wp!=NULL; wp= *(++wpp))
! 8365: free_word_etc(wp,etc);
! 8366: free_words(wsp);
! 8367: }
! 8368:
! 8369: /* return a pointer to a distinct and duplicate copy of *wp,
! 8370: created out of malloc space */
! 8371: Word *dup_word(wp)
! 8372: Word *wp;
! 8373: { Word *dup;
! 8374: if((dup=(Word *)malloc(sizeof(Word)))==NULL)
! 8375: abort("can't dup Word");
! 8376: alloc_census(Word,1);
! 8377: *dup = *wp;
! 8378: return(dup);
! 8379: }
! 8380:
! 8381: /* Return a pointer to a distinct and duplicate copy of *wp, and ALL it owns,
! 8382: created out of malloc space. (HOW they are duplicated is controlled by flags
! 8383: in etc.) */
! 8384: Word *dup_word_etc(wp,etc)
! 8385: Word *wp;
! 8386: Ident etc;
! 8387: { Word *dup;
! 8388: dup = dup_word(wp);
! 8389: if(dup->ws.mny>0) dup->ws = *dup_words_etc(&(wp->ws),etc);
! 8390: else dup->ws = empty_Words;
! 8391: if(dup->cs.mny>0) dup->cs = *dup_chars_etc(&(wp->cs),etc);
! 8392: else dup->cs = empty_Chars;
! 8393: if(dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(wp->bs),etc);
! 8394: else dup->bs = empty_Blobs;
! 8395: return(dup);
! 8396: }
! 8397:
! 8398: /* Return a pointer to a distinct local static duplicate of non-empty *wsp.
! 8399: Its wpa array is created newly out of malloc space.
! 8400: If etc&IsWord, all its Words are also duplicated,
! 8401: else the contents of wpa point to the old unduplicated Words.
! 8402: */
! 8403: Words *dup_words_etc(wsp,etc)
! 8404: Words *wsp;
! 8405: Ident etc; /* parts to duplicate */
! 8406: { static Words dup;
! 8407: register Word **wpp,**dpp;
! 8408: if((dup.mny=wsp->mny)<=0) dup = empty_Words;
! 8409: else { if((dup.wpa=(Word **)malloc((dup.mny+1)*sizeof(Word *)))==NULL)
! 8410: abort("can't dup ws.wpa");
! 8411: for(wpp=wsp->wpa,dpp=dup.wpa; *wpp!=NULL; wpp++,dpp++) {
! 8412: if(etc&IsWord) *dpp = dup_word_etc(*wpp,etc);
! 8413: else *dpp = *wpp;
! 8414: };
! 8415: *dpp = NULL;
! 8416: };
! 8417: return(&dup);
! 8418: }
! 8419:
! 8420: WordInterp *alloc_wordinterp()
! 8421: { WordInterp *p;
! 8422: if((p=(WordInterp *)malloc(sizeof(WordInterp)))==NULL)
! 8423: abort("can't alloc WordInterp");
! 8424: else { *p = empty_WordInterp;
! 8425: return(p);
! 8426: };
! 8427: }
! 8428:
! 8429: char *wordinterp_toa(p)
! 8430: WordInterp *p;
! 8431: { static char s[80];
! 8432: sprintf(s,"%s %s %s|%s|%s|%s",
! 8433: ident_toa(p->ident),
! 8434: ((p->s!=NULL)? p->s: ""),
! 8435: ((p->pp!=NULL)? p->pp: ""),
! 8436: ((p->by!=NULL)? p->by: ""),
! 8437: ((p->po!=NULL)? p->po: ""),
! 8438: ((p->ps!=NULL)? p->ps: "")
! 8439: );
! 8440: return(s);
! 8441: }
! 8442:
! 8443: /* Free Word and its parts, as specified by etc.
! 8444: Always free the pointer-arrays of ws, cs & bs.
! 8445: If etc&IsWord, free all Words in ws also.
! 8446: If etc&IsChar, free all Chars in cs also.
! 8447: If etc&IsBlob, free all Blobs in bs also.
! 8448: */
! 8449: free_word_etc(p,etc)
! 8450: Word *p;
! 8451: Ident etc;
! 8452: #define dbg_fwe (F)
! 8453: { if(dbg_fwe) {
! 8454: err("free_word_etc: %s",word_toa(p));
! 8455: err("free_word_etc: %s",ident_toa(etc));
! 8456: err_census_all;
! 8457: };
! 8458: free_words_etc(&(p->ws),IsALL);
! 8459: free_chars_etc(&(p->cs),etc);
! 8460: free_blobs_etc(&(p->bs),etc);
! 8461: if(p->ident&Word_label && p->l!=NULL) {
! 8462: free(p->l); p->l=NULL; p->ident &= ~Word_label;
! 8463: };
! 8464: if(etc&IsWord) free_word(p);
! 8465: if(dbg_fwe) err_census_all;
! 8466: }
! 8467:
! 8468: free_word(wp)
! 8469: Word *wp;
! 8470: { free(wp);
! 8471: free_census(Word,1);
! 8472: }
! 8473:
! 8474: fwrb_sfeats(fp,sfv)
! 8475: FILE *fp;
! 8476: SFv sfv;
! 8477: { register Pval *vp,*vq;
! 8478: for(vq=(vp=sfv)+SF_MNY; vp<vq; vp++)
! 8479: fwri_int3(fp,USHRT_MAX*(*vp)+0.5);
! 8480: #if dbg_fwrb_toa
! 8481: /** err("fwrb_sfeats: %s",sfeats_toa(sfv)); **/
! 8482: #endif
! 8483: }
! 8484:
! 8485: int frdb_sfeats(fp,sfv)
! 8486: FILE *fp;
! 8487: SFv sfv;
! 8488: { register Pval *vp,*vq;
! 8489: for(vq=(vp=sfv)+SF_MNY; vp<vq; vp++)
! 8490: *vp = frdi_int3(fp)/((Pval)USHRT_MAX);
! 8491: #if dbg_frdb_toa
! 8492: /** err("frdb_sfeats: %s",sfeats_toa(sfv)); **/
! 8493: #endif
! 8494: }
! 8495:
! 8496: /* return ptr to local static copy of Shapes of given size */
! 8497: Shapes *alloc_shapes(mny)
! 8498: int mny;
! 8499: { static Shapes shs;
! 8500: shs.mny = shs.alloc = mny;
! 8501: if((shs.sa=(Nb_s *)malloc(shs.alloc*sizeof(Nb_s)))==NULL)
! 8502: abort("can't alloc Shapes.sa[%d]",shs.alloc);
! 8503: return(&shs);
! 8504: }
! 8505:
! 8506: fwrb_shapes(fp,p)
! 8507: FILE *fp;
! 8508: Shapes *p; /* on entry, p->mny has already been written */
! 8509: { int dim;
! 8510: register Nb_s *sp,*sq;
! 8511: register Pval *vp;
! 8512: if(p->mny>0&&p->sa!=NULL) {
! 8513: for(sq=(sp=p->sa)+p->mny; sp<sq; sp++) {
! 8514: dim=Sh_dim[sp->t&(~Sh_tiny)];
! 8515: fwri_uint1(fp,(sp->t&0x7F)|((sp->t&Sh_tiny)?0x80:0x00));
! 8516: fwri_int2(fp,(*(vp=sp->p))*SHRT_MAX);
! 8517: if(dim>1) { fwri_int2(fp,(*(++vp))*SHRT_MAX);
! 8518: if(dim>2) { fwri_int2(fp,(*(++vp))*SHRT_MAX);
! 8519: if(dim>3) { fwri_int2(fp,(*(++vp))*SHRT_MAX);
! 8520: } } };
! 8521: };
! 8522: };
! 8523: #if dbg_fwrb_toa
! 8524: /** err("fwrb_shapes: %s",shapes_toa(p)); **/
! 8525: #endif
! 8526: }
! 8527:
! 8528: int frdb_shapes(fp,p)
! 8529: FILE *fp;
! 8530: Shapes *p; /* on entry, p->mny has already been read */
! 8531: { register Nb_s *sp,*sq;
! 8532: register Pval *vp;
! 8533: uint1 ui1;
! 8534: int dim;
! 8535:
! 8536: if(p->mny>0) {
! 8537: *p = *alloc_shapes(p->mny);
! 8538: for(sq=(sp=p->sa)+p->mny; sp<sq; sp++) {
! 8539: ui1 = frdi_uint1(fp);
! 8540: sp->t = ui1&0x7F|((ui1&0x80)?Sh_tiny:0);
! 8541: dim=Sh_dim[sp->t&(~Sh_tiny)];
! 8542: *(vp=sp->p) = ((float)frdi_int2(fp))/SHRT_MAX;
! 8543: if(dim>1) { *(++vp) = ((float)frdi_int2(fp))/SHRT_MAX;
! 8544: if(dim>2) { *(++vp) = ((float)frdi_int2(fp))/SHRT_MAX;
! 8545: if(dim>3) { *(++vp) = ((float)frdi_int2(fp))/SHRT_MAX;
! 8546: } } };
! 8547: };
! 8548: }
! 8549: else { p->alloc = 0;
! 8550: if(p->sa!=NULL) free(p->sa);
! 8551: p->sa = NULL;
! 8552: };
! 8553: #if dbg_frdb_toa
! 8554: /** err("frdb_shapes: %s",shapes_toa(p)); **/
! 8555: #endif
! 8556: }
! 8557:
! 8558: fwra_shapes_etc(fp,p,t)
! 8559: FILE *fp;
! 8560: Shapes *p;
! 8561: char *t; /* string of shape types (empty => all) */
! 8562: { Nb_s *s;
! 8563: int i,j;
! 8564: char a[80],f[10];
! 8565: for(i=0,s=p->sa; i<p->mny; i++,s++) {
! 8566: if(t[0]=='\0'||strchr(t,Sh_nam[s->t&(~Sh_tiny)])!=NULL) {
! 8567: sprintf(a,"%c%c ",
! 8568: Sh_nam[s->t&(~Sh_tiny)],
! 8569: (s->t&Sh_tiny)?'\'':' '
! 8570: );
! 8571: for(j=0;j<Sh_dim[s->t&(~Sh_tiny)];j++) {
! 8572: sprintf(f," %0.3f",s->p[j]);
! 8573: strcat(a,f);
! 8574: };
! 8575: fprintf(fp,"%s\n",a);
! 8576: };
! 8577: };
! 8578: }
! 8579:
! 8580: err_shapes(shp)
! 8581: Shapes *shp;
! 8582: { int si,di;
! 8583: Nb_s *sp;
! 8584: fprintf(stderr,"shapes %d:\n",shp->mny);
! 8585: for(si=0,sp=shp->sa; si<shp->mny; si++,sp++) {
! 8586: fprintf(stderr," %c",Sh_nam[sp->t]);
! 8587: for(di=0; di<Sh_dim[sp->t]; di++)
! 8588: fprintf(stderr," %6.3f",sp->p[di]);
! 8589: fprintf(stderr,"\n");
! 8590: };
! 8591: }
! 8592:
! 8593: /* Unconditionally free the malloc-space array of pointers, and empty the set.
! 8594: Don't free the records that it owned.
! 8595: */
! 8596: free_shapes(shp)
! 8597: Shapes *shp;
! 8598: { if(shp->sa!=NULL) {
! 8599: if(shp->alloc<=0) abort("can't free unalloc'ed shapes");
! 8600: else { free(shp->sa); shp->sa=NULL; };
! 8601: };
! 8602: shp->mny = shp->alloc = 0;
! 8603: }
! 8604:
! 8605: /* functions for RanParms */
! 8606:
! 8607: RanParms *alloc_ranparms()
! 8608: { RanParms *rp;
! 8609: if((rp=(RanParms *)malloc(sizeof(RanParms)))==NULL)
! 8610: abort("alloc_ranparms: can't alloc");
! 8611: *rp = empty_RanParms;
! 8612: return(rp);
! 8613: }
! 8614:
! 8615: free_ranparms(ran)
! 8616: RanParms *ran;
! 8617: { free(ran);
! 8618: }
! 8619:
! 8620: RanParms *dup_ranparms(p)
! 8621: RanParms *p;
! 8622: { RanParms *dup;
! 8623: dup = alloc_ranparms();
! 8624: *dup = *p;
! 8625: return(dup);
! 8626: }
! 8627:
! 8628: char *ranparms_toa(ran,select)
! 8629: RanParms *ran;
! 8630: char *select; /* a string, subset of: "*rpabejkstxy" if "*" or "" ALL */
! 8631: { static char s[200];
! 8632: char p[20];
! 8633: char *cp;
! 8634: static char select_all[] = "abejkprstxy";
! 8635: s[0]='\0';
! 8636: if(select[0]=='*'||select[0]=='\0') select=select_all;
! 8637: for(cp=select; *cp!='\0'; cp++) {
! 8638: switch(*cp) {
! 8639: case 'a': sprintf(p,"a%0.3f ",ran->skew/DtoR); strcat(s,p); break;
! 8640: case 'b': sprintf(p,"b%0.3f ",ran->bhgt); strcat(s,p); break;
! 8641: case 'e': sprintf(p,"e%0.3f ",ran->blur); strcat(s,p); break;
! 8642: case 'j': sprintf(p,"j%0.3f ",ran->jitter); strcat(s,p); break;
! 8643: case 'k': sprintf(p,"k%0.3f ",ran->kern); strcat(s,p); break;
! 8644: case 'p': sprintf(p,"p%g ",ran->size); strcat(s,p); break;
! 8645: case 'r': sprintf(p,"r%d,%d ",ran->res_x,ran->res_y); strcat(s,p); break;
! 8646: case 's': sprintf(p,"s%0.4f ",ran->speckle); strcat(s,p); break;
! 8647: case 't': sprintf(p,"t%0.3f ",ran->thresh); strcat(s,p); break;
! 8648: case 'x': sprintf(p,"x%0.3f ",ran->xscale); strcat(s,p); break;
! 8649: case 'y': sprintf(p,"y%0.3f ",ran->yscale); strcat(s,p); break;
! 8650: };
! 8651: };
! 8652: return(s);
! 8653: }
! 8654:
! 8655: RanParms *ato_ranparms(s)
! 8656: char *s;
! 8657: { static RanParms ran;
! 8658: char *f,n,*v;
! 8659: #define TOKEN_SEP "=, \n"
! 8660: f=strtok(s,TOKEN_SEP);
! 8661: while(f!=NULL&&strlen(f)>0) {
! 8662: n=f[0]; v=f+1;
! 8663: switch(n) {
! 8664: case 'r': /* res */
! 8665: ran.res_x = atoi(v);
! 8666: v=strtok((char *)0,TOKEN_SEP);
! 8667: ran.res_y = atoi(v);
! 8668: break;
! 8669: case 'p': ran.size = atof(v); break;
! 8670: case 'a': ran.skew = atof(v)*DtoR; break;
! 8671: case 'b': ran.bhgt = atof(v); break;
! 8672: case 'e': ran.blur = atof(v); break;
! 8673: case 'j': ran.jitter = atof(v); break;
! 8674: case 'k': ran.kern = atof(v); break;
! 8675: case 's': ran.speckle = atof(v); break;
! 8676: case 't': ran.thresh = atof(v); break;
! 8677: case 'x': ran.xscale = atof(v); break;
! 8678: case 'y': ran.yscale = atof(v); break;
! 8679: };
! 8680: f=strtok((char *)0,TOKEN_SEP);
! 8681: };
! 8682: return(&ran);
! 8683: }
! 8684:
! 8685: #if FWRI
! 8686: fwrb_ranparms(f,p)
! 8687: FILE *f;
! 8688: RanParms *p;
! 8689: { fwri_int2(f,p->res_x);
! 8690: fwri_int2(f,p->res_y);
! 8691: fwri_Pts(f,p->size);
! 8692: fwri_Radians(f,p->skew);
! 8693: fwri_Ems(f,p->bhgt);
! 8694: fwri_int3(f,p->blur*10000.0);
! 8695: fwri_int3(f,p->jitter*10000.0);
! 8696: fwri_int3(f,p->kern*10000.0);
! 8697: fwri_int3(f,p->speckle*10000.0);
! 8698: fwri_int3(f,p->thresh*10000.0);
! 8699: fwri_int3(f,p->xscale*10000.0);
! 8700: fwri_int3(f,p->yscale*10000.0);
! 8701: #if dbg_fwrb_toa
! 8702: err("fwrb_ranparms: %s",ranparms_toa(p));
! 8703: #endif
! 8704: }
! 8705: #else
! 8706: fwrb_ranparms(f,p)
! 8707: FILE *f;
! 8708: RanParms *p;
! 8709: { if((fwrite(p,sizeof(RanParms),1,f))!=1) return(0);
! 8710: #if dbg_fwrb_toa
! 8711: err("fwrb_ranparms: %s",ranparms_toa(p));
! 8712: #endif
! 8713: }
! 8714: #endif
! 8715:
! 8716: #if FRDI
! 8717: int frdb_ranparms(f,p)
! 8718: FILE *f;
! 8719: RanParms *p;
! 8720: { *p = empty_RanParms;
! 8721: if(feof(f))
! 8722: return(0);
! 8723: p->res_x=frdi_int2(f);
! 8724: p->res_y=frdi_int2(f);
! 8725: p->size=frdi_Pts(f);
! 8726: p->skew=frdi_Radians(f);
! 8727: p->bhgt=frdi_Ems(f);
! 8728: p->blur=frdi_int3(f)/10000.0;
! 8729: p->jitter=frdi_int3(f)/10000.0;
! 8730: p->kern=frdi_int3(f)/10000.0;
! 8731: p->speckle=frdi_int3(f)/10000.0;
! 8732: p->thresh=frdi_int3(f)/10000.0;
! 8733: p->xscale=frdi_int3(f)/10000.0;
! 8734: p->yscale=frdi_int3(f)/10000.0;
! 8735: #if dbg_frdb_toa
! 8736: err("frdb_ranparms: %s",ranparms_toa(p));
! 8737: #endif
! 8738: if(ferror(f)) return(-errno); else return(1);
! 8739: }
! 8740: #else
! 8741: int frdb_ranparms(fp,ran)
! 8742: FILE *fp;
! 8743: RanParms *ran;
! 8744: { if((fread(ran,sizeof(RanParms),1,fp))<1) return(0);
! 8745: #if dbg_frdb_toa
! 8746: err("frdb_ranparms: %s",ranparms_toa(ran));
! 8747: #endif
! 8748: }
! 8749: #endif
! 8750:
! 8751: Char *alloc_char()
! 8752: { Char *p;
! 8753: if((p=(Char *)malloc(sizeof(Char)))==NULL)
! 8754: abort("can't alloc Char");
! 8755: alloc_census(Char,1);
! 8756: *p = empty_Char;
! 8757: return(p);
! 8758: }
! 8759:
! 8760: char *char_toa(cp)
! 8761: Char *cp;
! 8762: { static char s[100],bfs[24];
! 8763: if(cp->bfsp==NULL) strcpy(bfs,"0");
! 8764: else if(cp->bfsp->bm.n==0) strcpy(bfs,"0");
! 8765: else if(cp->bfsp->bm.mny==0) sprintf(bfs,"%d",cp->bfsp->bm.n);
! 8766: else sprintf(bfs,"%d,%d",cp->bfsp->bm.n,cp->bfsp->bm.mny);
! 8767: sprintf(s,"%s bx%s w%d,h%d cs%d bl%d ar%d pe%d sf%d sh%d bf%s i%d",
! 8768: ident_toa(cp->ident),
! 8769: bbx_toa(&(cp->bx)),
! 8770: bbx_wid(&cp->bx),bbx_hgt(&cp->bx),
! 8771: cp->csp,
! 8772: cp->bmny,
! 8773: cp->area,cp->per,
! 8774: (cp->sfv==NULL)? 0: 1,
! 8775: cp->sh.mny,
! 8776: bfs,
! 8777: cp->il.mny
! 8778: );
! 8779: return(s);
! 8780: }
! 8781:
! 8782: /* compute the centroid of the Char (offset from bx.a) */
! 8783: Pp *char_centroid(cp)
! 8784: Char *cp;
! 8785: { static Pp c;
! 8786: Pp *bc; /* blob centroid */
! 8787: Blob *bp;
! 8788: int bi;
! 8789: c.x = c.y = 0.0;
! 8790: for(bi=0, bp=cp->fi; bi<cp->bmny; bi++, bp=bp->n) {
! 8791: bc = blob_centroid(bp);
! 8792: c.x += bp->area * (bc->x + (cp->bx.a.x - cp->bx.a.x));
! 8793: c.y += bp->area * (bc->y + (cp->bx.a.y - cp->bx.a.y));
! 8794: };
! 8795: c.x /= cp->area;
! 8796: c.y /= cp->area;
! 8797: return(&c);
! 8798: }
! 8799:
! 8800: #if FWRI
! 8801: fwrb_char(f,p)
! 8802: FILE *f;
! 8803: Char *p;
! 8804: {
! 8805: #if dbg_fwrb
! 8806: if((!(p->ident&IsChar))||(p->ident&(IsALL&(~IsChar))))
! 8807: err("fwrb_char: %s",char_toa(p));
! 8808: if(p->ident&Char_label && p->l==NULL) {
! 8809: err("fwrb_page: Char_label set but .l==NULL");
! 8810: p->ident &= ~Char_label;
! 8811: };
! 8812: if(p->ident&Char_ranparms && p->rp==NULL) {
! 8813: err("fwrb_page: Char_ranparms set but .rp==NULL");
! 8814: p->ident &= ~Char_ranparms;
! 8815: };
! 8816: #endif
! 8817: fwri_Ident(f,p->ident);
! 8818: fwri_Bbx(f,&(p->bx));
! 8819: fwri_Scoor(f,p->csp);
! 8820: fwri_uint4(f,p->area);
! 8821: fwri_uint4(f,p->per);
! 8822: fwri_Scoor(f,p->basl);
! 8823: fwri_uint3(f,p->bmny);
! 8824: fwri_uint2(f,p->il.mny);
! 8825: fwri_uint1(f,(p->sfv!=NULL)?SF_MNY:0);
! 8826: fwri_uint2(f,p->sh.mny);
! 8827: fwri_uint2(f,(p->bfsp!=NULL)?p->bfsp->bm.n:0);
! 8828: #if dbg_fwrb_toa
! 8829: err("fwrb_char: %s",char_toa(p));
! 8830: #endif
! 8831: if(p->ident&Char_label) fwrb_label(f,p->l);
! 8832: if(p->ident&Char_ranparms) fwrb_ranparms(f,p->rp);
! 8833: }
! 8834: #else
! 8835: fwrb_char(fp,cp)
! 8836: FILE *fp;
! 8837: Char *cp;
! 8838: { CharF cf;
! 8839: int stat;
! 8840: #if dbg_fwrb
! 8841: if((!(cp->ident&IsChar))||(cp->ident&(IsALL&(~IsChar))))
! 8842: err("fwrb_char: %s",char_toa(cp));
! 8843: #endif
! 8844: memset(&cf,'\0',sizeof(cf));
! 8845: if(cp->ident&Char_ranparms && cp->rp==NULL)
! 8846: cp->ident &= ~Char_ranparms;
! 8847: cf.ident = cp->ident | IsChar;
! 8848: cf.bx = cp->bx;
! 8849: cf.csp = cp->csp;
! 8850: cf.area = cp->area;
! 8851: cf.per = cp->per;
! 8852: /* basl omitted */
! 8853: cf.bmny = cp->bmny;
! 8854: cf.imny = cp->il.mny;
! 8855: cf.sfmny = (cp->sfv!=NULL)?SF_MNY:0;
! 8856: cf.shmny = cp->sh.mny;
! 8857: if(cp->bfsp!=NULL) cf.bfmny = cp->bfsp->bm.n; else cf.bfmny=0;
! 8858: if((stat=fwrite(&cf,sizeof(CharF),1,fp))!=1)
! 8859: abort("can't write CharF, status %d",stat);
! 8860: #if dbg_fwrb_toa
! 8861: err("fwrb_char: %s",char_toa(cp));
! 8862: #endif
! 8863: if(cf.ident&Char_ranparms) fwrb_ranparms(fp,cp->rp);
! 8864: if(cf.ident&Char_label) fwrb_label(fp,cp->l);
! 8865: }
! 8866: #endif
! 8867:
! 8868: fwrb_chars_etc(fp,cs,etc)
! 8869: FILE *fp;
! 8870: Chars cs;
! 8871: Ident etc;
! 8872: { register Char *cp,**cpp;
! 8873: if(cs.mny>0) for(cp= *(cpp=cs.cpa); cp!=NULL; cp= *(++cpp))
! 8874: fwrb_char_etc(fp,cp,etc);
! 8875: }
! 8876:
! 8877: fwrb_char_etc(fp,cp,etc)
! 8878: FILE *fp;
! 8879: Char *cp;
! 8880: Ident etc;
! 8881: { static Ident parts = (IsInterp|IsBlob|IsShapes|IsBfeats|IsSfeats);
! 8882: Char ch;
! 8883: if((etc&parts)!=parts) /* write selected parts */ {
! 8884: ch = *cp;
! 8885: if(!(etc&IsInterp)) ch.il.mny=0;
! 8886: if(!(etc&IsBlob)) ch.bmny=0;
! 8887: if(!(etc&IsSfeats)) ch.sfv = NULL;
! 8888: if(!(etc&IsShapes)) ch.sh = empty_Shapes;
! 8889: if(!(etc&IsBfeats)) ch.bfsp = NULL;
! 8890: cp = &ch; /* write modified record */
! 8891: };
! 8892: fwrb_char(fp,cp);
! 8893: if(cp->sfv!=NULL) fwrb_sfeats(fp,cp->sfv);
! 8894: if(cp->sh.mny>0) fwrb_shapes(fp,&(cp->sh));
! 8895: #if CPU!=CRAY
! 8896: if(cp->bfsp!=NULL) fwrb_bfeats(fp,cp->bfsp);
! 8897: #endif
! 8898: fwrb_interpl_etc(fp,cp->il,etc);
! 8899: if(cp->bmny>0) fwrb_blobl_etc(fp,cp->bmny,cp->fi,etc);
! 8900: }
! 8901:
! 8902: #if FRDI
! 8903: int frdb_char(f,p)
! 8904: FILE *f;
! 8905: Char *p;
! 8906: { int sf_mny,bf_mny;
! 8907: *p = empty_Char;
! 8908: if(feof(f))
! 8909: return(0);
! 8910: p->ident=frdi_Ident(f);
! 8911: frdi_Bbx(f,&(p->bx));
! 8912: p->csp=frdi_Scoor(f);
! 8913: p->area=frdi_uint4(f);
! 8914: p->per=frdi_uint4(f);
! 8915: p->basl=frdi_Scoor(f);
! 8916: p->bmny=frdi_uint3(f);
! 8917: p->il.mny=frdi_uint2(f);
! 8918: if((sf_mny=frdi_uint1(f))>0) {
! 8919: if((p->sfv=(Pval *)malloc(sf_mny*sizeof(Pval)))==NULL)
! 8920: abort("frdb_char: can't alloc p->sfv[%d]",sf_mny);
! 8921: memset(p->sfv,'\0',sf_mny*sizeof(Pval));
! 8922: };
! 8923: p->sh.mny=frdi_uint2(f);
! 8924: if((bf_mny=frdi_uint2(f))>0) {
! 8925: p->bfsp = alloc_bfeats(bf_mny,0);
! 8926: };
! 8927: #if dbg_frdb
! 8928: if((!(p->ident&IsChar))||(p->ident&(IsALL&(~IsChar))))
! 8929: err("frdb_char: %s",char_toa(p));
! 8930: #endif
! 8931: #if dbg_frdb_toa
! 8932: err("frdb_char: %s",char_toa(p));
! 8933: #endif
! 8934: if(p->ident&Char_label) p->l = frdb_label(f);
! 8935: if(p->ident&Char_ranparms) {
! 8936: p->rp = alloc_ranparms();
! 8937: frdb_ranparms(f,p->rp);
! 8938: };
! 8939: if(ferror(f)) return(-errno); else return(1);
! 8940: }
! 8941: #else
! 8942: int frdb_char(fp,cp)
! 8943: FILE *fp;
! 8944: Char *cp;
! 8945: { CharF cf;
! 8946: int stat;
! 8947: if((stat=fread(&cf,sizeof(CharF),1,fp))!=1)
! 8948: abort("frdb_char: can't read CharF, status %d",stat);
! 8949: *cp = empty_Char;
! 8950: cp->ident = cf.ident;
! 8951: cp->bx = cf.bx;
! 8952: cp->csp = cf.csp;
! 8953: cp->area = cf.area;
! 8954: cp->per = cf.per;
! 8955: cp->basl = 0;
! 8956: cp->bmny = cf.bmny;
! 8957: cp->il.mny = cf.imny;
! 8958: if(cf.sfmny>0) {
! 8959: if((cp->sfv=(Pval *)malloc(SF_MNY*sizeof(Pval)))==NULL)
! 8960: abort("frdb_char: can't alloc cp->sfv[%d]",SF_MNY);
! 8961: memset(cp->sfv,'\0',SF_MNY*sizeof(Pval));
! 8962: }
! 8963: else cp->sfv = NULL;
! 8964: cp->sh.mny = cf.shmny;
! 8965: #if CPU!=CRAY
! 8966: #if dbg_frdb
! 8967: if((!(cp->ident&IsChar))||(cp->ident&(IsALL&(~IsChar))))
! 8968: err("frdb_char: %s",char_toa(cp));
! 8969: #endif
! 8970: #endif
! 8971: #if dbg_frdb_toa
! 8972: err("frdb_char: %s",char_toa(cp));
! 8973: #endif
! 8974: if(cp->ident&Char_ranparms) {
! 8975: cp->rp = alloc_ranparms();
! 8976: frdb_ranparms(fp,cp->rp);
! 8977: };
! 8978: if(cp->ident&Char_label) cp->l = frdb_label(fp);
! 8979: #if CPU!=CRAY
! 8980: if(cf.bfmny>0) cp->bfsp = alloc_bfeats(cf.bfmny,0);
! 8981: else
! 8982: #endif
! 8983: cp->bfsp = NULL;
! 8984: if(ferror(fp)) return(-errno); else return(1);
! 8985: }
! 8986: #endif
! 8987:
! 8988: frdb_char_etc(fp,cp,etc)
! 8989: FILE *fp;
! 8990: Char *cp;
! 8991: Ident etc;
! 8992: { frdb_char(fp,cp);
! 8993: if(cp->sfv!=NULL) frdb_sfeats(fp,cp->sfv);
! 8994: if(cp->sh.mny>0) frdb_shapes(fp,&(cp->sh));
! 8995: #if CPU!=CRAY
! 8996: if(cp->bfsp!=NULL) {
! 8997: frdb_bfeats(fp,cp->bfsp);
! 8998: };
! 8999: #endif
! 9000: if(cp->il.mny>0) {
! 9001: frdb_interpl_etc(fp,&(cp->il),etc);
! 9002: /**if(!(etc&IsInterp)) free_interpl_etc(&(cp->il),IsALL);**/
! 9003: };
! 9004: if(etc&IsBlob && cp->bmny>0)
! 9005: frdb_blobl_etc(fp,cp->bmny,&(cp->fi),etc);
! 9006: else { cp->bmny = 0; cp->fi = NULL; };
! 9007: if(ferror(fp)) return(-errno); else return(1);
! 9008: }
! 9009:
! 9010: /* read a set of chars, and parts */
! 9011: frdb_chars_etc(fp,csp,etc)
! 9012: FILE *fp;
! 9013: Chars *csp;
! 9014: Ident etc;
! 9015: { int ci;
! 9016: register Char *cp,**cpp;
! 9017: if(csp->mny<=0) {
! 9018: *csp = empty_Chars;
! 9019: return(1);
! 9020: };
! 9021: if((cpp=csp->cpa=(Char **)malloc((csp->mny+1)*sizeof(Char *)))==NULL)
! 9022: abort("frdb_chars_etc: can't alloc Chars.cpa array");
! 9023: for(ci=0; ci<csp->mny; ci++) {
! 9024: *(cpp++) = cp = alloc_char();
! 9025: frdb_char_etc(fp,cp,etc);
! 9026: };
! 9027: *cpp = NULL;
! 9028: if(ferror(fp)) return(-errno); else return(1);
! 9029: }
! 9030:
! 9031: /* return a pointer to a distinct and duplicate copy of *cp;
! 9032: it is created out of malloc space.
! 9033: RanParms & label are treated as an integral part of the Char. */
! 9034: Char *dup_char(cp)
! 9035: Char *cp;
! 9036: { Char *dup;
! 9037: if((dup=(Char *)malloc(sizeof(Char)))==NULL)
! 9038: abort("can't dup Char");
! 9039: alloc_census(Char,1);
! 9040: *dup = *cp;
! 9041: if(dup->ident&Char_label && dup->l!=NULL)
! 9042: dup->l = strdup(cp->l);
! 9043: else {dup->ident &= ~Char_label; dup->l = NULL;};
! 9044: if(dup->ident&Char_ranparms && dup->rp!=NULL)
! 9045: dup->rp = dup_ranparms(cp->rp);
! 9046: else {dup->ident &= ~Char_ranparms; dup->rp = NULL;};
! 9047: return(dup);
! 9048: }
! 9049:
! 9050: /* return a pointer to a distinct and duplicate copy of *cp and those of
! 9051: its lists as specified by etc. (Does not conform to practice for dup_word_etc.)
! 9052: */
! 9053: Char *dup_char_etc(cp,etc)
! 9054: Char *cp;
! 9055: Ident etc;
! 9056: { Char *dup;
! 9057: dup = dup_char(cp);
! 9058: if(dup->bmny>0&&etc&IsBlob) dup->fi = dup_blobl_etc(cp->fi,etc);
! 9059: else {dup->bmny=0; dup->fi=NULL;};
! 9060: if(dup->il.mny>0&&etc&IsInterp) dup->il = *dup_interpl_etc(&(cp->il),etc);
! 9061: else dup->il = empty_Interpl;
! 9062: /**
! 9063: if(dup->sfv!=NULL>0&&etc&IsSfeats) dup->sfv = dup_sfeats(cp->sfv);
! 9064: else dup->sfv = NULL;
! 9065: if(dup->sh.mny>0&&etc&IsShapes) dup->sh = *dup_shapes(&cp->sh);
! 9066: else dup->sh = empty_Shapes;
! 9067: **/
! 9068: #if CPU!=CRAY
! 9069: if(dup->bfsp!=NULL>0&&etc&IsBfeats) dup->bfsp = dup_bfeats(cp->bfsp);
! 9070: else
! 9071: #endif
! 9072: dup->bfsp = NULL;
! 9073: return(dup);
! 9074: }
! 9075:
! 9076: /* Return a pointer to a local static duplicate of non-empty *csp.
! 9077: Its cpa array is new, created out of malloc space.
! 9078: If etc&IsChar, all its Characters are also duplicated,
! 9079: else the contents of cpa point to the old unduplicated Chars.
! 9080: */
! 9081: Chars *dup_chars_etc(csp,etc)
! 9082: Chars *csp;
! 9083: Ident etc; /* parts to duplicate */
! 9084: { static Chars dup;
! 9085: register Char **cpp,**dpp;
! 9086: if((dup.mny=csp->mny)<=0) dup = empty_Chars;
! 9087: else { if((dup.cpa=(Char **)malloc((dup.mny+1)*sizeof(Char *)))==NULL)
! 9088: abort("can't dup cs.cpa");
! 9089: for(cpp=csp->cpa,dpp=dup.cpa; (*cpp)!=NULL; cpp++,dpp++) {
! 9090: if(etc&IsChar) *dpp = dup_char_etc(*cpp,etc);
! 9091: else *dpp = *cpp;
! 9092: };
! 9093: *dpp = NULL;
! 9094: };
! 9095: return(&dup);
! 9096: }
! 9097:
! 9098: err_chars(p)
! 9099: Chars *p;
! 9100: { register Char **cpp;
! 9101: fprintf(stderr,"Chars %d: ",p->mny);
! 9102: if(p->mny>0) for(cpp=p->cpa; (*cpp)!=NULL; cpp++)
! 9103: fprintf(stderr,"%X ",*cpp);
! 9104: fprintf(stderr,"\n");
! 9105: }
! 9106:
! 9107: /* Make a Char out of a single Blob. Return a freshly-allocated Char
! 9108: that owns the given Blob as is (not duplicated, copied or freed).
! 9109: The Blob's next pointer is set to NULL. */
! 9110: Char *char_of_blob(b)
! 9111: Blob *b;
! 9112: { Char *c;
! 9113: c=alloc_char();
! 9114: c->bx = b->bx;
! 9115: c->area = b->area;
! 9116: c->per = b->per;
! 9117: c->bmny = 1;
! 9118: c->fi = b;
! 9119: b->n = NULL;
! 9120: return(c);
! 9121: }
! 9122:
! 9123: Interp *alloc_interp()
! 9124: { Interp *new;
! 9125: if((new=(Interp *)malloc(sizeof(Interp)))==NULL)
! 9126: abort("alloc_interp: can't malloc");
! 9127: alloc_census(Interp,1);
! 9128: *new = empty_Interp;
! 9129: return(new);
! 9130: }
! 9131:
! 9132: Interp *dup_interp(ip)
! 9133: Interp *ip;
! 9134: { Interp *dup;
! 9135: if((dup=(Interp *)malloc(sizeof(Interp)))==NULL)
! 9136: abort("dup_interp: can't malloc");
! 9137: alloc_census(Interp,1);
! 9138: *dup = *ip;
! 9139: return(dup);
! 9140: }
! 9141:
! 9142: /* Print the interpl */
! 9143: fwra_interpl(fp,ilp)
! 9144: FILE *fp;
! 9145: Interpl *ilp;
! 9146: { register Interp *cp;
! 9147: fprintf(fp,"Interpl[%d] ",ilp->mny);
! 9148: for(cp=ilp->fi; cp!=NULL; cp=cp->n) {
! 9149: fprintf(fp," %s --",interp_toa(cp));
! 9150: };
! 9151: fprintf(fp,"\n");
! 9152: }
! 9153:
! 9154: /* Print the interpl very briefly */
! 9155: fwra_interpl_brief(fp,ilp)
! 9156: FILE *fp;
! 9157: Interpl *ilp;
! 9158: { register Interp *ip;
! 9159: for(ip=ilp->fi; ip!=NULL; ip=ip->n) {
! 9160: fprintf(fp,"%s %s ",ip->ci.c,merit_toa(ip->m));
! 9161: };
! 9162: fprintf(fp,"\n");
! 9163: }
! 9164:
! 9165: err_interpl(ilp)
! 9166: Interpl *ilp;
! 9167: { fwra_interpl(stderr,ilp);
! 9168: }
! 9169:
! 9170: /* return the address of a local static copy of the given Interpl,
! 9171: for which each Interp is a duplicate of those in the given list */
! 9172: Interpl *dup_interpl_etc(ilp,etc)
! 9173: Interpl *ilp;
! 9174: Ident etc;
! 9175: { static Interpl lis;
! 9176: register Interp *cp,*pp,*dp;
! 9177: lis = *ilp;
! 9178: if(ilp->fi==NULL) return(NULL);
! 9179: for(pp=NULL,cp=ilp->fi; cp!=NULL; pp=dp,cp=cp->n) {
! 9180: dp=dup_interp(cp);
! 9181: if(pp==NULL) lis.fi = dp;
! 9182: else pp->n = dp;
! 9183: };
! 9184: pp->n=NULL;
! 9185: return(&lis);
! 9186: }
! 9187:
! 9188: /* Return a pointer to a local static duplicate of *isp.
! 9189: Its pa array is new, created out of malloc space.
! 9190: If etc&IsInterp, all its Interps are also duplicated,
! 9191: else the contents of pa point to the old unduplicated Interps.
! 9192: */
! 9193: Interps *dup_interps_etc(isp,etc)
! 9194: Interps *isp;
! 9195: Ident etc; /* parts to duplicate */
! 9196: { static Interps dup;
! 9197: register Interp **ipp,**dpp;
! 9198: dup = *isp;
! 9199: if(dup.mny<=0) dup = empty_Interps;
! 9200: else { if((dup.pa=(Interp **)malloc((dup.mny+1)*sizeof(Interp *)))==NULL)
! 9201: abort("can't dup (Interp *)is.pa[%d]",(dup.mny+1));
! 9202: for(ipp=isp->pa,dpp=dup.pa; *ipp!=NULL; ipp++,dpp++) {
! 9203: if(etc&IsInterp) *dpp = dup_interp(*ipp);
! 9204: else *dpp = *ipp;
! 9205: };
! 9206: *dpp = NULL;
! 9207: };
! 9208: return(&dup);
! 9209: }
! 9210:
! 9211: free_interps_etc(isp,etc)
! 9212: Interps *isp;
! 9213: Ident etc; /* parts to free */
! 9214: { register Interp **ipp,**dpp;
! 9215: if(etc&IsInterp) {
! 9216: /* free contents */
! 9217: for(ipp=isp->pa; *ipp!=NULL; ipp++) free_interp(*ipp);
! 9218: };
! 9219: if(isp->pa!=NULL) { free(isp->pa); isp->pa = NULL; };
! 9220: isp->mny = 0;
! 9221: }
! 9222:
! 9223: /* remove a char from a chars set */
! 9224: remove_char(cp,csp)
! 9225: Char *cp;
! 9226: Chars *csp;
! 9227: { register Char *rp,**rpp,**npp;
! 9228: if(csp->mny==0) err("remove_char: can't - Chars empty");
! 9229: else { for(rp= *(rpp=csp->cpa); rp!=NULL; rp= *(++rpp)) if(rp==cp) break;
! 9230: if(rp==NULL) err("remove_char: can't - not found");
! 9231: else { /* move later entries up */
! 9232: npp=rpp+1;
! 9233: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
! 9234: if((--(csp->mny))==0) {free(csp->cpa); csp->cpa=NULL;};
! 9235: /* don't bother to realloc downwards */
! 9236: };
! 9237: };
! 9238: }
! 9239:
! 9240: /* Append a char to the end of a chars set.
! 9241: Do NOT attempt to maintain Chars in order sorted ascending on Char.bx.a.x.
! 9242: Return appended Char *. */
! 9243: Char *append_char(cp,csp)
! 9244: Char *cp;
! 9245: Chars *csp;
! 9246: { register Char *rp,**rpp,**npp;
! 9247: if(csp->mny==0) {
! 9248: if((csp->cpa=(Char **)malloc(2*sizeof(Char *)))==NULL)
! 9249: abort("append_char: can't malloc csp->cpa[%d]",2);
! 9250: }
! 9251: else { if((csp->cpa=(Char **)realloc(
! 9252: csp->cpa,
! 9253: (csp->mny+2)*sizeof(Char *))
! 9254: )==NULL)
! 9255: abort("append_char: can't realloc csp->cpa[%d]",
! 9256: (csp->mny+2));
! 9257: };
! 9258: csp->cpa[csp->mny] = cp;
! 9259: csp->cpa[++csp->mny] = NULL;
! 9260: return(cp);
! 9261: }
! 9262:
! 9263: /* Insert a Char into a Chars set. Chars is assumed to be sorted ascending
! 9264: on on Char.bx.a.x, and this order is maintained.
! 9265: Return inserted Char * */
! 9266: Char *insert_char(cp,csp)
! 9267: Char *cp;
! 9268: Chars *csp;
! 9269: { register Char **cpp,*ncp,*pcp;
! 9270: if(csp->mny==0) {
! 9271: if((csp->cpa=(Char **)malloc(2*sizeof(Char *)))==NULL)
! 9272: abort("insert_char: can't malloc csp->cpa[%d]",2);
! 9273: csp->cpa[csp->mny] = cp;
! 9274: }
! 9275: else { if((cpp=csp->cpa=(Char **)realloc(
! 9276: csp->cpa,
! 9277: (csp->mny+2)*sizeof(Char *))
! 9278: )==NULL)
! 9279: abort("insert_char: can't realloc csp->cpa[%d]",csp->mny+2);
! 9280: while(((*cpp)!=NULL)&&(*cpp)->bx.a.x<cp->bx.a.x) cpp++;
! 9281: /* **cpp is now 1st entry >= *cp in sorted order */
! 9282: pcp=cp;
! 9283: do { ncp= *cpp;
! 9284: *(cpp++)=pcp;
! 9285: pcp=ncp;
! 9286: }
! 9287: while(pcp!=NULL);
! 9288: };
! 9289: csp->cpa[++csp->mny] = NULL;
! 9290: return(cp);
! 9291: }
! 9292:
! 9293: /* Append the contents of a "source" chars set to a "destination" chars set.
! 9294: Merely copy (Char *) pointers: don't duplicate Chars.
! 9295: Do NOT attempt to maintain Chars in order sorted ascending on Char.bx.a.x.
! 9296: Return destination (Chars *). */
! 9297: Chars *append_chars(s,d)
! 9298: Chars *s; /* source */
! 9299: Chars *d; /* destination */
! 9300: { register Char *rp,**rpp,**npp;
! 9301: if(s->mny==0) return(d);
! 9302: if(d->mny==0) {
! 9303: if((d->cpa=(Char **)malloc((s->mny+1)*sizeof(Char *)))==NULL)
! 9304: abort("append_chars: can't malloc d->cpa[%d]",2);
! 9305: }
! 9306: else { if((d->cpa=(Char **)realloc(
! 9307: d->cpa,
! 9308: (d->mny+s->mny+1)*sizeof(Char *))
! 9309: )==NULL)
! 9310: abort("append_chars: can't realloc d->cpa[%d]",
! 9311: (d->mny+s->mny+1));
! 9312: };
! 9313: memcpy(d->cpa+d->mny,s->cpa,(s->mny+1)*sizeof(Char *));
! 9314: d->mny += s->mny;
! 9315: return(d);
! 9316: }
! 9317:
! 9318: /* Insert a Char into the Chars owned by a given Word,
! 9319: maintaining order in set, and updating the Word's bx */
! 9320: Char *insert_char_word(cp,wp)
! 9321: Char *cp;
! 9322: Word *wp;
! 9323: { merge_bbx(&(cp->bx),&(wp->bx));
! 9324: return(insert_char(cp,&(wp->cs)));
! 9325: }
! 9326:
! 9327: free_char_etc(p,etc)
! 9328: Char *p; /* !=NULL */
! 9329: Ident etc;
! 9330: { if(etc&IsBlob) free_blobl_etc(&(p->bmny),&(p->fi),etc);
! 9331: if(etc&IsInterp) free_interpl(&(p->il));
! 9332: if(etc&IsSfeats && p->sfv!=NULL) { free(p->sfv); p->sfv=NULL; };
! 9333: if(etc&IsShapes) free_shapes(&(p->sh));
! 9334: #if CPU!=CRAY
! 9335: if(etc&IsBfeats && p->bfsp!=NULL) { free_bfeats(p->bfsp); p->bfsp=NULL; };
! 9336: #endif
! 9337: if(etc&IsChar) {
! 9338: if(p->ident&Char_label && p->l!=NULL) {
! 9339: free(p->l); p->l=NULL;
! 9340: p->ident &= ~Char_label;
! 9341: };
! 9342: if(p->ident&Char_ranparms && p->rp!=NULL) {
! 9343: free_ranparms(p->rp); p->rp=NULL;
! 9344: p->ident &= ~Char_ranparms;
! 9345: };
! 9346: free(p);
! 9347: free_census(Char,1);
! 9348: };
! 9349: }
! 9350:
! 9351: /* Unconditionally free the malloc-space array of pointers, and empty the set.
! 9352: Don't free the records that it owned.
! 9353: */
! 9354: free_chars(csp)
! 9355: Chars *csp;
! 9356: { if(csp->cpa!=NULL) { free(csp->cpa); csp->cpa = NULL; }
! 9357: csp->mny = 0;
! 9358: }
! 9359:
! 9360: free_chars_etc(csp,etc)
! 9361: Chars *csp;
! 9362: Ident etc;
! 9363: { register Char *cp,**cpp;
! 9364: if(csp->mny>0&&(etc&IsChar))
! 9365: for(cp= *(cpp=csp->cpa); cp!=NULL; cp= *(++cpp))
! 9366: free_char_etc(cp,etc);
! 9367: free_chars(csp);
! 9368: }
! 9369:
! 9370: /** Blob handling:
! 9371: alloc_blob_pool(sz,debug) - create pool of free blob records
! 9372: free_blob_pool() - free the pool
! 9373: Blob *alloc_blob() - allocate a new blob (in pool)
! 9374: free_blob(bp) - free a specified blob
! 9375: free_blob_runs(bp) - free a blob & the runs in its blob set
! 9376: free_blobl_etc(int *,Blob **,etc) - free blobs etc in char's blob list
! 9377: out_blob(bp) - print (ascii) to stdout
! 9378: fwrb_blob(fp,bp) - write binary Blob (only) to fp
! 9379: fwrb_blob_etc(fp,bp,etc) - write binary Blob & specified parts to fp
! 9380: frdb_blob_etc(fp,bp,etc) - read binary Blob & parts in specified form
! 9381: frdb_runfs(fp,bp,max) - read *bp's (binary) RunF's from fp
! 9382: err_blob(s,bp) - print (ascii) to stderr
! 9383: err_blob_runs(s,bp) - print Blob & its Runs (ascii) to stderr
! 9384: err_blob_runfs(s,bp) - print Blob & its RunFs (ascii) to stderr
! 9385: err_blob_briefly(s,bp) - print (ascii) to stderr
! 9386: err_blobf(s,bp) - print file-format blob (ascii) to stderr
! 9387: err_blob_stats() - report blob statistics
! 9388: blob_small(bp) - test whether its runs' data can be compressed to chars
! 9389: BUGS
! 9390: most fread/fwrite/fseek should be read/write/lseek, for speed
! 9391: -- but how to choose?
! 9392: **/
! 9393:
! 9394: /* make (empty) pool of `size' Blobs (return F if can't allocate) */
! 9395: boolean alloc_blob_pool(size,dbg)
! 9396: int size;
! 9397: boolean dbg;
! 9398: { register Blob *cbp, *cbq, *pbp;
! 9399: blob_max=size;
! 9400: if((blob_pool=(Blob *)malloc(blob_max*sizeof(Blob)))==NULL) return(F);
! 9401: blob_debug = dbg;
! 9402: pbp= &blob_fr;
! 9403: /* link up all blobs into free list using only first-ptrs */
! 9404: for(cbq=(cbp=blob_pool)+blob_max; cbp<cbq; cbp++) {
! 9405: pbp->n = cbp;
! 9406: pbp = cbp;
! 9407: };
! 9408: pbp->n = NULL; /* marks end of free list */
! 9409: blob_fr_mny = blob_max; blob_hi=0; blob_chopped = 0;
! 9410: hi_blob_no = 0;
! 9411: return(T);
! 9412: }
! 9413:
! 9414: free_blob_pool()
! 9415: { free(blob_pool);
! 9416: }
! 9417:
! 9418: Blob *alloc_blob()
! 9419: { Blob *p;
! 9420: if((p=(Blob *)malloc(sizeof(Blob)))==NULL)
! 9421: abort("alloc_blob: can't");
! 9422: alloc_census(Blob,1);
! 9423: *p = empty_Blob;
! 9424: return(p);
! 9425: }
! 9426:
! 9427: /* Unconditionally free this Blob record. */
! 9428: free_blob(bp)
! 9429: Blob *bp;
! 9430: { free(bp);
! 9431: free_census(Blob,1);
! 9432: }
! 9433:
! 9434: /* Allocate new Blob record and assign to it the next blob no */
! 9435: Blob *alloc_pool_blob()
! 9436: { register Blob *bp;
! 9437: if((bp = blob_fr.n)==NULL) {
! 9438: err("too many alloc_blob() calls - aborting:");
! 9439: #ifdef STATS
! 9440: err_blob_stats();
! 9441: #endif
! 9442: exit(1);
! 9443: };
! 9444: blob_fr.n = bp->n;
! 9445: #ifdef STATS
! 9446: blob_fr_mny--;
! 9447: if(blob_hi<(blob_max-blob_fr_mny)) blob_hi = blob_max-blob_fr_mny;
! 9448: #endif
! 9449: bp->no = hi_blob_no++;
! 9450: return(bp);
! 9451: }
! 9452:
! 9453: free_pool_blob(bp)
! 9454: Blob *bp;
! 9455: {
! 9456: if(blob_debug&&bp==NULL) abort("free_pool_blob: can't free a NULL Blob");
! 9457: #ifdef STATS
! 9458: blob_fr_mny++;
! 9459: if(blob_debug&&(blob_fr_mny>blob_max)) {
! 9460: err("free_pool_blob: too many free_blob() calls - aborting:");
! 9461: #ifdef STATS
! 9462: err_blob_stats();
! 9463: #endif
! 9464: exit(1);
! 9465: };
! 9466: #endif
! 9467: bp->n = blob_fr.n;
! 9468: blob_fr.n = bp;
! 9469: }
! 9470:
! 9471: /* free the runs belonging to this blob */
! 9472: free_runs(bp)
! 9473: Blob *bp;
! 9474: { register Run *crp,*nrp;
! 9475: if(bp->ident&Runs_ff) {
! 9476: if(bp->r.ff!=NULL) free(bp->r.ff);
! 9477: bp->r.ff=NULL;
! 9478: }
! 9479: else if(bp->ident&Runs_f) {
! 9480: for(crp=bp->r.f; crp!=NULL; crp=nrp) {
! 9481: nrp=crp->n;
! 9482: free_run(crp);
! 9483: };
! 9484: }
! 9485: else if(bp->ident&Runs_seek) /* none to free */ ;
! 9486: }
! 9487:
! 9488: /* free blob *bp and those parts (runs) specified */
! 9489: free_blob_etc(bp,etc)
! 9490: Blob *bp;
! 9491: Ident etc;
! 9492: { if(etc&IsRun) free_runs(bp);
! 9493: if(etc&IsBlob) free_blob(bp);
! 9494: }
! 9495:
! 9496: /* return a pointer to a distinct and duplicate copy of *bp;
! 9497: it is created out of malloc space */
! 9498: Blob *dup_blob(bp)
! 9499: Blob *bp;
! 9500: { Blob *dup;
! 9501: if((dup=(Blob *)malloc(sizeof(Blob)))==NULL)
! 9502: abort("dup_blob: can't malloc");
! 9503: alloc_census(Blob,1);
! 9504: *dup = *bp;
! 9505: return(dup);
! 9506: }
! 9507:
! 9508: /* return a pointer to a distinct and duplicate copy of *bp and what it owns,
! 9509: as described by etc; created out of malloc space */
! 9510: Blob *dup_blob_etc(bp,etc)
! 9511: Blob *bp;
! 9512: Ident etc;
! 9513: { Blob *dup;
! 9514: dup = dup_blob(bp);
! 9515: if(bp->runs>0) {
! 9516: if(bp->ident&Runs_ff) {
! 9517: int ri;
! 9518: RunF *rp,*drp;
! 9519: if((dup->r.ff=
! 9520: (RunF *)malloc(bp->runs*sizeof(RunF)))==NULL)
! 9521: abort("dup_blob_etc: can't malloc RunF[%d]",
! 9522: bp->runs);
! 9523: for(ri=0,rp=bp->r.ff,drp=dup->r.ff; ri<bp->runs; ri++)
! 9524: *(drp++) = *(rp++);
! 9525: }
! 9526: else abort("dup_blob_etc: only Runs_ff implemented");
! 9527: };
! 9528: return(dup);
! 9529: }
! 9530:
! 9531: /* Return a pointer to a local static duplicate of non-empty *bsp.
! 9532: Its bpa array is created newly out of malloc space.
! 9533: If etc&IsBlob, all its Blobs are also fresh duplicates,
! 9534: else the contents of bpa point to the old unduplicated Blobs.
! 9535: */
! 9536: Blobs *dup_blobs_etc(bsp,etc)
! 9537: Blobs *bsp;
! 9538: Ident etc; /* parts to duplicate */
! 9539: { static Blobs dup;
! 9540: register Blob **bpp,**dpp;
! 9541: if((dup.mny = bsp->mny)<=0) dup = empty_Blobs;
! 9542: else { if((dup.bpa=(Blob **)malloc((dup.mny+1)*sizeof(Blob *)))==NULL)
! 9543: abort("dup_blobs_etc: can't malloc bs.bpa[%d]",dup.mny+1);
! 9544: for(bpp=bsp->bpa,dpp=dup.bpa; *bpp!=NULL; bpp++,dpp++) {
! 9545: if(etc&IsBlob) *dpp = dup_blob_etc(*bpp,etc);
! 9546: else *dpp = *bpp;
! 9547: };
! 9548: *dpp = NULL;
! 9549: };
! 9550: return(&dup);
! 9551: }
! 9552:
! 9553: /* Split the given Blobs into two, *b0 & *b1, according to the value 0 or !0
! 9554: respectively returned by the function s(b,a) applied to each Blob *b and
! 9555: blind argument *a.
! 9556: s() will be evaluated exactly once for each Blob, and the Blob's will be
! 9557: assigned in the order found in the original Blobs. Only pointers to Blob's
! 9558: are created; the Blob's themselves are not duplicated. The original Blobs
! 9559: record is unchanged.
! 9560: */
! 9561: split_blobs(b,s,a,b0,b1)
! 9562: Blobs *b;
! 9563: int (*s)();
! 9564: VOID *a; /* passed transparently to s() */
! 9565: Blobs *b0,*b1;
! 9566: { char *sel,*sp;
! 9567: register Blob *bp,**bpp;
! 9568: Blob **b0pp;
! 9569: Blob **b1pp;
! 9570: *b0 = *b1 = empty_Blobs;
! 9571: if(b->mny<=0) return;
! 9572: if((sel=(char *)malloc(b->mny))==NULL)
! 9573: abort("split_blobs: can't malloc sel[%d]",b->mny);
! 9574: for(bp= *(bpp=b->bpa),sp=sel; bp!=NULL; bp= *(++bpp),sp++)
! 9575: if(*sp = s(bp,a)) b1->mny++; else b0->mny++;
! 9576: if(b0->mny>0)
! 9577: if((b0->bpa=(Blob **)malloc((b0->mny+1)*sizeof(Blob *)))==NULL)
! 9578: abort("split_blobs: can't malloc b0->bpa[%d]",b0->mny+1);
! 9579: if(b1->mny>0)
! 9580: if((b1->bpa=(Blob **)malloc((b1->mny+1)*sizeof(Blob *)))==NULL)
! 9581: abort("split_blobs: can't malloc b1->bpa[%d]",b1->mny+1);
! 9582: b0pp=b0->bpa;
! 9583: b1pp=b1->bpa;
! 9584: for(bp= *(bpp=b->bpa),sp=sel; bp!=NULL; bp= *(++bpp),sp++)
! 9585: if(*sp) *(b1pp++)=bp; else *(b0pp++)=bp;
! 9586: if(b0->mny>0) *b0pp=NULL;
! 9587: if(b1->mny>0) *b1pp=NULL;
! 9588: free(sel);
! 9589: }
! 9590:
! 9591: /* Return the address of the first in a list of Blobs, duplicated from
! 9592: the given list. */
! 9593: Blob *dup_blobl_etc(bp,etc)
! 9594: Blob *bp;
! 9595: Ident etc;
! 9596: { Blob *fi,*cp,*pp,*dp;
! 9597: if(bp==NULL) return(NULL);
! 9598: for(pp=NULL,cp=bp; cp!=NULL; pp=dp,cp=cp->n) {
! 9599: dp=dup_blob_etc(cp,etc);
! 9600: if(pp==NULL) fi = dp;
! 9601: else pp->n = dp;
! 9602: };
! 9603: pp->n=NULL;
! 9604: return(fi);
! 9605: }
! 9606:
! 9607: /* Prepend this blob to the given Char's bloblist; update Char's bx, area, & per.
! 9608: Inverse of `remove_blobl()'. */
! 9609: Blob *insert_blobl(bp,cp)
! 9610: Blob *bp;
! 9611: Char *cp;
! 9612: { register Blob *pbp,*nbp;
! 9613: if(cp->bmny>0) bp->n = cp->fi;
! 9614: else bp->n = NULL;
! 9615: cp->fi = bp;
! 9616: cp->bmny++;
! 9617: merge_bbx(&(bp->bx),&(cp->bx));
! 9618: cp->area += bp->area;
! 9619: cp->per += bp->per;
! 9620: return(bp);
! 9621: }
! 9622:
! 9623: /* Remove this blob from a char's bloblist; update Char's bx, area, per.
! 9624: Inverse of `insert_blobl()'. */
! 9625: remove_blobl(bp,cp)
! 9626: Blob *bp;
! 9627: Char *cp;
! 9628: { Blob *rp,*pp;
! 9629: Bbx bx; /* Char's new Bbx */
! 9630: if(cp->bmny==1) { /* frequent case */
! 9631: cp->fi=NULL; cp->bmny=0;
! 9632: }
! 9633: else if(cp->bmny>1){
! 9634: bx=empty_Bbx;
! 9635: pp=NULL;
! 9636: for(rp=cp->fi; rp!=NULL; pp=rp,rp=rp->n) {
! 9637: if(rp==bp) break;
! 9638: else { if(bx.a.x > rp->bx.a.x) bx.a.x = rp->bx.a.x;
! 9639: if(bx.a.y > rp->bx.a.y) bx.a.y = rp->bx.a.y;
! 9640: if(bx.b.x < rp->bx.b.x) bx.b.x = rp->bx.b.x;
! 9641: if(bx.b.y < rp->bx.b.y) bx.b.y = rp->bx.b.y;
! 9642: };
! 9643: };
! 9644: if(rp!=NULL) { /* remove from list */
! 9645: if(pp==NULL) cp->fi=bp->n;
! 9646: else pp->n=bp->n;
! 9647: cp->bmny--;
! 9648: for(rp=bp->n; rp!=NULL; rp=rp->n) {
! 9649: if(bx.a.x > rp->bx.a.x) bx.a.x = rp->bx.a.x;
! 9650: if(bx.a.y > rp->bx.a.y) bx.a.y = rp->bx.a.y;
! 9651: if(bx.b.x < rp->bx.b.x) bx.b.x = rp->bx.b.x;
! 9652: if(bx.b.y < rp->bx.b.y) bx.b.y = rp->bx.b.y;
! 9653: };
! 9654: cp->bx = bx;
! 9655: }
! 9656: else err("remove_blobl: can't - not found");
! 9657: }
! 9658: else err("remove_blobl: can't - Blobl empty");
! 9659: cp->area -= bp->area;
! 9660: cp->per -= bp->per;
! 9661: }
! 9662:
! 9663: /* prepend this blob to the given Blob list */
! 9664: Blob *prepend_blobl(bp,blp)
! 9665: Blob *bp;
! 9666: Blobl *blp;
! 9667: { register Blob *pbp,*nbp;
! 9668: if(blp->mny>0) bp->n = blp->fi;
! 9669: else { bp->n = NULL;
! 9670: blp->la = bp;
! 9671: };
! 9672: blp->fi = bp;
! 9673: blp->mny++;
! 9674: return(bp);
! 9675: }
! 9676:
! 9677: /* append this blob to the given Blob list */
! 9678: Blob *append_blobl(bp,blp)
! 9679: Blob *bp;
! 9680: Blobl *blp;
! 9681: { register Blob *pbp,*nbp;
! 9682: if(blp->mny==0) blp->fi = bp;
! 9683: else blp->la->n = bp;
! 9684: blp->la = bp;
! 9685: bp->n = NULL;
! 9686: blp->mny++;
! 9687: return(bp);
! 9688: }
! 9689:
! 9690: /* remove a blob from a blobs set */
! 9691: remove_blob(bp,bsp)
! 9692: Blob *bp;
! 9693: Blobs *bsp;
! 9694: { register Blob *rp,**rpp,**npp;
! 9695: if(bsp->mny==0) err("remove_blob: can't - Blobs empty");
! 9696: else { for(rp= *(rpp=bsp->bpa); rp!=NULL; rp= *(++rpp)) if(rp==bp) break;
! 9697: if(rp==NULL) err("remove_blob: can't - not found");
! 9698: else { /* move later entries up */
! 9699: npp=rpp+1;
! 9700: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
! 9701: if((--(bsp->mny))==0) {free(bsp->bpa); bsp->bpa=NULL;};
! 9702: /* don't bother to realloc downwards */
! 9703: };
! 9704: };
! 9705: }
! 9706:
! 9707: /* Append a blob to the end of a blobs set.
! 9708: Return appended Blob *. */
! 9709: Blob *append_blob(p,sp)
! 9710: Blob *p;
! 9711: Blobs *sp;
! 9712: { register Blob *rp,**rpp,**npp;
! 9713: if(sp->mny==0) {
! 9714: if((sp->bpa=(Blob **)malloc(2*sizeof(Blob *)))==NULL)
! 9715: abort("append_blob: can't malloc sp->bpa[2]");
! 9716: }
! 9717: else { if((sp->bpa=(Blob **)realloc(
! 9718: sp->bpa,
! 9719: (sp->mny+2)*sizeof(Blob *))
! 9720: )==NULL)
! 9721: abort("append_blob: can't realloc sp->bpa[%d]",sp->mny+2);
! 9722: };
! 9723: sp->bpa[sp->mny] = p;
! 9724: sp->bpa[++sp->mny] = NULL;
! 9725: return(p);
! 9726: }
! 9727:
! 9728: /* Append Blobs *p1 to Blobs *p2. On return, *p1 is unchanged, *p2 is in general
! 9729: longer, and all the Blob's owned by *p1 are now also owned by *p2. */
! 9730: append_blobs_blobs(p1,p2)
! 9731: Blobs *p1,*p2;
! 9732: { int mny;
! 9733: register Blob **pp1,**pp2;
! 9734: if(p1->mny==0) return;
! 9735: if(p2->mny==0) { *p2 = *dup_blobs_etc(p1,IsNONE); return; };
! 9736: mny = p2->mny + p1->mny;
! 9737: if((p2->bpa=(Blob **)realloc(p2->bpa,(mny+1)*sizeof(Blob *)))==NULL)
! 9738: abort("append_blobs_blobs: can't realloc p2->bpa[%d]",mny+1);
! 9739: pp1=p1->bpa; pp2=p2->bpa+p2->mny; while(*pp1!=NULL) *(pp2++) = *(pp1++);
! 9740: *pp2 = NULL;
! 9741: p2->mny = mny;
! 9742: }
! 9743:
! 9744: free_blobl_etc(mnyp,fip,etc)
! 9745: int *mnyp;
! 9746: Blob **fip;
! 9747: Ident etc;
! 9748: { register Blob *bp,*nbp;
! 9749: if(*mnyp>0) {
! 9750: for(bp= *fip; bp != NULL; bp=nbp)
! 9751: { nbp=bp->n; free_blob_etc(bp,etc); };
! 9752: };
! 9753: *mnyp=0;
! 9754: *fip=NULL;
! 9755: }
! 9756:
! 9757: /* Unconditionally free the malloc-space array of pointers, and empty the set.
! 9758: Don't free the records that it owned.
! 9759: */
! 9760: free_blobs(bsp)
! 9761: Blobs *bsp;
! 9762: { if(bsp->bpa!=NULL) { free(bsp->bpa); bsp->bpa=NULL; };
! 9763: bsp->mny = 0;
! 9764: }
! 9765:
! 9766: free_blobs_etc(bsp,etc)
! 9767: Blobs *bsp;
! 9768: Ident etc;
! 9769: { register Blob *bp, **bpp;
! 9770: if(bsp->mny>0&&(etc&IsBlob)) for(bp= *(bpp=bsp->bpa); bp!=NULL; bp= *(++bpp))
! 9771: free_blob_etc(bp,etc);
! 9772: free_blobs(bsp);
! 9773: }
! 9774:
! 9775: Blobs *blobl_to_blobs(blp)
! 9776: Blobl *blp;
! 9777: { static Blobs bs;
! 9778: register Blob *bp,**bpp;
! 9779: bs = empty_Blobs;
! 9780: bs.mny = blp->mny;
! 9781: if(bs.mny>0) {
! 9782: if((bs.bpa=(Blob **)malloc((bs.mny+1)*sizeof(Blob *)))==NULL)
! 9783: abort("blobl_to_blobs: can't malloc Blobs.bpa[%d]",bs.mny+1);
! 9784: for(bp=blp->fi,bpp=bs.bpa; bp!=NULL; bp=bp->n,bpp++)
! 9785: *bpp = bp;
! 9786: *bpp = NULL;
! 9787: };
! 9788: return(&bs);
! 9789: }
! 9790:
! 9791: int bp_tod(bp)
! 9792: Blob *bp;
! 9793: { if(bp==NULL) return(-2);
! 9794: else return(bp-blob_pool);
! 9795: }
! 9796:
! 9797: /* test whether for this Blob, each runs's data fields could all be compressed
! 9798: from a short to a char */
! 9799: boolean blob_small(bp)
! 9800: Blob *bp;
! 9801: { if(bp->runs>255) return(F);
! 9802: if(bbx_wid(&bp->bx)>255) return(F);
! 9803: if(bbx_hgt(&bp->bx)>255) return(F);
! 9804: return(T);
! 9805: }
! 9806:
! 9807: char *blob_toa(bp)
! 9808: Blob *bp;
! 9809: { char s1[80];
! 9810: static char s[80];
! 9811: Scoor hgt,wid;
! 9812: if(bp==NULL) strcpy(s,"NULL");
! 9813: else { hgt = bp->bx.b.y - bp->bx.a.y + 1;
! 9814: wid = bp->bx.b.x - bp->bx.a.x + 1;
! 9815: sprintf(s1,"%s bx%s w%d,h%d ar%d pe%d r.",
! 9816: ident_toa(bp->ident),
! 9817: bbx_toa(&(bp->bx)),
! 9818: wid,
! 9819: hgt,
! 9820: bp->area,
! 9821: bp->per
! 9822: );
! 9823: if(bp->ident&Runs_f) strcat(s1,"f");
! 9824: else if(bp->ident&Runs_ff) strcat(s1,"ff");
! 9825: else if(bp->ident&Runs_seek) strcat(s1,"sk");
! 9826: else if(bp->ident&Runs_g4) strcat(s1,"g");
! 9827: else strcat(s1,"?");
! 9828: sprintf(s,"%s%d",s1,bp->runs);
! 9829: };
! 9830: return(s);
! 9831: }
! 9832:
! 9833: /* compute the centroid of the Blob, w.r.t bx.a */
! 9834: Pp *blob_centroid(bp)
! 9835: Blob *bp;
! 9836: { static Pp c;
! 9837: RunF *rfp;
! 9838: int ri,area;
! 9839: c.x = c.y = 0.0;
! 9840: if(bp->ident&Runs_ff) {
! 9841: for(ri=0, rfp=bp->r.ff; ri<bp->runs; ri++, rfp++) {
! 9842: c.x += (area=(rfp->xe-rfp->xs+1)) * (rfp->xe+rfp->xs);
! 9843: c.y += area * rfp->y;
! 9844: };
! 9845: c.x /= 2.0*bp->area;
! 9846: c.y /= bp->area;
! 9847: }
! 9848: else abort("blob_centroid: only Runs_ff supported");
! 9849: return(&c);
! 9850: }
! 9851:
! 9852: /* write (printably) to stdout */
! 9853: out_blob(bp)
! 9854: Blob *bp;
! 9855: { Run *crp;
! 9856: static char pad[] = " ";
! 9857: short y;
! 9858: if(bp==NULL) fprintf(stderr,"Bb NULL.\n");
! 9859: else fprintf(stdout,"%s\n",blob_toa(bp));
! 9860: fprintf(stdout,"%sy%d:",pad,bp->bx.a.y);
! 9861: for(crp=bp->r.f,y=crp->y; crp!=NULL; crp=crp->n) {
! 9862: if(crp->y!=y) {
! 9863: fprintf(stdout,"\n%sy%d:",pad,crp->y);
! 9864: y=crp->y;
! 9865: };
! 9866: fprintf(stdout," [%d,%d]",crp->xs,crp->xe);
! 9867: };
! 9868: fprintf(stdout,"\n");
! 9869: }
! 9870:
! 9871: #if FWRI
! 9872: /* Write blob record (only) to FILE *f.
! 9873: Check whether Blob is ``small'' and label *p accordingly. */
! 9874: fwrb_blob(f,p)
! 9875: FILE *f;
! 9876: Blob *p;
! 9877: {
! 9878: #if dbg_fwrb
! 9879: if((!(p->ident&IsBlob))||(p->ident&(IsALL&(~IsBlob))))
! 9880: err("fwrb_blob: %s",blob_toa(p));
! 9881: #endif
! 9882: if(blob_small(p)) p->ident |= Blob_small; else p->ident &= ~Blob_small;
! 9883: fwri_Ident(f,p->ident);
! 9884: /* fwri_Seq(f,p->no); */
! 9885: fwri_Bbx(f,&(p->bx));
! 9886: fwri_uint4(f,p->area);
! 9887: fwri_uint4(f,p->per);
! 9888: /* don't write .n */
! 9889: fwri_Merit(f,p->m);
! 9890: fwri_uint3(f,p->runs);
! 9891: fwri_uint2(f,((p->bdsp==NULL)? 0: p->bdsp->mny));
! 9892: #if dbg_fwrb_toa
! 9893: err("fwrb_blob: %s",blob_toa(p));
! 9894: #endif
! 9895: }
! 9896: #else
! 9897: /* Write blob record (only) to FILE *fp.
! 9898: Check whether Blob is ``small'' and label *bp accordingly. */
! 9899: fwrb_blob(fp,bp)
! 9900: FILE *fp;
! 9901: Blob *bp;
! 9902: { BlobF bf;
! 9903: #if dbg_fwrb
! 9904: if((!(bp->ident&IsBlob))||(bp->ident&(IsALL&(~IsBlob))))
! 9905: err("fwrb_blob: %s",blob_toa(bp));
! 9906: #endif
! 9907: memset(&bf,'\0',sizeof(bf));
! 9908: if(blob_small(bp)) bp->ident |= Blob_small;
! 9909: else bp->ident &= ~Blob_small;
! 9910: bf.ident = bp->ident;
! 9911: bf.bx=bp->bx;
! 9912: bf.area=bp->area;
! 9913: bf.per=bp->per;
! 9914: bf.runs=bp->runs;
! 9915: if(bp->bdsp==NULL) bf.bdys=0;
! 9916: else bf.bdys=bp->bdsp->mny;
! 9917: if(blob_debug) err_blobf("",&bf);
! 9918: if(fwrite(&bf,sizeof(BlobF),1,fp)!=1)
! 9919: abort("fwrb_blob: can't fwrite");
! 9920: #if dbg_fwrb_toa
! 9921: err("fwrb_blob: %s",blob_toa(bp));
! 9922: #endif
! 9923: }
! 9924: #endif
! 9925:
! 9926: /* Write detailed description of Runs to stderr. */
! 9927: Blob *err_runs(name,bp)
! 9928: char *name;
! 9929: Blob *bp;
! 9930: { Run *rp;
! 9931: RunF *rfp,*rfe;
! 9932: int ri;
! 9933: if(bp->ident&Runs_f) {
! 9934: fprintf(stderr,"%s Runs_f[%d] in %s:\n",
! 9935: name,bp->runs,bbx_toa(&bp->bx));
! 9936: for(rp=bp->r.f,ri=0; rp!=NULL; rp=rp->n,ri++) {
! 9937: fprintf(stderr," %2d: %d[%d,%d]\n",
! 9938: ri,rp->y,rp->xs,rp->xe);
! 9939: };
! 9940: }
! 9941: else if(bp->ident&Runs_ff) {
! 9942: fprintf(stderr,"%s Runs_ff[%d] in %s: ",
! 9943: name,bp->runs,bbx_toa(&(bp->bx)));
! 9944: for(rfe=(rfp=bp->r.ff)+bp->runs,ri=0; rfp<rfe; rfp++,ri++) {
! 9945: fprintf(stderr," %d:%d[%d,%d]",
! 9946: ri,rfp->y,rfp->xs,rfp->xe);
! 9947: };
! 9948: fprintf(stderr,"\n");
! 9949: }
! 9950: else if(bp->ident&Runs_seek) {
! 9951: goto unsupported;
! 9952: }
! 9953: else { goto unsupported;
! 9954: };
! 9955: return;
! 9956: unsupported:
! 9957: abort("err_runs: %s unsupported",ident_toa(bp->ident));
! 9958: }
! 9959:
! 9960: /* Convert the type of Runs in *bp to the type specified by id.
! 9961: Supported: only bp->ident&Runs_f to id&Runs_ff.
! 9962: Return pointer to local static duplicate of *bp.
! 9963: */
! 9964: Blob *runs_to_runs(bp,id)
! 9965: Blob *bp;
! 9966: Ident id;
! 9967: { static Blob b;
! 9968: register Run *rp;
! 9969: RunF *rfp;
! 9970:
! 9971: b = *bp;
! 9972: if(bp->ident&Runs_f) {
! 9973: if(id&Runs_ff) {
! 9974: b.ident &= ~(Runs_f|Blob_small);
! 9975: b.ident |= Runs_ff;
! 9976: if(blob_small(bp)) b.ident |= Blob_small;
! 9977: if((b.r.ff=(RunF *)malloc(b.runs*sizeof(RunF)))==NULL)
! 9978: abort("runs_to_runs: can't malloc Blob.r.ff[%d]",
! 9979: b.runs); for(rp=bp->r.f,rfp=b.r.ff; rp!=NULL; rp=rp->n,rfp++) {
! 9980: /* y, xs, xe will be relative to Blob.bx.a */
! 9981: rfp->y = rp->y - bp->bx.a.y;
! 9982: rfp->xs = rp->xs - bp->bx.a.x;
! 9983: rfp->xe = rp->xe - bp->bx.a.x;
! 9984: /* above,below connecting indices are relative to
! 9985: the sequence no. of this run (ac>0 & bc>0) */
! 9986: if((rfp->ad = rp->ad)!=0)
! 9987: rfp->ac = rp->u.no - rp->ac->u.no;
! 9988: else rfp->ac = 0;
! 9989: if((rfp->bd = rp->bd)!=0)
! 9990: rfp->bc = rp->bc->u.no - rp->u.no;
! 9991: else rfp->bc = 0;
! 9992: if(0) err_runf(" ",rfp);
! 9993: };
! 9994: }
! 9995: else { goto unsupported;
! 9996: };
! 9997: }
! 9998: else if(bp->ident&Runs_ff) {
! 9999: if(bp->ident&Blob_small) {
! 10000: goto unsupported;
! 10001: }
! 10002: else { goto unsupported;
! 10003: };
! 10004: }
! 10005: else if(bp->ident&Runs_seek) {
! 10006: goto unsupported;
! 10007: }
! 10008: else { goto unsupported;
! 10009: };
! 10010: return(&b);
! 10011:
! 10012: unsupported:
! 10013: abort("runs_to_runs: %s --> %s unsupported",
! 10014: ident_toa(bp->ident),ident_toa(id));
! 10015: }
! 10016:
! 10017: #if CPU!=CRAY
! 10018: /* Write these RunFs to FILE *fp in CCITT Group 4 format.
! 10019: BUG: uses bitio to one end of a pipe, just to store the entire
! 10020: byte-stream so it can be counted; then, it is copied to *fp.
! 10021: This fails on large bitmaps since the space available for pipe
! 10022: buffering is limited by system constraints and can run out at any
! 10023: time (symptom: the user process hangs in I state). Also, since
! 10024: it relies so heavily on streams, it may not prove to be very portable.
! 10025: Should be rewritten with an expandable byte-buffer of some kind,
! 10026: which requires that the `putting' function in bitio be user-selectable.
! 10027: */
! 10028: fwrb_runfs_g4(fp,bxp,runs,ff)
! 10029: FILE *fp;
! 10030: Bbx *bxp;
! 10031: int runs;
! 10032: RunF *ff;
! 10033: #define dbg_fwrb_runfs_g4_detail F
! 10034: { RLE_Line l0,l1;
! 10035: RLE_Line *cl,*pl,*swap; /* current/prior/swap line */
! 10036: int wid,hgt; /* width,height of rectangular box of pixels */
! 10037: BITFILE *bf;
! 10038: int iri;
! 10039: RunF *irp;
! 10040: RLE_Run *crp;
! 10041: static int pipe_fd[2] = {-1,-1};
! 10042: static FILE *pipe_fp[2] = {NULL,NULL};
! 10043: unsigned long bytes,bi;
! 10044: int och;
! 10045: /* buffer g4 code in a pipe in order to count it */
! 10046: if(pipe_fd[0]==-1) {
! 10047: pipe(pipe_fd);
! 10048: if((pipe_fp[0] = fdopen(pipe_fd[0],"r"))==NULL)
! 10049: abort("fwrb_runfs_g4: can't open pipe \"r\", fd=%d",
! 10050: pipe_fd[0]);
! 10051: if((pipe_fp[1] = fdopen(pipe_fd[1],"w"))==NULL)
! 10052: abort("fwrb_runfs_g4: can't open pipe \"w\", fd=%d",
! 10053: pipe_fd[1]);
! 10054: /* leave this pipe open for the duration of the process */
! 10055: };
! 10056: /* treat pipe_fp[1] as a sequence of bits */
! 10057: if((bf=bopen(pipe_fp[1],"w"))==NULL)
! 10058: abort("fwrb_runfs_g4: can't open bitfile");
! 10059: wid = bbx_wid(bxp); hgt=bbx_hgt(bxp);
! 10060: BOF_to_g4(bf);
! 10061: cl= &l0; pl= &l1; cl->len = pl->len = wid; cl->y=0; pl->runs=0;
! 10062: iri=0; irp=ff;
! 10063: do { /* build current RLE_Line */
! 10064: crp=cl->r;
! 10065: while(iri<runs&&irp->y==cl->y) {
! 10066: crp->xs=irp->xs;
! 10067: crp->xe=irp->xe;
! 10068: if(dbg_fwrb_runfs_g4_detail)
! 10069: err("i%d: y%d x[%d,%d]",
! 10070: iri,cl->y,crp->xs,crp->xe);
! 10071: iri++; irp++; crp++;
! 10072: };
! 10073: cl->runs = crp-cl->r;
! 10074: /* write current RLE_line to file */
! 10075: rlel_to_g4(pl,cl,wid,bf);
! 10076: /* save current line as prior */
! 10077: swap=pl; pl=cl; cl=swap; cl->runs=0; cl->y=pl->y+1;
! 10078: }
! 10079: while(cl->y<hgt);
! 10080: /** By policy, don't append EOFB (i.e. omit EOF_to_g4(bf)) **/
! 10081: bytes = bclose(bf);
! 10082: if(dbg_fwrb_runs) err("fwrb_runfs_g4: %d bytes",bytes);
! 10083: #if FWRI
! 10084: fwri_uint4(fp,bytes);
! 10085: #else
! 10086: fwrite(&bytes,sizeof(bytes),1,fp);
! 10087: #endif
! 10088: /* copy contents in pipe to fp */
! 10089: fflush(pipe_fp[1]);
! 10090: for(bi=0;bi<bytes;bi++) {
! 10091: putc(och=getc(pipe_fp[0]),fp);
! 10092: #if dbg_fwrb_runs
! 10093: fprintf(stderr,"%02x",(unsigned char)och);
! 10094: #endif
! 10095: };
! 10096: if(dbg_fwrb_runs) fprintf(stderr,"\n");
! 10097: }
! 10098: #else
! 10099: fwrb_runfs_g4(fp,bxp,runs,ff)
! 10100: FILE *fp;
! 10101: Bbx *bxp;
! 10102: int runs;
! 10103: RunF *ff;
! 10104: { abort("fwrb_runfs_g4: unimplemented on Cray");
! 10105: }
! 10106: #endif
! 10107:
! 10108: #if CPU != CRAY
! 10109: /* Read a connected group of Runs in CCITT Group 4 format, into an array of RunFs.
! 10110: Return: 1 if normal & successful, 0 if EOF, and -1 if error.
! 10111: */
! 10112: int frdb_g4_runfs(fp,bxp,runs,ff)
! 10113: FILE *fp;
! 10114: Bbx *bxp; /* their bounding box, shrink-wrapped to fit exactly */
! 10115: int runs; /* expect exactly this number of runs */
! 10116: RunF *ff; /* space for `runs' RunFs */
! 10117: #define dbg_frdb_g4_runfs_detail F
! 10118: { RLE_Line *cl; /* current line */
! 10119: int wid,hgt; /* width,height of rectangular box of pixels */
! 10120: int y; /* height of current line */
! 10121: boolean bof;
! 10122: BITFILE *bf;
! 10123: static DST_table *tbl = NULL;
! 10124: int iri;
! 10125: RLE_Run *irp;
! 10126: int ori;
! 10127: RunF *orp;
! 10128: unsigned long bytes,g4_bytes;
! 10129: #if FRDI
! 10130: bytes=frdi_uint4(fp);
! 10131: #else
! 10132: fread(&bytes,sizeof(bytes),1,fp);
! 10133: #endif
! 10134: if(dbg_frdb_runs) err("frdb_g4_runfs: %d bytes",bytes);
! 10135: /* read FILE *fp as a sequence of bits */
! 10136: if((bf=bopen(fp,"r"))==NULL)
! 10137: abort("frdb_g4_runfs: can't open bitfile");
! 10138: if(tbl==NULL) {
! 10139: tbl=ccitt_table();
! 10140: if(dbg_frdb_g4_runfs_detail) ccitt_err_tbl(tbl);
! 10141: };
! 10142: wid=bbx_wid(bxp); hgt=bbx_hgt(bxp);
! 10143: y=0; bof=T; ori=0; orp=ff;
! 10144: while((y<hgt)&&(cl=g4_to_rlel(tbl,bf,bof,wid))!=NULL) {
! 10145: /* copy runs to RunF ff[] */
! 10146: for(iri=0,irp=cl->r; iri<cl->runs; iri++,irp++) {
! 10147: if(dbg_frdb_g4_runfs_detail)
! 10148: err("o%d i%d: y%d x[%d,%d]",
! 10149: ori,iri,y,irp->xs,irp->xe);
! 10150: if(ori<runs) {
! 10151: orp->y = y; orp->xs = irp->xs; orp->xe = irp->xe;
! 10152: orp++;
! 10153: }
! 10154: else err("frdb_g4_runfs: too many runs: ori%d >= runs%d",
! 10155: ori,runs);
! 10156: ori++;
! 10157: };
! 10158: y++; bof=F;
! 10159: };
! 10160: if(cl==NULL) {
! 10161: err("frdb_g4_runfs: unexpected EOF");
! 10162: return(0);
! 10163: };
! 10164: /* recover connectivity among runs, on the assumption that they
! 10165: are still in increasing lexicographic order on (y,xs) */
! 10166: fix_lag(orp-ff,(char *)ff,Runs_ff);
! 10167: if(ori!=runs) {
! 10168: err("frdb_g4_runfs: expected %d runs, but read %d",runs,ori);
! 10169: return(-1);
! 10170: };
! 10171: if((g4_bytes=bclose(bf))!=bytes) {
! 10172: err("frdb_g4_runfs: expected %d bytes, but read %d",
! 10173: bytes,g4_bytes);
! 10174: return(-1);
! 10175: };
! 10176: if(ferror(fp)) return(-errno); else return(1);
! 10177: }
! 10178: #else
! 10179: int frdb_g4_runfs(fp,bxp,runs,ff)
! 10180: FILE *fp;
! 10181: Bbx *bxp; /* exact bounding box, shrink-wrapped to fit */
! 10182: int runs; /* expect exactly this number of runs */
! 10183: RunF *ff; /* space for `runs' RunFs */
! 10184: { abort("frdb_g4_runfs: unimplemented on Cray");
! 10185: }
! 10186: #endif
! 10187:
! 10188: /* Write blob, etc to FILE *fp in binary format.
! 10189: If !(etc&IsBlob), then do nothing.
! 10190: else write Blob record and:
! 10191: If etc&IsRun, then also try to write Runs:
! 10192: If Blob.runs==0, write no runs.
! 10193: else
! 10194: if etc&Runs_g4, write in CCITT G4 format
! 10195: compact but needs large streams; may not port well;
! 10196: else write in Runs_ff format
! 10197: if blob is small enough, use compressed RunFS form on output.
! 10198:
! 10199: */
! 10200: fwrb_blob_etc(fp,bp,etc)
! 10201: FILE *fp;
! 10202: Blob *bp;
! 10203: Ident etc;
! 10204: { Ident sv_ident;
! 10205: int sv_runs;
! 10206: Run *rp;
! 10207: RunF rf;
! 10208: register RunF *rfp, *rfq;
! 10209: RunFS *rsp;
! 10210: #if FWRI
! 10211: RunFS rfs;
! 10212: #else
! 10213: static RunFS rfsa[256];
! 10214: #endif
! 10215: int ri;
! 10216: if(!(etc&IsBlob)) return;
! 10217:
! 10218: sv_ident = bp->ident;
! 10219: sv_runs = bp->runs;
! 10220: if(etc&IsRun) {
! 10221: /* decide which Runs_* bits should be set on output */
! 10222: bp->ident &= ~(Runs_f|Runs_ff|Runs_seek|Runs_g4);
! 10223: if(etc&Runs_g4) {
! 10224: bp->ident |= Runs_g4;
! 10225: }
! 10226: else { /* assume Runs_ff is wanted */
! 10227: bp->ident |= Runs_ff;
! 10228: };
! 10229: }
! 10230: else { bp->ident &= ~(IsRun|Runs_f|Runs_ff|Runs_seek|Runs_g4);
! 10231: bp->runs = 0;
! 10232: };
! 10233: fwrb_blob(fp,bp);
! 10234: bp->ident = sv_ident;
! 10235: bp->runs = sv_runs;
! 10236:
! 10237: if(bp->runs==0) return;
! 10238:
! 10239: if(etc&Runs_g4) {
! 10240: /* write CCITT Group 4 encoding for Runs */
! 10241: if(bp->ident&Runs_ff) {
! 10242: fwrb_runfs_g4(fp,&(bp->bx),bp->runs,bp->r.ff);
! 10243: }
! 10244: else abort("fwrb_blob_etc: etc&Runs_g4 but !(id&Runs_ff)");
! 10245: }
! 10246: else { /* Assume Runs_ff format is desired */
! 10247: if(bp->ident&Runs_f) {
! 10248: rp=bp->r.f;
! 10249: if(bp->ident&Blob_small) { /* use compressed Run records */
! 10250: if(blob_debug) err("small");
! 10251: /* can use small local static array */
! 10252: #if FWRI
! 10253: rsp= &rfs;
! 10254: #else
! 10255: rsp=rfsa;
! 10256: #endif
! 10257: while(rp!=NULL) {
! 10258: /* y, xs, xe will be relative to Blob.bx.a */
! 10259: rsp->y = rp->y - bp->bx.a.y;
! 10260: rsp->xs = rp->xs - bp->bx.a.x;
! 10261: rsp->xe = rp->xe - bp->bx.a.x;
! 10262: /* above,below connecting run indices are relative to
! 10263: the sequence no. of this run (ac>0 & bc>0) */
! 10264: if((rsp->ad = rp->ad)!=0)
! 10265: rsp->ac = rp->u.no - rp->ac->u.no;
! 10266: else rsp->ac = 0;
! 10267: if((rsp->bd = rp->bd)!=0)
! 10268: rsp->bc = rp->bc->u.no - rp->u.no;
! 10269: else rsp->bc = 0;
! 10270: if(blob_debug) err_runfs(" ",rsp);
! 10271: rp=rp->n;
! 10272: #if FWRI
! 10273: fwri_RunFS(fp,rsp);
! 10274: #else
! 10275: rsp++;
! 10276: #endif
! 10277: };
! 10278: #if !FWRI
! 10279: if(fwrite(rfsa,sizeof(RunFS),bp->runs,fp)!=bp->runs)
! 10280: abort("fwrb_blob_etc: can't fwrite RunFS[%d]",bp->runs);
! 10281: if(dbg_fwrb_runs)
! 10282: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunFS));
! 10283: #endif
! 10284: }
! 10285: else { if(blob_debug) err("large");
! 10286: while(rp!=NULL) {
! 10287: /* y, xs, xe will be relative to Blob.bx.a */
! 10288: rf.y = rp->y - bp->bx.a.y;
! 10289: rf.xs = rp->xs - bp->bx.a.x;
! 10290: rf.xe = rp->xe - bp->bx.a.x;
! 10291: /* above,below connecting run indices are relative to
! 10292: the sequence no. of this run (ac>0 & bc>0) */
! 10293: if((rf.ad = rp->ad)!=0)
! 10294: rf.ac = rp->u.no - rp->ac->u.no;
! 10295: else rf.ac = 0;
! 10296: if((rf.bd = rp->bd)!=0)
! 10297: rf.bc = rp->bc->u.no - rp->u.no;
! 10298: else rf.bc = 0;
! 10299: if(blob_debug) err_runf(" ",&rf);
! 10300:
! 10301: /* since there may be many, won't use a local array */
! 10302: #if FWRI
! 10303: fwri_RunF(fp,&rf);
! 10304: #else
! 10305: if(fwrite(&rf,sizeof(RunF),1,fp)!=1)
! 10306: abort("fwrb_blob_etc: can't fwrite RunF");
! 10307: #endif
! 10308: rp=rp->n;
! 10309: };
! 10310: if(dbg_fwrb_runs)
! 10311: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunF));
! 10312: };
! 10313: }
! 10314: else if(bp->ident&Runs_ff) {
! 10315: if(bp->ident&Blob_small) { /* use compressed Run records */
! 10316: if(blob_debug) err("small");
! 10317: /* can use small local static array */
! 10318: #if FWRI
! 10319: rsp= &rfs;
! 10320: #else
! 10321: rsp=rfsa;
! 10322: #endif
! 10323: for(rfp=bp->r.ff,ri=0; ri<bp->runs; rfp++,ri++) {
! 10324: rsp->y = rfp->y;
! 10325: rsp->xs = rfp->xs;
! 10326: rsp->xe = rfp->xe;
! 10327: rsp->ad = rfp->ad;
! 10328: rsp->bd = rfp->bd;
! 10329: rsp->ac = rfp->ac;
! 10330: rsp->bc = rfp->bc;
! 10331: #if FWRI
! 10332: fwri_RunFS(fp,rsp);
! 10333: #else
! 10334: rsp++;
! 10335: #endif
! 10336: };
! 10337: #if !FWRI
! 10338: if(fwrite(rfsa,sizeof(RunFS),bp->runs,fp)!=bp->runs)
! 10339: abort("fwrb_blob_etc: can't fwrite RunFS[%d]",bp->runs);
! 10340: if(dbg_fwrb_runs)
! 10341: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunFS));
! 10342: #endif
! 10343: }
! 10344: else { if(blob_debug) err("large");
! 10345: #if FWRI
! 10346: for(rfq=(rfp=bp->r.ff)+bp->runs; rfp<rfq; rfp++) {
! 10347: fwri_RunF(fp,rfp);
! 10348: };
! 10349:
! 10350: #else
! 10351: if(fwrite(bp->r.ff,sizeof(RunF),bp->runs,fp)!=bp->runs)
! 10352: abort("fwrb_blob_etc: can't fwrite RunF[%d]",bp->runs);
! 10353: if(dbg_fwrb_runs)
! 10354: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunF));
! 10355: #endif
! 10356: };
! 10357: };
! 10358: };
! 10359: }
! 10360:
! 10361: /* Read a given Blob's RunF's (binary) from FILE *fp; return F on EOF.
! 10362: If bp->runs<=max, read the RunF's into bp->r.ff, and set Runs_ff bit.
! 10363: otherwise ignore them all and set bp->r.ff==NULL. */
! 10364: int frdb_runfs(fp,bp,max)
! 10365: FILE *fp;
! 10366: Blob *bp; /* *bp's fields already set up */
! 10367: int max; /* maximum no. RunF records expected */
! 10368: { register RunFS *rsp,*rsq;
! 10369: static RunFS rfsa[256];
! 10370: register RunF *rfp,*rfq;
! 10371: if(bp->r.ff!=NULL && bp->runs <= max) {
! 10372: bp->ident |= Runs_ff; bp->ident &= ~(Runs_f|Runs_seek);
! 10373: if(bp->ident&Blob_small) {
! 10374: if(blob_debug) err("small");
! 10375: #if FRDI
! 10376: for(rsq=(rsp=rfsa)+bp->runs; rsp<rsq; rsp++) {
! 10377: frdi_RunFS(fp,rsp);
! 10378: };
! 10379: #else
! 10380: if(fread(rfsa,sizeof(RunFS),bp->runs,fp) < bp->runs)
! 10381: return(0);
! 10382: #endif
! 10383: /* copy compressed RunFS's into RunF's */
! 10384: for(rsq=(rsp=rfsa)+bp->runs,rfp=bp->r.ff;
! 10385: rsp<rsq;
! 10386: rsp++,rfp++) {
! 10387: /* beware sign extension from unsigned chars */
! 10388: if(blob_debug) err_runfs(" ",rsp);
! 10389: rfp->y = 0377&rsp->y;
! 10390: rfp->xs = 0377&rsp->xs;
! 10391: rfp->xe = 0377&rsp->xe;
! 10392: rfp->ad = 0377&rsp->ad;
! 10393: rfp->bd = 0377&rsp->bd;
! 10394: rfp->ac = 0377&rsp->ac;
! 10395: rfp->bc = 0377&rsp->bc;
! 10396: };
! 10397: }
! 10398: else { if(blob_debug) err("large");
! 10399: #if FRDI
! 10400: for(rfq=(rfp=bp->r.ff)+bp->runs; rfp<rfq; rfp++)
! 10401: frdi_RunF(fp,rfp);
! 10402: #else
! 10403: if(fread(bp->r.ff,sizeof(RunF),bp->runs,fp) != bp->runs)
! 10404: return(F);
! 10405: #endif
! 10406: };
! 10407: }
! 10408: else { bp->ident &= ~(Runs_ff|Runs_f);
! 10409: bp->ident |= Runs_seek;
! 10410: bp->r.seek=ftell(fp);
! 10411: /* skip past excessive no. of runs */
! 10412: /** What if FRDI?? **/
! 10413: if(bp->ident&Blob_small)
! 10414: fseek(fp,(long)((bp->runs)*sizeof(RunFS)),1);
! 10415: else
! 10416: fseek(fp,(long)((bp->runs)*sizeof(RunF)),1);
! 10417: };
! 10418: if(ferror(fp)) return(-errno); else return(1);
! 10419: }
! 10420:
! 10421: #if FRDI
! 10422: /* read a Blob record (only) into *p */
! 10423: int frdb_blob(f,p)
! 10424: FILE *f;
! 10425: Blob *p;
! 10426: { int bdy_mny;
! 10427: *p = empty_Blob;
! 10428: if(feof(f))
! 10429: return(0);
! 10430: p->ident=frdi_Ident(f);
! 10431: /* p->no=frdi_Seq(f); */
! 10432: frdi_Bbx(f,&(p->bx));
! 10433: p->area=frdi_uint4(f);
! 10434: p->per=frdi_uint4(f);
! 10435: /* don't read .n */
! 10436: p->m=frdi_Merit(f);
! 10437: p->runs=frdi_uint3(f);
! 10438: if((bdy_mny=frdi_uint2(f))>0) {
! 10439: p->bdsp = alloc_bdys();
! 10440: p->bdsp->mny = bdy_mny;
! 10441: };
! 10442: #if dbg_frdb
! 10443: if((!(p->ident&IsBlob))||(p->ident&(IsALL&(~IsBlob))))
! 10444: err("frdb_blob: %s",blob_toa(p));
! 10445: #endif
! 10446: #if dbg_frdb_toa
! 10447: err("frdb_blob: %s",blob_toa(p));
! 10448: #endif
! 10449: if(ferror(f))
! 10450: return(-errno);
! 10451: else return(1);
! 10452: }
! 10453: #else
! 10454: /* read a Blob record (only) into *bp; return F if EOF */
! 10455: int frdb_blob(fp,bp)
! 10456: FILE *fp;
! 10457: Blob *bp;
! 10458: { BlobF bf;
! 10459: if(fread(&bf,sizeof(BlobF),1,fp)!=1) return(0);
! 10460: if(blob_debug) err_blobf("bf",&bf);
! 10461: bp->ident=bf.ident;
! 10462: bp->no = 0;
! 10463: bp->bx=bf.bx;
! 10464: bp->area=bf.area;
! 10465: /*bp->per=bf.per;*/
! 10466: bp->runs=bf.runs;
! 10467: /*bp->bdys=bf.bdys;*/
! 10468: bp->n = NULL;
! 10469: bp->r.f = NULL;
! 10470: bp->bdsp = NULL;
! 10471: #if dbg_frdb
! 10472: if((!(bp->ident&IsBlob))||(bp->ident&(IsALL&(~IsBlob))))
! 10473: err("frdb_blob: %s",blob_toa(bp));
! 10474: #endif
! 10475: #if dbg_frdb_toa
! 10476: err("frdb_blob: %s",blob_toa(bp));
! 10477: #endif
! 10478: if(ferror(fp)) return(-errno); else return(1);
! 10479: }
! 10480: #endif
! 10481:
! 10482: err_blob(s,bp)
! 10483: char *s;
! 10484: Blob *bp;
! 10485: { fprintf(stderr,"%s ",s);
! 10486: if(bp==NULL) fprintf(stderr,"Blob NULL.\n");
! 10487: else fprintf(stderr,
! 10488: "Blob %d: x[%d,%d],y[%d,%d] ar%d ft%s r(#%d f%d)\n",
! 10489: bp->no,bp->bx.a.x,bp->bx.b.x,bp->bx.a.y,bp->bx.b.y,
! 10490: bp->area,ident_toa(bp->ident),bp->runs,rp_tod(bp->r.f));
! 10491: }
! 10492:
! 10493: err_blob_runs(s,bp)
! 10494: char *s;
! 10495: Blob *bp;
! 10496: { Run *crp;
! 10497: char cs[20];
! 10498: fprintf(stderr,"%s ",s);
! 10499: err_blob(s,bp);
! 10500: if(bp!=NULL&&bp->runs>0&&bp->r.f!=NULL) {
! 10501: sprintf(cs,"%*s",strlen(s)+2," ");
! 10502: for(crp=bp->r.f; crp!=NULL; crp=crp->n) err_run(cs,crp);
! 10503: };
! 10504: }
! 10505:
! 10506: err_blob_runfs(s,bp)
! 10507: char *s;
! 10508: Blob *bp;
! 10509: { RunF *crp;
! 10510: int ri;
! 10511: char cs[20];
! 10512: fprintf(stderr,"%s ",s);
! 10513: err_blob_briefly("",bp);
! 10514: if(bp!=NULL&&bp->runs>0&&bp->r.ff!=NULL) {
! 10515: sprintf(cs,"%*s",strlen(s)+2," ");
! 10516: for(crp=bp->r.ff,ri=0; ri<bp->runs; crp++,ri++) err_runf(cs,crp);
! 10517: };
! 10518: }
! 10519:
! 10520: err_blobf(s,bp)
! 10521: char *s;
! 10522: BlobF *bp;
! 10523: { Run *crp;
! 10524: char cs[20];
! 10525: fprintf(stderr,"%s ",s);
! 10526: if(bp==NULL) fprintf(stderr,"BlobF NULL.\n");
! 10527: else fprintf(stderr,
! 10528: "BlobF: x[%d,%d],y[%d,%d] ar%d ft%s #r%d\n",
! 10529: bp->bx.a.x,bp->bx.b.x,bp->bx.a.y,bp->bx.b.y,
! 10530: bp->area,ident_toa(bp->ident),bp->runs);
! 10531: }
! 10532:
! 10533: err_blob_briefly(s,bp)
! 10534: char s[];
! 10535: Blob *bp;
! 10536: { Run *crp;
! 10537: if(bp==NULL) err("%s Blob NULL.",s);
! 10538: else { fprintf(stderr,
! 10539: "%s Blob #%d: bx(%d,%d),(%d,%d) ar%d f%s runs%d ",
! 10540: s,
! 10541: bp->no,
! 10542: bp->bx.a.x,bp->bx.a.y,bp->bx.b.x,bp->bx.b.y,
! 10543: bp->area,
! 10544: ident_toa(bp->ident),
! 10545: bp->runs);
! 10546: fprintf(stderr,"\n");
! 10547: };
! 10548: }
! 10549:
! 10550: err_blob_stats()
! 10551: { err("Blob stats: %d now, %d total, %d hi-water\n",
! 10552: blob_max-blob_fr_mny,hi_blob_no+1,blob_hi);
! 10553: }
! 10554:
! 10555: /* write blob list starting at fi */
! 10556: fwrb_blobl_etc(fp,mny,fi,etc)
! 10557: FILE *fp;
! 10558: int mny;
! 10559: Blob *fi;
! 10560: Ident etc;
! 10561: { int bi;
! 10562: Blob *bp;
! 10563: if(mny>0) for(bi=0,bp=fi; bi<mny; bi++,bp=bp->n) {
! 10564: if(bp!=NULL) fwrb_blob_etc(fp,bp,etc);
! 10565: else { err("fwrb_blobl_etc: bmny==%d but %dth (Blob *) is NULL",
! 10566: mny,bi);
! 10567: break;
! 10568: };
! 10569: };
! 10570: }
! 10571:
! 10572: fwrb_blobs_etc(fp,bs,etc)
! 10573: FILE *fp;
! 10574: Blobs bs;
! 10575: Ident etc;
! 10576: { register Blob *bp,**bpp;
! 10577: if(bs.mny==0) return;
! 10578: for(bp= *(bpp=bs.bpa); bp!=NULL; bp= *(++bpp))
! 10579: fwrb_blob_etc(fp,bp,etc);
! 10580: }
! 10581:
! 10582: /* read a set of blobs, and their parts */
! 10583: frdb_blobs_etc(fp,bsp,etc)
! 10584: FILE *fp;
! 10585: Blobs *bsp;
! 10586: Ident etc; /* read only the parts indicated */
! 10587: { int bi;
! 10588: register Blob *bp,**bpp;
! 10589: if(bsp->mny<=0) {
! 10590: *bsp = empty_Blobs;
! 10591: return(1);
! 10592: };
! 10593:
! 10594: if((bpp=bsp->bpa=(Blob **)malloc((bsp->mny+1)*sizeof(Blob *)))==NULL)
! 10595: abort("frdb_blobs_etc: can't alloc Blobs.bpa[%d]",bsp->mny+1);
! 10596: for(bi=0; bi<bsp->mny; bi++) {
! 10597: *(bpp++) = bp = alloc_blob();
! 10598: if(!frdb_blob_etc(fp,bp,etc))
! 10599: abort("frdb_blobs_etc: unexpected EOF");
! 10600: };
! 10601: *bpp = NULL;
! 10602: if(ferror(fp)) return(-errno); else return(1);
! 10603: }
! 10604:
! 10605: /* Read a blob record into *bp, and then read its parts as specified by etc.
! 10606: If there aren't any runs, return normally.
! 10607: If etc&IsRun is false, then set Runs_seek and proceed as described below.
! 10608: If etc&Runs_ff, then the contents of r.ff is examined:
! 10609: if NULL, then space is allocated here for `runs' RunF's;
! 10610: if non-NULL, then on the assumption that it points to space for
! 10611: at least `runs' many, they are read into it.
! 10612: If etc&Runs_seek, then the ftell value is placed in r.seek,
! 10613: and the runs are simply skipped over.
! 10614: The Runs_f (list) option is unimplemented.
! 10615: The Blob is marked with the appropriate Runs_X bit.
! 10616: Return: 1 if normal & successful, 0 if EOF, and -1 if error.
! 10617: */
! 10618: int frdb_blob_etc(fp,bp,etc)
! 10619: FILE *fp;
! 10620: Blob *bp;
! 10621: Ident etc;
! 10622: { int stat;
! 10623: if((stat=frdb_blob(fp,bp))!=1)
! 10624: return(stat);
! 10625: if(bp->runs<=0) {
! 10626: bp->runs = 0;
! 10627: bp->r.ff = NULL;
! 10628: bp->ident &= ~(Runs_f|Runs_seek|Runs_g4);
! 10629: bp->ident |= Runs_ff;
! 10630: return(1);
! 10631: };
! 10632:
! 10633: if(!(etc&IsRun)) {
! 10634: etc |= IsRun|Runs_seek;
! 10635: etc &= ~(Runs_f|Runs_ff|Runs_g4);
! 10636: };
! 10637: if (!(etc&(Runs_f|Runs_ff|Runs_g4|Runs_seek)) || etc&Runs_ff) {
! 10638: /* Want to deliver Runs in Runf ff[] format */
! 10639: if(bp->r.ff==NULL) {
! 10640: if( (bp->r.ff=
! 10641: (RunF *)malloc(bp->runs*sizeof(RunF)))==NULL)
! 10642: abort("frdb_blob_etc: can't alloc r.ff[%d]",bp->runs);
! 10643: };
! 10644: if(bp->ident&Runs_g4) {
! 10645: /* Runs are in CCITT Group 4 format */
! 10646: stat=frdb_g4_runfs(fp,&(bp->bx),bp->runs,bp->r.ff);
! 10647: }
! 10648: else { /* Runs are in RunF or RunFS format */
! 10649: stat=frdb_runfs(fp,bp,bp->runs);
! 10650: };
! 10651: bp->ident |= Runs_ff; bp->ident &= ~(Runs_f|Runs_seek|Runs_g4);
! 10652: return(stat);
! 10653: }
! 10654: else if(etc&Runs_seek) {
! 10655: bp->ident |= Runs_seek; bp->ident &= ~(Runs_ff|Runs_f);
! 10656: bp->r.seek=ftell(fp); /* save seek addr */
! 10657: /* skip past runs */
! 10658: if(bp->ident&Blob_small)
! 10659: fseek(fp,(long)((bp->runs)*sizeof(RunFS)),1);
! 10660: else fseek(fp,(long)((bp->runs)*sizeof(RunF)),1);
! 10661: }
! 10662: else /* (etc&Runs_f) || (etc&Runs_g4) */ {
! 10663: abort("frdb_blob_etc: Runs_f & Runs_g4 etc option unimplemented");
! 10664: };
! 10665: if(ferror(fp)) return(-errno); else return(1);
! 10666: }
! 10667:
! 10668: /* read a number of blobs, and their parts, into linked-list (mny, *fi);
! 10669: return T iff not EOF */
! 10670: boolean frdb_blobl_etc(fp,bmny,fip,etc)
! 10671: FILE *fp;
! 10672: int bmny;
! 10673: Blob **fip;
! 10674: Ident etc;
! 10675: { int bi;
! 10676: register Blob *bp,**bpp;
! 10677: RunF *rp;
! 10678: int stat;
! 10679: if(bmny<=0) return(1);
! 10680: bi=0; bpp=fip;
! 10681: do { bp=alloc_blob();
! 10682: if((stat=frdb_blob_etc(fp,bp,etc))!=1) return(stat);
! 10683: *bpp=bp; bpp= &(bp->n);
! 10684: }
! 10685: while((++bi)<bmny);
! 10686: *bpp=NULL;
! 10687: if(ferror(fp)) return(-errno); else return(1);
! 10688: }
! 10689:
! 10690: char *interp_toa(ip)
! 10691: Interp *ip;
! 10692: { static char s[80];
! 10693: char ms[3],shs[3],szs[3],hts[3],prs[3];
! 10694: strcpy(ms,merit_toa(ip->m));
! 10695: strcpy(shs,merit_toa(ip->mshap));
! 10696: strcpy(szs,merit_toa(ip->msize));
! 10697: strcpy(hts,merit_toa(ip->mbhgt));
! 10698: strcpy(prs,merit_toa(ip->p));
! 10699: sprintf(s,"%s %s sz%s ba%d m%s (sh%s sz%s ht%s) p%s",
! 10700: ident_toa(ip->ident),
! 10701: #if CPU!=CRAY
! 10702: classid_toa(&(ip->ci)),
! 10703: #else
! 10704: ip->ci.c,
! 10705: #endif
! 10706: pts_toa(ip->size),
! 10707: ip->basl,
! 10708: ms,shs,szs,hts,prs);
! 10709: return(s);
! 10710: }
! 10711:
! 10712: frdb_interpl_etc(fp,ilp,etc)
! 10713: FILE *fp;
! 10714: Interpl *ilp;
! 10715: Ident etc;
! 10716: { int ii,stat;
! 10717: Interp *ip,*pp;
! 10718: if(ilp->mny<=0) {
! 10719: *ilp = empty_Interpl;
! 10720: return(1);
! 10721: };
! 10722:
! 10723: for(ii=0; ii<ilp->mny; ii++) {
! 10724: ip=alloc_interp();
! 10725: if(ii==0) ilp->fi = ip;
! 10726: else pp->n = ip;
! 10727: if((stat=frdb_interp(fp,ip))!=1) return(stat);
! 10728: pp=ip;
! 10729: };
! 10730: ip->n = NULL;
! 10731: if(ferror(fp)) return(-errno); else return(1);
! 10732: }
! 10733:
! 10734: #if FRDI
! 10735: int frdb_interp(f,p)
! 10736: FILE *f;
! 10737: Interp *p;
! 10738: { int stat;
! 10739: *p = empty_Interp;
! 10740: if(feof(f))
! 10741: return(0);
! 10742: p->ident=frdi_Ident(f);
! 10743: frdi_ClassId(f,&(p->ci));
! 10744: p->mshap=frdi_Merit(f);
! 10745: p->size=frdi_Pts(f);
! 10746: p->msize=frdi_Merit(f);
! 10747: p->basl=frdi_Scoor(f);
! 10748: p->mbhgt=frdi_Merit(f);
! 10749: p->m=frdi_Merit(f);
! 10750: p->p=frdi_Prob(f);
! 10751: #if dbg_frdb
! 10752: if((!(p->ident&IsInterp))||(p->ident&(IsALL&(~IsInterp))))
! 10753: err("frdb_interp: %s",interp_toa(p));
! 10754: #endif
! 10755: if(ferror(f)) return(-errno); else return(1);
! 10756: }
! 10757: #else
! 10758: int frdb_interp(fp,ip)
! 10759: FILE *fp;
! 10760: Interp *ip;
! 10761: { InterpF inf;
! 10762: int stat;
! 10763: if((stat=fread(&inf,sizeof(InterpF),1,fp))!=1) {
! 10764: err("can't fread InterpF, status %d",stat);
! 10765: return(stat);
! 10766: };
! 10767: *ip = empty_Interp;
! 10768: ip->ident = inf.ident;
! 10769: ip->ci = inf.ci;
! 10770: ip->clp = NULL;
! 10771: ip->clsp = NULL;
! 10772: ip->mshap = inf.mshap;
! 10773: ip->size = inf.size;
! 10774: ip->msize = inf.msize;
! 10775: ip->basl = inf.basl;
! 10776: ip->mbhgt = inf.mbhgt;
! 10777: ip->m = inf.m;
! 10778: #if dbg_frdb
! 10779: if((!(ip->ident&IsInterp))||(ip->ident&(IsALL&(~IsInterp))))
! 10780: err("frdb_interp: %s",interp_toa(ip));
! 10781: #endif
! 10782: if(ferror(fp)) return(-errno); else return(1);
! 10783: }
! 10784: #endif
! 10785:
! 10786: free_interpl(ilp)
! 10787: Interpl *ilp;
! 10788: { int ii;
! 10789: Interp *ip,*np;
! 10790: if(ilp->mny>0) {
! 10791: for(ip=ilp->fi; ip!=NULL; ip=np) { np=ip->n; free_interp(ip); }
! 10792: ilp->mny=0;
! 10793: };
! 10794: ilp->fi=NULL;
! 10795: };
! 10796:
! 10797: fwrb_interpl_etc(fp,is,etc)
! 10798: FILE *fp;
! 10799: Interpl is;
! 10800: Ident etc;
! 10801: { Interp *ip;
! 10802: int ii;
! 10803: if(is.mny>0) for(ii=0,ip=is.fi; ii<is.mny; ii++,ip=ip->n)
! 10804: fwrb_interp_etc(fp,ip,etc);
! 10805: }
! 10806:
! 10807: /* remove this Interp from the Interp-list */
! 10808: remove_interpl(ip,ilp)
! 10809: Interp *ip;
! 10810: Interpl *ilp;
! 10811: { Interp *rp,*pp;
! 10812: if(ilp->mny==1) { /* frequent case */
! 10813: ilp->fi=NULL; ilp->mny=0;
! 10814: }
! 10815: else if(ilp->mny>1){
! 10816: pp=NULL;
! 10817: for(rp=ilp->fi; rp!=ip&&rp!=NULL; pp=rp,rp=rp->n) ;
! 10818: if(rp!=NULL) { /* remove from list */
! 10819: if(pp==NULL) ilp->fi=ip->n;
! 10820: else pp->n=ip->n;
! 10821: ilp->mny--;
! 10822: }
! 10823: else err("remove_interpl: can't - not found");
! 10824: }
! 10825: else err("remove_interpl: can't - Interpl empty");
! 10826: }
! 10827:
! 10828: /* prepend this Interp to the Interp-list */
! 10829: prepend_interpl(ip,ilp)
! 10830: Interp *ip;
! 10831: Interpl *ilp;
! 10832: { Interp *rp,*pp;
! 10833: ip->n = ilp->fi;
! 10834: ilp->fi = ip;
! 10835: ilp->mny++;
! 10836: }
! 10837:
! 10838: fwrb_interp_etc(fp,ip,etc)
! 10839: FILE *fp;
! 10840: Interp *ip;
! 10841: Ident etc;
! 10842: { fwrb_interp(fp,ip);
! 10843: }
! 10844:
! 10845: #if FWRI
! 10846: fwrb_interp(f,p)
! 10847: FILE *f;
! 10848: Interp *p;
! 10849: { InterpF inf;
! 10850: int stat;
! 10851: #if dbg_fwrb
! 10852: if((!(p->ident&IsInterp))||(p->ident&(IsALL&(~IsInterp))))
! 10853: err("fwrb_interp: %s",interp_toa(p));
! 10854: #endif
! 10855: fwri_Ident(f,p->ident);
! 10856: fwri_ClassId(f,&(p->ci));
! 10857: fwri_Merit(f,p->mshap);
! 10858: fwri_Pts(f,p->size);
! 10859: fwri_Merit(f,p->msize);
! 10860: fwri_Scoor(f,p->basl);
! 10861: fwri_Merit(f,p->mbhgt);
! 10862: fwri_Merit(f,p->m);
! 10863: fwri_Prob(f,p->p);
! 10864: #if dbg_fwrb_toa
! 10865: err("fwrb_interp: %s",interp_toa(p));
! 10866: #endif
! 10867: }
! 10868: #else
! 10869: fwrb_interp(fp,ip)
! 10870: FILE *fp;
! 10871: Interp *ip;
! 10872: { InterpF inf;
! 10873: int stat;
! 10874: #if dbg_fwrb
! 10875: if((!(ip->ident&IsInterp))||(ip->ident&(IsALL&(~IsInterp))))
! 10876: err("fwrb_interp: %s",interp_toa(ip));
! 10877: #endif
! 10878: memset(&inf,'\0',sizeof(inf));
! 10879: inf.ident = ip->ident;
! 10880: inf.ci = ip->ci;
! 10881: inf.mshap = ip->mshap;
! 10882: inf.size = ip->size;
! 10883: inf.msize = ip->msize;
! 10884: inf.basl = ip->basl;
! 10885: inf.mbhgt = ip->mbhgt;
! 10886: inf.m = ip->m;
! 10887: if((stat=fwrite(&inf,sizeof(InterpF),1,fp))!=1)
! 10888: abort("fwrb_interp: can't fwrite, status %d",stat);
! 10889: #if dbg_fwrb_toa
! 10890: err("fwrb_interp: %s",interp_toa(ip));
! 10891: #endif
! 10892: }
! 10893: #endif
! 10894:
! 10895: /** Run handling:
! 10896: alloc_run_pool -create pool of free run records
! 10897: free_run_pool - free entire pool
! 10898: alloc_run - allocate a new run from pool
! 10899: free_run - free a specified run (into pool)
! 10900: err_run - print Run (ascii) to stderr
! 10901: err_runb - print Run (ascii) to stderr (after added to blob set)
! 10902: err_runf - print RunF (ascii) to stderr (after added to blob set)
! 10903: err_runfs - print RunFS (ascii) to stderr (after added to blob set)
! 10904: err_run_stats - report statistics to stderr
! 10905: **/
! 10906:
! 10907: /* RunPool functions: variable-size pool, speed-optimized alloc/free */
! 10908:
! 10909: /* Initialize pool of Runs with increment `incr' (return F if can't allocate) */
! 10910: boolean alloc_run_pool(incr,dbg)
! 10911: int incr;
! 10912: boolean dbg; /* trace actions on Runs */
! 10913: { register Run *crp, *prp;
! 10914: register int i;
! 10915: _RunPool.incr = incr;
! 10916: _RunPool.pools = 1;
! 10917: if((_RunPool.pool=(Run **)malloc(_RunPool.pools*sizeof(Run *)))==NULL)
! 10918: return(F);
! 10919: if((_RunPool.pool[_RunPool.pools-1] =
! 10920: (Run *)malloc(_RunPool.incr*sizeof(Run)))==NULL) {
! 10921: free(_RunPool.pool);
! 10922: return(F);
! 10923: };
! 10924: _RunPool.next = 0;
! 10925: _RunPool.free = NULL;
! 10926: #if STATS
! 10927: _RunPool.total = 0;
! 10928: #endif
! 10929: _RunPool.dbg = dbg;
! 10930: if(_RunPool.dbg) err("alloc_run_pool: incr%d",_RunPool.incr);
! 10931: return(T);
! 10932: }
! 10933:
! 10934: free_run_pool()
! 10935: { register int i;
! 10936: for(i=0; i<_RunPool.pools; i++) free(_RunPool.pool[i]);
! 10937: free(_RunPool.pool);
! 10938: }
! 10939:
! 10940: /* The ``hard'' case of allocating runs from RunPool: can't be inline */
! 10941: Run *hard_alloc_run()
! 10942: { _RunPool.pools++;
! 10943: if((_RunPool.pool=
! 10944: (Run **)realloc(_RunPool.pool,_RunPool.pools*sizeof(Run *)))==NULL)
! 10945: abort("alloc_Run: can't realloc");
! 10946: if((_RunPool.cur=_RunPool.pool[_RunPool.pools-1] =
! 10947: (Run *)malloc(_RunPool.incr*sizeof(Run)))==NULL)
! 10948: abort("alloc_Run: can't malloc");
! 10949: _RunPool.next=1;
! 10950: *(_RunPool.cur) = empty_Run;
! 10951: return(_RunPool.cur);
! 10952: }
! 10953:
! 10954: int rp_tod(rp)
! 10955: Run *rp;
! 10956: { return((int)rp);
! 10957: }
! 10958:
! 10959: char *runf_toa(rp)
! 10960: RunF *rp;
! 10961: { static char s[80];
! 10962: char s1[80];
! 10963: strcpy(s,"RunF ");
! 10964: if(rp==NULL) strcat(s,"NULL");
! 10965: else { sprintf(s1,
! 10966: "y%d,x[%d,%d] lag(ad%d,bd%d ac%d,bc%d)",
! 10967: rp->y,rp->xs,rp->xe,
! 10968: rp->ad,rp->bd, rp->ac,rp->bc );
! 10969: strcat(s,s1);
! 10970: };
! 10971: return(s);
! 10972: }
! 10973:
! 10974: char *runfs_toa(rp)
! 10975: RunFS *rp;
! 10976: { static char s[80];
! 10977: char s1[80];
! 10978: strcpy(s,"RunFS ");
! 10979: if(rp==NULL) strcat(s,"NULL");
! 10980: else { sprintf(s1,
! 10981: "y%d,x[%d,%d] lag(ad%d,bd%d ac%d,bc%d)",
! 10982: rp->y,rp->xs,rp->xe,
! 10983: rp->ad,rp->bd, rp->ac,rp->bc );
! 10984: strcat(s,s1);
! 10985: };
! 10986: return(s);
! 10987: }
! 10988:
! 10989: err_run(s,rp)
! 10990: char *s;
! 10991: Run *rp;
! 10992: { fprintf(stderr,"%s ",s);
! 10993: if(rp==NULL) fprintf(stderr,"Run NULL.\n");
! 10994: else fprintf(stderr,
! 10995: "Run %d: y%d,x[%d,%d] l(n%d) t(o%x ad%d,bd%d ac%d,bc%d)\n",
! 10996: rp_tod(rp), rp->y,rp->xs,rp->xe,
! 10997: rp_tod(rp->n),
! 10998: #if CPU!=CRAY
! 10999: (int)rp->u.o,
! 11000: #else
! 11001: 0,
! 11002: #endif
! 11003: rp->ad,rp->bd,
! 11004: rp_tod(rp->ac),
! 11005: rp_tod(rp->bc) );
! 11006: }
! 11007:
! 11008: /* print Run after it has been added to Blob set */
! 11009: err_runb(s,rp)
! 11010: char *s;
! 11011: Run *rp;
! 11012: { fprintf(stderr,"%s ",s);
! 11013: if(rp==NULL) fprintf(stderr,"Run NULL.\n");
! 11014: else fprintf(stderr,
! 11015: "Run %d: y%d,x[%d,%d] l(n%d) t(no%d ad%d,bd%d ac%d,bc%d)\n",
! 11016: rp_tod(rp), rp->y,rp->xs,rp->xe,
! 11017: rp_tod(rp->n),
! 11018: rp->u.no, rp->ad,rp->bd, rp_tod(rp->ac),rp_tod(rp->bc) );
! 11019: }
! 11020:
! 11021: err_runf(s,rp)
! 11022: char *s;
! 11023: RunF *rp;
! 11024: { fprintf(stderr,"%s ",s);
! 11025: if(rp==NULL) fprintf(stderr,"RunF NULL.\n");
! 11026: else fprintf(stderr,
! 11027: "RunF: y%d,x[%d,%d] t(ad%d,bd%d ac%d,bc%d)\n",
! 11028: rp->y,rp->xs,rp->xe,
! 11029: rp->ad,rp->bd, rp->ac,rp->bc );
! 11030: }
! 11031:
! 11032: err_runfs(s,rp)
! 11033: char *s;
! 11034: RunFS *rp;
! 11035: { RunF rf;
! 11036: rf.y = 0377&rp->y;
! 11037: rf.xs = 0377&rp->xs;
! 11038: rf.xe = 0377&rp->xe;
! 11039: rf.ad = 0377&rp->ad;
! 11040: rf.bd = 0377&rp->bd;
! 11041: rf.ac = 0377&rp->ac;
! 11042: rf.bc = 0377&rp->bc;
! 11043: err_runf(s,&rf);
! 11044: }
! 11045:
! 11046: int runs_of_blob(p,ra,max)
! 11047: Blob *p;
! 11048: RLE_Yrun *ra;
! 11049: int max;
! 11050: { int runs,ri;
! 11051: RunF *rfp;
! 11052: runs = p->runs;
! 11053: if(runs>max) {
! 11054: err("runs_of_blob: max exceeded - skip this blob");
! 11055: runs = 0;
! 11056: }
! 11057: else if(runs>0) {
! 11058: if(p->ident&Runs_ff) {
! 11059: for(ri=0,rfp=p->r.ff; ri<runs; ri++,rfp++) {
! 11060: ra->y = p->bx.a.y + rfp->y;
! 11061: ra->xs = p->bx.a.x + rfp->xs;
! 11062: ra->xe = p->bx.a.x + rfp->xe;
! 11063: ra++;
! 11064: };
! 11065: }
! 11066: else { err("runs_of_blob: handle only Runs_ff - skip this blob");
! 11067: runs = 0;
! 11068: };
! 11069: };
! 11070: return(runs);
! 11071: }
! 11072:
! 11073: int no_runs_of_blobl(p)
! 11074: Blobl *p;
! 11075: { int runs;
! 11076: Blob *pp;
! 11077: runs = 0;
! 11078: if(p->mny>0) for(pp=p->fi; pp!=NULL; pp=pp->n) runs += pp->runs;
! 11079: return(runs);
! 11080: }
! 11081:
! 11082: int runs_of_blobl(p,ra,max)
! 11083: Blobl *p;
! 11084: RLE_Yrun *ra;
! 11085: int max;
! 11086: { int runs;
! 11087: Blob *pp;
! 11088: runs = 0;
! 11089: if(p->mny>0) for(pp=p->fi; pp!=NULL; pp=pp->n)
! 11090: runs += runs_of_blob(pp,ra+runs,max-runs);
! 11091: return(runs);
! 11092: }
! 11093:
! 11094: int no_runs_of_char(p)
! 11095: Char *p;
! 11096: { int runs;
! 11097: Blobl bl;
! 11098: runs = 0;
! 11099: bl.mny = p->bmny; bl.fi = p->fi;
! 11100: runs += no_runs_of_blobl(&bl);
! 11101: return(runs);
! 11102: }
! 11103:
! 11104: int runs_of_char(p,ra,max)
! 11105: Char *p;
! 11106: RLE_Yrun *ra;
! 11107: int max;
! 11108: { int runs;
! 11109: Blobl bl;
! 11110: runs = 0;
! 11111: bl.mny = p->bmny; bl.fi = p->fi;
! 11112: runs += runs_of_blobl(&bl,ra,max);
! 11113: return(runs);
! 11114: }
! 11115:
! 11116: /* ascending lexicographic order on y,xs */
! 11117: int rn_asc(r1,r2)
! 11118: RLE_Yrun *r1,*r2;
! 11119: { if(r1->y < r2->y) return(-1);
! 11120: else if(r1->y==r2->y) {
! 11121: if(r1->xs < r2->xs) return(-1);
! 11122: else if (r1->xs == r2->xs) return(0);
! 11123: else return(1);
! 11124: }
! 11125: else return(1);
! 11126: }
! 11127:
! 11128: RLE_Lines *rlines_of_char(chp)
! 11129: Char *chp;
! 11130: { static RLE_Lines rls;
! 11131: int no_runs,cy,ri;
! 11132: RLE_Run *lr;
! 11133: RLE_Yrun *ra,*cr;
! 11134: RLE_Line *cl;
! 11135: /* count runs */
! 11136: no_runs = no_runs_of_char(chp);
! 11137: /* allocate runs array */
! 11138: if((ra=(RLE_Yrun *)malloc(no_runs*sizeof(RLE_Yrun)))==NULL)
! 11139: abort("rlines_of_char: can't malloc ra[%d]",no_runs);
! 11140: runs_of_char(chp,ra,no_runs);
! 11141: /* sort runs ascending on (y,xs) */
! 11142: qsort(ra,no_runs,sizeof(RLE_Yrun),rn_asc);
! 11143: /* count RLE_lines.mny */
! 11144: rls.mny = 0; cy=Scoor_MIN;
! 11145: for(ri=0,cr=ra; ri<no_runs; ri++,cr++)
! 11146: if(cr->y!=cy) {
! 11147: rls.mny++;
! 11148: cy = cr->y;
! 11149: };
! 11150: /* allocate RLE_lines */
! 11151: if((rls.rla=(RLE_Line *)malloc(rls.mny*sizeof(RLE_Line)))==NULL)
! 11152: abort("rlines_of_page: can't malloc rls.rla[%d]",rls.mny);
! 11153: /* fill in RLE_lines */
! 11154: cy=Scoor_MIN; cl=rls.rla-1;
! 11155: for(ri=0,cr=ra; ri<no_runs; ri++,cr++) {
! 11156: if(cr->y!=cy) {
! 11157: cl++;
! 11158: cl->y = cy = cr->y;
! 11159: cl->runs = 0;
! 11160: lr = cl->r;
! 11161: };
! 11162: lr->xs = cr->xs; lr->xe = cr->xe; lr++; cl->runs++;
! 11163: };
! 11164: free(ra);
! 11165: return(&rls);
! 11166: }
! 11167:
! 11168: int asc_merit(m1,m2)
! 11169: Merit *m1,*m2;
! 11170: { if(*m1 < *m2) return(-1);
! 11171: else if(*m1 > *m2) return(1);
! 11172: else return(0);
! 11173: }
! 11174:
! 11175: /* Word merit is computed as a function of the merit of its Chars.
! 11176: No Chars forces merit to 0.0.
! 11177: The result is dominated by the weakest merit in the Word, slightly
! 11178: improved by the others. */
! 11179: Merit wordmerit(w)
! 11180: Word *w;
! 11181: { register Char *cp,**cpp;
! 11182: static int m_alloc = 0;
! 11183: static Merit *ma; /* ma[m_alloc] */
! 11184: int mi;
! 11185: Merit m;
! 11186: double wgt,sumwgt;
! 11187:
! 11188: if(w->cs.mny<=0) return(0.0);
! 11189: if(w->cs.mny>m_alloc) {
! 11190: if(m_alloc==0) {
! 11191: m_alloc=w->cs.mny;
! 11192: if((ma=(Merit *)malloc(m_alloc*sizeof(Merit)))==NULL)
! 11193: abort("wordmerit: can't malloc ma[%d]",m_alloc);
! 11194: }
! 11195: else { m_alloc=w->cs.mny;
! 11196: if((ma=(Merit *)realloc(ma,m_alloc*sizeof(Merit)))==NULL)
! 11197: abort("wordmerit: can't realloc ma[%d]",m_alloc);
! 11198: };
! 11199: };
! 11200: for(cp= *(cpp=w->cs.cpa),mi=0; cp!=NULL; cp= *(++cpp),mi++) {
! 11201: if(cp->area==0 || cp->il.mny==0) ma[mi]=0.0;
! 11202: else ma[mi] = cp->il.fi->m;
! 11203: };
! 11204: qsort(ma,w->cs.mny,sizeof(Merit),asc_merit);
! 11205: #define DOM (5.0)
! 11206: /* The worst merit is DOM times more significant than second worst, which
! 11207: is DOM times more significant than the third worst, and so on.
! 11208: */
! 11209: m=ma[0]; sumwgt=wgt=1.0;
! 11210: for(mi=1; mi<w->cs.mny; mi++) {
! 11211: m += ma[mi]*(wgt /= DOM); sumwgt += wgt;
! 11212: };
! 11213: m /= sumwgt;
! 11214: return(m);
! 11215: }
! 11216:
! 11217: WordSet *alloc_wordset(top,cut,cap)
! 11218: double top; /* initial maximum merit (is never reduced) */
! 11219: double cut; /* cut ratio: don't keep merit < cut*top */
! 11220: int cap; /* capacity: maximum no. at a time (0 ==> no limit) */
! 11221: { WordSet *res;
! 11222: if((res=(WordSet *)malloc(sizeof(WordSet)))==NULL)
! 11223: abort("alloc_wordset: can't");
! 11224: *res = empty_WordSet;
! 11225: res->top = top;
! 11226: res->cut = cut;
! 11227: if((res->cap = cap)==0) res->cap=INT_MAX;
! 11228: return(res);
! 11229: }
! 11230:
! 11231: int free_wordset_etc(s,etc)
! 11232: WordSet *s;
! 11233: Ident etc;
! 11234: { int high;
! 11235: free_words_etc(&(s->ws),etc);
! 11236: high = s->high;
! 11237: free(s);
! 11238: return(high);
! 11239: }
! 11240:
! 11241: /* Find the maximum-merit word in the set; among ties, pick the first seen. */
! 11242: Word *find_max_wordset(s)
! 11243: WordSet *s;
! 11244: { register Word *max,**wpp;
! 11245: max=NULL;
! 11246: if(s->ws.mny>0) for(wpp=s->ws.wpa; *wpp!=NULL; wpp++) {
! 11247: if(max==NULL || max->m < (*wpp)->m) max=(*wpp);
! 11248: };
! 11249: return(max);
! 11250: }
! 11251:
! 11252: /* Find the maximum-merit word in the set; among ties, pick the last seen. */
! 11253: Word *find_min_wordset(s)
! 11254: WordSet *s;
! 11255: { register Word *min,**wpp;
! 11256: min=NULL;
! 11257: if(s->ws.mny>0) for(wpp=s->ws.wpa; *wpp!=NULL; wpp++) {
! 11258: if(min==NULL || min->m >= (*wpp)->m) min=(*wpp);
! 11259: };
! 11260: return(min);
! 11261: }
! 11262:
! 11263: /* Insert a Word (without duplicating it).
! 11264: Update top, min, max, & high.
! 11265: If the new word's merit is equal to the current maximum, it does not become
! 11266: become the new maximum.
! 11267: If the new word's merit is equal to the current minimum, it becomes
! 11268: the new minimum.
! 11269: */
! 11270: put_wordset(w,s)
! 11271: Word *w; /* must have w->m set up */
! 11272: WordSet *s;
! 11273: { insert_word(w,&(s->ws));
! 11274: if(max_wordset(s)==NULL || max_wordset(s)->m < w->m) {
! 11275: max_wordset(s) = w;
! 11276: if(s->top < max_wordmerit(s)) s->top = max_wordmerit(s);
! 11277: };
! 11278: if(min_wordset(s)==NULL || min_wordset(s)->m >= w->m)
! 11279: min_wordset(s) = w;
! 11280: if(s->high < s->ws.mny) s->high = s->ws.mny;
! 11281: }
! 11282:
! 11283: /* Remove a Word (without freeing it). Maintain min/max, but don't prune items.
! 11284: Also, don't lower top or high. */
! 11285: Word *get_wordset(w,s)
! 11286: Word *w;
! 11287: WordSet *s;
! 11288: { if(w==NULL || s->ws.mny==0) return(NULL);
! 11289: remove_word(w,&s->ws);
! 11290: if(s->ws.mny==0) {
! 11291: max_wordset(s) = NULL;
! 11292: min_wordset(s) = NULL;
! 11293: }
! 11294: else { if(w==max_wordset(s)) max_wordset(s) = find_max_wordset(s);
! 11295: if(w==min_wordset(s)) min_wordset(s) = find_min_wordset(s);
! 11296: };
! 11297: return(w);
! 11298: }
! 11299:
! 11300: /* Remove a Word (without freeing it). Maintain min/max. Don't lower top. */
! 11301: Word *remove_wordset(w,s,n)
! 11302: Word *w;
! 11303: WordSet *s;
! 11304: char *n;
! 11305: { register Word *gw;
! 11306: #if dbg_ws
! 11307: if(w!=NULL) err("remove_wordset: %X %s",w,word_toa(w));
! 11308: else err("remove_wordset: NULL");
! 11309: #endif
! 11310: gw=get_wordset(w,s);
! 11311: #if dbg_ws
! 11312: err_wordset(s,n);
! 11313: #endif
! 11314: return(gw);
! 11315: }
! 11316:
! 11317: /* Check whether a given Word is identical to any already in a given set.
! 11318: Word *w must have its hash key set up. */
! 11319: boolean member_wordset(w,s)
! 11320: Word *w;
! 11321: WordSet *s;
! 11322: { register Word **ww;
! 11323: if(s->ws.mny>0) {
! 11324: for(ww=s->ws.wpa; (*ww)!=NULL; ww++) {
! 11325: if(w->hash==(*ww)->hash && eq_word(w,(*ww)))
! 11326: return(T);
! 11327: };
! 11328: };
! 11329: return(F);
! 11330: }
! 11331:
! 11332: /* Insert a Word into a set, maintaining uniqueness, a ``range'' property, and
! 11333: a maximum capacity.
! 11334: Uniqueness is maintained by refusing to insert words that are identical
! 11335: (eq_word()) to a word already in the set (or in set `u').
! 11336: The range property is that every word in the set must have merit no less
! 11337: than `s->cut' times the lifetime maximum for the set `s->top'.
! 11338: Maximum capacity is maintained as follows: if insertion would mean more
! 11339: members than `cap', then either (a) the insertion is refused (if its
! 11340: merit is less than the current `min', or (b) the current `min' is deleted
! 11341: (and silently freed in its entirety), and the insertion occurs.
! 11342: The inserted Word is not duplicated. If, as a result of an insertion,
! 11343: some of its words no longer satisfy the range property, they are silently
! 11344: removed (and freed in their entirety).
! 11345: Return T iff the Word is actually inserted.
! 11346: */
! 11347: boolean insert_wordset(w,s,n,u)
! 11348: Word *w;
! 11349: WordSet *s;
! 11350: char *n; /* name of set `s' */
! 11351: WordSet *u; /* if !=NULL, also check uniqueness here */
! 11352: { Word *fr;
! 11353: #if dbg_ws
! 11354: err("insert_wordset: %X %s",w,word_toa(w));
! 11355: #endif
! 11356: if((w->m = wordmerit(w)) >= (s->cut * s->top)) {
! 11357: w->hash = hash_word(w);
! 11358: if(member_wordset(w,s) || (u!=NULL&&member_wordset(w,u)))
! 11359: /* don't insert */
! 11360: return(F);
! 11361: if(s->ws.mny==s->cap) /* at capacity */ {
! 11362: if(w->m <= min_wordmerit(s)) /* too poor */ return(F);
! 11363: else { fr = remove_wordset(min_wordset(s),s);
! 11364: free_word_etc(fr,IsALL);
! 11365: };
! 11366: };
! 11367: put_wordset( w, s );
! 11368: if(max_wordset(s)==w) /* this has become the new maximum */ {
! 11369: while(min_wordmerit(s) < (s->cut * s->top)) {
! 11370: fr = remove_wordset(min_wordset(s),s);
! 11371: free_word_etc(fr,IsALL);
! 11372: };
! 11373: };
! 11374: #if dbg_ws
! 11375: err_wordset(s,n);
! 11376: #endif
! 11377: return(T);
! 11378: }
! 11379: else {
! 11380: #if dbg_ws
! 11381: err_wordset(s,n);
! 11382: #endif
! 11383: return(F);
! 11384: };
! 11385: }
! 11386:
! 11387: err_wordset(s,n)
! 11388: WordSet *s;
! 11389: char *n; /* name of set */
! 11390: { char m1[10],m2[10];
! 11391: register Word *wp,**wpp;
! 11392: fprintf( stderr,"WordSet %s: t%g c%g [%s/%X,%s/%X] m%d h%d: ",
! 11393: n,
! 11394: s->top,s->cut,
! 11395: strcpy(m1,merit_toa(max_wordmerit(s))),max_wordset(s),
! 11396: strcpy(m2,merit_toa(min_wordmerit(s))),min_wordset(s),
! 11397: s->ws.mny,s->high );
! 11398: if(s->ws.mny>0) for(wp= *(wpp=s->ws.wpa); wp!=NULL; wp= *(++wpp))
! 11399: fprintf(stderr,"%X/%s/%d ",wp,merit_toa(wp->m),wp->cs.mny);
! 11400: fprintf(stderr,"\n");
! 11401: }
! 11402:
! 11403: translate_txtln(lp,off)
! 11404: Txtln *lp;
! 11405: Sp off;
! 11406: { lp->bx = *translate_bbx(&lp->bx,off);
! 11407: lp->basl += off.y;
! 11408: translate_chars(lp->cs,off);
! 11409: }
! 11410:
! 11411: translate_chars(csp,off)
! 11412: Chars *csp;
! 11413: Sp off;
! 11414: { register Char *cp,**cpp;
! 11415: for(cp= *(cpp=csp->cpa); cp!=NULL; cp= *(++cpp))
! 11416: translate_char(cp,off);
! 11417: }
! 11418:
! 11419: translate_char(cp,off)
! 11420: Char *cp;
! 11421: Sp off;
! 11422: { cp->bx = *translate_bbx(&cp->bx,off);
! 11423: translate_blobl(cp,off);
! 11424: }
! 11425:
! 11426: translate_blobs(b,off)
! 11427: Blobs *b;
! 11428: Sp off;
! 11429: { register Blob *bp,**bpp;
! 11430: if(b->mny>0) for ( bp= *(bpp=b->bpa); bp!=NULL; bp= *(++bpp) )
! 11431: translate_blob(bp,off);
! 11432: }
! 11433:
! 11434: translate_blobl(cp,off)
! 11435: Char *cp;
! 11436: Sp off;
! 11437: { int bi;
! 11438: register Blob *bp;
! 11439: for(bi=0,bp=cp->fi; bi<cp->bmny&&bp!=NULL; bi++,bp=bp->n)
! 11440: translate_blob(bp,off);
! 11441: }
! 11442:
! 11443: translate_blob(bp,off)
! 11444: Blob *bp;
! 11445: Sp off;
! 11446: { bp->bx = *translate_bbx(&bp->bx,off);
! 11447: }
! 11448:
! 11449: 0707070035351137141006640007620000050000010262240476773367000000700000107063Text.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 11450: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 11451: /* The copyright notice does not imply actual or intended publication. */
! 11452: /* AUTHORS: */
! 11453: /* H. S. Baird - ATT-BL MH - first versions */
! 11454:
! 11455: /* Text.h - typedefs, constants, and function declarations for document-images
! 11456: (see Text.c for companion functions.)
! 11457: INCLUDES
! 11458: requires prior:
! 11459: #include "stdocr.h"
! 11460: */
! 11461:
! 11462: #define dbg_fwrb_toa (F) /* err("%s",R_toa()) for each record written */
! 11463: #define dbg_frdb_toa (F) /* err("%s",R_toa()) for each record read */
! 11464:
! 11465: #define DIM_VERSION (0) /* current version no. of Dim-file format */
! 11466:
! 11467: #include "Bfeats.h"
! 11468:
! 11469: #define Ident int /* identification bits [MUST BE >=32 bits] */
! 11470:
! 11471: #define fwri_Ident(F,V) fwri_uint4((F),(V))
! 11472: #define frdi_Ident(F) frdi_uint4(F)
! 11473:
! 11474: /* Ident bits */
! 11475: /* identifies external file record type(s) */
! 11476: #define IsPage 04000000000
! 11477: #define IsBlock 02000000000
! 11478: #define IsTxtln 01000000000
! 11479: #define IsWord 00020000000
! 11480: #define IsChar 00400000000
! 11481: #define IsBlob 00200000000
! 11482: #define IsRun 00100000000 /* should be IsRuns or IsLag */
! 11483: #define IsRuns (IsRun)
! 11484: #define IsInterp 00040000000 /* Char interpretation */
! 11485: #define IsBdy 00010000000
! 11486: #define IsShapes 00004000000
! 11487: #define IsLag 00002000000
! 11488: #define IsBfeats 00001000000
! 11489: #define IsSfeats 00000400000
! 11490: #define IsWordInterp 00000200000
! 11491: /* Runs: set in Blob records' ids.
! 11492: At most one of these may be set in main memory.
! 11493: Only Runs_ff or Runs_g4 may be set in peripheral file format. */
! 11494: #define Runs_f 00000010000 /* Runs are in list, starting *.r.f */
! 11495: #define Runs_ff 00000020000 /* RunFs are in array, at *.r.ff */
! 11496: #define Runs_seek 00000040000 /* Runs are still in file, at *.seek */
! 11497: #define Runs_g4 00000100000 /* Runs are in CCITT Group 4 format */
! 11498:
! 11499: /* CCITT Group 4 format in peripheral files consists of (a) an unsigned long count,
! 11500: then (b) that many bytes of Group 4 encoding exactly as in CCITT
! 11501: Recommendation T.6, except that no EOFB code is appended, since the end of
! 11502: the bitmap can be detected using the bounding box of the owning Blob.
! 11503: Instead, the last scan line of the bitmap is merely padded to the nearest
! 11504: full byte with '0' bits. This compresses the representation by about
! 11505: a factor of 8 on average, compared to RunF/RunFS encoding. */
! 11506:
! 11507: #define IsALL (IsPage|IsBlock|IsTxtln|IsWord|IsChar|IsBlob|IsRun|IsBdy|IsInterp|IsShapes|IsLag|IsBfeats|IsSfeats|IsWordInterp)
! 11508: #define IsNONE 0
! 11509:
! 11510:
! 11511: /* Enable optional debugging-support code to maintain a count of selected record
! 11512: types that are allocated using alloc_* free_* and dup_* functions. The counts
! 11513: are in units of records, not bytes. By design, has no effect at all on
! 11514: correctness. */
! 11515: #define ALLOC_CENSUS (0)
! 11516:
! 11517: #if ALLOC_CENSUS
! 11518:
! 11519: typedef struct Census {
! 11520: int Page_mny;
! 11521: int Block_mny;
! 11522: int Txtln_mny;
! 11523: int Word_mny;
! 11524: int Char_mny;
! 11525: int Blob_mny;
! 11526: int Run_mny;
! 11527: int Interp_mny;
! 11528: int Bfeats_mny;
! 11529: int BMask_mny;
! 11530: } Census;
! 11531:
! 11532: #define Init_Census {0,0,0,0,0,0,0,0,0,0}
! 11533: #if MAIN
! 11534: Census empty_Census = Init_Census;
! 11535: Census _CENSUS = Init_Census;
! 11536: #else
! 11537: extern Census empty_Census;
! 11538: extern Census _CENSUS;
! 11539: #endif
! 11540:
! 11541: #define alloc_census(id,n) _CENSUS./**/id/**/_mny += (n)
! 11542: #define free_census(id,n) _CENSUS./**/id/**/_mny -= (n)
! 11543: #define err_census(S,C) err("%s P%d B%d l%d w%d c%d b%d r%d i%d bf%d bm%d",\
! 11544: S,(C)->Page_mny,(C)->Block_mny,(C)->Txtln_mny,(C)->Word_mny,\
! 11545: (C)->Char_mny,(C)->Blob_mny,(C)->Run_mny,(C)->Interp_mny,\
! 11546: (C)->Bfeats_mny,(C)->BMask_mny )
! 11547: #define err_census_all err_census("allocated: ",&(_CENSUS))
! 11548: #define err_census_rec(rp) { \
! 11549: Census *cs; cs = (Census *)census_rec((rp)); \
! 11550: err_census(ident_toa((rp)->ident),cs); \
! 11551: }
! 11552: #else
! 11553:
! 11554: #define alloc_census(i,n)
! 11555: #define free_census(i,n)
! 11556: #define err_census(s,c)
! 11557: #define err_census_all
! 11558: #define err_census_rec(r)
! 11559:
! 11560: #endif
! 11561:
! 11562:
! 11563: /* Most record types can own an ASCII label, which is simply a
! 11564: '\0'-terminated string. Its uses are varied. */
! 11565: #define MAX_LABEL_LEN 128 /* maximum no. characters in a label string */
! 11566:
! 11567: #if FWRI
! 11568:
! 11569: #if dbg_fwrb_toa
! 11570: #define fwrb_label(F,L) { \
! 11571: fwri_str((F),(L)); \
! 11572: err("fwrb_label: \"%s\"",(L)); \
! 11573: }
! 11574: #else
! 11575: #define fwrb_label(F,L) { \
! 11576: fwri_str((F),(L)); \
! 11577: }
! 11578: #endif
! 11579:
! 11580: #else
! 11581:
! 11582: #if dbg_fwrb_toa
! 11583: #define fwrb_label(F,L) { \
! 11584: fputs((L),(F)); \
! 11585: fputc('\0',(F)); \
! 11586: err("fwrb_label: \"%s\"",(L)); \
! 11587: }
! 11588: #else
! 11589: #define fwrb_label(F,L) { \
! 11590: fputs((L),(F)); \
! 11591: fputc('\0',(F)); \
! 11592: }
! 11593: #endif
! 11594:
! 11595: #endif
! 11596:
! 11597: char *frdb_label();
! 11598:
! 11599: /* A boundary is an ordered list of vertices.
! 11600: In some uses, it is assumed to close: in this case, the first point
! 11601: is not repeated at the end.
! 11602: `vn' counts the no. vertices. bdy_trace omits consecutive duplicates and
! 11603: compresses horizontal and vertical runs.
! 11604: `per' counts the no. of pixels on the 8-connected boundary. An attempt has been
! 11605: made not to count consecutive duplicate pixels, but this may be buggy.
! 11606: `ren' counts the number of run-ends touched. Each run contributes two ends,
! 11607: even if it is one pixel long. The sum of ren-counts among all bdys for a blob
! 11608: should equal exactly twice the no. runs.
! 11609: Note that vn<=per and vn<=2*ren, and (probably) ren<=per.
! 11610: A ``smoothed'' version (courtesy of John Hobby) may be given in s[],
! 11611: expressed in fractional pixels.
! 11612: */
! 11613: typedef struct Bdy {
! 11614: Ident ident; /* shows type of boundary */
! 11615: Bbx bx; /* bounding box (usually relative to blob's bx.a) */
! 11616: long per; /* no. pixels in 8-connected perimeter */
! 11617: int ren; /* no. run-ends touched */
! 11618: int vn; /* no. distinct vertices in v[] */
! 11619: Sp *v; /* array of vn+1 vertices, v[0]==v[vn] (malloc space) */
! 11620: short fr; /* fraction of pixels used in smoothed outline */
! 11621: int sn; /* no. distinct smoothed vertices in s[] */
! 11622: Sp *s; /* array of sn+1 vertices, s[0]==s[sn] (malloc space) */
! 11623: int an; /* no. vertices in polygonal approximation */
! 11624: Sp **ap; /* approx'n: array of an ptrs into v[] (in malloc space) */
! 11625: float err; /* error tolerance used for approximation */
! 11626: int hn; /* no. vertices in convex hull of polygonal approx'n */
! 11627: Sp ***hpp; /* convex hull: array of hn ptrs into ap[] (malloc) */
! 11628: struct Bdy *n; /* for use when a member of a linked-list */
! 11629: } Bdy;
! 11630:
! 11631: #define Init_Bdy {IsBdy,Init_Bbx,0,0,0,NULL,1,0,NULL,0,NULL,0.0,0,NULL,NULL}
! 11632: #if MAIN
! 11633: Bdy empty_Bdy = Init_Bdy;
! 11634: #else
! 11635: extern Bdy empty_Bdy;
! 11636: #endif
! 11637:
! 11638: #define Bdy_verts 00000000001 /* vertices */
! 11639: #define Bdy_approx 00000000002 /* polygonal approx'n */
! 11640: #define Bdy_hull 00000000004 /* convex hull */
! 11641: #define Bdy_ALL (Bdy_verts|Bdy_approx|Bdy_hull)
! 11642: #define Bdy_ccw 00000000100 /* winding order is counter-clockwise*/
! 11643: #define Bdy_half 00000000200 /* uses half-pixel boundary points */
! 11644:
! 11645: /* A boundaries-set is an ordered list of boundaries.
! 11646: In some uses, they are used to enclose a connected region: in this case,
! 11647: all are closed, and the first is conventionally the exterior and the others
! 11648: are interior boundaries. The interior is then always to the left
! 11649: of the boundary: that is, the exterior boundary is oriented counter-
! 11650: clockwise, and the interior boundaries clockwise */
! 11651: typedef struct Bdys {
! 11652: int mny; /* no. boundaries */
! 11653: long per; /* perimeter of all bdys */
! 11654: Bdy *b; /* array of boundaries (malloc space) (sometimes first) */
! 11655: } Bdys;
! 11656:
! 11657: #define Init_Bdys {0,0,NULL}
! 11658: #if MAIN
! 11659: Bdys empty_Bdys = Init_Bdys;
! 11660: #else
! 11661: extern Bdys empty_Bdys;
! 11662: #endif
! 11663:
! 11664: /* A boundary edge is an ordered pair of vertices along a boundary. It implicitly
! 11665: describes an 8-connected sequence of pixels from a to b, inclusive. Also
! 11666: used for straight-line approximations to the set of pixels, and the convex hull
! 11667: of such an approximation. */
! 11668: typedef struct BdyEdge {
! 11669: Bdy *byp; /* boundary to which it belongs */
! 11670: Sp *ap,*bp; /* ptrs into byp->v */
! 11671: long per; /* perimeter: no. 8-connected pixels */
! 11672: Pp ctr; /* centroid */
! 11673: Radians ang; /* ls-fitted angle (directed roughly from a to b) */
! 11674: Pp a; /* endpoints a & b (with sub-pixel precision) */
! 11675: Pp b;
! 11676: } BdyEdge;
! 11677:
! 11678: #define Init_BdyEdge {NULL,NULL,NULL,0,Init_Zero_Pp,0.0,Init_Zero_Pp,Init_Zero_Pp}
! 11679: #if MAIN
! 11680: BdyEdge empty_BdyEdge = Init_BdyEdge;
! 11681: #else
! 11682: extern BdyEdge empty_BdyEdge;
! 11683: #endif
! 11684:
! 11685: /* Ordered set of BdyEdges */
! 11686: typedef struct BdyEdges {
! 11687: int mny;
! 11688: BdyEdge **pa; /* NULL-terminated array of pointers to BdyEdges */
! 11689: } BdyEdges;
! 11690:
! 11691: #define Init_BdyEdges {0,NULL}
! 11692: #if MAIN
! 11693: BdyEdges empty_BdyEdges = Init_BdyEdges;
! 11694: #else
! 11695: extern BdyEdges empty_BdyEdges;
! 11696: #endif
! 11697:
! 11698: /* Moments of a region (or boundary-list) of pixels */
! 11699:
! 11700: typedef struct Moments {
! 11701: /* 0th moment */
! 11702: int M00; /* area: sum of 1 */
! 11703: /* 1st moments */
! 11704: int M10; /* sum of xi */
! 11705: int M01; /* sum of yi */
! 11706: Pp c; /* centroid: M10/M00, M01/M00 */
! 11707: /* 2nd moments (relative to centroid) */
! 11708: float M20; /* sum of rxi*rxi */
! 11709: float M11; /* sum of rxi*ryi */
! 11710: float M02; /* sum of ryi*ryi */
! 11711: Radians a; /* orientation angle, in [-PI/2,PI/2) (radians) */
! 11712: Pp d; /* directional vector of principal axis */
! 11713: } Moments;
! 11714:
! 11715: #define Init_Moments {0,0,0,{0.0,0.0},0.0,0.0,0.0,0.0,{0.0,0.0}}
! 11716: #if MAIN
! 11717: Moments zero_Moments = Init_Moments;
! 11718: #else
! 11719: extern Moments zero_Moments;
! 11720: #endif
! 11721:
! 11722: /* functions in Text.c */
! 11723: Bdy *alloc_bdy();
! 11724: Bdys *alloc_bdys();
! 11725:
! 11726: /* functions in Bdy.c */
! 11727: Bdys *dup_bdys_etc();
! 11728: Bdy *dup_bdy_etc();
! 11729: Bdys *boundaries();
! 11730: char *moments_toa();
! 11731: Moments *bdy_moments();
! 11732: boolean fit_bdyedge();
! 11733: BdyEdge *dup_bdyedge();
! 11734: BdyEdge *append_bdyedge();
! 11735: remove_bdyedge();
! 11736: free_bdyedges();
! 11737: BdyEdges *dup_bdyedges();
! 11738:
! 11739: /* Each Run is initially inserted into a `line set', owned by its scan Line.
! 11740: Later, as connections are discovered, it joins a `tree set'.
! 11741: When the forest of trees of which it is a part is finally complete, the Run
! 11742: is removed from its `line set', and added to a `blob set'.
! 11743: */
! 11744:
! 11745: typedef struct Run { /* internal (main memory) record */
! 11746: Scoor y, xs, xe; /* coordinates of black interval (y,[xs,xe]) */
! 11747: struct Run *n; /* line & blob sets: next Run */
! 11748: unsigned short ad, bd; /* tree set: above,below degrees (no. conn'd)*/
! 11749: struct Run *ac, *bc; /* tree set: above,below leftmost connections */
! 11750: union { struct Tree *o; /* tree set: owner Tree */
! 11751: int no; /* blob set: sequence no. 0,1,... in set */
! 11752: } u; /* (overlain fields) */
! 11753: } Run;
! 11754:
! 11755: #define Init_Run {0,0,0,NULL,0,0,NULL,NULL}
! 11756: #if MAIN
! 11757: Run empty_Run = Init_Run;
! 11758: #else
! 11759: extern Run empty_Run;
! 11760: #endif
! 11761:
! 11762: /* Peripheral file format. `ac' and `bc' are relative to the position
! 11763: of this run in the canonical run order. */
! 11764: typedef struct RunF { /* external (peripheral file) record (full size) */
! 11765: Scoor y, xs, xe; /* coordinates of black interval (y,[xs,xe]) */
! 11766: unsigned short ad, bd; /* above,below degrees */
! 11767: unsigned short ac, bc; /* above,below leftmost connections (indices) */
! 11768: } RunF;
! 11769:
! 11770: #define Init_RunF {0,0,0,0,0,0,0}
! 11771: #if MAIN
! 11772: RunF empty_RunF = Init_RunF;
! 11773: #else
! 11774: extern RunF empty_RunF;
! 11775: #endif
! 11776:
! 11777: #define fwri_RunF(F,P) { \
! 11778: fwri_Scoor((F),(P)->y); \
! 11779: fwri_Scoor((F),(P)->xs); \
! 11780: fwri_Scoor((F),(P)->xe); \
! 11781: fwri_uint2((F),(P)->ad); \
! 11782: fwri_uint2((F),(P)->bd); \
! 11783: fwri_uint2((F),(P)->ac); \
! 11784: fwri_uint2((F),(P)->bc); \
! 11785: }
! 11786:
! 11787: #define frdi_RunF(F,P) ( feof(F)? 0 : ( \
! 11788: (P)->y=frdi_Scoor(F), \
! 11789: (P)->xs=frdi_Scoor(F), \
! 11790: (P)->xe=frdi_Scoor(F), \
! 11791: (P)->ad=frdi_uint2(F), \
! 11792: (P)->bd=frdi_uint2(F), \
! 11793: (P)->ac=frdi_uint2(F), \
! 11794: (P)->bc=frdi_uint2(F), \
! 11795: (ferror(F)? -errno: 1) ) )
! 11796:
! 11797: /* In `well-behaved' text, the overwhelming majority of Blobs are small
! 11798: enough that all their Runs can be encoded using character data fields,
! 11799: a factor of two saving, which is important since a dense IEEE proceedings
! 11800: page blob file would otherwise require 2.3Mbytes */
! 11801: typedef struct RunFS { /* external (peripheral file) record (small size) */
! 11802: unsigned char y, xs, xe;/* coordinates of black interval (y,[xs,xe]) */
! 11803: unsigned char ad, bd; /* above,below degrees */
! 11804: unsigned char ac, bc; /* above,below leftmost connections (indices) */
! 11805: } RunFS;
! 11806:
! 11807: #define Init_RunFS {0,0,0,0,0,0,0}
! 11808: #if MAIN
! 11809: RunFS empty_RunFS = Init_RunFS;
! 11810: #else
! 11811: extern RunFS empty_RunFS;
! 11812: #endif
! 11813:
! 11814: #define fwri_RunFS(F,P) { \
! 11815: fwri_uint1((F),(P)->y); \
! 11816: fwri_uint1((F),(P)->xs); \
! 11817: fwri_uint1((F),(P)->xe); \
! 11818: fwri_uint1((F),(P)->ad); \
! 11819: fwri_uint1((F),(P)->bd); \
! 11820: fwri_uint1((F),(P)->ac); \
! 11821: fwri_uint1((F),(P)->bc); \
! 11822: }
! 11823:
! 11824: #define frdi_RunFS(F,P) ( feof(F)? 0: ( \
! 11825: (P)->y=frdi_uint1(F), \
! 11826: (P)->xs=frdi_uint1(F), \
! 11827: (P)->xe=frdi_uint1(F), \
! 11828: (P)->ad=frdi_uint1(F), \
! 11829: (P)->bd=frdi_uint1(F), \
! 11830: (P)->ac=frdi_uint1(F), \
! 11831: (P)->bc=frdi_uint1(F), \
! 11832: (ferror(F)? -errno: 1) ) )
! 11833:
! 11834: /* Set of runs. PROPOSED NEW FORMAT. Not yet incorporated widely. */
! 11835: typedef struct Runs {
! 11836: Ident ident; /* IsRuns & Runs_fi, Runs_ff, Runs_fs, or Runs_sk flags */
! 11837: int mny; /* no. runs */
! 11838: union { /* access to runs */
! 11839: struct Run *fi; /* first run of singly-linked list */
! 11840: struct RunF *ff; /* top of RunF[mny] array */
! 11841: struct RunFS *fs; /* top of RunFS[mny] array */
! 11842: long sk; /* seek(F,seek,0) will find them in file F */
! 11843: } r;
! 11844: } Runs;
! 11845:
! 11846: #define Init_Runs {IsRuns,0} /* NOTE: can't initialize union */
! 11847: #if MAIN
! 11848: Runs empty_Runs = Init_Runs;
! 11849: #else
! 11850: extern Runs empty_Runs;
! 11851: #endif
! 11852:
! 11853: /* INTERNAL management */
! 11854:
! 11855: #if !MAIN
! 11856: extern
! 11857: #endif
! 11858: struct {
! 11859: int incr; /* size of each pool[i] */
! 11860: int pools; /* no. of pools allocated */
! 11861: Run **pool; /* malloc space Run pool[pools][0..incr-1] */
! 11862: int next; /* the next avail Run is: pool[pools-1][next] */
! 11863: Run *free; /* head of free lifo list (NULL if none) */
! 11864: Run *cur; /* most-recently allocated Run */
! 11865: int total; /* total no. ever allocated */
! 11866: boolean dbg;
! 11867: } _RunPool
! 11868: #if MAIN
! 11869: = {0,0,NULL,0,NULL,NULL,0,F}
! 11870: #endif
! 11871: ;
! 11872:
! 11873: /* Run management routines (Text.c) */
! 11874: boolean alloc_run_pool();
! 11875: free_run_pool();
! 11876: Run *hard_alloc_run();
! 11877: err_run();
! 11878: err_runb();
! 11879: err_runf();
! 11880: err_runfs();
! 11881: err_run_stats();
! 11882:
! 11883: /* Allocate a Run from the RunPool (returns (Run *)) -- mostly inline */
! 11884: #define alloc_run() ( _RunPool.total++, (_RunPool.free!=NULL)? \
! 11885: (_RunPool.cur=_RunPool.free,_RunPool.free=_RunPool.cur->n, \
! 11886: *(_RunPool.cur)=empty_Run,_RunPool.cur): \
! 11887: ( (_RunPool.next<_RunPool.incr)? \
! 11888: (_RunPool.cur=_RunPool.pool[_RunPool.pools-1]+(_RunPool.next++), \
! 11889: *(_RunPool.cur)=empty_Run,_RunPool.cur): \
! 11890: hard_alloc_run() ) )
! 11891:
! 11892: /* Free a Run back into the RunPool -- entirely inline */
! 11893: #define free_run(rp) { (rp)->n = _RunPool.free; _RunPool.free = (rp); }
! 11894:
! 11895: /* EXTERNAL file format:
! 11896: If BlobF.runs is zero, then conventionally the Runs have simply been omitted.
! 11897: The RunF.y, RunF.xs, & RunF.xe coordinates are offsets from BlobF.bx.a
! 11898: (their blob's left-top corner). RunF.ac & RunF.bc index into an array of
! 11899: only those RunF records belonging to the current BlobF, in ascending
! 11900: lexicographic order on (RunF.y,RunF.xs) -- so that they are in the range
! 11901: [0,BlobF.runs-1].
! 11902: IMPROVEMENTS:
! 11903: */
! 11904:
! 11905: /* some subroutines are too lazy to handle indefinitely large blobs */
! 11906: #define Runs_Max 10000
! 11907:
! 11908: /* A Blob is (formally) a maximal 8-connected set of black pixels.
! 11909: The connectivity algorithm finds them in strictly increasing order on
! 11910: (y,xe) of its Run with highest (y,xe).
! 11911: */
! 11912:
! 11913: typedef struct Blob { /* internal (main memory) record */
! 11914: Ident ident; /* identification bits */
! 11915: Seq no; /* blob sequence no */
! 11916: Bbx bx;
! 11917: long area;
! 11918: long per;
! 11919: struct Blob *n; /* free set: next blob */
! 11920: Merit m; /* Only used locally (not for peripheral file) */
! 11921: Runs *rsp; /* runs (not yet used) */
! 11922: Bdys *bdsp; /* boundaries (in malloc space); NULL if none */
! 11923: /* presently in use (but planned to be replaced by Runs) */
! 11924: int runs;
! 11925: union { /* to find runs */
! 11926: struct Run *f; /* blob set: first run */
! 11927: struct RunF *ff; /* top of RunF array */
! 11928: long seek; /* seek(f,seek,0) will find them */
! 11929: } r;
! 11930: } Blob;
! 11931:
! 11932: #define Init_Blob {IsBlob,0,Init_Bbx,0,0,NULL,0.0,NULL,NULL,0,}
! 11933: #if MAIN
! 11934: Blob empty_Blob = Init_Blob;
! 11935: #else
! 11936: extern Blob empty_Blob;
! 11937: #endif
! 11938:
! 11939: typedef struct Blobs { /* Blob set */
! 11940: int mny; /* the number of pointers in set */
! 11941: Blob **bpa; /* pts to NULL-terminated array[mny+1] of pointers */
! 11942: } Blobs;
! 11943:
! 11944: #define Init_Blobs {0,NULL}
! 11945: #if MAIN
! 11946: Blobs empty_Blobs = Init_Blobs;
! 11947: #else
! 11948: extern Blobs empty_Blobs;
! 11949: #endif
! 11950:
! 11951: /* Singly-linked list of Blobs. Only forward `next' links Blob.n are used. */
! 11952: typedef struct Blobl { /* Blob list */
! 11953: int mny; /* the number in set */
! 11954: Blob *fi; /* to first */
! 11955: Blob *la; /* to last */
! 11956: } Blobl;
! 11957:
! 11958: #define Init_Blobl {0,NULL,NULL}
! 11959: #if MAIN
! 11960: Blobl empty_Blobl = Init_Blobl;
! 11961: #else
! 11962: extern Blobl empty_Blobl;
! 11963: #endif
! 11964:
! 11965: typedef struct BlobF { /* external file format */
! 11966: Ident ident; /* identification bits: IsBlob must be set */
! 11967: Bbx bx;
! 11968: long area;
! 11969: long per;
! 11970: int runs; /* no. runs to follow */
! 11971: short bdys; /* no. bdys to follow */
! 11972: } BlobF;
! 11973:
! 11974: /* Blob identification bits */
! 11975: #define Blob_lm 00000000001 /* touches left margin */
! 11976: #define Blob_rm 00000000002 /* touches right margin */
! 11977: #define Blob_tm 00000000004 /* touches top margin */
! 11978: #define Blob_bm 00000000010 /* touches bottom margin */
! 11979: #define Blob_chopt 00000000020 /* chopped (at the top) */
! 11980: #define Blob_chopb 00000000040 /* chopped (at the bottom) */
! 11981: #define Blob_chopl 00000002000 /* chopped (at the left) */
! 11982: #define Blob_chopr 00000004000 /* chopped (at the right) */
! 11983: #define Blob_small 00000000200 /* its runs (can be) compressed x2 */
! 11984: #define Blob_local 00000000400 /* unassigned: avail for local pgm use */
! 11985:
! 11986: /* INTERNAL management: */
! 11987:
! 11988: int hi_blob_no; /* current highest blob no */
! 11989:
! 11990: /* Blobs are allocated from a pool of free ones */
! 11991: int blob_max;
! 11992: Blob *blob_pool;
! 11993: Blob blob_fr; /* head of list of free blobs */
! 11994: int blob_fr_mny;
! 11995: int blob_hi; /* high-water mark in blob pool */
! 11996: int blob_chopped; /* total no. of blobs that were chopped */
! 11997: boolean blob_debug; /* debug traces? */
! 11998:
! 11999: /* EXTERNAL file format:
! 12000: A Blob file consists of an arbitrary number of:
! 12001: BlobF record, followed by BlobF.runs instances of:
! 12002: RunF record
! 12003: If BlobF.runs is zero, then conventionally the Runs have simply been omitted.
! 12004: The RunF.y, RunF.xs, & RunF.xe coordinates are relative offsets from BlobF.bx.a
! 12005: (their blob's left-top corner). RunF.ac & RunF.bc index into an array of
! 12006: only those RunF records belonging to the current BlobF, in ascending
! 12007: lexicographic order on (RunF.y,RunF.xs) -- so that they are in the range
! 12008: [0,BlobF.runs-1]. If ad(or, bd)==0, the ac(or, bc) is undefined (conn sets
! 12009: them conventionally to 0).
! 12010: */
! 12011:
! 12012: /* Blob management routines (conBlob.c) */
! 12013: Blob *alloc_blob();
! 12014: free_blob();
! 12015: boolean alloc_blob_pool();
! 12016: free_blob_pool();
! 12017: Blob *alloc_pool_blob();
! 12018: free_pool_blob();
! 12019: out_blob();
! 12020: fwrb_blob_etc();
! 12021: boolean frdb_blob_etc();
! 12022: boolean frdb_runfs();
! 12023: err_blob();
! 12024: err_blob_runs();
! 12025: err_blob_runfs();
! 12026: err_blob_briefly();
! 12027: err_blobf();
! 12028: err_blob_stats();
! 12029: boolean blob_small();
! 12030:
! 12031: /* Compute height-above-baseline in ems of Char *cp w.r.t. Txtln *lp,
! 12032: on a page of y-resolution res. The txtln's `basl' & `size' must be set up. */
! 12033: #define char_bhgt(cp,lp,res) \
! 12034: ((((cp)->bx.b.y - (lp)->basl)/(double)(res)*INS_PER_PT*(lp)->size))
! 12035:
! 12036: /* an Interpretation of a Char */
! 12037: typedef struct Interp {
! 12038: Ident ident;
! 12039: struct Cl *clp;
! 12040: struct Class *clsp;
! 12041: ClassId ci; /* class id (font, size, name, variant) */
! 12042: Merit mshap; /* shape merit in [0,1] */
! 12043: Pts size; /* implied text size */
! 12044: Merit msize; /* size merit in [0,1] */
! 12045: Scoor basl; /* implied absolute baseline location */
! 12046: Merit mbhgt; /* height-above-baseline merit in [0,1] */
! 12047: Merit m; /* match merit (due to mshap, msize, & mbhgt) */
! 12048: Prob p; /* approximate probability */
! 12049: struct Interp *n; /* next in singly-linked list */
! 12050: } Interp;
! 12051:
! 12052: #define Init_Interp {IsInterp,NULL,NULL,Init_ClassId,0.0,0.0,0.0,0,0.0,0.0,0.0,NULL}
! 12053: #if MAIN
! 12054: Interp empty_Interp = Init_Interp;
! 12055: #else
! 12056: extern Interp empty_Interp;
! 12057: #endif
! 12058:
! 12059: /* Interp.ident flags: */
! 12060: #define Interp_spelled 00000000001 /* has passed a spelling check */
! 12061:
! 12062: #define free_interp(i) {free((i)); free_census(Interp,1); }
! 12063:
! 12064: typedef struct InterpF {
! 12065: Ident ident;
! 12066: ClassId ci; /* class id (font, size, name, variant) */
! 12067: Merit mshap; /* shape merit */
! 12068: Pts size; /* implied text size (in points) */
! 12069: Merit msize; /* size merit */
! 12070: Scoor basl; /* implied baseline location */
! 12071: Merit mbhgt; /* height-above-baseline merit */
! 12072: Merit m; /* match merit (due to shp, siz, hgt) */
! 12073: } InterpF;
! 12074:
! 12075: /* a list of interpretations */
! 12076: typedef struct Interpl {
! 12077: short mny; /* no. in list */
! 12078: struct Interp *fi; /* first in list (mny==0 -> fi==NULL) */
! 12079: } Interpl;
! 12080:
! 12081: #define Init_Interpl {0,NULL}
! 12082: #if MAIN
! 12083: Interpl empty_Interpl = Init_Interpl;
! 12084: #else
! 12085: extern Interpl empty_Interpl;
! 12086: #endif
! 12087:
! 12088: /* a set of interpretations */
! 12089: typedef struct Interps {
! 12090: short mny; /* no. in set */
! 12091: struct Interp **pa; /* NULL-terminated array of ptrs (malloc spc) */
! 12092: Merit m; /* combined merit (normalized product) */
! 12093: } Interps;
! 12094:
! 12095: #define Init_Interps {0,NULL,0.0}
! 12096: #if MAIN
! 12097: Interps empty_Interps = Init_Interps;
! 12098: #else
! 12099: extern Interps empty_Interps;
! 12100: #endif
! 12101:
! 12102: typedef struct Shapes {
! 12103: short mny; /* no. items in set */
! 12104: short alloc; /* no. items that can fit in array (alloc>=mny) */
! 12105: Nb_s *sa; /* ptr to contiguous array (malloc space) */
! 12106: } Shapes;
! 12107:
! 12108: #define Init_Shapes {0,0,NULL}
! 12109: #if MAIN
! 12110: Shapes empty_Shapes = Init_Shapes;
! 12111: #else
! 12112: extern Shapes empty_Shapes;
! 12113: #endif
! 12114:
! 12115: #define SH_INCR (20) /* Shapes are allocated by this increment */
! 12116:
! 12117: #define init_sh(sh) { \
! 12118: (sh)->alloc = SH_INCR; \
! 12119: if(((sh)->sa=(Nb_s *)malloc((sh)->alloc*sizeof(Nb_s)))==NULL) \
! 12120: abort("can't alloc sh->sa[%d]",(sh)->alloc); \
! 12121: (sh)->mny = 0; \
! 12122: }
! 12123:
! 12124: #define add_sh(s,sh) { \
! 12125: if((sh)->mny==(sh)->alloc) { \
! 12126: (sh)->alloc += SH_INCR; \
! 12127: if(((sh)->sa=(Nb_s *)realloc((sh)->sa,(sh)->alloc*sizeof(Nb_s)))==NULL) \
! 12128: abort("can't alloc (sh)->sa[%d]",(sh)->alloc); \
! 12129: }; \
! 12130: (sh)->sa[(sh)->mny++] = *(s); \
! 12131: }
! 12132:
! 12133: /* Parameters governing the pseudo-random generation of a Char image
! 12134: using a 1st-order statistical model of imaging. */
! 12135: typedef struct RanParms {
! 12136: short res_x; /* -r resolution (scanner pels/inch) */
! 12137: short res_y; /* (for now, equal to res_x) */
! 12138: Pts size; /* -p size of text */
! 12139: Radians skew; /* -a skew angle */
! 12140: Ems bhgt; /* -b height above baseline */
! 12141: float blur; /* -e blurring std err (scanner pels) */
! 12142: float jitter; /* -j jitter std err (scanner pels) */
! 12143: float kern; /* -k kerning std err (scanner pels) */
! 12144: float speckle; /* -s pel-wise additive noise std err (scanner pels) */
! 12145: float thresh; /* -t threshold for binarization */
! 12146: float xscale; /* -x horizontal scaling (dimensionless) */
! 12147: float yscale; /* -y vertical scaling (dimensionless) */
! 12148: } RanParms;
! 12149: #define Init_RanParms {0,0,0.0,0.0,0.0,0.7,0.0,0.0,0.125,0.25,1.0,1.0}
! 12150: #if MAIN
! 12151: RanParms empty_RanParms = Init_RanParms;
! 12152: #else
! 12153: extern RanParms empty_RanParms;
! 12154: #endif
! 12155:
! 12156: RanParms *alloc_ranparms();
! 12157: RanParms *dup_ranparms();
! 12158: char *ranparms_toa();
! 12159: RanParms *ato_ranparms();
! 12160: fwrb_ranparms();
! 12161: int frdb_ranparms();
! 12162:
! 12163: /* Char - a character: isolated, elementary symbol of the writing system;
! 12164: linguists might call this a `graph' */
! 12165: typedef struct Char {
! 12166: Ident ident; /* feature bits */
! 12167: Bbx bx;
! 12168: Scoor csp; /* space before character in Txtln (abs. coords) */
! 12169: long area; /* no. pixels */
! 12170: long per; /* perimeter (all bdys) */
! 12171: Scoor basl; /* baseline (absolute coordinates, local copy) */
! 12172: /* next should be Blobl */
! 12173: int bmny; /* no. blobs in Char */
! 12174: struct Blob *fi; /* 1st in list (p.n ptrs) (bmny==0 -> fi==NULL) */
! 12175: Pval *sfv; /* scalar-features (SFv) */
! 12176: Shapes sh; /* set of shapes (size- & loc'n-invariant) */
! 12177: Bfeats *bfsp; /* binary features */
! 12178: RanParms *rp; /* randomizing parameters */
! 12179: Interpl il; /* interpretations */
! 12180: char *l; /* label (ASCII string in malloc space) */
! 12181: } Char;
! 12182:
! 12183: #define Init_Char {IsChar,Init_Bbx,0,0L,0L,Scoor_MIN,0,NULL,NULL,Init_Shapes,NULL,NULL,Init_Interpl,NULL}
! 12184: #if MAIN
! 12185: Char empty_Char = Init_Char;
! 12186: #else
! 12187: extern Char empty_Char;
! 12188: #endif
! 12189:
! 12190: /* Char.ident flags: */
! 12191: #define Char_spelled 00000000001 /* Its 1st Interp is in correct spelling */
! 12192: #define Char_confused 00000000002 /* The classifier may have confused this */
! 12193: #define Char_termhyp 00000000004 /* a terminal hyphen of its Word */
! 12194: #define Char_omit 00000000010 /* can be omitted */
! 12195: #define Char_label 00000000020 /* has an ASCII string label */
! 12196: #define Char_ranparms 00000000040 /* has RanParms */
! 12197: #define Char_split 00000000100 /* resulted from splitting a Char */
! 12198: #define Char_merged 00000000200 /* resulted from merging Chars */
! 12199:
! 12200: typedef struct Chars {
! 12201: int mny; /* mny==0 -> cpa==NULL */
! 12202: Char **cpa; /* pts to NULL-term'd array of ptrs (in malloc space) */
! 12203: } Chars;
! 12204:
! 12205: #define Init_Chars {0,NULL}
! 12206: #if MAIN
! 12207: Chars empty_Chars = Init_Chars;
! 12208: #else
! 12209: extern Chars empty_Chars;
! 12210: #endif
! 12211:
! 12212: /* CharF - Char external file format */
! 12213: typedef struct CharF {
! 12214: Ident ident; /* feature bits: IsChar must be set */
! 12215: Bbx bx;
! 12216: Scoor csp; /* space before character in Txtln (abs. coords) */
! 12217: long area;
! 12218: long per;
! 12219: short bmny; /* no. blobs to follow */
! 12220: short imny; /* no. interpretations (follows immediately) */
! 12221: short sfmny; /* no. scalar features (follows immediately) */
! 12222: short shmny; /* no. shape features (follows immediately) */
! 12223: short bfmny; /* no. binary features (follows immediately) */
! 12224: /* if ident&Char_ranparms, RanParms follows CharF */
! 12225: /* if ident&Char_label, label follows CharF ('\0'-terminated string) */
! 12226: } CharF;
! 12227:
! 12228: Char *alloc_char(); /* in Text.c */
! 12229: Char *append_char();
! 12230: Char *insert_char();
! 12231: Char *insert_char_word();
! 12232: Char *dup_char();
! 12233: Char *dup_char_etc();
! 12234: Chars *append_chars();
! 12235: Chars *dup_chars_etc();
! 12236:
! 12237: typedef struct Words {
! 12238: int mny; /* mny==0 -> wpa==NULL */
! 12239: struct Word **wpa; /* pts to NULL-term'd array of ptrs */
! 12240: } Words;
! 12241:
! 12242: #define Init_Words {0,NULL}
! 12243: #if MAIN
! 12244: Words empty_Words = Init_Words;
! 12245: #else
! 12246: extern Words empty_Words;
! 12247: #endif
! 12248:
! 12249: /* Word - one or more Chars lying in a textline close together.
! 12250: wsp (word space) is always >=0 and is scaled by xheight (of Txtln) */
! 12251: typedef struct Word {
! 12252: Ident ident; /* feature bits */
! 12253: Bbx bx;
! 12254: float wsp; /* space before word (multiple of wst*em) */
! 12255: Merit m; /* Word merit (function of its Char's merits) */
! 12256: Prob p; /* probability */
! 12257: Words ws; /* set of alternative segmentations */
! 12258: Chars cs;
! 12259: Blobs bs;
! 12260: char *l; /* label (ASCII string in malloc space) */
! 12261: int hash; /* hash key for fast equality checking */
! 12262: } Word;
! 12263:
! 12264: #define Init_Word {IsWord,Init_Bbx,0.0,0.0,0.0,Init_Words,Init_Chars,Init_Blobs,NULL,0}
! 12265: #if MAIN
! 12266: Word empty_Word = Init_Word;
! 12267: #else
! 12268: extern Word empty_Word;
! 12269: #endif
! 12270:
! 12271: /* Word-interpretation (as printable ASCII string).
! 12272: All string fields must point to malloc-space strings.
! 12273: */
! 12274: typedef struct WordInterp {
! 12275: Ident ident; /* identifies word type */
! 12276: char *s; /* entire string = pp+by+po+ps */
! 12277: char *pp; /* punctuation prefix */
! 12278: char *by; /* body of word */
! 12279: char *po; /* possessive ('s 'S) or negative (n't N'T) suffix */
! 12280: char *ps; /* punctuation suffix */
! 12281: } WordInterp;
! 12282:
! 12283: #define Init_WordInterp {IsWordInterp,NULL,NULL,NULL,NULL,NULL}
! 12284: #if MAIN
! 12285: WordInterp empty_WordInterp = Init_WordInterp;
! 12286: #else
! 12287: extern WordInterp empty_WordInterp;
! 12288: #endif
! 12289:
! 12290: WordInterp *dup_wordinterp_etc();
! 12291:
! 12292: /* Word.ident & WordInterp.ident flags: */
! 12293: #define Word_spelled 00000000001 /* by spells correctly */
! 12294: #define Word_wf 00000000002 /* s is well-formed */
! 12295: #define Word_ok 00000000004 /* s is ok ("acceptable") */
! 12296: #define Word_numeric 00000000010 /* by is numeric */
! 12297: #define Word_initcap 00000000020 /* by has initial capital */
! 12298: #define Word_allcaps 00000000040 /* by is all caps */
! 12299: #define Word_hyphens 00000000100 /* by has imbedded hyphens */
! 12300: #define Word_slashes 00000000200 /* by has imbedded slashes */
! 12301: #define Word_endsent 00000000400 /* end of sentence: ps has .!? */
! 12302: #define Word_termhyp 00000001000 /* some interpretation ends with hyphen */
! 12303: #define Word_label 00000002000 /* has an ASCII string label */
! 12304: #define Word_allalp 00000004000 /* s is all alphabetic */
! 12305: #define Word_bodalp 00000010000 /* by is all alphabetic */
! 12306:
! 12307: /* WordF - Word external file format */
! 12308: typedef struct WordF {
! 12309: Ident ident; /* feature bits: IsWord must be set */
! 12310: Bbx bx;
! 12311: float wsp; /* space before word (multiple of thr) */
! 12312: float m; /* merit */
! 12313: short wmny; /* no. Words (in Word.ws) to follow this Word */
! 12314: short cmny; /* no. Chars to follow this Word */
! 12315: short bmny; /* no. Blobs to follow this Word */
! 12316: /* if ident&Word_label, label follows WordF ('\0'-terminated string) */
! 12317: } WordF;
! 12318:
! 12319: /* constant pitch model for a Txtln */
! 12320: typedef struct ConstPitch {
! 12321: Ems w; /* Character pitch */
! 12322: Scoor o; /* origin (one of the character break points) */
! 12323: float r; /* max/min autocorrelation ratio - the larger the better */
! 12324: } ConstPitch;
! 12325:
! 12326: #define Init_ConstPitch {0.0,0,0.0}
! 12327: #if MAIN
! 12328: ConstPitch empty_ConstPitch = Init_ConstPitch;
! 12329: #else
! 12330: extern ConstPitch empty_ConstPitch;
! 12331: #endif
! 12332:
! 12333: typedef struct Txtlns {
! 12334: short mny;
! 12335: struct Txtln **lpa; /* to array of Txtln's (if mny==0, lpa==NULL) */
! 12336: } Txtlns;
! 12337:
! 12338: #define Init_Txtlns {0,NULL}
! 12339: #if MAIN
! 12340: Txtlns empty_Txtlns = Init_Txtlns;
! 12341: #else
! 12342: extern Txtlns empty_Txtlns;
! 12343: #endif
! 12344:
! 12345: /* Text Line */
! 12346: #define Txtln_label 00000000004 /* has an ASCII string label */
! 12347: #define Txtln_size 00000000002 /* dominant text size chosen */
! 12348: #define Txtln_basl 00000000001 /* dominant baseline chosen */
! 12349:
! 12350: typedef struct Txtln {
! 12351: Ident ident;
! 12352: Bbx bx;
! 12353: Pts size; /* dominant text size (0 means unknown) */
! 12354: Scoor basl; /* dominant baseline (absolute y coordinate) */
! 12355: short *proj; /* ptr to malloc space projection array */
! 12356: ConstPitch *cp; /* ptr to malloc space constant-pitch model */
! 12357: Merit m; /* merit */
! 12358: Txtlns ls; /* alternative Txtln segmentations */
! 12359: Words ws; /* sorted asc. on x */
! 12360: Chars cs; /* sorted asc. on bx.a.x */
! 12361: Blobs bs; /* misc. non-char blobs */
! 12362: char *l; /* label (ASCII string in malloc space) */
! 12363: } Txtln;
! 12364:
! 12365: #define Init_Txtln {IsTxtln,Init_Bbx,0.0,0,NULL,NULL,0.0,Init_Txtlns,Init_Words,Init_Chars,Init_Blobs,NULL}
! 12366: #if MAIN
! 12367: Txtln empty_Txtln = Init_Txtln;
! 12368: #else
! 12369: extern Txtln empty_Txtln;
! 12370: #endif
! 12371:
! 12372: /* Text Line */
! 12373: typedef struct TxtlnF {
! 12374: Ident ident; /* IsTxtln must be set */
! 12375: Bbx bx;
! 12376: Scoor basl; /* baseline (absolute y coordinate) */
! 12377: Pts size; /* text size (<=0.0 means none is known) */
! 12378: short pmny; /* no. shorts in projection array to follow */
! 12379: float m; /* merit */
! 12380: short lmny; /* no. alternative txtlns to follow */
! 12381: short wmny; /* no. words to follow */
! 12382: short cmny; /* no. chars to follow */
! 12383: int bmny; /* no. blobs to follow */
! 12384: /* if ident&Txtln_label, label follows TxtlnF ('\0'-terminated string) */
! 12385: } TxtlnF;
! 12386:
! 12387: /* blocks of text */
! 12388: typedef struct Blocks {
! 12389: short mny; /* if mny==0, bpa==NULL */
! 12390: struct Block **bpa; /* to NULL-term'd array of ptrs */
! 12391: } Blocks;
! 12392:
! 12393: #define Init_Blocks {0,NULL}
! 12394: #if MAIN
! 12395: Blocks empty_Blocks = Init_Blocks;
! 12396: #else
! 12397: extern Blocks empty_Blocks;
! 12398: #endif
! 12399:
! 12400: /* block of text */
! 12401: typedef struct Block {
! 12402: Ident ident;
! 12403: Bbx bx; /* bounding box of block */
! 12404: Radians skew; /* skew angle (as correction to Page.skew) */
! 12405: Radians shear; /* shear angle (as correction to Page.shear) */
! 12406: Ems wst; /* word-space threshhold */
! 12407: Merit m; /* merit */
! 12408: Blocks bks; /* Blocks nested within this one */
! 12409: Txtlns ls;
! 12410: Words ws;
! 12411: Chars cs;
! 12412: Blobs bs;
! 12413: char *l; /* label (ASCII string in malloc space) */
! 12414: } Block;
! 12415:
! 12416: #define Init_Block {IsBlock,Init_Bbx,0.0,0.0,0.0,0.0,Init_Blocks,Init_Txtlns,Init_Words,Init_Chars,Init_Blobs,NULL}
! 12417: #if MAIN
! 12418: Block empty_Block = Init_Block;
! 12419: #else
! 12420: extern Block empty_Block;
! 12421: #endif
! 12422:
! 12423: /* Ident bits for Blocks */
! 12424: #define Block_wst 00000000001 /* word-space-thresh set up */
! 12425: #define Block_label 00000000002 /* has an ASCII string label */
! 12426:
! 12427: #define Block_mb (1)
! 12428:
! 12429: /* block of text */
! 12430: typedef struct BlockF {
! 12431: Ident ident; /* IsBlock must be set */
! 12432: Bbx bx;
! 12433: Ems wst; /* word-space threshold */
! 12434: float skew;
! 12435: float shear;
! 12436: #if Block_mb
! 12437: float m;
! 12438: short bkmny;
! 12439: #endif
! 12440: short lmny;
! 12441: short wmny;
! 12442: int cmny;
! 12443: int bmny;
! 12444: /* if ident&Block_label, label follows BlockF ('\0'-terminated string) */
! 12445: } BlockF;
! 12446:
! 12447: /* page */
! 12448: typedef struct Page {
! 12449: Ident ident;
! 12450: Bbx bx; /* extreme indices in pixels */
! 12451: short res_x; /* resolution in pixels/inch: x & y */
! 12452: short res_y;
! 12453: Radians skew; /* skew angle */
! 12454: Radians shear; /* shear correction */
! 12455: Blocks bks; /* blocks */
! 12456: Txtlns ls; /* textlines (those not in any block) */
! 12457: Words ws; /* words (not in any textline) */
! 12458: Chars cs; /* chars (not in any word) */
! 12459: Blobs bs; /* blobs (not in any char) */
! 12460: char *l; /* label (ASCII string in malloc space) */
! 12461: } Page;
! 12462:
! 12463: #define Init_Page {IsPage,Init_Bbx,0,0,0.0,0.0,Init_Blocks,Init_Txtlns,Init_Words,Init_Chars,Init_Blobs,NULL}
! 12464: #if MAIN
! 12465: Page empty_Page = Init_Page;
! 12466: #else
! 12467: extern Page empty_Page;
! 12468: #endif
! 12469:
! 12470: #define Page_label 00000000001 /* has a label */
! 12471:
! 12472: /* Pages of text */
! 12473: typedef struct Pages {
! 12474: unsigned short mny; /* if mny==0, pa==NULL */
! 12475: struct Page **pa; /* to NULL-term'd array of ptrs */
! 12476: } Pages;
! 12477:
! 12478: #define Init_Pages {0,NULL}
! 12479: #if MAIN
! 12480: Pages empty_Pages = Init_Pages;
! 12481: #else
! 12482: extern Pages empty_Pages;
! 12483: #endif
! 12484:
! 12485: typedef struct PageF {
! 12486: Ident ident; /* IsPage bit must be set */
! 12487: short res_x,res_y; /* resolution in pixels/inch: x & y */
! 12488: Bbx bx; /* extreme indices in pixels */
! 12489: float skew; /* original page skew angle, radians */
! 12490: float shear; /* original page shear angle, radians */
! 12491: short bkmny; /* no. blocks */
! 12492: short lmny; /* no. textlines (not in any block) */
! 12493: short wmny; /* no. words (not in any textline) */
! 12494: int cmny; /* no. chars (not in any word) */
! 12495: int bmny; /* no. blobs (not in any char)) */
! 12496: /* if ident&Page_label, label follows PageF ('\0'-terminated string) */
! 12497: } PageF;
! 12498:
! 12499: #define Page_new 00000000001 /* Page is in ``new'' format */
! 12500:
! 12501: /* Each Dim-file begins with a Doc record */
! 12502: typedef struct Doc {
! 12503: unsigned short version; /* file format version number */
! 12504: Pages ps;
! 12505: char *l; /* ASCII label */
! 12506: } Doc;
! 12507:
! 12508: #define Init_Doc {0,Init_Pages,NULL}
! 12509: #if MAIN
! 12510: Doc empty_Doc = Init_Doc;
! 12511: #else
! 12512: extern Doc empty_Doc;
! 12513: #endif
! 12514:
! 12515: char *ident_toa();
! 12516: Ident cto_ident();
! 12517: Ident cto_flag();
! 12518: char *merit_toa();
! 12519: Page *alloc_page();
! 12520: char *page_toa();
! 12521: Page *dup_page();
! 12522: Page *dup_page_etc();
! 12523: Block *alloc_block();
! 12524: char *block_toa();
! 12525: Block *dup_block();
! 12526: Block *dup_block_etc();
! 12527: Block *append_block();
! 12528: Blocks *dup_blocks_etc();
! 12529: ConstPitch *alloc_constpitch();
! 12530: char *constpitch_toa();
! 12531: Txtln *alloc_txtln();
! 12532: char *txtln_toa();
! 12533: Word *alloc_word();
! 12534: char *word_toa();
! 12535: boolean eq_word();
! 12536: int hash_word();
! 12537: Char *alloc_char();
! 12538: char *char_toa();
! 12539: Pp *char_centroid();
! 12540: Char *char_of_blob();
! 12541: char *interp_toa();
! 12542: char *blob_toa();
! 12543: Pp *blob_centroid();
! 12544: char *runf_toa();
! 12545: char *runfs_toa();
! 12546: char *pp_toa();
! 12547: char *bdyedge_toa();
! 12548: Blob *dup_blob();
! 12549: Blob *dup_blob_etc();
! 12550: Blob *dup_blobl_etc();
! 12551: Blob *runs_to_runs();
! 12552: Blobs *dup_blobs_etc();
! 12553: Blobs *blobl_to_blobs();
! 12554: Interp *alloc_interp();
! 12555: Interp *dup_interp();
! 12556: Interpl *dup_interpl_etc();
! 12557: Interps *dup_interps_etc();
! 12558: Word *append_word();
! 12559: Word *insert_word();
! 12560: Word *insert_word_txtln();
! 12561: Word *dup_word();
! 12562: Word *dup_word_etc();
! 12563: Words *dup_words_etc();
! 12564: Txtln *dup_txtln();
! 12565: Txtln *dup_txtln_etc();
! 12566: Txtlns *dup_txtlns_etc();
! 12567: Block *dup_block();
! 12568: Block *dup_block_etc();
! 12569: Radians add_ang();
! 12570: Radians subtract_ang();
! 12571:
! 12572: /* in-line macroes */
! 12573:
! 12574: /* Merge the `source' Bbx into the `destination' Bbx, expanding the dest Bbx
! 12575: as required. The source Bbx is unmodified. Usage:
! 12576: merge_bbx(s,d)
! 12577: Bbx *s,*d;
! 12578: */
! 12579: #define merge_bbx(s,d) { \
! 12580: if((s)->a.x < (d)->a.x) (d)->a.x = (s)->a.x; \
! 12581: if((s)->a.y < (d)->a.y) (d)->a.y = (s)->a.y; \
! 12582: if((s)->b.x > (d)->b.x) (d)->b.x = (s)->b.x; \
! 12583: if((s)->b.y > (d)->b.y) (d)->b.y = (s)->b.y; \
! 12584: }
! 12585:
! 12586: /* Experimental implementation of a data structure for maintaining a set
! 12587: of distinct Words whose merit falls within a dynamically-varying range.
! 12588: This implementation is worst-case quadratic time.
! 12589: BUGS: insert_wordset shouldn't duplicate the word.
! 12590: */
! 12591:
! 12592: #define dbg_ws (0) /* if !=0, enable WordSet debugging tracing */
! 12593:
! 12594: typedef struct WordSet {
! 12595: double cut; /* cut-fraction */
! 12596: int cap; /* capacity: maximum number permitted at any time */
! 12597: double top; /* maximum merit seen since allocation */
! 12598: Words ws; /* sorted by top-choice merit */
! 12599: Word *max,*min; /* maximum/minimum entries currently in ws */
! 12600: int high; /* high-water: max. no. entries in history */
! 12601: } WordSet;
! 12602: #define Init_WordSet {1.0,INT_MAX,0.0,Init_Words,NULL,NULL,0}
! 12603: #if MAIN
! 12604: WordSet empty_WordSet = Init_WordSet;
! 12605: #else
! 12606: extern WordSet empty_WordSet;
! 12607: #endif
! 12608:
! 12609: #define size_wordset(s) ((s)->ws.mny)
! 12610: #define top_wordset(s) ((s)->top)
! 12611: #define max_wordset(s) ((s)->max)
! 12612: #define min_wordset(s) ((s)->min)
! 12613: #define max_wordmerit(s) ((max_wordset((s))!=NULL)? (max_wordset((s)))->m: 0.0)
! 12614: #define min_wordmerit(s) ((min_wordset((s))!=NULL)? (min_wordset((s)))->m: 0.0)
! 12615:
! 12616: Merit wordmerit();
! 12617: WordSet *alloc_wordset();
! 12618: boolean insert_wordset();
! 12619: Word *remove_wordset();
! 12620: int free_wordset_etc();
! 12621: err_wordset();
! 12622: 0707070035351137151006640007620000050000010263160476773367000001000000001554Units.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 12623: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 12624: /* The copyright notice does not imply actual or intended publication. */
! 12625: /* AUTHORS: */
! 12626: /* H. S. Baird - ATT-BL MH - first versions */
! 12627:
! 12628: #define UNITS "icpPsu" /* units notation for: inches, cm, points, picas,
! 12629: scanner pixel (Scoor), and basic unit (also Scoor) */
! 12630:
! 12631: #define INCHES_PER_POINT (0.0138) /* cf. Chicago Manual of Style */
! 12632:
! 12633: #define RADIANS_PER_DEGREE (PI/180.0)
! 12634: #define DtoR (RADIANS_PER_DEGREE) /* degrees * DtoR = radians */
! 12635:
! 12636: #define Radians double /* angle in radians */
! 12637:
! 12638: /* machine-independent I/O has a resolution of 0.1 second of arc */
! 12639: #define fwri_Radians(F,V) fwri_int3((F),(V)*2062648.1)
! 12640: #define frdi_Radians(F) (frdi_int3(F)/(Radians)2062648.1)
! 12641: 0707070035351137161006640007620000050000010263200476773367000001000000012421abort.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 12642: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 12643: /* The copyright notice does not imply actual or intended publication. */
! 12644: /* AUTHORS: */
! 12645: /* H. S. Baird - ATT-BL MH - first versions */
! 12646:
! 12647: /* abort.h - three terse message, warning, and abort functions.
! 12648: out(s,a,...) print message to stdout
! 12649: err(s,a,...) print warning to stderr
! 12650: abort(s,a,...) complain to stderr and exit abnormally.
! 12651: The 's' argument is a printf string, and the 'a',... are (up to 15) arguments
! 12652: matching %-fields. These routines prefix the program name and append `\n' to
! 12653: the printf string, then write to:
! 12654: `out': stdout
! 12655: `err' & `abort': stderr
! 12656: Abort also says " - abort", and exits abnormally.
! 12657: This #include should be preceded by `#define CMDNAME "xxx"' so that `xxx:'
! 12658: will be prefixed to msg and abort strings. */
! 12659:
! 12660: #ifndef CMDNAME
! 12661: #define CMDNAME "hsb"
! 12662: #endif
! 12663:
! 12664: #define MSGMAX 120
! 12665:
! 12666: #ifndef boolean
! 12667: #define boolean int
! 12668: #define T 1
! 12669: #define F 0
! 12670: #endif
! 12671:
! 12672: /* WARNING: these function-call versions do not port well:
! 12673: e.g. floating-point arguments are botched on MIPS and SGI machines */
! 12674:
! 12675: out(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
! 12676: char *s;
! 12677: { static char m[MSGMAX];
! 12678: strcpy(m,CMDNAME);
! 12679: strcat(m,": ");
! 12680: strcat(m,s);
! 12681: strcat(m,"\n");
! 12682: fprintf(stdout,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
! 12683: }
! 12684:
! 12685: err(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
! 12686: char *s;
! 12687: { char m[MSGMAX];
! 12688: strcpy(m,CMDNAME);
! 12689: strcat(m,": ");
! 12690: strcat(m,s);
! 12691: strcat(m,"\n");
! 12692: fprintf(stderr,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
! 12693: }
! 12694:
! 12695: abort(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
! 12696: char *s;
! 12697: { static char m[MSGMAX];
! 12698: strcpy(m,s);
! 12699: strcat(m," - abort");
! 12700: err(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
! 12701: exit(1);
! 12702: }
! 12703:
! 12704: /* These hybrid macro/function forms ports well, but are awkward to use... */
! 12705:
! 12706: char *_F(s)
! 12707: char *s;
! 12708: { static char m[MSGMAX];
! 12709: strcpy(m,CMDNAME);
! 12710: strcat(m,": ");
! 12711: strcat(m,s);
! 12712: strcat(m,"\n");
! 12713: return(m);
! 12714: }
! 12715:
! 12716: #define out0(Z) fprintf(stdout,_F(Z))
! 12717: #define out1(Z,A) fprintf(stdout,_F(Z),A)
! 12718: #define out2(Z,A,B) fprintf(stdout,_F(Z),A,B)
! 12719: #define out3(Z,A,B,C) fprintf(stdout,_F(Z),A,B,C)
! 12720: #define out4(Z,A,B,C,D) fprintf(stdout,_F(Z),A,B,C,D)
! 12721: #define out5(Z,A,B,C,D,E) fprintf(stdout,_F(Z),A,B,C,D,E)
! 12722: #define out6(Z,A,B,C,D,E,F) fprintf(stdout,_F(Z),A,B,C,D,E,F)
! 12723: #define out7(Z,A,B,C,D,E,F,G) fprintf(stdout,_F(Z),A,B,C,D,E,F,G)
! 12724: #define out8(Z,A,B,C,D,E,F,G,H) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H)
! 12725: #define out9(Z,A,B,C,D,E,F,G,H,I) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H,I)
! 12726: #define out10(Z,A,B,C,D,E,F,G,H,I,J) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H,I,J)
! 12727: #define out11(Z,A,B,C,D,E,F,G,H,I,J,K) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H,I,J,K)
! 12728:
! 12729: #define err0(Z) fprintf(stderr,_F(Z))
! 12730: #define err1(Z,A) fprintf(stderr,_F(Z),A)
! 12731: #define err2(Z,A,B) fprintf(stderr,_F(Z),A,B)
! 12732: #define err3(Z,A,B,C) fprintf(stderr,_F(Z),A,B,C)
! 12733: #define err4(Z,A,B,C,D) fprintf(stderr,_F(Z),A,B,C,D)
! 12734: #define err5(Z,A,B,C,D,E) fprintf(stderr,_F(Z),A,B,C,D,E)
! 12735: #define err6(Z,A,B,C,D,E,F) fprintf(stderr,_F(Z),A,B,C,D,E,F)
! 12736: #define err7(Z,A,B,C,D,E,F,G) fprintf(stderr,_F(Z),A,B,C,D,E,F,G)
! 12737: #define err8(Z,A,B,C,D,E,F,G,H) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H)
! 12738: #define err9(Z,A,B,C,D,E,F,G,H,I) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H,I)
! 12739: #define err10(Z,A,B,C,D,E,F,G,H,I,J) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H,I,J)
! 12740: #define err11(Z,A,B,C,D,E,F,G,H,I,J,K) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H,I,J,K)
! 12741:
! 12742: char *_G(s)
! 12743: char *s;
! 12744: { static char m[MSGMAX];
! 12745: strcpy(m,CMDNAME);
! 12746: strcat(m,": ");
! 12747: strcat(m,s);
! 12748: strcat(m," - abort\n");
! 12749: return(m);
! 12750: }
! 12751:
! 12752: #define abort0(Z) fprintf(stderr,_G(Z))
! 12753: #define abort1(Z,A) fprintf(stderr,_G(Z),A)
! 12754: #define abort2(Z,A,B) fprintf(stderr,_G(Z),A,B)
! 12755: #define abort3(Z,A,B,C) fprintf(stderr,_G(Z),A,B,C)
! 12756: #define abort4(Z,A,B,C,D) fprintf(stderr,_G(Z),A,B,C,D)
! 12757: #define abort5(Z,A,B,C,D,E) fprintf(stderr,_G(Z),A,B,C,D,E)
! 12758: #define abort6(Z,A,B,C,D,E,F) fprintf(stderr,_G(Z),A,B,C,D,E,F)
! 12759: #define abort7(Z,A,B,C,D,E,F,G) fprintf(stderr,_G(Z),A,B,C,D,E,F,G)
! 12760: #define abort8(Z,A,B,C,D,E,F,G,H) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H)
! 12761: #define abort9(Z,A,B,C,D,E,F,G,H,I) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H,I)
! 12762: #define abort10(Z,A,B,C,D,E,F,G,H,I,J) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H,I,J)
! 12763: #define abort11(Z,A,B,C,D,E,F,G,H,I,J,K) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H,I,J,K)
! 12764:
! 12765: boolean ask_more()
! 12766: { FILE *tty;
! 12767: char reply[20];
! 12768: static int skip = 0;
! 12769: if(skip<=0) {
! 12770: fputs("MORE? ",(tty=fopen("/dev/tty","w"))); fclose(tty);
! 12771: fgets(reply,20,(tty=fopen("/dev/tty","r"))); fclose(tty);
! 12772: switch (reply[0]) {
! 12773: case '\0': case 'y': case 'Y':
! 12774: return(T);
! 12775: case 'n': case 'N': case 'q': case 'Q':
! 12776: return(F);
! 12777: case '0': case '1': case '2': case '3': case '4':
! 12778: case '5': case '6': case '7': case '8': case '9':
! 12779: skip = atoi(reply);
! 12780: return(T);
! 12781: case '*':
! 12782: skip = INT_MAX;
! 12783: return(T);
! 12784: default:
! 12785: skip = 0;
! 12786: return(T);
! 12787: };
! 12788: }
! 12789: else skip--;
! 12790: return(T);
! 12791: }
! 12792:
! 12793: boolean ask_quit()
! 12794: { FILE *tty;
! 12795: char reply[20];
! 12796: fputs("QUIT? ",(tty=fopen("/dev/tty","w"))); fclose(tty);
! 12797: fgets(reply,20,(tty=fopen("/dev/tty","r"))); fclose(tty);
! 12798: switch (reply[0]) {
! 12799: case 'y': case 'Y':
! 12800: return(F);
! 12801: case 'n': case 'N': case 'q': case 'Q':
! 12802: return(T);
! 12803: };
! 12804: return(F);
! 12805: }
! 12806:
! 12807: 0707070035351137171006640007620000050000010263220476773367100000600000171751bcp.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 12808: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 12809: /* The copyright notice does not imply actual or intended publication. */
! 12810: /* AUTHORS: */
! 12811: /* H. S. Baird - ATT-BL MH - first versions */
! 12812: /* T. J. ThompsonT - ATT-BL HO - extensions */
! 12813:
! 12814: /* bcp.c - translate among binary image file formats, optionally trimming,
! 12815: shifting, scaling, and rotating the image on the fly. Scaling is by
! 12816: arbitrary real factors, separately in X & Y. Rotation is still crude and
! 12817: slow.
! 12818: USAGE:
! 12819: bcp [options...] [I [O]]
! 12820: I/O:
! 12821: If O is omitted, all output is concatenated to stdout.
! 12822: If I is also omitted, all input is read from stdin.
! 12823: If I is a filename, it is the sole input; but, if it is a directory name,
! 12824: then every leaf of its file tree is processed in turn; and, in this case,
! 12825: if O also is specified, it is forced to become the root directory
! 12826: of an isomorphic tree of output files (this use of Unix file trees
! 12827: may be defeated using compile-time option FILE_TREE).
! 12828:
! 12829: [PROPOSED: An input file may be a catenation of pages. These may vary
! 12830: in TYPE and other parameters. They will all be translated to the same
! 12831: output type, and catenated to one file, each with a complete translated
! 12832: header. Generally, a complete picfile header must be repeated at the
! 12833: top of each page: exceptions include TYPE=cdf, which packs pages in its
! 12834: own peculiar way.]
! 12835:
! 12836: OPTIONS:
! 12837: NOTE: lengths, distances, and pixel indices are assumed to be in
! 12838: units of pixels (scanner units), unless one of "icpPs" is appended,
! 12839: meaning inches, cm, points, picas, or (explicitly) scanner pixels.
! 12840: This applies to option: -w (seems buggy).
! 12841:
! 12842: -B[io] read/write bitfile(9.5) format (doesn't use TYPE= header).
! 12843: [doesn't run-length encode yet: may be bulky.]
! 12844: -M write TYPE=bitmap format.
! 12845: -P write Postscript format (only on Suns; by Tim Thompson, ATT-BL HO)
! 12846: -Rx[,y] force output resolutions to x,y (overrides -xX[,Y]) (pixels/inch).
! 12847: Requires a RES=X Y line in the header.
! 12848: -R= Force the output resolution to be equal to the greater of
! 12849: the input resolutions.
! 12850: -S write Sun rasterfile format (only on Suns; by Tim Thompson,
! 12851: ATT-BL HO)
! 12852: -Tt when reading TYPE=dump, binarize the image by thresholding each
! 12853: pixel value as follows: (pixel<t)? black: white. (default: -T128)
! 12854: -Ww shrink-wrap output around black artwork, surrounding it with equal
! 12855: margins of width w (pixels), then translate so that the left-top
! 12856: corner of the margin box is at 0,0 (works only with TYPE=document-
! 12857: image input). (w must be >= 0)
! 12858: -Zx[,y] set input resolution to RES=x y (overriding existing RES, if any)
! 12859: -b write binary format (TYPE=binary)
! 12860: -d? trace to stderr:
! 12861: -dR comment on any change in resolution
! 12862: -dc point out oddities in cdf files which are, by default,
! 12863: silently corrected
! 12864: -dh file headers (a good first debugging step)
! 12865: -dm margins
! 12866: -dr runs (exhaustive, voluminous)
! 12867: -ds status and summary statistics (brief)
! 12868: -g31 write CCITT FAX Group 3 1-dim encoding
! 12869: -31 ditto
! 12870: -g32 write CCITT FAX Group 3 2-dim encoding (see also -k option)
! 12871: -32 ditto
! 12872: -g4 write CCITT FAX Group 4 encoding (the default output format)
! 12873: -4 ditto
! 12874: -kK set the 'k' for g32 encoding on output (default: -k4)
! 12875: -oX,Y offset the result by X,Y (merely shift the bounding box)
! 12876: -p write TYPE=dump NCHAN=1 format; input binary pixels
! 12877: are mapped to grey as follows: (pixel==white)? 255: 0.
! 12878: -r write rle format (this is Pavlidis' obsolescent OCR format)
! 12879: -t[lrbN] top of the page is really at the left/right/bottom;
! 12880: after all other transformations are carried out, the image
! 12881: will be rotated to bring the real top of page to the top.
! 12882: By arbitrary convention, the top-left corner of the rotated
! 12883: image will be equal to the top-left corner of the image
! 12884: resulting from all the other transformations.
! 12885: [UNFINISHED, UNDER DEVELOPMENT: -tr & -tb; -tN, where N is a
! 12886: numeric string, is interpreted as a counterclockwise rotation by
! 12887: N degrees: for now, only handle +/-20 degrees. The present code
! 12888: for -tN is slow and subject to aliasing.]
! 12889: -v reverse video: swap black and white
! 12890: -wL,T,R,B specify window to select:
! 12891: (L,T) is the left-top (origin) and (R,B) the OPEN right-bottom
! 12892: corner (i.e. the corner coordinates are not included.) A '%'
! 12893: argument defaults to the input window parameter.
! 12894: [NOTE: since non-zero L,T windows are still not everywhere well
! 12895: supported (by pcp, met, etc), it might be best to shift the
! 12896: new L,T to 0,0 on output -- but this is not done now.]
! 12897: -xX[,Y] expansion factor(s), horizontally and vertically;
! 12898: if only one is specified, they are assumed equal
! 12899: (default: -x1.0,1.0) May be overridden by -Rx[,y].
! 12900: Requires a RES=X Y line in the header.
! 12901: DESCRIPTION
! 12902: This translates among these formats of binary images:
! 12903: ccitt-g31, ccitt-g32, ccitt-g4, picture (TYPE=dump NCHAN=1), binary, rle,
! 12904: bitfile(9.5), cdf, Sun rasterfile (TYPE=bitmap), and Postscript. All require
! 12905: a TYPE= header in picfile format (see below), except bitfile(9.5) (as a result,
! 12906: to read these, must use special option: -Bi). Most require WINDOW=ox oy cx cy
! 12907: and RES=x y header lines also.
! 12908: Optionally, the image may be modified on the fly by the following
! 12909: operations performed in this order:
! 12910: trimming - a subset of the input image is selected (-w option)
! 12911: shifting - the origin is shifted (-o)
! 12912: scaling - real scaling factors are applied, in X & Y separately (-x, -R)
! 12913: rotation - by 90, 180, 270 degrees - UNDER DEVELOPMENT (-t option)
! 12914: reverse-video - swap black and white (-v option)
! 12915: Note that scaling changes the effective digitizing resolution by arbitrary
! 12916: real factors (expansion or contraction), in X and Y separately. Presently,
! 12917: this is accomplished naively by replication or deletion of pixels. If it is
! 12918: ever desired to apply more interesting image-processing techniques (such as
! 12919: smoothing and resampling), the required changes may be safely confined to
! 12920: functions transform_rlels() (in bcp.c) & transform_rlel() (in rlelib.c).
! 12921: Accepts TYPE=document-image (or TYPE=dim), flattening its hierarchy,
! 12922: and writes it out as a single page image.
! 12923: PICFILE FORMAT (briefly summarized; see picture(5))
! 12924: Each picture file comprises an ASCII header followed by binary data.
! 12925: The header is terminated by two newlines (an empty line). A typical header is:
! 12926: TYPE=ccitt-g4
! 12927: WINDOW=0 0 640 480
! 12928: RES=300 300
! 12929: (note the final empty line)
! 12930: TYPE must come first. The other lines may come in any order. WINDOW gives
! 12931: the x,y coordinates of the upper left corner (inclusive) and lower right
! 12932: corners (exclusive). Typically, an image of WxH pixels will be described
! 12933: by WINDOW=0 0 W H. RES=X Y gives the digitizing resolution horizontally and
! 12934: vertically, in integral pixels/inch. Supported TYPEs include:
! 12935:
! 12936: dump A two-dimensional array of pixel structures. NCHAN=1 is required:
! 12937: one byte per pixel. On input, the grey pixel values are thresholded
! 12938: to binary (see option -T). On output, black is 0 and white is 255.
! 12939:
! 12940: bitmap One bit/pixel, packed into bytes high-order bit first. Black is `1'.
! 12941: Each horizontal row is padded to a 16-bit boundary with `0'.
! 12942: (This is identical to Sun rasterfile format, except for the ASCII
! 12943: header.)
! 12944:
! 12945: ccitt-g4 CCITT FAX Group 4 compressed image. Similarly, ccitt-g31 means
! 12946: Group 3/1-D and ccitt-g32 means Group 3/2-D.
! 12947:
! 12948: (Obsolescent 112 formats:
! 12949: rle A run-length coding, better for binary images (see rle.h).
! 12950: binary 1 bit/pixel, packed into bytes low-order bit first. Black is `1'.
! 12951: Each horizontal row is padded to a full byte with `0'.)
! 12952:
! 12953: NOTE: bitfile(9.5) doesn't use an ASCII header.
! 12954:
! 12955: (Odd formats in use outside 112, sometimes very heavily:
! 12956: cdf supported on input only, and only the first page of several.
! 12957: tiff not yet supported.)
! 12958:
! 12959: IMPLEMENTATION STATUS
! 12960: CCITT FAX ``uncompressed'' (or, ``transparent'') mode is not implemented,
! 12961: either while encoding or decoding.
! 12962: Cdf is an input-only option; Sun rasterfile and Postscript are output-only options.
! 12963: Postscript output is useful only for very small images.
! 12964: Rotations are only partially implemented, and are slow.
! 12965:
! 12966: KNOWN BUGS (30 May 89)
! 12967: WINDOW=OX OY CX CY where OX or OY are non-zero is not handled correctly
! 12968: for every combination of file types.
! 12969: Unit gets passed wrongly to vto_scoor().
! 12970: Rle can't be both inout and output (design flaw: they share a buffer).
! 12971: Beware off-by-one errors (top or bottom line omitted); has not been
! 12972: carefully checked for all file type combinations.
! 12973:
! 12974: AUTHORS
! 12975: Dec 1988 - Henry S. Baird (AT&T Bell Labs MH) - first working draft
! 12976: Mar 1989 - Tim Thompson (BL HO) - extensions for SunOS, bug fixes, etc
! 12977: */
! 12978:
! 12979: #include <stdio.h>
! 12980: #include <string.h>
! 12981: #include <ctype.h>
! 12982: #include "CPU.h"
! 12983: #define MAIN 1
! 12984: #include "stdocr.h"
! 12985: #include "rle.h"
! 12986: #include "pic.h"
! 12987: #include "Text.h"
! 12988: /* Ugly stubs just to prevent Text.h dragging in many other *.h & *.o files */
! 12989: Bfeats *alloc_bfeats(){}; free_bfeats(){}; Bfeats *dup_bfeats(){};
! 12990: fwrb_bfeats(){}; frdb_bfeats(){}; fix_lag(){}; char *classid_toa(){};
! 12991: #include "Bitmap.h"
! 12992: #include "CCITT.h"
! 12993: #include "bitio.h"
! 12994: #if FILE_TREE
! 12995: #include "Path.h"
! 12996: #endif
! 12997: #define CMDNAME "bcp"
! 12998: #include "abort.h"
! 12999:
! 13000: double atof(),sin(),cos();
! 13001: char *strchr();
! 13002:
! 13003: /* Runtime options values */
! 13004: static struct {
! 13005: boolean from_bitfile; /* -Bi */
! 13006: boolean to_bitfile; /* -Bo */
! 13007: boolean to_bitmap; /* -M */
! 13008: boolean to_g31; /* -g31 or -31 */
! 13009: boolean to_g32; /* -g32 or -32 */
! 13010: boolean to_g4; /* -g4 or -4 */
! 13011: boolean to_rle; /* -r */
! 13012: boolean to_bin; /* -b */
! 13013: boolean to_pic; /* -p */
! 13014: boolean to_post; /* -P */
! 13015: boolean to_rast; /* -S */
! 13016: boolean omit_hdr; /* -O */
! 13017: Sp out_res; /* -R (-1 = unspecified; -2 = force-equal) */
! 13018: Scoor shrinkwrap; /* -W (-1 = unspecified) */
! 13019: Sp in_res; /* -Z (SHRT_MIN,SHRT_MIN = unspecified) */
! 13020: int g32_k; /* -k */
! 13021: int metheus; /* -m */
! 13022: Sp offset; /* -o */
! 13023: boolean dbg_any;
! 13024: boolean dbg_R; /* -dR */
! 13025: boolean dbg_c; /* -dc */
! 13026: boolean dbg_h; /* -dh */
! 13027: boolean dbg_m; /* -dm */
! 13028: boolean dbg_r; /* -dr */
! 13029: boolean dbg_s; /* -ds */
! 13030: boolean show; /* -s */
! 13031: char top; /* -tT takes on values: 't', 'l', 'r', 'b', 'a' */
! 13032: float top_angle; /* -t angular value (set if top=='a') (Radians) */
! 13033: int thresh; /* -Tt */
! 13034: boolean reverse; /* -v */
! 13035: char *optarg_l; /* -w?,,, */
! 13036: char *optarg_t; /* -w,?,, */
! 13037: char *optarg_r; /* -w,,?, */
! 13038: char *optarg_b; /* -w,,,? */
! 13039: Bbx trim; /* output margins resulting from -w */
! 13040: Pp expand; /* -x */
! 13041: char *in_fn;
! 13042: char *out_fn;
! 13043: } _O = {
! 13044: F, F, F, F, F, T, F, F, F, F, F,
! 13045: F, {-1,-1}, -1, {SHRT_MIN,SHRT_MIN}, 4, -1, Init_Zero_Sp,
! 13046: F, F, F, F, F, F, F, F,
! 13047: 't',0.0,
! 13048: 128,
! 13049: F,
! 13050: NULL, NULL, NULL, NULL,
! 13051: Init_Max_Bbx,
! 13052: {1.0,1.0},
! 13053: NULL, NULL };
! 13054:
! 13055: parse_args(arc,arv)
! 13056: int arc; char **arv;
! 13057: { /* getopt support */
! 13058: int optch;
! 13059: extern int optind;
! 13060: extern char *optarg;
! 13061:
! 13062: char *metheus_ev,metheus_digit;
! 13063: char *fs;
! 13064:
! 13065: /* default metheus number */
! 13066: if((metheus_ev=(char *)getenv("FB"))!=NULL) {
! 13067: metheus_digit = metheus_ev[(int)strlen(metheus_ev)-1];
! 13068: if((int)isdigit(metheus_digit)) {
! 13069: _O.metheus = (metheus_digit - '0');
! 13070: };
! 13071: };
! 13072:
! 13073: while((optch=getopt(arc,arv,"B:MOPR:ST:W:Z:3:4bd:g:k:m:o:prst:vw:x:"))!=EOF)
! 13074: switch(optch) {
! 13075: case 'B':
! 13076: switch(*optarg) {
! 13077: case 'o':
! 13078: _O.to_bitfile = T;
! 13079: _O.to_g4 = F;
! 13080: break;
! 13081: case 'i':
! 13082: _O.from_bitfile = T;
! 13083: break;
! 13084: default:
! 13085: abort("option -B%s is illegal",optarg);
! 13086: break;
! 13087: };
! 13088: break;
! 13089: case 'M': _O.to_bitmap = T; _O.to_g4 = F; break;
! 13090: case 'O': _O.omit_hdr = T; break;
! 13091: case 'P':
! 13092: #if CPU==SUN
! 13093: _O.to_post = T; _O.to_g4 = F;
! 13094: #else
! 13095: abort("-P option available only on Suns");
! 13096: #endif
! 13097: break;
! 13098: case 'R':
! 13099: if(*optarg=='=') {
! 13100: _O.out_res.x = _O.out_res.y = -2;
! 13101: fs=NULL;
! 13102: }
! 13103: else if((fs=strtok(optarg,","))!=NULL) {
! 13104: if(strcmp(fs,"%")!=0) {
! 13105: _O.out_res.x = atoi(fs);
! 13106: };
! 13107: };
! 13108: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
! 13109: if(strcmp(fs,"%")!=0) {
! 13110: _O.out_res.y = atoi(fs);
! 13111: };
! 13112: }
! 13113: else _O.out_res.y = _O.out_res.x;
! 13114: break;
! 13115: case 'S':
! 13116: #if CPU==SUN
! 13117: _O.to_rast = T; _O.to_g4 = F;
! 13118: #else
! 13119: abort("-S option available only on Suns");
! 13120: #endif
! 13121: break;
! 13122: case 'T': _O.thresh=atoi(optarg); break;
! 13123: case 'W': _O.shrinkwrap=atoi(optarg);
! 13124: if(_O.shrinkwrap<0) {
! 13125: err("-W%d must be >=0; force to -W0",
! 13126: _O.shrinkwrap);
! 13127: _O.shrinkwrap=0;
! 13128: };
! 13129: break;
! 13130: case 'Z':
! 13131: if((fs=strtok(optarg,","))!=NULL) {
! 13132: if(strcmp(fs,"%")!=0) {
! 13133: _O.in_res.x = atoi(fs);
! 13134: };
! 13135: };
! 13136: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
! 13137: if(strcmp(fs,"%")!=0) {
! 13138: _O.in_res.y = atoi(fs);
! 13139: };
! 13140: }
! 13141: else _O.in_res.y = _O.in_res.x;
! 13142: break;
! 13143: case '3':
! 13144: switch (*optarg) {
! 13145: case '1':
! 13146: _O.to_g31=T;
! 13147: _O.to_g4=F;
! 13148: break;
! 13149: case '2':
! 13150: _O.to_g32=T;
! 13151: _O.to_g4=F;
! 13152: break;
! 13153: default:
! 13154: abort("bad option: -g3%s",optarg);
! 13155: break;
! 13156: };
! 13157: break;
! 13158: case '4': _O.to_g4=T; break;
! 13159: case 'b':
! 13160: _O.to_bin=T;
! 13161: _O.to_g4=F;
! 13162: break;
! 13163: case 'd':
! 13164: _O.dbg_any=T;
! 13165: switch(*optarg) {
! 13166: case 'R': _O.dbg_R = T; break;
! 13167: case 'c': _O.dbg_c = T; break;
! 13168: case 'h': _O.dbg_h = T; break;
! 13169: case 'm': _O.dbg_m = T; break;
! 13170: case 'r': _O.dbg_r = T; break;
! 13171: case 's': _O.dbg_s = T; break;
! 13172: };
! 13173: break;
! 13174: case 'g':
! 13175: switch (optarg[0]) {
! 13176: case '3':
! 13177: switch (optarg[1]) {
! 13178: case '1':
! 13179: _O.to_g31=T;
! 13180: _O.to_g4=F;
! 13181: break;
! 13182: case '2':
! 13183: _O.to_g32=T;
! 13184: _O.to_g4=F;
! 13185: break;
! 13186: default:
! 13187: abort("bad option: -g%s",optarg);
! 13188: break;
! 13189: };
! 13190: break;
! 13191: case '4': _O.to_g4=T; break;
! 13192: default:
! 13193: abort("bad option: -g%s",optarg);
! 13194: break;
! 13195: };
! 13196: break;
! 13197: case 'k': _O.g32_k = atoi(optarg); break;
! 13198: case 'm': _O.metheus = atoi(optarg); break;
! 13199: case 'o':
! 13200: if((fs=strtok(optarg,","))!=NULL) {
! 13201: if(strcmp(fs,"%")!=0)
! 13202: _O.offset.x = atoi(fs);
! 13203: };
! 13204: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
! 13205: if(strcmp(fs,"%")!=0)
! 13206: _O.offset.y = atoi(fs);
! 13207: };
! 13208: break;
! 13209: case 'p':
! 13210: _O.to_pic=T;
! 13211: _O.to_g4=F;
! 13212: break;
! 13213: case 'r':
! 13214: _O.to_rle = T;
! 13215: _O.to_g4 = F;
! 13216: break;
! 13217: case 's': _O.show = T; break;
! 13218: case 't': _O.top = *optarg;
! 13219: if(strchr("0123456789.+-",_O.top)!=NULL) {
! 13220: _O.top = 'a'; /* angular value */
! 13221: _O.top_angle = atof(optarg)*DtoR;
! 13222: };
! 13223: break;
! 13224: case 'v': _O.reverse = T; break;
! 13225: case 'w':
! 13226: if( (fs=strtok(optarg,","))!=NULL
! 13227: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
! 13228: _O.optarg_l = strdup(fs);
! 13229: if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
! 13230: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
! 13231: _O.optarg_t = strdup(fs);
! 13232: if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
! 13233: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
! 13234: _O.optarg_r = strdup(fs);
! 13235: if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
! 13236: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
! 13237: _O.optarg_b = strdup(fs);
! 13238: break;
! 13239: case 'x':
! 13240: if((fs=strtok(optarg,","))!=NULL) {
! 13241: if(strcmp(fs,"%")!=0) {
! 13242: if(*fs=='/')
! 13243: _O.expand.x = 1.0/atof(fs+1);
! 13244: else _O.expand.x = atof(fs);
! 13245: if(_O.expand.x<=0.0)
! 13246: _O.expand.x=1.0;
! 13247: };
! 13248: };
! 13249: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
! 13250: if(strcmp(fs,"%")!=0) {
! 13251: if(*fs=='/')
! 13252: _O.expand.y = 1.0/atof(fs+1);
! 13253: else _O.expand.y = atof(fs);
! 13254: if(_O.expand.y<=0.0)
! 13255: _O.expand.y=1.0;
! 13256: };
! 13257: }
! 13258: else _O.expand.y = _O.expand.x;
! 13259: break;
! 13260: default: break;
! 13261: };
! 13262: switch(arc-optind) {
! 13263: case 2:
! 13264: _O.out_fn = strdup(arv[optind+1]);
! 13265: case 1:
! 13266: _O.in_fn = strdup(arv[optind]);
! 13267: case 0:
! 13268: break;
! 13269: default:
! 13270: abort("<= two filenames expected");
! 13271: break;
! 13272: };
! 13273: if(_O.show&&_O.metheus==-1) {
! 13274: err("FB=/dev/omM not specified, using /dev/om0");
! 13275: _O.metheus = 0;
! 13276: };
! 13277: }
! 13278:
! 13279: unimplemented()
! 13280: { abort("unimplemented");
! 13281: }
! 13282:
! 13283: typedef struct Copy_arg {
! 13284: boolean bop; /* beginning of page */
! 13285: PIC_hdr *ph;
! 13286: int wid; /* bbx_wid(&(ph->bx)) (for speed) */
! 13287: BITFILE *bf;
! 13288: DST_table *tbl; /* for CCITT input */
! 13289: int k; /* CCITT Group 3 2-D k */
! 13290: int thresh; /* for input pic files */
! 13291: RLE_Lines rles; /* for TYPE=document-image or TYPE=dim */
! 13292: } Copy_arg;
! 13293: #define Init_Copy_arg {T,NULL,INT_MIN,NULL,NULL,4,128,Init_RLE_Lines}
! 13294: #if MAIN
! 13295: Copy_arg empty_Copy_arg = Init_Copy_arg;
! 13296: #else
! 13297: extern Copy_arg empty_Copy_arg;
! 13298: #endif
! 13299:
! 13300: /* SOURCES: return the next RLE_Line from the given file type, with run indices
! 13301: shifted to lie within [ a->ph->bx.a.x, a->ph->bx.b.x ].
! 13302: **** BUGS: not all handle non-zero a->ph->bx.a.x yet.
! 13303: */
! 13304:
! 13305: /* Handles non-zero a->ph->bx.a.x. */
! 13306: RLE_Line *cdf_mrlc_source(a)
! 13307: Copy_arg *a;
! 13308: #define dbg_cdf (0)
! 13309: { static RLE_Line rl;
! 13310: int n; /* no. pixels decoded */
! 13311: int col; /* color: 0=white, 1=black */
! 13312: int byte; /* input byte */
! 13313: int nb; /* no. bytes read for this line */
! 13314: int ni; /* nibble index: 0=1st (low-order), 1=2nd(high-order) */
! 13315: int nib; /* current nibble */
! 13316: int mult; /* multiplier for current nibble */
! 13317: int run; /* no. pixels in current run */
! 13318: RLE_Run *rp;
! 13319: #define toggle_color() {if(col) col=0; else col=1;}
! 13320: /* get next byte into `byte' */
! 13321: #define getbyte() { \
! 13322: if((byte=getc(a->ph->fp))==EOF) goto eof; nb++; \
! 13323: if(dbg_cdf) err("byte0x%x",byte); \
! 13324: }
! 13325: /* get next nibble into `nib' */
! 13326: #define getnib() { \
! 13327: if(ni) { getbyte(); ni=0; nib=byte&0x0F; } \
! 13328: else { ni=1; nib=(byte>>4); } \
! 13329: if(dbg_cdf) err("nib0x%x byte0x%x ni%d",nib,byte,ni); \
! 13330: }
! 13331: /* get next run into `run' */
! 13332: #define getrun() { \
! 13333: run=0; mult=1; \
! 13334: do {getnib(); run += mult * (nib&0x07); mult *= 8;} while(nib&0x08); \
! 13335: if(dbg_cdf) err("run%d %c",run,((col)? 'B': 'W')); \
! 13336: }
! 13337: a->bop = F;
! 13338: n=0; col=0; ni=1; nb=0; rp=rl.r;
! 13339: do { getrun();
! 13340: if(col) {/* black run */
! 13341: if(run>0) { /* ... of >0 length */
! 13342: rp->xs = a->ph->bx.a.x + n+1;
! 13343: rp->xe = a->ph->bx.a.x + (n+=run);
! 13344: if((rp-rl.r)>0 && ((rp-1)->xe >= rp->xs-1) ) {
! 13345: if(_O.dbg_c) err("cdf_mrlc_source: abutting black runs [%d,%d] & [%d,%d] - merged",
! 13346: (rp-1)->xs,(rp-1)->xe,
! 13347: rp->xs,rp->xe );
! 13348: /* merge with prior black run */
! 13349: (rp-1)->xe = rp->xe;
! 13350: }
! 13351: else rp++;
! 13352: }
! 13353: else { /* zero-length black run */
! 13354: if( _O.dbg_c && (rp-rl.r)>0 )
! 13355: err("cdf_mrlc_source: zero-length black run [%d,%d] in middle of line - ignored",
! 13356: n,n);
! 13357: };
! 13358: }
! 13359: else { /* white run */
! 13360: n+=run;
! 13361: };
! 13362: toggle_color();
! 13363: }
! 13364: while(n<a->wid);
! 13365: /* read 2 EOL nibbles */
! 13366: getnib(); getnib();
! 13367: rl.runs = rp - rl.r;
! 13368: rl.len = a->wid;
! 13369: if(rl.runs>0 && rl.r[rl.runs-1].xe>=a->wid) {
! 13370: if(_O.dbg_c)
! 13371: err("cdf_mrlc_source: run [%d,%d] in line of length %d - truncated",
! 13372: rl.r[rl.runs-1].xs,rl.r[rl.runs-1].xe,a->wid);
! 13373: rl.r[rl.runs-1].xe = a->wid-1;
! 13374: if(rl.r[rl.runs-1].xs>rl.r[rl.runs-1].xe) {
! 13375: rl.runs--;
! 13376: };
! 13377: };
! 13378: rl.y = a->ph->cy++;
! 13379: if(_O.dbg_r) nerr_RLE_Line("cdf_source: ",&rl);
! 13380: return(&rl);
! 13381:
! 13382: eof: if(dbg_cdf)
! 13383: err("cdf_mrlc_source: unexpected EOF, input line %d",a->ph->cy);
! 13384: return(NULL);
! 13385: }
! 13386:
! 13387: int no_runs_of_page(p)
! 13388: Page *p;
! 13389: { int runs;
! 13390: runs = 0;
! 13391: runs += no_runs_of_blocks(&p->bks);
! 13392: runs += no_runs_of_txtlns(&p->ls);
! 13393: runs += no_runs_of_words(&p->ws);
! 13394: runs += no_runs_of_chars(&p->cs);
! 13395: runs += no_runs_of_blobs(&p->bs);
! 13396: return(runs);
! 13397: }
! 13398:
! 13399: int runs_of_page(p,ra,max)
! 13400: Page *p;
! 13401: RLE_Yrun *ra;
! 13402: int max;
! 13403: { int runs;
! 13404: runs = 0;
! 13405: runs += runs_of_blocks(&p->bks,ra,max);
! 13406: runs += runs_of_txtlns(&p->ls,ra+runs,max-runs);
! 13407: runs += runs_of_words(&p->ws,ra+runs,max-runs);
! 13408: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
! 13409: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
! 13410: return(runs);
! 13411: }
! 13412:
! 13413: int no_runs_of_blocks(p)
! 13414: Blocks *p;
! 13415: { int runs;
! 13416: Block *pp,**ppp;
! 13417: runs = 0;
! 13418: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
! 13419: runs += no_runs_of_block(pp);
! 13420: return(runs);
! 13421: }
! 13422:
! 13423: int runs_of_blocks(p,ra,max)
! 13424: Blocks *p;
! 13425: RLE_Yrun *ra;
! 13426: int max;
! 13427: { int runs;
! 13428: Block *pp,**ppp;
! 13429: runs = 0;
! 13430: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
! 13431: runs += runs_of_block(pp,ra+runs,max-runs);
! 13432: return(runs);
! 13433: }
! 13434:
! 13435: int no_runs_of_block(p)
! 13436: Block *p;
! 13437: { int runs;
! 13438: runs = 0;
! 13439: runs += no_runs_of_txtlns(&p->ls);
! 13440: runs += no_runs_of_words(&p->ws);
! 13441: runs += no_runs_of_chars(&p->cs);
! 13442: runs += no_runs_of_blobs(&p->bs);
! 13443: return(runs);
! 13444: }
! 13445:
! 13446: int runs_of_block(p,ra,max)
! 13447: Block *p;
! 13448: RLE_Yrun *ra;
! 13449: int max;
! 13450: { int runs;
! 13451: runs = 0;
! 13452: runs += runs_of_txtlns(&p->ls,ra+runs,max-runs);
! 13453: runs += runs_of_words(&p->ws,ra+runs,max-runs);
! 13454: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
! 13455: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
! 13456: return(runs);
! 13457: }
! 13458:
! 13459: int no_runs_of_txtlns(p)
! 13460: Txtlns *p;
! 13461: { int runs;
! 13462: Txtln *pp,**ppp;
! 13463: runs = 0;
! 13464: if(p->mny>0) for(pp= *(ppp=p->lpa); pp!=NULL; pp= *(++ppp))
! 13465: runs += no_runs_of_txtln(pp);
! 13466: return(runs);
! 13467: }
! 13468:
! 13469: int runs_of_txtlns(p,ra,max)
! 13470: Txtlns *p;
! 13471: RLE_Yrun *ra;
! 13472: int max;
! 13473: { int runs;
! 13474: Txtln *pp,**ppp;
! 13475: runs = 0;
! 13476: if(p->mny>0) for(pp= *(ppp=p->lpa); pp!=NULL; pp= *(++ppp))
! 13477: runs += runs_of_txtln(pp,ra+runs,max-runs);
! 13478: return(runs);
! 13479: }
! 13480:
! 13481: int no_runs_of_txtln(p)
! 13482: Txtln *p;
! 13483: { int runs;
! 13484: runs = 0;
! 13485: runs += no_runs_of_words(&p->ws);
! 13486: runs += no_runs_of_chars(&p->cs);
! 13487: runs += no_runs_of_blobs(&p->bs);
! 13488: return(runs);
! 13489: }
! 13490:
! 13491: int runs_of_txtln(p,ra,max)
! 13492: Txtln *p;
! 13493: RLE_Yrun *ra;
! 13494: int max;
! 13495: { int runs;
! 13496: runs = 0;
! 13497: runs += runs_of_words(&p->ws,ra+runs,max-runs);
! 13498: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
! 13499: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
! 13500: return(runs);
! 13501: }
! 13502:
! 13503: int no_runs_of_words(p)
! 13504: Words *p;
! 13505: { int runs;
! 13506: Word *pp,**ppp;
! 13507: runs = 0;
! 13508: if(p->mny>0) for(pp= *(ppp=p->wpa); pp!=NULL; pp= *(++ppp))
! 13509: runs += no_runs_of_word(pp);
! 13510: return(runs);
! 13511: }
! 13512:
! 13513: int runs_of_words(p,ra,max)
! 13514: Words *p;
! 13515: RLE_Yrun *ra;
! 13516: int max;
! 13517: { int runs;
! 13518: Word *pp,**ppp;
! 13519: runs = 0;
! 13520: if(p->mny>0) for(pp= *(ppp=p->wpa); pp!=NULL; pp= *(++ppp))
! 13521: runs += runs_of_word(pp,ra+runs,max-runs);
! 13522: return(runs);
! 13523: }
! 13524:
! 13525: int no_runs_of_word(p)
! 13526: Word *p;
! 13527: { int runs;
! 13528: runs = 0;
! 13529: runs += no_runs_of_chars(&p->cs);
! 13530: runs += no_runs_of_blobs(&p->bs);
! 13531: return(runs);
! 13532: }
! 13533:
! 13534: int runs_of_word(p,ra,max)
! 13535: Word *p;
! 13536: RLE_Yrun *ra;
! 13537: int max;
! 13538: { int runs;
! 13539: runs = 0;
! 13540: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
! 13541: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
! 13542: return(runs);
! 13543: }
! 13544:
! 13545: int no_runs_of_chars(p)
! 13546: Chars *p;
! 13547: { int runs;
! 13548: Char *pp,**ppp;
! 13549: runs = 0;
! 13550: if(p->mny>0) for(pp= *(ppp=p->cpa); pp!=NULL; pp= *(++ppp))
! 13551: runs += no_runs_of_char(pp);
! 13552: return(runs);
! 13553: }
! 13554:
! 13555: int runs_of_chars(p,ra,max)
! 13556: Chars *p;
! 13557: RLE_Yrun *ra;
! 13558: int max;
! 13559: { int runs;
! 13560: Char *pp,**ppp;
! 13561: runs = 0;
! 13562: if(p->mny>0) for(pp= *(ppp=p->cpa); pp!=NULL; pp= *(++ppp))
! 13563: runs += runs_of_char(pp,ra+runs,max-runs);
! 13564: return(runs);
! 13565: }
! 13566:
! 13567: int no_runs_of_blobs(p)
! 13568: Blobs *p;
! 13569: { int runs;
! 13570: Blob *pp,**ppp;
! 13571: runs = 0;
! 13572: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
! 13573: runs += pp->runs;
! 13574: return(runs);
! 13575: }
! 13576:
! 13577: int runs_of_blobs(p,ra,max)
! 13578: Blobs *p;
! 13579: RLE_Yrun *ra;
! 13580: int max;
! 13581: { int runs;
! 13582: Blob *pp,**ppp;
! 13583: runs = 0;
! 13584: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
! 13585: runs += runs_of_blob(pp,ra+runs,max-runs);
! 13586: return(runs);
! 13587: }
! 13588:
! 13589: /* ascending lexicographic order on y,xs */
! 13590: int local_rn_asc(r1,r2)
! 13591: RLE_Yrun *r1,*r2;
! 13592: { if(r1->y < r2->y) return(-1);
! 13593: else if(r1->y==r2->y) {
! 13594: if(r1->xs < r2->xs) return(-1);
! 13595: else if (r1->xs == r2->xs) return(0);
! 13596: else return(1);
! 13597: }
! 13598: else return(1);
! 13599: }
! 13600:
! 13601: RLE_Lines *rle_lines_of_page(pgp)
! 13602: Page *pgp;
! 13603: { static RLE_Lines rls;
! 13604: int no_runs,cy,ri;
! 13605: RLE_Yrun *ra,*cr;
! 13606: RLE_Run *lr;
! 13607: RLE_Line *cl;
! 13608: /* count runs */
! 13609: no_runs = no_runs_of_page(pgp);
! 13610: if(_O.dbg_r) err("no_runs %d",no_runs);
! 13611: /* allocate runs array */
! 13612: if((ra=(RLE_Yrun *)malloc(no_runs*sizeof(RLE_Yrun)))==NULL)
! 13613: abort("rle_lines_of_page: can't malloc ra[%d]",no_runs);
! 13614: runs_of_page(pgp,ra,no_runs);
! 13615: /* sort runs ascending on (y,xs) */
! 13616: qsort(ra,no_runs,sizeof(RLE_Yrun),local_rn_asc);
! 13617: /* count RLE_lines.mny */
! 13618: rls.mny = 0; cy=INT_MIN;
! 13619: for(ri=0,cr=ra; ri<no_runs; ri++,cr++)
! 13620: if(cr->y!=cy) {
! 13621: rls.mny++;
! 13622: cy = cr->y;
! 13623: };
! 13624: /* allocate RLE_lines */
! 13625: if((rls.rla=(RLE_Line *)malloc(rls.mny*sizeof(RLE_Line)))==NULL)
! 13626: abort("rle_lines_of_page: can't malloc rls.rla[%d]",rls.mny);
! 13627: /* fill in RLE_lines */
! 13628: cy=INT_MIN; cl=rls.rla-1;
! 13629: for(ri=0,cr=ra; ri<no_runs; ri++,cr++) {
! 13630: if(cr->y!=cy) {
! 13631: cl++;
! 13632: cl->y = cy = cr->y;
! 13633: cl->runs = 0;
! 13634: lr = cl->r;
! 13635: };
! 13636: lr->xs = cr->xs; lr->xe = cr->xe; lr++; cl->runs++;
! 13637: };
! 13638: free(ra);
! 13639: return(&rls);
! 13640: }
! 13641:
! 13642: Bbx *bbx_of_rle_lines(rlsp)
! 13643: RLE_Lines *rlsp;
! 13644: { static Bbx res;
! 13645: Bbx r;
! 13646: int li,ri;
! 13647: RLE_Line *lp;
! 13648: RLE_Run *rp;
! 13649: res = empty_Bbx;
! 13650: for(li=0,lp=rlsp->rla; li<rlsp->mny; li++,lp++) {
! 13651: r.a.y = r.b.y = lp->y;
! 13652: for(ri=0,rp=lp->r; ri<lp->runs; ri++,rp++) {
! 13653: r.a.x = rp->xs;
! 13654: r.b.x = rp->xe;
! 13655: merge_bbx(&r,&res);
! 13656: };
! 13657: };
! 13658: return(&res);
! 13659: }
! 13660:
! 13661: translate_rle_lines(r,p)
! 13662: RLE_Lines *r;
! 13663: Sp p;
! 13664: { int li,ri;
! 13665: RLE_Line *lp;
! 13666: RLE_Run *rp;
! 13667: for(li=0,lp=r->rla; li<r->mny; li++,lp++) {
! 13668: lp->y += p.y;
! 13669: for(ri=0,rp=lp->r; ri<lp->runs; ri++,rp++) {
! 13670: rp->xs += p.x;
! 13671: rp->xe += p.x;
! 13672: };
! 13673: };
! 13674: }
! 13675:
! 13676: RLE_Line *binary_source(a)
! 13677: Copy_arg *a;
! 13678: { static RLE_Line rl;
! 13679: unsigned char *inline;
! 13680: a->bop = F;
! 13681: if(PIC_rline(a->ph,&inline)==1) {
! 13682: rl.runs =
! 13683: rlbr(inline,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
! 13684: rl.y = a->ph->cy;
! 13685: rl.len = a->wid;
! 13686: if(_O.dbg_r) nerr_RLE_Line("binary_source: ",&rl);
! 13687: return(&rl);
! 13688: }
! 13689: else { if(_O.dbg_r) nerr_RLE_Line("binary_source: ",NULL);
! 13690: return(NULL);
! 13691: };
! 13692: }
! 13693:
! 13694: RLE_Line *bitmap_source(a)
! 13695: Copy_arg *a;
! 13696: { static RLE_Line rl;
! 13697: unsigned char *inline;
! 13698: register unsigned char *cp,*ep,*rb;
! 13699: a->bop = F;
! 13700: if(PIC_rline(a->ph,&inline)==1) {
! 13701: /* reverse bit order in each byte */
! 13702: rb=bm_consts.Rbits;
! 13703: ep=(cp=inline)+a->ph->bpl;
! 13704: while(cp<ep) { *cp = rb[*cp]; cp++; };
! 13705: rl.runs =
! 13706: rlbr(inline,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
! 13707: rl.y = a->ph->cy;
! 13708: rl.len = a->wid;
! 13709: if(_O.dbg_r) nerr_RLE_Line("bitmap_source: ",&rl);
! 13710: return(&rl);
! 13711: }
! 13712: else { if(_O.dbg_r) nerr_RLE_Line("binary_source: ",NULL);
! 13713: return(NULL);
! 13714: };
! 13715: }
! 13716:
! 13717: RLE_Line *bitfile_source(a)
! 13718: Copy_arg *a;
! 13719: #define dbg_Bi (F)
! 13720: { static RLE_Line rl;
! 13721: unsigned char *cp,*ep,*pp;
! 13722: int ch,ci;
! 13723: a->bop = F;
! 13724: /* copy current line to prior */
! 13725: memcpy(a->ph->pline,a->ph->line,a->ph->bpl);
! 13726: /* read one binary raster line */
! 13727: ep=(cp=a->ph->line)+a->ph->bpl;
! 13728: while(cp<ep) {
! 13729: if((ch=getc(a->ph->fp))!=EOF) {
! 13730: if(ch<127) {
! 13731: if(dbg_Bi) err("cb: %o",ch);
! 13732: if((fread(cp,1,2*ch,a->ph->fp))==2*ch) {
! 13733: cp += 2*ch;
! 13734: }
! 13735: else return(NULL);
! 13736: }
! 13737: else { ch &= 0x7F;
! 13738: if(dbg_Bi) err("cb: 0200+%o",ch);
! 13739: if((fread(cp,1,2,a->ph->fp))==2) {
! 13740: cp += 2;
! 13741: for(ci=0;ci<ch-1;ci++,cp+=2) {
! 13742: *cp = *(cp-2);
! 13743: *(cp+1) = *(cp-1);
! 13744: };
! 13745: }
! 13746: else return(NULL);
! 13747: };
! 13748: }
! 13749: else return(NULL);
! 13750: };
! 13751: /* reverse bit-order, & xor with prior line */
! 13752: for(ep=(cp=a->ph->line)+a->ph->bpl,pp=a->ph->pline; cp<ep; cp++,pp++) {
! 13753: *cp = bm_consts.Rbits[*cp] ^ *pp;
! 13754: if(dbg_Bi) err("db: %o = ?? ^ %o",*cp,*pp);
! 13755: };
! 13756: rl.runs =
! 13757: rlbr(a->ph->line,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
! 13758: rl.y = ++a->ph->cy;
! 13759: rl.len = a->wid;
! 13760: if(_O.dbg_r) nerr_RLE_Line("bitfile_source: ",&rl);
! 13761: return(&rl);
! 13762: }
! 13763:
! 13764: RLE_Line *dim_source(a)
! 13765: Copy_arg *a;
! 13766: { static RLE_Line *rlp,*rlq,rl;
! 13767: if(a->bop) {
! 13768: a->ph->cy = a->ph->bx.a.y-1;
! 13769: rlq=(rlp=a->rles.rla)+a->rles.mny;
! 13770: };
! 13771: if(_O.dbg_r) {
! 13772: err("dim_source: a->bop %d a->ph->cy %d",a->bop,a->ph->cy);
! 13773: nerr_RLE_Line("*rlp",rlp);
! 13774: };
! 13775: a->bop = F;
! 13776: a->ph->cy++;
! 13777: if(rlp<rlq) {
! 13778: if(a->ph->cy < rlp->y) {
! 13779: rl.y = a->ph->cy;
! 13780: rl.runs = 0;
! 13781: rl.len = a->wid;
! 13782: if(_O.dbg_r) nerr_RLE_Line("dim_source: ",&rl);
! 13783: return(&rl);
! 13784: }
! 13785: else if(a->ph->cy == rlp->y) {
! 13786: rlp->len = a->wid;
! 13787: rlp++;
! 13788: if(_O.dbg_r) nerr_RLE_Line("dim_source: ",rlp-1);
! 13789: return(rlp-1);
! 13790: }
! 13791: else { while(rlp<rlq && a->ph->cy>rlp->y) rlp++;
! 13792: if(rlp>=rlq) {
! 13793: if(_O.dbg_r) nerr_RLE_Line("dim_source: NULL");
! 13794: return(NULL);
! 13795: }
! 13796: else { rlp->len = a->wid;
! 13797: rlp++;
! 13798: if(_O.dbg_r) nerr_RLE_Line("dim_source: ",rlp-1);
! 13799: return(rlp-1);
! 13800: };
! 13801: };
! 13802: }
! 13803: else { if(_O.dbg_r) nerr_RLE_Line("dim_source: NULL");
! 13804: return(NULL);
! 13805: };
! 13806: }
! 13807:
! 13808: RLE_Line *rle_source(a)
! 13809: Copy_arg *a;
! 13810: { static RLE_Line *rl;
! 13811: a->bop = F;
! 13812: if((rl=RLE_get_Line(a->ph->bx.a.x,a->ph->bx.b.x))!=NULL) {
! 13813: a->ph->cy = rl->y;
! 13814: rl->len = a->wid;
! 13815: if(_O.dbg_r) nerr_RLE_Line("rle_source: ",rl);
! 13816: return(rl);
! 13817: }
! 13818: else { if(_O.dbg_r) nerr_RLE_Line("rle_source: ",NULL);
! 13819: return(NULL);
! 13820: };
! 13821: }
! 13822:
! 13823: /* Read next line of runs from pic file, with runs shifted to lie in the range
! 13824: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
! 13825: RLE_Line *pic_source(a)
! 13826: Copy_arg *a;
! 13827: { static RLE_Line rl;
! 13828: unsigned char *inline;
! 13829: a->bop = F;
! 13830: if(PIC_rline(a->ph,&inline)==1) {
! 13831: rl.runs = trcr(inline,
! 13832: 0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,
! 13833: a->thresh,rl.r);
! 13834: rl.y = a->ph->cy;
! 13835: rl.len = a->wid;
! 13836: if(_O.dbg_r) nerr_RLE_Line("pic_source: ",&rl);
! 13837: return(&rl);
! 13838: }
! 13839: else { if(_O.dbg_r) nerr_RLE_Line("pic_source: ",NULL);
! 13840: return(NULL);
! 13841: };
! 13842: }
! 13843:
! 13844: /* Read next line of runs from g31 file, with runs shifted to lie in the range
! 13845: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
! 13846: RLE_Line *g31_source(a)
! 13847: Copy_arg *a;
! 13848: { static RLE_Line *rlp,rl;
! 13849: RLE_Run *rp,*ep,*np;
! 13850: if((rlp=g31_to_rlel(a->tbl,a->bf,a->bop))!=NULL) {
! 13851: a->bop = F;
! 13852: rlp->y = ++a->ph->cy;
! 13853: rlp->len = a->wid;
! 13854: if(a->ph->bx.a.x!=0) {
! 13855: /* must shift run indices */
! 13856: rl.y = rlp->y;
! 13857: rl.len = rlp->len;
! 13858: if((rl.runs=rlp->runs)>0) {
! 13859: for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
! 13860: np->xs = rp->xs + a->ph->bx.a.x;
! 13861: np->xe = rp->xe + a->ph->bx.a.x;
! 13862: };
! 13863: };
! 13864: if(_O.dbg_r) nerr_RLE_Line("g31_source: ",&rl);
! 13865: return(&rl);
! 13866: }
! 13867: else { if(_O.dbg_r) nerr_RLE_Line("g31_source: ",rlp);
! 13868: return(rlp);
! 13869: };
! 13870: }
! 13871: else { if(_O.dbg_r) nerr_RLE_Line("g31_source: ",NULL);
! 13872: return(NULL);
! 13873: };
! 13874: }
! 13875:
! 13876: /* Read next line of runs from g32 file, with runs shifted to lie in the range
! 13877: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
! 13878: RLE_Line *g32_source(a)
! 13879: Copy_arg *a;
! 13880: { static RLE_Line *rlp,rl;
! 13881: RLE_Run *rp,*ep,*np;
! 13882: if((rlp=g32_to_rlel(a->tbl,a->bf,a->bop))!=NULL) {
! 13883: a->bop = F;
! 13884: rlp->y = ++a->ph->cy;
! 13885: rlp->len = a->wid;
! 13886: if(a->ph->bx.a.x!=0) {
! 13887: /* must shift run indices */
! 13888: if(_O.dbg_r) err("g32_source: shift +%d",a->ph->bx.a.x);
! 13889: rl.y = rlp->y;
! 13890: rl.len = rlp->len;
! 13891: if((rl.runs=rlp->runs)>0) {
! 13892: for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
! 13893: np->xs = rp->xs + a->ph->bx.a.x;
! 13894: np->xe = rp->xe + a->ph->bx.a.x;
! 13895: };
! 13896: };
! 13897: if(_O.dbg_r) nerr_RLE_Line("g32_source: ",&rl);
! 13898: return(&rl);
! 13899: }
! 13900: else { if(_O.dbg_r) nerr_RLE_Line("g32_source: ",rlp);
! 13901: return(rlp);
! 13902: };
! 13903: }
! 13904: else { if(_O.dbg_r) nerr_RLE_Line("g32_source: ",NULL);
! 13905: return(NULL);
! 13906: };
! 13907: }
! 13908:
! 13909: /* Read next line of runs from g4 file, after shifting runs to lie in the range
! 13910: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
! 13911: RLE_Line *g4_source(a)
! 13912: Copy_arg *a;
! 13913: { static RLE_Line *rlp,rl;
! 13914: RLE_Run *rp,*ep,*np;
! 13915: if((rlp=g4_to_rlel(a->tbl,a->bf,a->bop,a->wid))!=NULL) {
! 13916: a->bop = F;
! 13917: rlp->y = ++a->ph->cy;
! 13918: rlp->len = a->wid;
! 13919: if(a->ph->bx.a.x!=0) { /* shift runs */
! 13920: rl.y = rlp->y;
! 13921: rl.len = rlp->len;
! 13922: if((rl.runs=rlp->runs)>0) {
! 13923: for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
! 13924: np->xs = rp->xs + a->ph->bx.a.x;
! 13925: np->xe = rp->xe + a->ph->bx.a.x;
! 13926: };
! 13927: };
! 13928: if(_O.dbg_r) nerr_RLE_Line("g4_source: ",&rl);
! 13929: return(&rl);
! 13930: }
! 13931: else { if(_O.dbg_r) nerr_RLE_Line("g4_source: ",rlp);
! 13932: return(rlp);
! 13933: };
! 13934: }
! 13935: else { a->bop = F;
! 13936: if(_O.dbg_r) nerr_RLE_Line("g4_source: ",NULL);
! 13937: return(NULL);
! 13938: };
! 13939: }
! 13940:
! 13941: binary_sink(rl,a)
! 13942: RLE_Line *rl;
! 13943: Copy_arg *a;
! 13944: { int stat;
! 13945: if(_O.dbg_r) nerr_RLE_Line("binary_sink: ",rl);
! 13946: if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
! 13947: if(rl!=NULL) {
! 13948: memset(a->ph->line,'\0',a->ph->bpl);
! 13949: if(rl->runs>0) {
! 13950: /* convert *rl to binary, using ``little-endian'' bit-order */
! 13951: brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
! 13952: };
! 13953: if((stat=PIC_wline(a->ph,a->ph->line))!=1)
! 13954: abort("binary_sink: can't write: stat %d",stat);
! 13955: };
! 13956: return(1);
! 13957: }
! 13958:
! 13959: bitmap_sink(rl,a)
! 13960: RLE_Line *rl;
! 13961: Copy_arg *a;
! 13962: { int stat;
! 13963: if(_O.dbg_r) nerr_RLE_Line("bitmap_sink: ",rl);
! 13964: if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
! 13965: if(rl!=NULL) {
! 13966: memset(a->ph->line,'\0',a->ph->bpl);
! 13967: if(rl->runs>0) {
! 13968: /* convert *rl to binary, using ``big-endian'' bit-order */
! 13969: brrlb(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
! 13970: };
! 13971: if((stat=PIC_wline(a->ph,a->ph->line))!=1)
! 13972: abort("bitmap_sink: can't write: stat %d",stat);
! 13973: };
! 13974: return(1);
! 13975: }
! 13976:
! 13977: /* Write bitfile(9.5) format */
! 13978: bitfile_sink(rl,a)
! 13979: RLE_Line *rl;
! 13980: Copy_arg *a;
! 13981: #define dbg_Bo (F)
! 13982: { int stat;
! 13983: int ci,towrite;
! 13984: register unsigned char uc,*cp,*pp,*ep;
! 13985: if(_O.dbg_r||dbg_Bo) nerr_RLE_Line("bitfile_sink: ",rl);
! 13986: if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
! 13987: if(rl!=NULL) {
! 13988: /* copy current to prior */
! 13989: memcpy(a->ph->pline,a->ph->line,a->ph->bpl);
! 13990: memset(a->ph->line,'\0',a->ph->bpl);
! 13991: if(rl->runs>0) {
! 13992: /* convert *rl to binary, using ``big-endian'' bit-order */
! 13993: brrlb(rl->runs,rl->r,
! 13994: a->ph->bx.a.x,a->ph->bx.b.x,
! 13995: 0,a->ph->line);
! 13996: if(dbg_Bo) {
! 13997: unsigned char *cb,*eb;
! 13998: fprintf(stderr,"a->ph->line: ");
! 13999: for(eb=(cb=a->ph->line)+a->ph->bpl;cb<eb;cb++)
! 14000: fprintf(stderr,"%02X",*cb);
! 14001: fprintf(stderr,"\n");
! 14002: };
! 14003: };
! 14004: /* break up output into blocks of 2*126 bytes;
! 14005: SHOULD also try run-length coding */
! 14006: ci=0; while((towrite=a->ph->bpl-ci) > 0) {
! 14007: if(towrite >= 2*127) towrite=2*126;
! 14008: /* write control byte for block */
! 14009: uc = towrite/2;
! 14010: if(dbg_Bo) err("cb: %02X",uc);
! 14011: putc(uc,a->ph->fp);
! 14012: for(ep=(cp=a->ph->line+ci)+towrite,pp=a->ph->pline+ci;
! 14013: cp<ep; cp++,pp++) {
! 14014: /* write XOR byte */
! 14015: uc = *cp ^ *pp;
! 14016: if(dbg_Bo) err("db %d: %02X = c%02X ^ p%02X",cp-a->ph->line,uc,*cp,*pp);
! 14017: putc(uc,a->ph->fp);
! 14018: };
! 14019: ci += towrite;
! 14020: };
! 14021: }
! 14022: else { free(a->ph->line); a->ph->line=NULL;
! 14023: free(a->ph->pline); a->ph->pline=NULL;
! 14024: fflush(a->ph->fp);
! 14025: };
! 14026: }
! 14027:
! 14028: rle_sink(rl,a)
! 14029: RLE_Line *rl;
! 14030: Copy_arg *a;
! 14031: { if(_O.dbg_r) nerr_RLE_Line("rle_sink: ",rl);
! 14032: if(a->bop) {
! 14033: RIC_hdr rh;
! 14034: rh.bx = a->ph->bx;
! 14035: rh.res_x = a->ph->res_x;
! 14036: rh.res_y = a->ph->res_y;
! 14037: RLE_put_hdr(fileno(a->ph->fp),&rh,1);
! 14038: a->ph->cy = a->ph->bx.a.y-1;
! 14039: a->bop=F;
! 14040: };
! 14041: if(rl!=NULL) {
! 14042: if(rl->runs>0) RLE_put_Line(fileno(a->ph->fp),rl);
! 14043: a->ph->cy++;
! 14044: }
! 14045: else RLE_close(fileno(a->ph->fp));
! 14046: return(1);
! 14047: }
! 14048:
! 14049: /* Write next line of runs to g31 file, after shifting runs to lie in the range
! 14050: [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
! 14051: g31_sink(rl,a)
! 14052: RLE_Line *rl;
! 14053: Copy_arg *a;
! 14054: { int stat;
! 14055: RLE_Line crl;
! 14056: RLE_Run *rp,*ep,*np;
! 14057: if(_O.dbg_r) nerr_RLE_Line("g31_sink: ",rl);
! 14058: if(a->bop) {
! 14059: PIC_put_hdr(a->ph);
! 14060: /* treat FILE *a->ph->fp as a sequence of bits */
! 14061: if((a->bf=bopen(a->ph->fp,"w"))==NULL)
! 14062: abort("g31_sink: can't open bitfile");
! 14063: BOF_to_g31(a->bf);
! 14064: a->bop=F;
! 14065: };
! 14066: if(rl!=NULL) {
! 14067: /* check that rl->len is consistent with a->ph */
! 14068: if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
! 14069: err("g31_sink: rl->len %d != wid(a->ph.bx) %d",
! 14070: rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
! 14071: rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
! 14072: };
! 14073: if(rl->runs>0) {
! 14074: if(a->ph->bx.a.x!=0) { /* shift runs */
! 14075: crl.y = rl->y;
! 14076: crl.len = rl->len;
! 14077: crl.runs = rl->runs;
! 14078: for(ep=(rp=rl->r)+rl->runs,np=crl.r;
! 14079: rp<ep;
! 14080: rp++,np++) {
! 14081: np->xs = rp->xs - a->ph->bx.a.x;
! 14082: np->xe = rp->xe - a->ph->bx.a.x;
! 14083: };
! 14084: rlel_to_g31(&crl,crl.len,a->bf);
! 14085: }
! 14086: else rlel_to_g31(rl,rl->len,a->bf);
! 14087: }
! 14088: else rlel_to_g31(NULL,rl->len,a->bf);
! 14089: a->ph->cy++;
! 14090: }
! 14091: else { EOF_to_g31(a->bf);
! 14092: bclose(a->bf);
! 14093: };
! 14094: return(1);
! 14095: }
! 14096:
! 14097: /* Write next line of runs to g32 file, after shifting runs to lie in the range
! 14098: [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
! 14099: g32_sink(rl,a)
! 14100: RLE_Line *rl;
! 14101: Copy_arg *a;
! 14102: { static RLE_Line prl;
! 14103: RLE_Line *pl;
! 14104: RLE_Line crl;
! 14105: RLE_Run *rp,*ep,*np;
! 14106: if(_O.dbg_r) nerr_RLE_Line("g32_sink: ",rl);
! 14107: if(a->bop) {
! 14108: PIC_put_hdr(a->ph);
! 14109: /* treat FILE *a->ph->fp as a sequence of bits */
! 14110: if((a->bf=bopen(a->ph->fp,"w"))==NULL)
! 14111: abort("can't open bitfile");
! 14112: BOF_to_g32(a->bf);
! 14113: a->bop=F;
! 14114: prl.runs = 0;
! 14115: };
! 14116: if(rl!=NULL) {
! 14117: /* check that rl->len is consistent with a->ph */
! 14118: if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
! 14119: err("g32_sink: rl->len %d != wid(a->ph.bx) %d",
! 14120: rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
! 14121: rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
! 14122: };
! 14123: prl.len = rl->len;
! 14124: prl.y = rl->y - 1;
! 14125: if(((a->ph->cy+1-a->ph->bx.a.y)%a->k)==0) pl=NULL; else pl=&prl;
! 14126: if(rl->runs>0) {
! 14127: if(a->ph->bx.a.x!=0) { /* shift runs */
! 14128: crl.y = rl->y;
! 14129: crl.len = rl->len;
! 14130: crl.runs = rl->runs;
! 14131: for(ep=(rp=rl->r)+rl->runs,np=crl.r;
! 14132: rp<ep;
! 14133: rp++,np++) {
! 14134: np->xs = rp->xs - a->ph->bx.a.x;
! 14135: np->xe = rp->xe - a->ph->bx.a.x;
! 14136: };
! 14137: rlel_to_g32(pl,&crl,crl.len,a->bf);
! 14138: prl.y=crl.y;
! 14139: prl.len=crl.len;
! 14140: prl.runs=crl.runs;
! 14141: memcpy(prl.r,crl.r,2*prl.runs*sizeof(short));
! 14142: }
! 14143: else { rlel_to_g32(pl,rl,rl->len,a->bf);
! 14144: prl.y=rl->y;
! 14145: prl.len=rl->len;
! 14146: prl.runs=rl->runs;
! 14147: memcpy(prl.r,rl->r,2*prl.runs*sizeof(short));
! 14148: };
! 14149: }
! 14150: else { rlel_to_g32(pl,NULL,rl->len,a->bf);
! 14151: prl.y=rl->y;
! 14152: prl.len=rl->len;
! 14153: prl.runs=0;
! 14154: }
! 14155: a->ph->cy++;
! 14156: }
! 14157: else { EOF_to_g32(a->bf);
! 14158: bclose(a->bf);
! 14159: prl.runs = 0;
! 14160: };
! 14161: return(1);
! 14162: }
! 14163:
! 14164: /* Write next line of runs to g4 file, after shifting runs to lie in the range
! 14165: [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
! 14166: g4_sink(rl,a)
! 14167: RLE_Line *rl;
! 14168: Copy_arg *a;
! 14169: { static RLE_Line prl;
! 14170: RLE_Line crl;
! 14171: RLE_Run *rp,*ep,*np;
! 14172: if(_O.dbg_r) nerr_RLE_Line("g4_sink: ",rl);
! 14173: if(a->bop) {
! 14174: PIC_put_hdr(a->ph);
! 14175: /* treat FILE *a->ph->fp as a sequence of bits */
! 14176: if((a->bf=bopen(a->ph->fp,"w"))==NULL)
! 14177: abort("can't open bitfile");
! 14178: BOF_to_g4(a->bf);
! 14179: a->bop=F;
! 14180: prl.runs = 0;
! 14181: };
! 14182: if(rl!=NULL) {
! 14183: /* check that rl->len is consistent with a->ph */
! 14184: if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
! 14185: err("g4_sink: rl->len %d != wid(a->ph.bx) %d",
! 14186: rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
! 14187: rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
! 14188: };
! 14189: if(rl->runs>0) {
! 14190: if(a->ph->bx.a.x!=0) { /* shift runs */
! 14191: crl.y = rl->y;
! 14192: crl.len = rl->len;
! 14193: crl.runs = rl->runs;
! 14194: for(ep=(rp=rl->r)+rl->runs,np=crl.r;
! 14195: rp<ep;
! 14196: rp++,np++) {
! 14197: np->xs = rp->xs - a->ph->bx.a.x;
! 14198: np->xe = rp->xe - a->ph->bx.a.x;
! 14199: };
! 14200: rlel_to_g4(&prl,&crl,crl.len,a->bf);
! 14201: prl.y=crl.y;
! 14202: prl.len=crl.len;
! 14203: prl.runs=crl.runs;
! 14204: memcpy(prl.r,crl.r,2*prl.runs*sizeof(short));
! 14205: }
! 14206: else { rlel_to_g4(&prl,rl,rl->len,a->bf);
! 14207: prl.y=rl->y;
! 14208: prl.len=rl->len;
! 14209: prl.runs=rl->runs;
! 14210: memcpy(prl.r,rl->r,2*prl.runs*sizeof(short));
! 14211: };
! 14212: }
! 14213: else { rlel_to_g4(&prl,NULL,rl->len,a->bf);
! 14214: prl.runs=0;
! 14215: }
! 14216: a->ph->cy++;
! 14217: }
! 14218: else { EOF_to_g4(a->bf);
! 14219: bclose(a->bf);
! 14220: prl.runs = 0;
! 14221: };
! 14222: return(1);
! 14223: }
! 14224:
! 14225: pic_sink(rl,a)
! 14226: RLE_Line *rl;
! 14227: Copy_arg *a;
! 14228: { int stat;
! 14229: if(_O.dbg_r) nerr_RLE_Line("pic_sink: ",rl);
! 14230: if(a->bop) {
! 14231: PIC_put_hdr(a->ph);
! 14232: a->bop=F;
! 14233: };
! 14234: if(rl!=NULL) {
! 14235: crrl(rl->runs,rl->r,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->line);
! 14236: if((stat=PIC_wline(a->ph,a->ph->line))!=1)
! 14237: abort("pic_sink: can't write: stat %d",stat);
! 14238: };
! 14239: return(1);
! 14240: }
! 14241:
! 14242: #if CPU==SUN
! 14243: post_sink(rl,a)
! 14244: RLE_Line *rl;
! 14245: Copy_arg *a;
! 14246: { int stat;
! 14247: if(_O.dbg_r) nerr_RLE_Line("post_sink: ",rl);
! 14248: if (a->bop) {
! 14249: PIC_put_hdr(a->ph); /* needed for allocation of h->line? */
! 14250: POST_start(a->ph);
! 14251: a->bop = F;
! 14252: };
! 14253: if(rl!=NULL) {
! 14254: memset(a->ph->line,'\0',a->ph->bpl);
! 14255: if(rl->runs>0) {
! 14256: /* convert *rl to binary, using ``little-endian'' bit-order */
! 14257: brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
! 14258: };
! 14259: if((stat=POST_wline(a->ph,a->ph->line))!=1)
! 14260: abort("post_sink: can't write: stat %d",stat);
! 14261: }
! 14262: else { POST_end();
! 14263: };
! 14264: return(1);
! 14265: }
! 14266: #else
! 14267: post_sink() {abort("-P postscript output unimplemented");};
! 14268: #endif
! 14269:
! 14270: #if CPU==SUN
! 14271: rast_sink(rl,a)
! 14272: RLE_Line *rl;
! 14273: Copy_arg *a;
! 14274: { int stat;
! 14275: if(_O.dbg_r) nerr_RLE_Line("rast_sink: ",rl);
! 14276: if (a->bop) {
! 14277: PIC_put_hdr(a->ph); /* needed for allocation of h->line? */
! 14278: RAST_start(a->ph);
! 14279: a->bop = F;
! 14280: };
! 14281: if(rl!=NULL) {
! 14282: memset(a->ph->line,'\0',a->ph->bpl);
! 14283: if(rl->runs>0) {
! 14284: /* convert *rl to binary, using ``little-endian'' bit-order */
! 14285: brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
! 14286: };
! 14287: if((stat=RAST_wline(a->ph,a->ph->line))!=1)
! 14288: abort("rast_sink: can't write: stat %d",stat);
! 14289: }
! 14290: else { RAST_end();
! 14291: };
! 14292: return(1);
! 14293: }
! 14294: #else
! 14295: rast_sink() {abort("-S sunraster output unimplemented");};
! 14296: #endif
! 14297:
! 14298: /* Save RLE_Line *rl in buffer, as packed binary, using ``little-endian''
! 14299: bit-packing order, rounding each line to the nearest int for speed.
! 14300: If a->bop, malloc a complete, contiguous buffer holding the entire page,
! 14301: and initialize its contents to zeroes.
! 14302: On each call with rl!=NULL, convert the given line to binary & save in buffer.
! 14303: When called with rl==NULL but a!=NULL, signalling end-of-page, do nothing.
! 14304: Normally, return kludgey (unsigned int *)1, like other sink functions.
! 14305: When called with rl==NULL && a==NULL, return pointer to buffer.
! 14306: It is the responsibility of the calling code to free the buffer. */
! 14307: unsigned int *binary_buffer(rl,a)
! 14308: RLE_Line *rl;
! 14309: Copy_arg *a;
! 14310: { static unsigned int *buf = NULL;
! 14311: static int ipl = 0; /* ints/line */
! 14312: int bufsz; /* (bytes) */
! 14313: unsigned int *result;
! 14314: #define BITS_PER_INT (8*sizeof(int))
! 14315: if(a!=NULL && a->bop) {
! 14316: /* round up to int boundary */
! 14317: ipl = (bbx_wid(&(a->ph->bx))+BITS_PER_INT-1)/BITS_PER_INT;
! 14318: bufsz = sizeof(int)*ipl*bbx_hgt(&(a->ph->bx));
! 14319: if((buf=(unsigned int *)malloc(bufsz))==NULL)
! 14320: abort("binary_buffer: can't alloc int buf[%d]",bufsz/sizeof(int));
! 14321: memset(buf,'\0',bufsz);
! 14322: a->bop=F;
! 14323: };
! 14324: if(rl!=NULL) {
! 14325: /* convert *rl to binary, using ``little-endian'' bit-order */
! 14326: if(rl->runs>0) {
! 14327: /* *rl --> binary, with ``little-endian'' bit-order */
! 14328: #if BIG_ENDIAN
! 14329: brrlb( rl->runs, rl->r, a->ph->bx.a.x, a->ph->bx.b.x,
! 14330: 0, buf+(ipl*(rl->y-a->ph->bx.a.y)) );
! 14331: #else
! 14332: brrl( rl->runs, rl->r, a->ph->bx.a.x, a->ph->bx.b.x,
! 14333: 0, buf+(ipl*(rl->y-a->ph->bx.a.y)) );
! 14334: #endif
! 14335: };
! 14336: return((unsigned int *)1);
! 14337: }
! 14338: else { if(a!=NULL) return((unsigned int *)1);
! 14339: else { result = buf;
! 14340: buf = NULL; ipl = 0;
! 14341: return(result);
! 14342: };
! 14343: };
! 14344: }
! 14345:
! 14346: /* Rotate binary buffer *buf (whose shape is specified by a->ph->bx),
! 14347: through angle tra->rot, and write the resulting stream of RLE_Line's to
! 14348: sink() one at a time, along with a rotated version of *a as the 2nd argument.
! 14349: Only PI/2 is supported; UNDER DEVELOPMENT: other multiples of PI/2 and
! 14350: small arbitrary angles. */
! 14351: rotate_binary_buffer(buf,tra,sink,a)
! 14352: unsigned int *buf;
! 14353: Transform_rlel_arg *tra;
! 14354: int (*sink)(); /* takes args: (RLE_Line *), and int */
! 14355: Copy_arg *a;
! 14356: { register int ipl; /* ints/line in binary buffer */
! 14357: Copy_arg ra; /* rotated */
! 14358: RLE_Line rl;
! 14359: #define TINY_ANG (PI/1000)
! 14360: /* round up to int boundary */
! 14361: ipl = (bbx_wid(&(a->ph->bx))+BITS_PER_INT-1)/BITS_PER_INT;
! 14362: ra = *a;
! 14363: ra.bop=T;
! 14364: if((ra.ph = (PIC_hdr *)malloc(sizeof(PIC_hdr)))==NULL)
! 14365: abort("rotate_binary_buffer: can't malloc ra.ph");
! 14366: *(ra.ph) = *(a->ph);
! 14367: /* by arbitrary convention, rotated bx.a will coincide with input bx.a */
! 14368: if(tra->rot <= PI/2+TINY_ANG && tra->rot >= PI/2-TINY_ANG) {
! 14369: int ey,ii;
! 14370: register RLE_Run *rp;
! 14371: register unsigned int *cb,*eb,bm,obm;
! 14372: register short rx;
! 14373: ra.ph->bx.b.x = a->ph->bx.a.x + bbx_hgt(&(a->ph->bx)) - 1;
! 14374: ra.ph->bx.b.y = a->ph->bx.a.y + bbx_wid(&(a->ph->bx)) - 1;
! 14375: rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
! 14376: rl.y = ra.ph->bx.a.y; ey=ra.ph->bx.b.y;
! 14377: ii=0; bm=01;
! 14378: do { obm=0; /* assume 0 left of margin */
! 14379: rp=rl.r-1;
! 14380: rx=ra.ph->bx.a.x;
! 14381: cb=(eb=buf+ii)+((rl.len-1)*ipl);
! 14382: do { if((*cb & bm)!=obm) {
! 14383: if(obm) { rp->xe=rx-1; obm=0; }
! 14384: else { (++rp)->xs=rx; obm=bm; };
! 14385: };
! 14386: rx++;
! 14387: }
! 14388: while( (cb -= ipl) >= eb );
! 14389: if(obm) rp->xe=rx-1;
! 14390: rl.runs = rp - rl.r + 1;
! 14391: sink(&rl,&ra);
! 14392: if((bm<<=1)==0) {ii++; bm=01;};
! 14393: }
! 14394: while((++rl.y)<=ey);
! 14395: }
! 14396: else if(tra->rot <= PI+TINY_ANG && tra->rot >= PI-TINY_ANG) {
! 14397: rl.len = ra.wid;
! 14398: abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
! 14399: tra->rot/DtoR);
! 14400: }
! 14401: else if(tra->rot <= 3*PI/2+TINY_ANG && tra->rot >= 3*PI/2-TINY_ANG) {
! 14402: ra.ph->bx.b.x = a->ph->bx.a.x + bbx_hgt(&(a->ph->bx)) - 1;
! 14403: ra.ph->bx.b.y = a->ph->bx.a.y + bbx_wid(&(a->ph->bx)) - 1;
! 14404: rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
! 14405: abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
! 14406: tra->rot/DtoR);
! 14407: }
! 14408: else if(tra->rot <= 20.0*DtoR && tra->rot >= -20.0*DtoR) {
! 14409: /* rotation by ``small'' angle */
! 14410: Sp ce; /* center of image to be rotated */
! 14411: double rcos,rsin; /* real rotation vector (cos,sin) */
! 14412: double irx,iry; /* current rotated pixel location */
! 14413: register int sx,sy,ex,ey,rx,ry;
! 14414: register RLE_Run *rp;
! 14415: register int pel,opel;
! 14416: register int orx,ory;
! 14417: if(0) err("rotate_binary_buffer: tra->rot==%g deg under development",
! 14418: tra->rot/DtoR);
! 14419: /* conventionally, keep the same window as the input image,
! 14420: while rotating about its midpoint */
! 14421: rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
! 14422: sx = ra.ph->bx.a.x; ex = ra.ph->bx.b.x;
! 14423: sy = ra.ph->bx.a.y; ey = ra.ph->bx.b.y;
! 14424: ce.x = sx + bbx_wid(&(ra.ph->bx))/2;
! 14425: ce.y = sy + bbx_hgt(&(ra.ph->bx))/2;
! 14426: rcos = cos(tra->rot); rsin = sin(tra->rot);
! 14427: for(ory=sy; ory<=ey; ory++) {
! 14428: opel=0; /* left of output margin: assume pel==0 */
! 14429: rp=rl.r-1;
! 14430: irx = ((rcos*(sx - ce.x) - rsin*(ory - ce.y))) + ce.x;
! 14431: iry = ((rsin*(sx - ce.x) + rcos*(ory - ce.y))) + ce.y;
! 14432: for(orx=sx; orx<=ex; orx++) {
! 14433: rx = (int)(irx + 0.5); ry = (int)(iry + 0.5);
! 14434: if(rx<sx || rx>ex || ry<sy || ry>ey)
! 14435: /* outside input image: assume pel==0 */
! 14436: pel=0;
! 14437: else /* look at bit within input image */ {
! 14438: int ix,iy,bx;
! 14439: iy = (ry-sy)*ipl;
! 14440: ix = rx/BITS_PER_INT;
! 14441: bx = rx%BITS_PER_INT;
! 14442: #if BIG_ENDIAN
! 14443: pel = (buf[ iy + ix ] & (01<<(BITS_PER_INT-bx-1))) ? 1 : 0;
! 14444: #else
! 14445: pel = (buf[ iy + ix ] & (01<<bx)) ? 1 : 0;
! 14446: #endif
! 14447: };
! 14448: if(pel!=opel) {
! 14449: if(opel) { rp->xe=orx-1; opel=0; }
! 14450: else { (++rp)->xs=orx; opel=pel; };
! 14451: };
! 14452: /* step one pel to the right in output image */
! 14453: irx += rcos; iry += rsin;
! 14454: };
! 14455: if(opel) rp->xe=orx-1;
! 14456: rl.runs = rp - rl.r + 1;
! 14457: rl.y = ory;
! 14458: sink(&rl,&ra);
! 14459: };
! 14460: }
! 14461: else { abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
! 14462: tra->rot/DtoR);
! 14463: };
! 14464: sink(NULL,&ra); /* signal end-of-page */
! 14465: }
! 14466:
! 14467: /* Copy a source of RLE_Lines to a sink of RLE_Lines, transforming them
! 14468: by trimming, shifting, scaling, truncation, and rotation.
! 14469: The source is function ir(), which returns non-empty lines only,
! 14470: or NULL on end of page. It is passed `bop=T' on beginning of page.
! 14471: On return from ir(), ia->ph->cy holds the index of the line, whose height is
! 14472: guaranteed to lie in the range [ia->ph->bx.a.y,ia->ph->bx.b.y].
! 14473: All input runs are guaranteed to lie in [ia->ph->bx.a.x,ia->ph->bx.b.x].
! 14474: The maximum length (in pels) of each source line is ia->wid.
! 14475: The sink function or() takes two arguments:
! 14476: RLE_Line *rl; ==NULL on end-of-page
! 14477: Copy_arg *a;
! 14478: The lines sent to the sink must be in unbroken ascending integer
! 14479: sequence of rl->y (thus blank lines must be explicitly sent). At all times,
! 14480: oa->ph->cy is the line last written. After the first call to or(),
! 14481: oa->ph->cy lies in the range [oa->ph->bx.a.y,oa->ph->bx.b.y].
! 14482: Trimming, shifting, scaling, and truncation are performed either
! 14483: here or in function transform_rlel(). Rotation is handled specially:
! 14484: the complete output image (after all other transformations have been
! 14485: performed) is saved in an intermediate buffer (as packed binary), then
! 14486: rotated. Rotation is much slower than the other operations, mainly due
! 14487: to the necessity of touching every pixel. (Manhattan rotations might be
! 14488: faster if the buffer held RLE_lines, but then it would be next-to-impossible
! 14489: to extend to arbitrary rotations someday.)
! 14490: */
! 14491: transform_rlels(ir,ia,or,oa,tra)
! 14492: RLE_Line *(*ir)(); /* return next RLE_Line */
! 14493: Copy_arg *ia; /* used here (bop & wid) & passed to ir() */
! 14494: int (*or)(); /* write next RLE_Line */
! 14495: Copy_arg *oa; /* used here (bop && ph->bx.*.y) & passed to or() */
! 14496: Transform_rlel_arg *tra;
! 14497: { RLE_Line *irl,*orl;
! 14498: static RLE_Line rl0 = Init_RLE_Line; /* empty line */
! 14499: int tr_y; /* transformed y */
! 14500: int (*sv_or)();
! 14501: if(tra->rot!=0.0) {
! 14502: /* if must rotate the image, first buffer the entire
! 14503: set of output RLE_Lines */
! 14504: sv_or = or;
! 14505: or = (int (*)())binary_buffer;
! 14506: };
! 14507: /* signal beginning of page; reset in source() & sink() functions */
! 14508: ia->bop=oa->bop=T;
! 14509: /* set first output line number to write */
! 14510: tra->dy = (tra->sy = oa->ph->bx.a.y);
! 14511: while((irl=ir(ia))!=NULL) {
! 14512: if(F&&_O.dbg_r) nerr_RLE_Line("trans.i: ",irl);
! 14513: /* trim input lines' Y */
! 14514: if(irl->y < tra->tr.a.y) continue;
! 14515: if(irl->y > tra->tr.b.y) break;
! 14516: /* compute the output Y that is equal to the last
! 14517: of the group of transformed equivalent Y's */
! 14518: tr_y = (int)((irl->y + tra->off.y + 1)*tra->scl.y) - 1;
! 14519: /* truncate if necessary */
! 14520: if(tr_y>oa->ph->bx.b.y) tr_y = oa->ph->bx.b.y;
! 14521: /* supply implicit blank line(s) of the same length */
! 14522: while(tra->sy < tr_y) {
! 14523: rl0.len = ia->wid;
! 14524: transform_rlel(&rl0,tra,or,oa);
! 14525: };
! 14526: irl->len = ia->wid;
! 14527: transform_rlel(irl,tra,or,oa);
! 14528: };
! 14529: /* supply terminating blank line(s) of the same length */
! 14530: while(tra->sy < oa->ph->bx.b.y) {
! 14531: rl0.len = ia->wid;
! 14532: transform_rlel(&rl0,tra,or,oa);
! 14533: };
! 14534: transform_rlel(NULL,tra,or,oa); /* signal end of page */
! 14535: /* read input until end of page occurs; this is required
! 14536: to support catenated pages */
! 14537: while(irl!=NULL) irl=ir(ia);
! 14538: if(tra->rot!=0.0) {
! 14539: unsigned int *buf;
! 14540: buf = binary_buffer(NULL,NULL);
! 14541: if(buf!=NULL) {
! 14542: rotate_binary_buffer(buf,tra,sv_or,oa);
! 14543: free(buf);
! 14544: };
! 14545: };
! 14546: }
! 14547:
! 14548: process_page(i,o)
! 14549: Copy_arg *i,*o;
! 14550: { RLE_Line *(*source)();
! 14551: int (*sink)();
! 14552: char unit,*up,cpy[40]; /* units character */
! 14553: Transform_rlel_arg tra;
! 14554:
! 14555: i->wid = bbx_wid(&(i->ph->bx));
! 14556:
! 14557: _O.trim = max_Bbx; /* start by trimming nothing */
! 14558: /* translate units in option arguments */
! 14559: if(_O.optarg_l!=NULL) {
! 14560: strcpy(cpy,_O.optarg_l);
! 14561: if((up=strpbrk(cpy,UNITS))!=NULL) {
! 14562: unit= *up; *up='\0';
! 14563: _O.trim.a.x=vto_scoor(atof(cpy),unit,i->ph->res_x);
! 14564: }
! 14565: else /* assume scanner coordinates */
! 14566: _O.trim.a.x=atoi(cpy);
! 14567: };
! 14568: if(_O.optarg_r!=NULL) {
! 14569: strcpy(cpy,_O.optarg_r);
! 14570: if((up=strpbrk(cpy,UNITS))!=NULL) {
! 14571: unit= *up; *up='\0';
! 14572: _O.trim.b.x=vto_scoor(atof(cpy),unit,i->ph->res_x);
! 14573: }
! 14574: else /* assume scanner coordinates */
! 14575: _O.trim.b.x=atoi(cpy);
! 14576: _O.trim.b.x--; /* -w coordinate is open, Bbx is closed */
! 14577: };
! 14578: if(_O.optarg_t!=NULL) {
! 14579: strcpy(cpy,_O.optarg_t);
! 14580: if((up=strpbrk(cpy,UNITS))!=NULL) {
! 14581: unit= *up; *up='\0';
! 14582: _O.trim.a.y=vto_scoor(atof(cpy),unit,i->ph->res_y);
! 14583: }
! 14584: else /* assume scanner coordinates */
! 14585: _O.trim.a.y=atoi(cpy);
! 14586: };
! 14587: if(_O.optarg_b!=NULL) {
! 14588: strcpy(cpy,_O.optarg_b);
! 14589: if((up=strpbrk(cpy,UNITS))!=NULL) {
! 14590: unit= *up; *up='\0';
! 14591: _O.trim.b.y=vto_scoor(atof(cpy),unit,i->ph->res_y);
! 14592: }
! 14593: else /* assume scanner coordinates */
! 14594: _O.trim.b.y=atoi(cpy);
! 14595: _O.trim.b.y--; /* -w coordinate is open, Bbx is closed */
! 14596: };
! 14597: /* Modified output margins may lie OUTSIDE the input window as well
! 14598: as within it. */
! 14599: if(_O.trim.a.x==Scoor_MIN) _O.trim.a.x=i->ph->bx.a.x;
! 14600: if(_O.trim.b.x==Scoor_MAX) _O.trim.b.x=i->ph->bx.b.x;
! 14601: if(_O.trim.a.y==Scoor_MIN) _O.trim.a.y=i->ph->bx.a.y;
! 14602: if(_O.trim.b.y==Scoor_MAX) _O.trim.b.y=i->ph->bx.b.y;
! 14603: if(_O.dbg_m) err("trim: %s",bbx_toa(&(_O.trim)));
! 14604:
! 14605: if(strcmp(i->ph->type,"binary")==0) { source = binary_source; }
! 14606: else if(strcmp(i->ph->type,"bitmap")==0) { source = bitmap_source; }
! 14607: else if(strcmp(i->ph->type,"bitfile")==0) { source = bitfile_source; }
! 14608: else if(strcmp(i->ph->type,"document-image")==0) { source = dim_source; }
! 14609: else if(strcmp(i->ph->type,"dim")==0) { source = dim_source; }
! 14610: else if(strcmp(i->ph->type,"rle")==0) {
! 14611: RIC_hdr rh;
! 14612: /* reopen RLE file to use system I/O (awkward, obsolescent) */
! 14613: lseek(fileno(i->ph->fp),0L,0);
! 14614: RLE_open(fileno(i->ph->fp),&rh);
! 14615: i->ph->cy = i->ph->bx.a.y-1;
! 14616: source = rle_source;
! 14617: }
! 14618: else if(strcmp(i->ph->type,"pico")==0
! 14619: ||strcmp(i->ph->type,"dump")==0) {
! 14620: i->thresh = _O.thresh;
! 14621: source = pic_source;
! 14622: }
! 14623: else if(strcmp(i->ph->type,"ccitt-g31")==0) {
! 14624: if((i->bf=bopen(i->ph->fp,"r"))==NULL)
! 14625: abort("can't open bitfile");
! 14626: i->tbl = ccitt_table();
! 14627: source = g31_source;
! 14628: }
! 14629: else if(strcmp(i->ph->type,"ccitt-g32")==0) {
! 14630: if((i->bf=bopen(i->ph->fp,"r"))==NULL)
! 14631: abort("can't open bitfile");
! 14632: i->tbl = ccitt_table();
! 14633: source = g32_source;
! 14634: }
! 14635: else if(strcmp(i->ph->type,"ccitt-g4")==0) {
! 14636: if((i->bf=bopen(i->ph->fp,"r"))==NULL)
! 14637: abort("can't open bitfile");
! 14638: i->tbl = ccitt_table();
! 14639: source = g4_source;
! 14640: }
! 14641: else if(strcmp(i->ph->type,"cdf-mrlc")==0) { source = cdf_mrlc_source; }
! 14642: else abort("Input file TYPE=%s unsupported",i->ph->type);
! 14643:
! 14644: if(_O.dbg_h) err("In %s",PIC_hdr_toa(i->ph));
! 14645:
! 14646: /* Adjudicate -R and -x options */
! 14647: if(_O.out_res.x==-2) {
! 14648: /* -R= specified: force resolutions to be equal to the greater */
! 14649: if(i->ph->res_x < i->ph->res_y) {
! 14650: _O.out_res.x = _O.out_res.y = i->ph->res_y;
! 14651: }
! 14652: else if(i->ph->res_y < i->ph->res_x) {
! 14653: _O.out_res.x = _O.out_res.y = i->ph->res_x;
! 14654: }
! 14655: else _O.out_res.x = _O.out_res.y = i->ph->res_x;
! 14656: };
! 14657: if(_O.out_res.x!=-1) { /* -Rx specified; override -xX */
! 14658: _O.expand.x = ((double)_O.out_res.x)/i->ph->res_x;
! 14659: if(_O.dbg_R && _O.expand.x!=1.0)
! 14660: err("horizontal resolution changed: x%g (%d -> %d)",
! 14661: _O.expand.x,i->ph->res_x,_O.out_res.x);
! 14662: };
! 14663: if(_O.out_res.y!=-1) { /* -R,y specified; override -x,Y */
! 14664: _O.expand.y = ((double)_O.out_res.y)/i->ph->res_y;
! 14665: if(_O.dbg_R && _O.expand.y!=1.0)
! 14666: err("vertical resolution changed: x%g (%d -> %d)",
! 14667: _O.expand.y,i->ph->res_y,_O.out_res.y);
! 14668: };
! 14669:
! 14670: /* Setup image transformation parameters */
! 14671: tra = empty_Transform_rlel_arg;
! 14672: tra.tr = _O.trim;
! 14673: tra.off = _O.offset;
! 14674: tra.scl = _O.expand;
! 14675: tra.wh.x = bbx_wid(&(tra.tr));
! 14676: tra.wh.y = bbx_hgt(&(tra.tr));
! 14677: tra.rev = _O.reverse;
! 14678: if(tra.scl.x!=1.0) {
! 14679: tra.wh.x = (int)(tra.wh.x*tra.scl.x+0.5);
! 14680: };
! 14681: if(tra.scl.y!=1.0) {
! 14682: tra.wh.y = (int)(tra.wh.y*tra.scl.y+0.5);
! 14683: };
! 14684: switch(_O.top) {
! 14685: case 't': /* default */ break;
! 14686: case 'l': /* top is really at left */
! 14687: tra.rot = (Radians)(PI/2);
! 14688: break;
! 14689: case 'b': /* top is really at bottom */
! 14690: tra.rot = (Radians)(PI);
! 14691: break;
! 14692: case 'r': /* top is really at right */
! 14693: tra.rot = (Radians)((3*PI)/2);
! 14694: break;
! 14695: case 'a': /* rotation angle given */
! 14696: tra.rot = _O.top_angle;
! 14697: break;
! 14698: };
! 14699: /* is the transform the identity? (speed-optimized special case) */
! 14700: tra.ident = ( (bbx_eq(&(tra.tr),&(i->ph->bx)))
! 14701: && (tra.scl.x==1.0)
! 14702: && (tra.scl.y==1.0)
! 14703: && (tra.off.x==0)
! 14704: && (tra.off.y==0)
! 14705: && (tra.rot==0.0) );
! 14706:
! 14707: /* compute transformed output box & resolution;
! 14708: don't rotate here (see transform_rlels()) */
! 14709: if(tra.ident) {
! 14710: o->ph->bx = i->ph->bx;
! 14711: o->ph->res_x = i->ph->res_x;
! 14712: o->ph->res_y = i->ph->res_y;
! 14713: }
! 14714: else { o->ph->bx = tra.tr;
! 14715: o->ph->bx.a.x += tra.off.x;
! 14716: o->ph->bx.b.x += tra.off.x;
! 14717: o->ph->bx.a.y += tra.off.y;
! 14718: o->ph->bx.b.y += tra.off.y;
! 14719: if(tra.scl.x!=1.0) {
! 14720: o->ph->bx.a.x = tra.scl.x*o->ph->bx.a.x;
! 14721: o->ph->bx.b.x = o->ph->bx.a.x + tra.wh.x-1;
! 14722: };
! 14723: if(tra.scl.y!=1.0) {
! 14724: o->ph->bx.a.y = tra.scl.y*o->ph->bx.a.y;
! 14725: o->ph->bx.b.y = o->ph->bx.a.y + tra.wh.y-1;
! 14726: };
! 14727: o->ph->res_x = (i->ph->res_x*tra.scl.x + 0.5);
! 14728: o->ph->res_y = (i->ph->res_y*tra.scl.y + 0.5);
! 14729: };
! 14730:
! 14731: if(_O.to_bin)
! 14732: { strcpy(o->ph->type,"binary"); sink = binary_sink; }
! 14733: else if(_O.to_bitfile)
! 14734: { strcpy(o->ph->type,"bitfile"); sink = bitfile_sink; }
! 14735: else if(_O.to_bitmap)
! 14736: { strcpy(o->ph->type,"bitmap"); sink = bitmap_sink; }
! 14737: else if (_O.to_rle) {
! 14738: if(strcmp(i->ph->type,"rle")==0)
! 14739: abort("can't both read and write TYPE=rle - sorry");
! 14740: strcpy(o->ph->type,"rle"); sink = rle_sink;
! 14741: }
! 14742: else if(_O.to_g31) { strcpy(o->ph->type,"ccitt-g31"); sink = g31_sink; }
! 14743: else if(_O.to_g32) {
! 14744: strcpy(o->ph->type,"ccitt-g32");
! 14745: o->k = _O.g32_k;
! 14746: sink = g32_sink;
! 14747: }
! 14748: else if(_O.to_g4) { strcpy(o->ph->type,"ccitt-g4"); sink = g4_sink; }
! 14749: else if(_O.to_pic) { strcpy(o->ph->type,"dump"); sink = pic_sink; }
! 14750: #if CPU==SUN
! 14751: else if(_O.to_post) { strcpy(o->ph->type,"postscript"); sink = post_sink; }
! 14752: #endif
! 14753: #if CPU==SUN
! 14754: else if(_O.to_rast) { strcpy(o->ph->type,"sunraster"); sink = rast_sink; }
! 14755: #endif
! 14756: if(i->ph->misc!=NULL) {
! 14757: o->ph->misc = i->ph->misc;
! 14758: i->ph->misc = NULL;
! 14759: };
! 14760: if(_O.dbg_h) err("Out %s",PIC_hdr_toa(o->ph));
! 14761:
! 14762: transform_rlels(source,i,sink,o,&tra);
! 14763:
! 14764: /* Synchronize filedes pointer with stream pointer */
! 14765: lseek(fileno(o->ph->fp),o->ph->seek = ftell(o->ph->fp),0);
! 14766: }
! 14767:
! 14768: /* A file may be a catenation of pages. */
! 14769: process_fps(i,o)
! 14770: FILE *i,*o;
! 14771: { Copy_arg ia,oa;
! 14772: int stat;
! 14773: ia = oa = empty_Copy_arg;
! 14774: ia.ph = alloc_PIC_hdr(i);
! 14775: oa.ph = alloc_PIC_hdr(o);
! 14776:
! 14777: stat=PIC_get_hdr(ia.ph);
! 14778: if(_O.dbg_h && stat!=1) err("PIC_get_hdr() returns status %d",stat);
! 14779:
! 14780: /* enforce bitfile(9) I/O restrictions */
! 14781: if(_O.from_bitfile && strcmp(ia.ph->type,"bitfile")!=0)
! 14782: abort("-Bi requires input to be bitfile(9.5) format");
! 14783: if(!_O.from_bitfile && strcmp(ia.ph->type,"bitfile")==0) {
! 14784: /* TYPE= is missing, erroneously: refuse to recognize it */
! 14785: abort("TYPE=... header is missing");
! 14786: };
! 14787:
! 14788: if(strcmp(ia.ph->type,"document-image")==0
! 14789: || strcmp(ia.ph->type,"dim")==0) {
! 14790: Page pg;
! 14791: skip_doc(i);
! 14792: if(frdb_page_etc(i,&pg,IsALL)==1) {
! 14793: ia.ph->bx = pg.bx;
! 14794: ia.ph->res_x = pg.res_x;
! 14795: ia.ph->res_y = pg.res_y;
! 14796: ia.rles = *rle_lines_of_page(&pg);
! 14797: if(_O.shrinkwrap!=-1) {
! 14798: Sp trans;
! 14799: ia.ph->bx = *bbx_of_rle_lines(&ia.rles);
! 14800: ia.ph->bx.a.x -= _O.shrinkwrap;
! 14801: ia.ph->bx.a.y -= _O.shrinkwrap;
! 14802: ia.ph->bx.b.x += _O.shrinkwrap;
! 14803: ia.ph->bx.b.y += _O.shrinkwrap;
! 14804: if(bbx_area(&(ia.ph->bx))<=0)
! 14805: abort("-W%d shrinks to nothing",_O.shrinkwrap);
! 14806: trans.x = -ia.ph->bx.a.x; trans.y = -ia.ph->bx.a.y;
! 14807: translate_rle_lines(&ia.rles,trans);
! 14808: ia.ph->bx.b.x = bbx_wid(&ia.ph->bx)-1;
! 14809: ia.ph->bx.b.y = bbx_hgt(&ia.ph->bx)-1;
! 14810: ia.ph->bx.a.x = ia.ph->bx.a.y = 0;
! 14811: };
! 14812: free_page_etc(&pg,IsALL&(~IsPage));
! 14813: }
! 14814: else { free_page_etc(&pg,IsALL&(~IsPage));
! 14815: abort("can't read document-image file");
! 14816: };
! 14817: };
! 14818: if(_O.in_res.x!=SHRT_MIN&&_O.in_res.y!=SHRT_MIN) {
! 14819: /* force input RES to given values */
! 14820: if(ia.ph->res_x!=0 || ia.ph->res_y!=0) {
! 14821: err("input: RES=%d %d overridden by -Z%d,%d\n",
! 14822: ia.ph->res_x,ia.ph->res_y,_O.in_res.x,_O.in_res.y);
! 14823: };
! 14824: ia.ph->res_x = _O.in_res.x;
! 14825: ia.ph->res_y = _O.in_res.y;
! 14826: };
! 14827: if(ia.ph->res_x<=0 || ia.ph->res_y<=0)
! 14828: err("input: RES=%d %d may cause problems (set using -Zx,y)",
! 14829: ia.ph->res_x,ia.ph->res_y);
! 14830:
! 14831: while(strlen(ia.ph->type)>0 && stat==1 && !feof(i)
! 14832: && !ferror(i) && !ferror(o)) {
! 14833: process_page(&ia,&oa);
! 14834: if( strcmp(ia.ph->type,"cdf")==0
! 14835: || strcmp(ia.ph->type,"cdf-mrlc")==0 ) {
! 14836: stat=CDF_next_page(ia.ph);
! 14837: }
! 14838: else { if((stat=PIC_get_hdr(ia.ph))==1) {
! 14839: /* enforce bitfile(9) I/O restrictions */
! 14840: if(_O.from_bitfile && strcmp(ia.ph->type,"bitfile")!=0)
! 14841: abort("-Bi means input must be picfile");
! 14842: if(!_O.from_bitfile && strcmp(ia.ph->type,"bitfile")==0) {
! 14843: /* TYPE= is missing, erroneously: silently quit */
! 14844: if(_O.dbg_h) err("strange input before normal EOF - ignored");
! 14845: strcpy(ia.ph->type,"");
! 14846: };
! 14847: };
! 14848: };
! 14849: if(_O.dbg_h && stat!=1)
! 14850: err("PIC_get_hdr() returns status %d",stat);
! 14851: };
! 14852:
! 14853: /* EOF or error */
! 14854: free_PIC_hdr(ia.ph);
! 14855: free_PIC_hdr(oa.ph);
! 14856: }
! 14857:
! 14858: #if FILE_TREE
! 14859: /* Process filenames: if NULL, use stdin/stdout; if files, read them;
! 14860: if directories, create a parallel file tree and process the leaves
! 14861: pairwise. */
! 14862: process_fns(i,o)
! 14863: char *i; /* may be NULL; not yet fopened for read */
! 14864: char *o; /* may be NULL; not yet fopened for write */
! 14865: #define dbg_ft (F)
! 14866: { FILE *i_fp;
! 14867: FILE *o_fp;
! 14868: char *branch;
! 14869: if(dbg_ft) err("processs(\"%s\",\"%s\")",i,o);
! 14870: branch=path_toa(&path_process.path,1);
! 14871: if(dbg_ft&&branch[0]!='\0') err("%s",branch);
! 14872: if(i==NULL||i[0]=='\0') i_fp=stdin;
! 14873: else if( (i_fp=fopen(i,"r"))==NULL ) {
! 14874: err("can't open input file %s - skip it",i);
! 14875: return;
! 14876: };
! 14877: if(o==NULL||o[0]=='\0') o_fp=stdout;
! 14878: else if( (o_fp=fopen(o,"w"))==NULL ) {
! 14879: err("can't open output file %s - skip it",o);
! 14880: return;
! 14881: };
! 14882: process_fps(i_fp,o_fp);
! 14883: if(i_fp!=stdin) fclose(i_fp);
! 14884: if(o_fp!=stdout) fclose(o_fp); else fflush(o_fp);
! 14885: };
! 14886: #else
! 14887: /* Process filenames: if NULL, use stdin/stdout; if files, open and process them.
! 14888: */
! 14889: process_fns(i_fn,o_fn)
! 14890: char *i_fn; /* may be NULL; not yet fopened for read */
! 14891: char *o_fn; /* may be NULL; not yet fopened for write */
! 14892: { FILE *i_fp;
! 14893: FILE *o_fp;
! 14894: if(i_fn==NULL||strlen(i_fn)==0) i_fp = stdin;
! 14895: else { if((i_fp=fopen(i_fn,"r"))==NULL)
! 14896: abort("can't open input file %s",i_fn);
! 14897: };
! 14898: if(o_fn==NULL||strlen(o_fn)==0) o_fp = stdout;
! 14899: else { if((o_fp=fopen(o_fn,"w"))==NULL)
! 14900: abort("can't open output file %s",o_fn);
! 14901: };
! 14902: process_fps(i_fp,o_fp);
! 14903: if(i_fp!=stdin) fclose(i_fp);
! 14904: if(o_fp!=stdout) fclose(o_fp); else fflush(o_fp);
! 14905: };
! 14906: #endif
! 14907:
! 14908: main(arc,arv)
! 14909: int arc; char **arv;
! 14910: { parse_args(arc,arv);
! 14911: #if FILE_TREE
! 14912: process_file_trees(process_fns,_O.in_fn,_O.out_fn);
! 14913: #else
! 14914: process_fns(_O.in_fn,_O.out_fn);
! 14915: #endif
! 14916: }
! 14917:
! 14918: nerr_RLE_Line(s,rl)
! 14919: char *s;
! 14920: RLE_Line *rl;
! 14921: { RLE_Run *r;
! 14922: int ri;
! 14923: if(rl==NULL) fprintf(stderr,"%15s RLEL NULL.\n",s);
! 14924: else { fprintf(stderr,"%15s RLEL y%d r%d l%d: ",s,rl->y,rl->runs,rl->len);
! 14925: for(ri=0,r=rl->r; ri<rl->runs; ri++,r++)
! 14926: fprintf(stderr,"[%d,%d] ",r->xs,r->xe);
! 14927: fprintf(stderr,"\n");
! 14928: };
! 14929: }
! 14930: 0707070035351137201006640007620000050000010263350476773367100001000000030702bitio.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 14931: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 14932: /* The copyright notice does not imply actual or intended publication. */
! 14933: /* AUTHORS: */
! 14934: /* H. S. Baird - ATT-BL MH - first versions */
! 14935:
! 14936: /* bitio.h - view a stream file as a sequence of binary values, hiding the
! 14937: bit- and byte-packing format of the file. The format of input and output
! 14938: files may differ. Reading and writing are performed by macroes for speed;
! 14939: the price for this is that the file formats must be fixed at compile time.
! 14940:
! 14941: SYNOPSIS
! 14942: #include <stdio.h>
! 14943: #include "bitio.h"
! 14944:
! 14945: BITFILE *bopen(stream,type);
! 14946: FILE *stream;
! 14947: char *type;
! 14948:
! 14949: int getb(bitfile);
! 14950: BITFILE *bitfile;
! 14951:
! 14952: putb(bit,bitfile);
! 14953: int bit;
! 14954:
! 14955: padb(bitfile,bit,bdy,len);
! 14956: int bit,bdy,len;
! 14957:
! 14958: char *bbuffer(bitfile);
! 14959:
! 14960: unsigned long bsize(bitfile);
! 14961:
! 14962: unsigned long bflush(bitfile);
! 14963:
! 14964: unsigned long bclose(bitfile);
! 14965:
! 14966: COMPILER DEPENDENCIES
! 14967: The compiler's data types must include:
! 14968: unsigned char: 8 bits each
! 14969: unsigned short: 2 unsigned chars each
! 14970: unsigned int: 2 unsigned shorts each
! 14971: DESCRIPTION
! 14972: Bopen views the named stream file as a bit file to be read (if type is "r")
! 14973: or written (if type is "w" or "wb"). The stream file must already have been
! 14974: fopen(3)ed, and the first bit to be read/written will be the first bit in its
! 14975: next byte in getc(3)/putc(3) order. Bopen returns a pointer which identifies
! 14976: the bitfile to the other functions. System or stream I/O to/from the
! 14977: associated stream should not be used until after bclose is called.
! 14978: If bopen's type is "wb", then the entire output stream will be buffered
! 14979: in main memory until bflush or bclose are called. At any time, bbuffer
! 14980: returns this buffer's address and bsize its length in bytes.
! 14981: Getb returns the next bit from the named bitfile. It returns EOF on
! 14982: end of file or read error. EOF may occur on a byte, short, or int boundary,
! 14983: depending on file format.
! 14984: Putb appends the given bit to the named bitfile.
! 14985: Padb writes 'bit' enough times (possibly 0) so that if a bitstring
! 14986: of length 'len' were written next it would end on a 'bdy'-bit boundary
! 14987: (may do the wrong thing if 'bdy' doesn't divide UINT_MAX).
! 14988: Bflush ensures that all written bits have been written to the stream
! 14989: via putc(3). The output is padded with 0 bits to a byte, short, or int
! 14990: boundary, depending on file format. It returns the number of bytes (not bits)
! 14991: written since bopen or the last bflush. The bitfile remains open. It does not
! 14992: fflush(3) the associated stream.
! 14993: Bclose causes a bflush and frees all buffers. It returns the total
! 14994: number of bytes (not bits) read/written since bopen. It fflush(3)'es,
! 14995: but does not fclose(3) the associated stream.
! 14996:
! 14997: Bitfile formats are selected at compile time: see `FORMAT:' at the
! 14998: end of this file. The formats for input and output may differ. Formats
! 14999: include:
! 15000: a each bit is an ASCII character: '0' or '1', in putc(3) order; not padded.
! 15001: 0 the low-order (0001) bit in each byte is first ("little-endian"), and
! 15002: bytes are in putc(3) order; EOF and padding at a byte boundary.
! 15003: 1 the high-order (0200) bit in each byte is first ("big-endian"), and
! 15004: bytes are in putc(3) order; EOF and padding at a byte boundary.
! 15005: 10 the low-order (0001) bit in each byte is first ("little-endian"), but
! 15006: bytes are reversed (in each pair) from putc(3) order; EOF and padding
! 15007: at a short boundary.
! 15008: 11 the high-order (0200) bit in each byte is first ("big-endian"), but
! 15009: bytes are reversed (in each pair) from putc(3) order; EOF and padding
! 15010: at a short boundary.
! 15011: Planned (data structures are in place; code will be implemented if needed):
! 15012: 100 the low-order (0001) bit in each byte is first ("little-endian"), and
! 15013: bytes (in each pair) are in putc(3) order; but shorts (in each pair)
! 15014: are reversed from putc(3) order; EOF and padding at an int boundary.
! 15015: 101, 110, 111 - by obvious analogy
! 15016: BUGS
! 15017: Putting to an input bitfile or getting from an output bitfile is
! 15018: erroneous, but is not checked for.
! 15019: */
! 15020:
! 15021: #define BUFFERED (T) /* enable buffering of output */
! 15022:
! 15023: typedef struct BITFILE {
! 15024: FILE *fp; /* associated stream */
! 15025: char type; /* one of 'r','w' */
! 15026: int ic; /* byte just read */
! 15027: unsigned long nb; /* no. bytes read/written since bopen */
! 15028: unsigned long alloc; /* no. bytes allocated in buffer */
! 15029: char *buf; /* buffer (in malloc space) */
! 15030: char *cp; /* next char in buffer */
! 15031: unsigned int n; /* no. bits written so far (mod UINT_MAX) */
! 15032: unsigned char cm; /* single-bit mask */
! 15033: unsigned short sm; /* single-bit mask */
! 15034: unsigned int im; /* single-bit mask */
! 15035: union { struct { /* used to reorder char & short order */
! 15036: union { struct {
! 15037: unsigned char c0;
! 15038: unsigned char c1;
! 15039: } cc;
! 15040: unsigned short s;
! 15041: } s0;
! 15042: union { struct {
! 15043: unsigned char c0;
! 15044: unsigned char c1;
! 15045: } cc;
! 15046: unsigned short s;
! 15047: } s1;
! 15048: } ss;
! 15049: unsigned int i;
! 15050: } i;
! 15051: } BITFILE;
! 15052: #define Init_BITFILE {NULL,'\0',0,0L,0L,NULL,NULL,0,0,0}
! 15053: #if MAIN
! 15054: BITFILE empty_BITFILE = Init_BITFILE;
! 15055: #else
! 15056: extern BITFILE empty_BITFILE;
! 15057: #endif
! 15058:
! 15059: /* Code common to all formats: */
! 15060: #if MAIN
! 15061: BITFILE *bopen_rw(s,t)
! 15062: FILE *s;
! 15063: char *t;
! 15064: { BITFILE *f;
! 15065: if((f=(BITFILE *)malloc(sizeof(BITFILE)))==NULL) {
! 15066: err("bopen: can't alloc");
! 15067: return(NULL);
! 15068: };
! 15069: *f = empty_BITFILE;
! 15070: f->fp = s;
! 15071: f->type = *t;
! 15072: return(f);
! 15073: }
! 15074: #else
! 15075: BITFILE *bopen_rw();
! 15076: #endif
! 15077:
! 15078: #define bbuffer(f) ((f)->buf)
! 15079: #define bsize(f) ((bbuffer(f)!=NULL)? ((f)->cp - (f)->buf): 0L)
! 15080:
! 15081: #if !BUFFERED
! 15082: #define bputc(c,f) putc((c),(f)->fp)
! 15083: #define bbflush(f) (0L)
! 15084: #else
! 15085: #define BITFILE_incr (512) /* buffer allocations are in these increments */
! 15086:
! 15087: #if MAIN
! 15088: brealloc(f)
! 15089: BITFILE *f;
! 15090: { int nbuf; /* no. bytes in buffer */
! 15091: nbuf = bsize(f);
! 15092: f->alloc += BITFILE_incr;
! 15093: if((f->buf=(char *)realloc(f->buf,f->alloc))==NULL)
! 15094: abort("");
! 15095: f->cp = f->buf + nbuf;
! 15096: }
! 15097: #endif
! 15098:
! 15099: #define bputc(c,f) { \
! 15100: if((f)->buf==NULL) putc((c),(f)->fp); \
! 15101: else { if(bsize(f)==(f)->alloc) brealloc(f); \
! 15102: *(++((f)->cp))=(c); \
! 15103: } \
! 15104: }
! 15105:
! 15106: #if MAIN
! 15107: unsigned long bbflush(f)
! 15108: BITFILE *f; /* f->buf!=NULL && bsize(f)>0 */
! 15109: { register char *cp,*cq;
! 15110: unsigned long nbuf;
! 15111: nbuf = bsize(f);
! 15112: for(cq=(cp=f->buf)+nbuf; cp<cq; cp++) putc(*cp,f->fp);
! 15113: f->cp=f->buf;
! 15114: return(nbuf);
! 15115: }
! 15116: #else
! 15117: unsigned long bbflush();
! 15118: #endif
! 15119: #endif
! 15120:
! 15121: /* Code particular to each format: */
! 15122:
! 15123: /* Format a: ASCII file, one printable char ('0' or '1') per bit: */
! 15124: #define bopen_r_a(s) bopen_rw((s),"r")
! 15125: #define bopen_w_a(s) bopen_rw((s),"w")
! 15126: #define getb_a(f) ( (((f)->ic=getc((f)->fp))!=EOF)? \
! 15127: ((f)->nb++, \
! 15128: ((f)->ic=='0')? \
! 15129: 0: \
! 15130: (((f)->ic=='1')? 1: EOF)): \
! 15131: EOF )
! 15132: #define putb_a(b,f) { if((b)) bputc('1',f); else bputc('0',f); (f)->nb++; }
! 15133: #define bflush_a(f) ( (bsize(f)>0)? bbflush(f): (0L) )
! 15134:
! 15135: /* Format 0: the low-order bit (0001) in each byte is first ("little-endian"),
! 15136: and bytes are in putc(3) order; */
! 15137: #if MAIN
! 15138: BITFILE *bopen_r_0(s)
! 15139: FILE *s;
! 15140: { BITFILE *f;
! 15141: if((f=bopen_rw(s,"r"))!=NULL) {
! 15142: f->cm=0000;
! 15143: };
! 15144: return(f);
! 15145: }
! 15146: #else
! 15147: BITFILE *bopen_r_0();
! 15148: #endif
! 15149: #if MAIN
! 15150: BITFILE *bopen_w_0(s)
! 15151: FILE *s;
! 15152: { BITFILE *f;
! 15153: if((f=bopen_rw(s,"w"))!=NULL) {
! 15154: f->i.ss.s0.cc.c0=0000;
! 15155: f->cm=0001;
! 15156: };
! 15157: return(f);
! 15158: }
! 15159: #else
! 15160: BITFILE *bopen_w_0();
! 15161: #endif
! 15162: #define getb_0(f) ( ((f)->cm)? \
! 15163: ( ((f)->cm&(f)->ic)? \
! 15164: ((f)->cm<<=1,1): \
! 15165: ((f)->cm<<=1,0) ): \
! 15166: ( (((f)->ic=getc((f)->fp))==EOF)? \
! 15167: EOF: \
! 15168: ( (f)->nb++, \
! 15169: (f)->cm=0001, \
! 15170: ((f)->cm&(f)->ic)? \
! 15171: ((f)->cm<<=1,1): \
! 15172: ((f)->cm<<=1,0) ) ) )
! 15173: #define putb_0(b,f) { \
! 15174: if((b)) (f)->i.ss.s0.cc.c0 |= (f)->cm; \
! 15175: if( !((f)->cm<<=1) ) { \
! 15176: bputc((f)->i.ss.s0.cc.c0,f); \
! 15177: (f)->nb++; \
! 15178: (f)->i.ss.s0.cc.c0=0000; (f)->cm=0001; \
! 15179: }; \
! 15180: (f)->n++; \
! 15181: }
! 15182: #define bflush_0(f) (padb((f),0,8,0), (bsize(f)>0)? bbflush(f): 0L)
! 15183:
! 15184: /* Format 1: the high-order bit (0200) in each byte is first ("big-endian"), and
! 15185: bytes are in putc(3) order; */
! 15186: #if MAIN
! 15187: BITFILE *bopen_r_1(s)
! 15188: FILE *s;
! 15189: { BITFILE *f;
! 15190: if((f=bopen_rw(s,"r"))!=NULL) {
! 15191: f->cm=0000;
! 15192: };
! 15193: return(f);
! 15194: }
! 15195: #else
! 15196: BITFILE *bopen_r_1();
! 15197: #endif
! 15198: #if MAIN
! 15199: BITFILE *bopen_w_1(s)
! 15200: FILE *s;
! 15201: { BITFILE *f;
! 15202: if((f=bopen_rw(s,"w"))!=NULL) {
! 15203: f->i.ss.s0.cc.c0=0000;
! 15204: f->cm=0200;
! 15205: };
! 15206: return(f);
! 15207: }
! 15208: #else
! 15209: BITFILE *bopen_w_1();
! 15210: #endif
! 15211: #define getb_1(f) ( ((f)->cm)? \
! 15212: ( ((f)->cm&(f)->ic)? \
! 15213: ((f)->cm>>=1,1): \
! 15214: ((f)->cm>>=1,0) ): \
! 15215: ( (((f)->ic=getc((f)->fp))==EOF)? \
! 15216: EOF: \
! 15217: ( (f)->nb++, \
! 15218: (f)->cm=0200, \
! 15219: ((f)->cm&(f)->ic)? \
! 15220: ((f)->cm>>=1,1): \
! 15221: ((f)->cm>>=1,0) ) ) )
! 15222: #define putb_1(b,f) { \
! 15223: if((b)) (f)->i.ss.s0.cc.c0 |= (f)->cm; \
! 15224: if( !((f)->cm>>=1) ) { \
! 15225: bputc((f)->i.ss.s0.cc.c0,f); \
! 15226: (f)->nb++; \
! 15227: (f)->i.ss.s0.cc.c0=0000; (f)->cm=0200; \
! 15228: }; \
! 15229: (f)->n++; \
! 15230: }
! 15231: #define bflush_1(f) (padb((f),0,8,0), (bsize(f)>0)? bbflush(f): 0L)
! 15232:
! 15233: /* Format 10: the low-order (0001) bit in each byte is first ("little-endian"), and
! 15234: bytes are reversed (in each pair) from putc(3) order;
! 15235: */
! 15236: #if MAIN
! 15237: BITFILE *bopen_r_10(s)
! 15238: FILE *s;
! 15239: { BITFILE *f;
! 15240: if((f=bopen_rw(s,"r"))!=NULL) {
! 15241: f->sm=0000000;
! 15242: };
! 15243: return(f);
! 15244: }
! 15245: #else
! 15246: BITFILE *bopen_r_10();
! 15247: #endif
! 15248: #if MAIN
! 15249: BITFILE *bopen_w_10(s)
! 15250: FILE *s;
! 15251: { BITFILE *f;
! 15252: if((f=bopen_rw(s,"w"))!=NULL) {
! 15253: f->i.ss.s0.s=0000000;
! 15254: f->sm=0000001;
! 15255: };
! 15256: return(f);
! 15257: }
! 15258: #else
! 15259: BITFILE *bopen_w_10();
! 15260: #endif
! 15261: #define getb_10(f) ( ((f)->sm)? \
! 15262: ( ((f)->sm&(f)->i.ss.s0.s)? \
! 15263: ((f)->sm<<=1,1): \
! 15264: ((f)->sm<<=1,0) ): \
! 15265: ( (((f)->ic=getc((f)->fp))==EOF)? \
! 15266: EOF: \
! 15267: ( (f)->nb++, \
! 15268: (f)->i.ss.s0.cc.c1=(f)->ic&0377, \
! 15269: ( (((f)->ic=getc((f)->fp))==EOF)? \
! 15270: EOF: \
! 15271: ( (f)->nb++, \
! 15272: (f)->i.ss.s0.cc.c0=(f)->ic&0377, \
! 15273: (f)->sm=0000001, \
! 15274: ((f)->sm&(f)->i.ss.s0.s)? \
! 15275: ((f)->sm<<=1,1): \
! 15276: ((f)->sm<<=1,0) ) ) ) ) )
! 15277: #define putb_10(b,f) { \
! 15278: if((b)) (f)->i.ss.s0.s |= (f)->sm; \
! 15279: if( !((f)->sm<<=1) ) { \
! 15280: bputc((f)->i.ss.s0.cc.c1,f); \
! 15281: (f)->nb++; \
! 15282: bputc((f)->i.ss.s0.cc.c0,f); \
! 15283: (f)->nb++; \
! 15284: (f)->i.ss.s0.s=0000000; (f)->sm=0000001; \
! 15285: }; \
! 15286: (f)->n++; \
! 15287: }
! 15288: #define bflush_10(f) (padb((f),0,16,0), (bsize(f)>0)? bbflush(f): 0L)
! 15289:
! 15290: /* Format 11: the high-order (0200) bit in each byte is first ("little-endian"),
! 15291: and bytes are reversed (in each pair) from putc(3) order.
! 15292: */
! 15293: #if MAIN
! 15294: BITFILE *bopen_r_11(s)
! 15295: FILE *s;
! 15296: { BITFILE *f;
! 15297: if((f=bopen_rw(s,"r"))!=NULL) {
! 15298: f->sm=0000000;
! 15299: };
! 15300: return(f);
! 15301: }
! 15302: #else
! 15303: BITFILE *bopen_r_11();
! 15304: #endif
! 15305: #if MAIN
! 15306: BITFILE *bopen_w_11(s)
! 15307: FILE *s;
! 15308: { BITFILE *f;
! 15309: if((f=bopen_rw(s,"w"))!=NULL) {
! 15310: f->i.ss.s0.s=0000000;
! 15311: f->sm=0100000;
! 15312: };
! 15313: return(f);
! 15314: }
! 15315: #else
! 15316: BITFILE *bopen_w_11();
! 15317: #endif
! 15318: #define getb_11(f) ( ((f)->sm)? \
! 15319: ( ((f)->sm&(f)->i.ss.s0.s)? \
! 15320: ((f)->sm>>=1,1): \
! 15321: ((f)->sm>>=1,0) ): \
! 15322: ( (((f)->ic=getc((f)->fp))==EOF)? \
! 15323: EOF: \
! 15324: ( (f)->nb++, \
! 15325: (f)->i.ss.s0.cc.c0=(f)->ic&0377, \
! 15326: ( (((f)->ic=getc((f)->fp))==EOF)? \
! 15327: EOF: \
! 15328: ( (f)->nb++, \
! 15329: (f)->i.ss.s0.cc.c1=(f)->ic&0377, \
! 15330: (f)->sm=0100000, \
! 15331: ((f)->sm&(f)->i.ss.s0.s)? \
! 15332: ((f)->sm>>=1,1): \
! 15333: ((f)->sm>>=1,0) ) ) ) ) )
! 15334: #define putb_11(b,f) { \
! 15335: if((b)) (f)->i.ss.s0.s |= (f)->sm; \
! 15336: if( !((f)->sm>>=1) ) { \
! 15337: bputc((f)->i.ss.s0.cc.c0,f); \
! 15338: (f)->nb++; \
! 15339: bputc((f)->i.ss.s0.cc.c1,f); \
! 15340: (f)->nb++; \
! 15341: (f)->i.ss.s0.s=0000000; (f)->sm=0100000; \
! 15342: }; \
! 15343: (f)->n++; \
! 15344: }
! 15345: #define bflush_11(f) (padb((f),0,16,0), (bsize(f)>0)? bbflush(f): 0L)
! 15346:
! 15347: /**************************************************************/
! 15348: /* FORMAT: may be selected here (input and output may differ) */
! 15349:
! 15350: /* Input: */
! 15351: #define bopen_r(s) bopen_r_0((s))
! 15352: #define getb(f) getb_0(f)
! 15353: /* Output: */
! 15354: #define bopen_w(s) bopen_w_0((s))
! 15355: #define putb(b,f) putb_0((b),(f))
! 15356: #define bflush(f) bflush_0(f)
! 15357:
! 15358: /**************************************************************/
! 15359:
! 15360: /* Code common to all formats: */
! 15361: #if MAIN
! 15362: BITFILE *bopen(s,t)
! 15363: FILE *s;
! 15364: char *t;
! 15365: { BITFILE *res;
! 15366: if(*(t)=='r') res=bopen_r(s);
! 15367: else if(*(t)=='w') {
! 15368: res=bopen_w(s);
! 15369: #if BUFFERED
! 15370: if(*(t+1)=='b') {
! 15371: res->alloc = BITFILE_incr;
! 15372: if((res->buf=(char *)malloc(res->alloc))==NULL)
! 15373: abort("bopen: can't alloc buffer");
! 15374: res->cp = res->buf;
! 15375: };
! 15376: #endif
! 15377: }
! 15378: else abort("bopen: bad type: \"%s\"",t);
! 15379: return(res);
! 15380: }
! 15381: #else
! 15382: BITFILE *bopen();
! 15383: #endif
! 15384:
! 15385: #if MAIN
! 15386: padb(f,b,B,l)
! 15387: BITFILE *f;
! 15388: char b;
! 15389: int l,B;
! 15390: { while(((f)->n+(l))%(B)) putb((b),(f));
! 15391: }
! 15392: #endif
! 15393:
! 15394: #if MAIN
! 15395: unsigned long bclose(f)
! 15396: BITFILE *f;
! 15397: { unsigned long nb,nbuf;
! 15398: if(f->type=='w') {
! 15399: nbuf=bflush(f);
! 15400: fflush(f->fp);
! 15401: #if BUFFERED
! 15402: if(f->buf!=NULL) { free(f->buf); f->buf=NULL; }
! 15403: #endif
! 15404: };
! 15405: nb=f->nb;
! 15406: free(f);
! 15407: return(nb);
! 15408: }
! 15409: #else
! 15410: unsigned long bclose();
! 15411: #endif
! 15412: 0707070035350557131006640007620000050000010263430476773367100001000000000615boole.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 15413: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 15414: /* The copyright notice does not imply actual or intended publication. */
! 15415: /* AUTHORS: */
! 15416: /* H. S. Baird - ATT-BL MH - first versions */
! 15417: /* boole.h */
! 15418:
! 15419: #define boolean int
! 15420: #define T 1
! 15421: #define F 0
! 15422: 0707070035350321011006640007620000050000010263450476773367100000700000020537fioi.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 15423: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 15424: /* The copyright notice does not imply actual or intended publication. */
! 15425: /* AUTHORS: */
! 15426: /* H. S. Baird - ATT-BL MH - first versions */
! 15427:
! 15428: /* fioi.h - buffered I/O of machine-, OS-, and compiler-independent binary values.
! 15429:
! 15430: Machine-, OS-, and compiler-independence of 'fioi' functions require that:
! 15431: 1) chars are exactly 8 bits and their contents are invariant under I/O;
! 15432: 2) the order of chars, as written by putc() and read by getc(), is
! 15433: also invariant, across all machines, OS, and compilers.
! 15434: Both of these requirements are customarily met by UNIX OS & tools.
! 15435:
! 15436: All values are written/read as a stream of char's, ultimately
! 15437: using putc() & getc() macroes.
! 15438: To maximize speed, macroes are used wherever possible:
! 15439: - the first argument F of each macro is a stream (FILE *).
! 15440: - write macroes have the form fwri_TYPE(F,value); `value' is assigned to
! 15441: a variable of type TYPE before it is written (so compiler-dependent type
! 15442: coercions may apply).
! 15443: - read macroes have the form frdi_TYPE(F), returning a value of type TYPE.
! 15444: Arguments to these macroes are evaluated exactly once.
! 15445: */
! 15446:
! 15447: /** MACHINE-DEPENDENT CUSTOMIZATION OF TYPES **/
! 15448: /* For each machine, all these types must be supported in the sense that
! 15449: some roughly-equivalent machine-supported type exists. If an exact
! 15450: equivalent doesn't exist, pick the shortest that is at least as long
! 15451: (in no. bytes), if possible. If there is no machine representation
! 15452: at least as long as specified, the only penalty will be the inevitable one:
! 15453: when a value is read, it may be truncated to the maximum value that can be
! 15454: represented.
! 15455: */
! 15456: #define int1 char /* 8-bit signed 2's complement integer */
! 15457: #define int2 short /* 16-bit signed 2's complement integer */
! 15458: #define int3 int /* 24-bit signed 2's complement integer */
! 15459: #define int4 int /* 32-bit signed 2's complement integer */
! 15460: #define int8 long /* 64-bit signed 2's complement integer */
! 15461: #define uint1 unsigned char /* 8-bit unsigned integer */
! 15462: #define uint2 unsigned short /* 16-bit unsigned integer */
! 15463: #define uint3 unsigned int /* 24-bit unsigned integer */
! 15464: #define uint4 unsigned int /* 32-bit unsigned integer */
! 15465: #define uint8 unsigned long /* 64-bit unsigned integer */
! 15466:
! 15467: /* IEEE 64-bit floating point format */
! 15468: typedef struct Ieeed {
! 15469: int8 l;
! 15470: int8 h;
! 15471: } Ieeed;
! 15472:
! 15473: /* Cope with unsigned chars on 3B2 & compensate for bug on MIPS */
! 15474: #if CPU!=ATT3B && CPU!=MIPS
! 15475: #define toint1(c) (int1)(c)
! 15476: #else
! 15477: #if MAIN
! 15478: int toint1(c)
! 15479: register int c;
! 15480: { if ( ((1<<7)&c) !=0 ) return(c-256);
! 15481: else return c;
! 15482: }
! 15483: #else
! 15484: extern int toint1();
! 15485: #endif
! 15486: #endif
! 15487:
! 15488: /** THE REST OF THIS FILE IS MACHINE-, OS-, and COMPILER-INDEPENDENT **/
! 15489:
! 15490: typedef struct Fioi {
! 15491: int1 i1;
! 15492: int2 i2;
! 15493: int3 i3;
! 15494: int4 i4;
! 15495: int8 i8;
! 15496: uint1 ui1;
! 15497: uint2 ui2;
! 15498: uint3 ui3;
! 15499: uint4 ui4;
! 15500: uint8 ui8;
! 15501: char str[100];
! 15502: } Fioi;
! 15503: #define Init_Fioi {0,0,0,0,0,0,0,0,0,0,""}
! 15504: #if MAIN
! 15505: Fioi _Fioi = Init_Fioi;
! 15506: #else
! 15507: extern Fioi _Fioi;
! 15508: #endif
! 15509:
! 15510: /* Characters */
! 15511: #define fwri_ch(F,V) putc((V),(F))
! 15512: #define frdi_ch(F) getc((F))
! 15513:
! 15514: #if T /* TRANSITIONAL: used to read: "#if FWRI" */
! 15515: /* Strings are '\0'-terminated both in main memory & in peripheral files. */
! 15516: #define fwri_str(F,S) { fputs((S),(F)); putc('\0',(F)); }
! 15517: #else
! 15518: /* Strings are '\0'-terminated in the variable and '\n'-terminated in the file.
! 15519: BAD, OBSOLESCENT POLICY: both should use '\0'-termination */
! 15520: #define fwri_str(F,S) { fputs((S),(F)); putc('\n',(F)); }
! 15521: #endif
! 15522:
! 15523: #define MAX_FIO_STRLEN (128)
! 15524:
! 15525: #if T /* TRANSITIONAL: used to read: "#if FRDI" */
! 15526:
! 15527: /* Strings are '\0'-terminated both in main memory & in peripheral files. */
! 15528: /*** TRANSITIONAL PATCH: accept '\n' as a terminator also; this will be disabled
! 15529: as soon as all classifier tables have been recreated with FWRI==T. ***/
! 15530: /* Read string of maximum length MAX_FIO_STRLEN; return pointer to malloc space */
! 15531: #if MAIN
! 15532: char *frdi_str(f)
! 15533: FILE *f;
! 15534: { static char s[MAX_FIO_STRLEN+1];
! 15535: register int ch;
! 15536: register char *c,*ce;
! 15537: char *res;
! 15538: ce=(c=s)+MAX_FIO_STRLEN;
! 15539: while((c<ce)&&((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) *(c++) = ch;
! 15540: *c='\0';
! 15541: if(c==ce) /* label is truncated; find end of it */ {
! 15542: while(((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) ;
! 15543: };
! 15544: if((res=(char *)strdup(s))==NULL)
! 15545: abort("frdi_str: can't dup char *s[%d]",strlen(s));
! 15546: return(res);
! 15547: }
! 15548: #else
! 15549: char *frdi_str();
! 15550: #endif
! 15551: /* 's' is an already-allocated buffer of known length >=N (including '\0') */
! 15552: #if MAIN
! 15553: int frdi_strn(f,s,n)
! 15554: FILE *f;
! 15555: char s[];
! 15556: int n;
! 15557: { register int ch;
! 15558: register char *c,*ce;
! 15559: ce=(c=s)+n-1;
! 15560: while((c<ce)&&((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) *(c++) = ch;
! 15561: *c='\0';
! 15562: if(c==ce) /* label is truncated; find end of it */ {
! 15563: while(((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) ;
! 15564: };
! 15565: if(ch==EOF) return(0); else if(ferror(f)) return(-errno); else return(1);
! 15566: }
! 15567: #else
! 15568: int frdi_strn();
! 15569: #endif
! 15570:
! 15571: #else
! 15572:
! 15573: /* Strings are '\0'-terminated in the variable and '\n'-terminated in the file.
! 15574: BAD, OBSOLESCENT POLICY: both should use '\0'-termination */
! 15575: /* Read string of maximum length MAX_FIO_STRLEN; return pointer to malloc space */
! 15576: #if MAIN
! 15577: char *frdi_str(f)
! 15578: FILE *f;
! 15579: { static char s[MAX_FIO_STRLEN+1];
! 15580: register int ch;
! 15581: register char *c,*ce;
! 15582: char *res;
! 15583: ce=(c=s)+MAX_FIO_STRLEN;
! 15584: while((c<ce)&&((ch=getc(f))!=EOF)&&(ch!='\n')) *(c++) = ch;
! 15585: *c='\0';
! 15586: if(c==ce) /* label is truncated; find end of it */ {
! 15587: while(((ch=getc(f))!=EOF)&&(ch!='\n')) ;
! 15588: };
! 15589: if((res=(char *)strdup(s))==NULL)
! 15590: abort("frdi_str: can't dup char *s[%d]",strlen(s));
! 15591: return(res);
! 15592: }
! 15593: #else
! 15594: char *frdi_str();
! 15595: #endif
! 15596: /* S is an already-allocated buffer of known length >=N (including '\0') */
! 15597: #define frdi_strn(F,S,N) ( feof(F)? 0 : ( \
! 15598: fgets((S),(N),(F)), \
! 15599: ( (((S)[strlen((S))-1])=='\n')? (S)[strlen((S))-1]='\0': 1 ), \
! 15600: (ferror(F)? -errno: 1) ) )
! 15601:
! 15602: #endif
! 15603:
! 15604: /* Integers (unsigned and signed) are written low-order byte first. */
! 15605: #define fwri_uint1(F,V) fwri_ch((F),(uint1)(V))
! 15606: #define frdi_uint1(F) ((uint1)frdi_ch((F)))
! 15607:
! 15608: #define fwri_uint2(F,V) { fwri_uint1((F),_Fioi.ui2=(V)); \
! 15609: fwri_uint1((F),_Fioi.ui2>>8); }
! 15610: #define frdi_uint2(F) ((uint2)( _Fioi.ui2=frdi_uint1((F)), \
! 15611: (frdi_uint1((F))<<8)|_Fioi.ui2 ))
! 15612:
! 15613: #define fwri_uint3(F,V) { fwri_uint2((F),_Fioi.ui3=(V)); \
! 15614: fwri_uint1((F),_Fioi.ui3>>16); }
! 15615: #define frdi_uint3(F) ((uint3)( _Fioi.ui3=frdi_uint2((F)), \
! 15616: (frdi_uint1((F))<<16)|_Fioi.ui3 ))
! 15617:
! 15618: #define fwri_uint4(F,V) { fwri_uint2((F),_Fioi.ui4=(V)); \
! 15619: fwri_uint2((F),_Fioi.ui4>>16); }
! 15620: #define frdi_uint4(F) ((uint4)( _Fioi.ui4=frdi_uint2((F)), \
! 15621: (frdi_uint2((F))<<16)|_Fioi.ui4 ))
! 15622:
! 15623: #define fwri_uint8(F,V) { fwri_uint4((F),_Fioi.ui8=(V)); \
! 15624: fwri_uint4((F),_Fioi.ui8>>32); }
! 15625: #define frdi_uint8(F) ((uint8)( _Fioi.ui8=frdi_uint4((F)), \
! 15626: (frdi_uint4((F))<<32)|_Fioi.ui8 ))
! 15627:
! 15628: /* Signed integers are assumed to be 2's complement.
! 15629: Note the suppression of inappropriate sign-extensions using judicious
! 15630: unsigned reads. */
! 15631:
! 15632: #define fwri_int1(F,V) fwri_ch((F),_Fioi.i1=(V))
! 15633: #define frdi_int1(F) (toint1(frdi_ch((F))))
! 15634:
! 15635: #define fwri_int2(F,V) { fwri_int1((F),_Fioi.i2=(V)); \
! 15636: fwri_int1((F),_Fioi.i2>>8); }
! 15637: #define frdi_int2(F) ((int2)( _Fioi.i2=frdi_uint1((F)), \
! 15638: (frdi_int1((F))<<8)|_Fioi.i2 ))
! 15639:
! 15640: #define fwri_int3(F,V) { fwri_int2((F),_Fioi.i3=(V)); \
! 15641: fwri_int1((F),_Fioi.i3>>16); }
! 15642: #define frdi_int3(F) ((int3)( _Fioi.i3=frdi_uint2((F)), \
! 15643: (frdi_int1((F))<<16)|_Fioi.i3 ))
! 15644:
! 15645: #define fwri_int4(F,V) { fwri_int2((F),_Fioi.i4=(V)); \
! 15646: fwri_int2((F),_Fioi.i4>>16); }
! 15647: #define frdi_int4(F) ((int4)( _Fioi.i4=frdi_uint2((F)), \
! 15648: (frdi_int2((F))<<16)|_Fioi.i4 ))
! 15649:
! 15650: #define fwri_int8(F,V) { fwri_int4((F),_Fioi.i8=(V)); \
! 15651: fwri_int4((F),_Fioi.i8>>32); }
! 15652: #define frdi_int8(F) ((int8)( _Fioi.i8=frdi_uint4((F)), \
! 15653: (frdi_int4((F))<<32)|_Fioi.i8 ))
! 15654:
! 15655:
! 15656: /* Floating point */
! 15657: #if MAIN
! 15658: /* See Marsha Grabow & George Gilmer & KT */
! 15659: void
! 15660: dtoieeed(ieee,native)
! 15661: Ieeed *ieee;
! 15662: double native;
! 15663: {
! 15664: double fr, ho, f;
! 15665: int iexp;
! 15666:
! 15667: if(native < 0) {
! 15668: dtoieeed(ieee, -native);
! 15669: ieee->h |= 0x80000000L;
! 15670: return;
! 15671: }
! 15672: if(native == 0) {
! 15673: ieee->l = 0;
! 15674: ieee->h = 0;
! 15675: return;
! 15676: }
! 15677: fr = frexp(native, &iexp);
! 15678: f = 2097152L; /* shouldnt use fp constants here */
! 15679: fr = modf(fr*f, &ho);
! 15680: ieee->h = ho;
! 15681: ieee->h &= 0xfffffL;
! 15682: ieee->h |= (iexp+1022L) << 20;
! 15683: f = 65536L;
! 15684: fr = modf(fr*f, &ho);
! 15685: ieee->l = ho;
! 15686: ieee->l <<= 16;
! 15687: ieee->l |= (long)(fr*f);
! 15688: }
! 15689: #else
! 15690: void dtoieeed();
! 15691: #endif
! 15692: 0707070035350321111006640007620000050000010263500476773367100000700000002300font.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 15693: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 15694: /* The copyright notice does not imply actual or intended publication. */
! 15695: /* AUTHORS: */
! 15696: /* H. S. Baird - ATT-BL MH - first versions */
! 15697: /* font.h - typedefs, etc for font-characteristic functions:
! 15698: The baseline is defined by the locus of bottoms of all characters that
! 15699: have no descenders and are not punctuation.
! 15700: The top is the top of characters without risers (negative).
! 15701: The `rise' is the (negative) height of risers (above baseline), and `descent'
! 15702: is the positive) distance below baseline.
! 15703: */
! 15704:
! 15705: /* font attributes, in absolute scanner coordinates */
! 15706: typedef struct FontAttr {
! 15707: Scoor body; /* point size */
! 15708: Scoor xhgt; /* x-height */
! 15709: Scoor ascd; /* height of ascenders (above xheight, >0) */
! 15710: Scoor caph; /* capital height (above baseline, >0) */
! 15711: Scoor desc; /* height of descenders (below baseline, >0) */
! 15712: Scoor doth; /* height of punctuation dots */
! 15713: } FontAttr;
! 15714:
! 15715: #ifdef MAIN
! 15716: FontAttr *ps_to_attr(); /* pointsize, digit'n resol'n --> attributes */
! 15717: xhgt_to_ps();
! 15718: caph_to_ps();
! 15719: #endif
! 15720: 0707070035350320471006640007620000050000010263510476773367200000700000124016jslr.c /* AT&T PROPRIETARY: Developed at AT&T Expense */
! 15721: /* AUTHORS: */
! 15722: /* H. S. Baird - ATT-BL MH - first versions */
! 15723: /* rlbr - run-length encode a binary raster line
! 15724: `rasp' is a raster line of bits. rasp[0] is the leftmost byte in the line and
! 15725: the 001 bit is the leftmost bit in each byte ("little-endian").
! 15726: Analyzes the line into a series of runs of `1's, placing them into array
! 15727: `runs'. Observes margins: starts at `lm' bit and continues through `rm'; bits
! 15728: outside margins are assumed 0. A `run' is two shorts (the starting &
! 15729: ending indices of the run of `1's, inclusive). The indices are shifted
! 15730: so that the index of `lm' becomes `olm'. Returns the number of runs.
! 15731: NOTES:
! 15732: The contents of the raster-line are restored to their orginal
! 15733: state on return. The user must ensure that:
! 15734: (1) margins fall within `rasp';
! 15735: (2) `rasp' has one extra byte at the end for use by this routine; and
! 15736: (3) `runs' is big enough to hold the worst-case no. of runs that could
! 15737: result, which is (rm-lm)/2+1.
! 15738: */
! 15739:
! 15740: int rlbr(rasp,lm,rm,olm,runp)
! 15741: char unsigned rasp[]; /* binary raster line (with 1 extra byte at end) */
! 15742: int lm,rm; /* left,right margin bit indices within raster */
! 15743: int olm; /* on output, `lm' index has become `olm' */
! 15744: short runp[]; /* array of run-segments [xs,xe] (pairs of short) */
! 15745: { register char unsigned *bp,*ep; /* byte pointers into raster line */
! 15746: register short cb; /* x_coordinate of 1st bit of current byte */
! 15747: register short *xp; /* ptr to x-coordinate in run-length array */
! 15748: register short prior; /* prior bit, coded 0400 or 0000 */
! 15749:
! 15750: char unsigned *lbp,*rbp; /* ptrs to margin bytes */
! 15751: int lo,ro; /* `offset' of margin bits in bytes */
! 15752: char unsigned svlb,svrb,svrrb; /* unmodified copies of margin bytes */
! 15753:
! 15754: if(lm>rm) return(0);
! 15755: /* compute margins' bytes, save copies, set bits outside margins to 0 */
! 15756: lbp=rasp+(lm/8); svlb= *lbp;
! 15757: /* force bits left of lm to 0 */
! 15758: lo=lm%8; if(lo>0) *lbp &= (0377<<lo);
! 15759: rbp=rasp+(rm/8); svrb= *rbp;
! 15760: /* force bits right of rm to 0 */
! 15761: ro=rm%8; if(ro<7) *rbp &= (0377>>(7-ro));
! 15762: /* place a 0000 byte to right of margin byte, to force good termination */
! 15763: svrrb= *(rbp+1); *(rbp+1)='\0';
! 15764:
! 15765: /* MAIN LOOP */
! 15766: prior=0000; /* act as if there's a 0 byte to left of margin byte */
! 15767: xp=runp;
! 15768: bp=lbp;
! 15769: ep=rbp+2;
! 15770: cb=(-lo+olm);
! 15771: do { switch( prior | *(bp++) ) {
! 15772: /* contents of rlbr.c1 come below here */
! 15773: case 00: break;
! 15774: case 01: *(xp++)=cb; *(xp++)=cb; break;
! 15775: case 02: *(xp++)=cb+1; *(xp++)=cb+1; break;
! 15776: case 03: *(xp++)=cb; *(xp++)=cb+1; break;
! 15777: case 04: *(xp++)=cb+2; *(xp++)=cb+2; break;
! 15778: case 05: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; break;
! 15779: case 06: *(xp++)=cb+1; *(xp++)=cb+2; break;
! 15780: case 07: *(xp++)=cb; *(xp++)=cb+2; break;
! 15781: case 010: *(xp++)=cb+3; *(xp++)=cb+3; break;
! 15782: case 011: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; break;
! 15783: case 012: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; break;
! 15784: case 013: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; break;
! 15785: case 014: *(xp++)=cb+2; *(xp++)=cb+3; break;
! 15786: case 015: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; break;
! 15787: case 016: *(xp++)=cb+1; *(xp++)=cb+3; break;
! 15788: case 017: *(xp++)=cb; *(xp++)=cb+3; break;
! 15789: case 020: *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15790: case 021: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15791: case 022: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15792: case 023: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15793: case 024: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15794: case 025: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15795: case 026: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15796: case 027: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
! 15797: case 030: *(xp++)=cb+3; *(xp++)=cb+4; break;
! 15798: case 031: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; break;
! 15799: case 032: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; break;
! 15800: case 033: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; break;
! 15801: case 034: *(xp++)=cb+2; *(xp++)=cb+4; break;
! 15802: case 035: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; break;
! 15803: case 036: *(xp++)=cb+1; *(xp++)=cb+4; break;
! 15804: case 037: *(xp++)=cb; *(xp++)=cb+4; break;
! 15805: case 040: *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15806: case 041: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15807: case 042: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15808: case 043: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15809: case 044: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15810: case 045: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15811: case 046: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15812: case 047: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15813: case 050: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15814: case 051: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15815: case 052: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15816: case 053: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15817: case 054: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15818: case 055: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15819: case 056: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15820: case 057: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
! 15821: case 060: *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15822: case 061: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15823: case 062: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15824: case 063: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15825: case 064: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15826: case 065: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15827: case 066: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15828: case 067: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
! 15829: case 070: *(xp++)=cb+3; *(xp++)=cb+5; break;
! 15830: case 071: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 15831: case 072: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 15832: case 073: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 15833: case 074: *(xp++)=cb+2; *(xp++)=cb+5; break;
! 15834: case 075: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; break;
! 15835: case 076: *(xp++)=cb+1; *(xp++)=cb+5; break;
! 15836: case 077: *(xp++)=cb; *(xp++)=cb+5; break;
! 15837: case 0100: *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15838: case 0101: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15839: case 0102: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15840: case 0103: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15841: case 0104: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15842: case 0105: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15843: case 0106: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15844: case 0107: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15845: case 0110: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15846: case 0111: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15847: case 0112: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15848: case 0113: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15849: case 0114: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15850: case 0115: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15851: case 0116: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15852: case 0117: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15853: case 0120: *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15854: case 0121: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15855: case 0122: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15856: case 0123: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15857: case 0124: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15858: case 0125: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15859: case 0126: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15860: case 0127: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15861: case 0130: *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15862: case 0131: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15863: case 0132: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15864: case 0133: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15865: case 0134: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15866: case 0135: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15867: case 0136: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15868: case 0137: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
! 15869: case 0140: *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15870: case 0141: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15871: case 0142: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15872: case 0143: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15873: case 0144: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15874: case 0145: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15875: case 0146: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15876: case 0147: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15877: case 0150: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15878: case 0151: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15879: case 0152: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15880: case 0153: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15881: case 0154: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15882: case 0155: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15883: case 0156: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15884: case 0157: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
! 15885: case 0160: *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15886: case 0161: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15887: case 0162: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15888: case 0163: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15889: case 0164: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15890: case 0165: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15891: case 0166: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15892: case 0167: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 15893: case 0170: *(xp++)=cb+3; *(xp++)=cb+6; break;
! 15894: case 0171: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 15895: case 0172: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 15896: case 0173: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 15897: case 0174: *(xp++)=cb+2; *(xp++)=cb+6; break;
! 15898: case 0175: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; break;
! 15899: case 0176: *(xp++)=cb+1; *(xp++)=cb+6; break;
! 15900: case 0177: *(xp++)=cb; *(xp++)=cb+6; break;
! 15901: case 0200: *(xp++)=cb+7; prior=0400; break;
! 15902: case 0201: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+7; prior=0400; break;
! 15903: case 0202: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+7; prior=0400; break;
! 15904: case 0203: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+7; prior=0400; break;
! 15905: case 0204: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
! 15906: case 0205: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
! 15907: case 0206: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
! 15908: case 0207: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
! 15909: case 0210: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15910: case 0211: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15911: case 0212: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15912: case 0213: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15913: case 0214: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15914: case 0215: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15915: case 0216: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15916: case 0217: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
! 15917: case 0220: *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15918: case 0221: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15919: case 0222: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15920: case 0223: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15921: case 0224: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15922: case 0225: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15923: case 0226: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15924: case 0227: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15925: case 0230: *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15926: case 0231: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15927: case 0232: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15928: case 0233: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15929: case 0234: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15930: case 0235: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15931: case 0236: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15932: case 0237: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
! 15933: case 0240: *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15934: case 0241: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15935: case 0242: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15936: case 0243: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15937: case 0244: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15938: case 0245: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15939: case 0246: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15940: case 0247: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15941: case 0250: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15942: case 0251: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15943: case 0252: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15944: case 0253: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15945: case 0254: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15946: case 0255: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15947: case 0256: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15948: case 0257: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15949: case 0260: *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15950: case 0261: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15951: case 0262: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15952: case 0263: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15953: case 0264: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15954: case 0265: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15955: case 0266: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15956: case 0267: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15957: case 0270: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15958: case 0271: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15959: case 0272: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15960: case 0273: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15961: case 0274: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15962: case 0275: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15963: case 0276: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15964: case 0277: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
! 15965: case 0300: *(xp++)=cb+6; prior=0400; break;
! 15966: case 0301: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+6; prior=0400; break;
! 15967: case 0302: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; prior=0400; break;
! 15968: case 0303: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+6; prior=0400; break;
! 15969: case 0304: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
! 15970: case 0305: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
! 15971: case 0306: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
! 15972: case 0307: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
! 15973: case 0310: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15974: case 0311: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15975: case 0312: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15976: case 0313: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15977: case 0314: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15978: case 0315: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15979: case 0316: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15980: case 0317: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
! 15981: case 0320: *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15982: case 0321: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15983: case 0322: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15984: case 0323: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15985: case 0324: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15986: case 0325: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15987: case 0326: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15988: case 0327: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15989: case 0330: *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15990: case 0331: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15991: case 0332: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15992: case 0333: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15993: case 0334: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15994: case 0335: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15995: case 0336: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15996: case 0337: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
! 15997: case 0340: *(xp++)=cb+5; prior=0400; break;
! 15998: case 0341: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; prior=0400; break;
! 15999: case 0342: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; prior=0400; break;
! 16000: case 0343: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; prior=0400; break;
! 16001: case 0344: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
! 16002: case 0345: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
! 16003: case 0346: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
! 16004: case 0347: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
! 16005: case 0350: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16006: case 0351: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16007: case 0352: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16008: case 0353: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16009: case 0354: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16010: case 0355: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16011: case 0356: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16012: case 0357: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
! 16013: case 0360: *(xp++)=cb+4; prior=0400; break;
! 16014: case 0361: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; prior=0400; break;
! 16015: case 0362: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; prior=0400; break;
! 16016: case 0363: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; prior=0400; break;
! 16017: case 0364: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
! 16018: case 0365: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
! 16019: case 0366: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
! 16020: case 0367: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
! 16021: case 0370: *(xp++)=cb+3; prior=0400; break;
! 16022: case 0371: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; prior=0400; break;
! 16023: case 0372: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; prior=0400; break;
! 16024: case 0373: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; prior=0400; break;
! 16025: case 0374: *(xp++)=cb+2; prior=0400; break;
! 16026: case 0375: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; prior=0400; break;
! 16027: case 0376: *(xp++)=cb+1; prior=0400; break;
! 16028: case 0377: *(xp++)=cb; prior=0400; break;
! 16029:
! 16030: case 0400: *(xp++)=cb-1; prior=0000; break;
! 16031: case 0401: *(xp++)=cb; prior=0000; break;
! 16032: case 0402: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; prior=0000; break;
! 16033: case 0403: *(xp++)=cb+1; prior=0000; break;
! 16034: case 0404: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; prior=0000; break;
! 16035: case 0405: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; prior=0000; break;
! 16036: case 0406: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; prior=0000; break;
! 16037: case 0407: *(xp++)=cb+2; prior=0000; break;
! 16038: case 0410: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
! 16039: case 0411: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
! 16040: case 0412: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
! 16041: case 0413: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
! 16042: case 0414: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; prior=0000; break;
! 16043: case 0415: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; prior=0000; break;
! 16044: case 0416: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; prior=0000; break;
! 16045: case 0417: *(xp++)=cb+3; prior=0000; break;
! 16046: case 0420: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16047: case 0421: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16048: case 0422: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16049: case 0423: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16050: case 0424: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16051: case 0425: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16052: case 0426: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16053: case 0427: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
! 16054: case 0430: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
! 16055: case 0431: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
! 16056: case 0432: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
! 16057: case 0433: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
! 16058: case 0434: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; prior=0000; break;
! 16059: case 0435: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; prior=0000; break;
! 16060: case 0436: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; prior=0000; break;
! 16061: case 0437: *(xp++)=cb+4; prior=0000; break;
! 16062: case 0440: *(xp++)=cb-1; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16063: case 0441: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16064: case 0442: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16065: case 0443: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16066: case 0444: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16067: case 0445: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16068: case 0446: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16069: case 0447: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16070: case 0450: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16071: case 0451: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16072: case 0452: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16073: case 0453: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16074: case 0454: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16075: case 0455: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16076: case 0456: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16077: case 0457: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
! 16078: case 0460: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16079: case 0461: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16080: case 0462: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16081: case 0463: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16082: case 0464: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16083: case 0465: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16084: case 0466: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16085: case 0467: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
! 16086: case 0470: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
! 16087: case 0471: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
! 16088: case 0472: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
! 16089: case 0473: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
! 16090: case 0474: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+5; prior=0000; break;
! 16091: case 0475: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; prior=0000; break;
! 16092: case 0476: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+5; prior=0000; break;
! 16093: case 0477: *(xp++)=cb+5; prior=0000; break;
! 16094: case 0500: *(xp++)=cb-1; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16095: case 0501: *(xp++)=cb; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16096: case 0502: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16097: case 0503: *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16098: case 0504: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16099: case 0505: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16100: case 0506: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16101: case 0507: *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16102: case 0510: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16103: case 0511: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16104: case 0512: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16105: case 0513: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16106: case 0514: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16107: case 0515: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16108: case 0516: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16109: case 0517: *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16110: case 0520: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16111: case 0521: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16112: case 0522: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16113: case 0523: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16114: case 0524: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16115: case 0525: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16116: case 0526: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16117: case 0527: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16118: case 0530: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16119: case 0531: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16120: case 0532: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16121: case 0533: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16122: case 0534: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16123: case 0535: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16124: case 0536: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16125: case 0537: *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
! 16126: case 0540: *(xp++)=cb-1; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16127: case 0541: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16128: case 0542: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16129: case 0543: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16130: case 0544: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16131: case 0545: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16132: case 0546: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16133: case 0547: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16134: case 0550: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16135: case 0551: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16136: case 0552: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16137: case 0553: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16138: case 0554: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16139: case 0555: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16140: case 0556: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16141: case 0557: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
! 16142: case 0560: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16143: case 0561: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16144: case 0562: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16145: case 0563: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16146: case 0564: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16147: case 0565: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16148: case 0566: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16149: case 0567: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
! 16150: case 0570: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
! 16151: case 0571: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
! 16152: case 0572: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
! 16153: case 0573: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
! 16154: case 0574: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+6; prior=0000; break;
! 16155: case 0575: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; prior=0000; break;
! 16156: case 0576: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+6; prior=0000; break;
! 16157: case 0577: *(xp++)=cb+6; prior=0000; break;
! 16158: case 0600: *(xp++)=cb-1; *(xp++)=cb+7; break;
! 16159: case 0601: *(xp++)=cb; *(xp++)=cb+7; break;
! 16160: case 0602: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+7; break;
! 16161: case 0603: *(xp++)=cb+1; *(xp++)=cb+7; break;
! 16162: case 0604: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; break;
! 16163: case 0605: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; break;
! 16164: case 0606: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+7; break;
! 16165: case 0607: *(xp++)=cb+2; *(xp++)=cb+7; break;
! 16166: case 0610: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16167: case 0611: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16168: case 0612: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16169: case 0613: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16170: case 0614: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16171: case 0615: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16172: case 0616: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16173: case 0617: *(xp++)=cb+3; *(xp++)=cb+7; break;
! 16174: case 0620: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16175: case 0621: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16176: case 0622: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16177: case 0623: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16178: case 0624: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16179: case 0625: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16180: case 0626: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16181: case 0627: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16182: case 0630: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16183: case 0631: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16184: case 0632: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16185: case 0633: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16186: case 0634: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16187: case 0635: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16188: case 0636: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16189: case 0637: *(xp++)=cb+4; *(xp++)=cb+7; break;
! 16190: case 0640: *(xp++)=cb-1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16191: case 0641: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16192: case 0642: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16193: case 0643: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16194: case 0644: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16195: case 0645: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16196: case 0646: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16197: case 0647: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16198: case 0650: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16199: case 0651: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16200: case 0652: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16201: case 0653: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16202: case 0654: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16203: case 0655: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16204: case 0656: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16205: case 0657: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16206: case 0660: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16207: case 0661: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16208: case 0662: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16209: case 0663: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16210: case 0664: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16211: case 0665: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16212: case 0666: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16213: case 0667: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16214: case 0670: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16215: case 0671: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16216: case 0672: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16217: case 0673: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16218: case 0674: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16219: case 0675: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16220: case 0676: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16221: case 0677: *(xp++)=cb+5; *(xp++)=cb+7; break;
! 16222: case 0700: *(xp++)=cb-1; *(xp++)=cb+6; break;
! 16223: case 0701: *(xp++)=cb; *(xp++)=cb+6; break;
! 16224: case 0702: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; break;
! 16225: case 0703: *(xp++)=cb+1; *(xp++)=cb+6; break;
! 16226: case 0704: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; break;
! 16227: case 0705: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; break;
! 16228: case 0706: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; break;
! 16229: case 0707: *(xp++)=cb+2; *(xp++)=cb+6; break;
! 16230: case 0710: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16231: case 0711: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16232: case 0712: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16233: case 0713: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16234: case 0714: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16235: case 0715: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16236: case 0716: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16237: case 0717: *(xp++)=cb+3; *(xp++)=cb+6; break;
! 16238: case 0720: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16239: case 0721: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16240: case 0722: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16241: case 0723: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16242: case 0724: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16243: case 0725: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16244: case 0726: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16245: case 0727: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16246: case 0730: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16247: case 0731: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16248: case 0732: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16249: case 0733: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16250: case 0734: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16251: case 0735: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16252: case 0736: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16253: case 0737: *(xp++)=cb+4; *(xp++)=cb+6; break;
! 16254: case 0740: *(xp++)=cb-1; *(xp++)=cb+5; break;
! 16255: case 0741: *(xp++)=cb; *(xp++)=cb+5; break;
! 16256: case 0742: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; break;
! 16257: case 0743: *(xp++)=cb+1; *(xp++)=cb+5; break;
! 16258: case 0744: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; break;
! 16259: case 0745: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; break;
! 16260: case 0746: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; break;
! 16261: case 0747: *(xp++)=cb+2; *(xp++)=cb+5; break;
! 16262: case 0750: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16263: case 0751: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16264: case 0752: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16265: case 0753: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16266: case 0754: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16267: case 0755: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16268: case 0756: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16269: case 0757: *(xp++)=cb+3; *(xp++)=cb+5; break;
! 16270: case 0760: *(xp++)=cb-1; *(xp++)=cb+4; break;
! 16271: case 0761: *(xp++)=cb; *(xp++)=cb+4; break;
! 16272: case 0762: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; break;
! 16273: case 0763: *(xp++)=cb+1; *(xp++)=cb+4; break;
! 16274: case 0764: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; break;
! 16275: case 0765: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; break;
! 16276: case 0766: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; break;
! 16277: case 0767: *(xp++)=cb+2; *(xp++)=cb+4; break;
! 16278: case 0770: *(xp++)=cb-1; *(xp++)=cb+3; break;
! 16279: case 0771: *(xp++)=cb; *(xp++)=cb+3; break;
! 16280: case 0772: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; break;
! 16281: case 0773: *(xp++)=cb+1; *(xp++)=cb+3; break;
! 16282: case 0774: *(xp++)=cb-1; *(xp++)=cb+2; break;
! 16283: case 0775: *(xp++)=cb; *(xp++)=cb+2; break;
! 16284: case 0776: *(xp++)=cb-1; *(xp++)=cb+1; break;
! 16285: case 0777: break;
! 16286:
! 16287: /* contents of jslr.c1 come above here */
! 16288: };
! 16289: cb += 8;
! 16290: }
! 16291: while(bp<ep);
! 16292: /* restore margin bytes */
! 16293: *lbp = svlb;
! 16294: *rbp = svrb;
! 16295: *(rbp+1) = svrrb;
! 16296: return((xp-runp)/2);
! 16297: };
! 16298: 0707070035350320511006640007620000050000010263540476773367200001100000001652limits.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 16299: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 16300: /* The copyright notice does not imply actual or intended publication. */
! 16301: /* AUTHORS: */
! 16302: /* H. S. Baird - ATT-BL MH - first versions */
! 16303: /* Extreme values of integral types (conforms to Oct 1, 86 draft ANSI C std) */
! 16304: #define CHAR_BIT 8
! 16305: #define SCHAR_MIN -128
! 16306: #define SCHAR_MAX 127
! 16307: #define UCHAR_MIN 0
! 16308: #define UCHAR_MAX 255
! 16309: #define CHAR_MIN SCHAR_MIN /* type char sign-extends */
! 16310: #define CHAR_MAX SCHAR_MAX /* type char sign-extends */
! 16311:
! 16312: #define SHRT_MIN -32768
! 16313: #define SHRT_MAX 32767
! 16314: #define USHRT_MIN 0
! 16315: #define USHRT_MAX 65535
! 16316:
! 16317: #define INT_MIN -2147483648
! 16318: #define INT_MAX 2147483647
! 16319: #define UINT_MIN 0
! 16320: #define UINT_MAX 4294967295
! 16321:
! 16322: #define LONG_MIN -2147483648
! 16323: #define LONG_MAX 2147483647
! 16324: #define ULONG_MIN 0
! 16325: #define ULONG_MAX 4294967295
! 16326: 0707070035351106241006640007620000050000010263560476773367300001000000025436myftw.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 16327: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 16328: /* The copyright notice does not imply actual or intended publication. */
! 16329: /* AUTHORS: */
! 16330: /* H. S. Baird - ATT-BL MH - first versions */
! 16331: /*
! 16332: * ftw - file tree walk
! 16333: *
! 16334: * int ftw (path, fn, depth) char *path; int (*fn)(); int depth;
! 16335: *
! 16336: * Given a path name, ftw starts from the file given by that path
! 16337: * name and visits each file and directory in the tree beneath
! 16338: * that file. If a single file has multiple links within the
! 16339: * structure, it will be visited once for each such link.
! 16340: * For each object visited, fn is called with four arguments.
! 16341: * The fourth can often be ignored; it is a pointer, say S,
! 16342: * declared "struct FTW *S", discussed in more detail below.
! 16343: * The first contains the path name of the object, the second
! 16344: * contains a pointer to a stat buffer which will usually hold
! 16345: * appropriate information for the object and the third contains
! 16346: * an integer value giving additional information about the
! 16347: * object, as follows:
! 16348: *
! 16349: * FTW_F The object is a file for which stat was
! 16350: * successful. It does not guarantee that the
! 16351: * file can actually be read.
! 16352: *
! 16353: * FTW_D The object is a directory for which stat and
! 16354: * open for read were both successful. This is
! 16355: * a preorder visit -- objects in the directory
! 16356: * are yet to be visited.
! 16357: *
! 16358: * FTW_DNR The object is a directory for which stat
! 16359: * succeeded, but which cannot be read. Because
! 16360: * the directory cannot be read, fn will not be
! 16361: * called for any descendants of this directory.
! 16362: *
! 16363: * FTW_DP The object is a directory for which stat and
! 16364: * open for read were both successful. This is
! 16365: * a postorder visit -- everything in the directory
! 16366: * has already been visited.
! 16367: *
! 16368: * FTW_NS Lstat failed on the object. If errno is EACCES,
! 16369: * then the failure stems from lack of
! 16370: * appropriate permission. This indication will
! 16371: * be given, for example, for each file in a directory
! 16372: * with read but no execute permission. Whenever
! 16373: * stat fails, it is not possible to determine
! 16374: * whether this object is a file or a directory.
! 16375: * The stat buffer passed to fn will contain garbage.
! 16376: *
! 16377: * FTW_SL The object is a symbolic link. Set S->quit
! 16378: * (a component of the structure pointed to by
! 16379: * the fourth parameter to fn) to FTW_FOLLOW to
! 16380: * have the link followed and the object to which
! 16381: * it points visited.
! 16382: *
! 16383: * FTW_NSL Lstat succeeded, but stat failed on the object.
! 16384: * This is only possible when following a symbolic
! 16385: * link.
! 16386: *
! 16387: * Among the components of the structure to which the fourth
! 16388: * parameter, S, to fn points is S->quit. If the caller sets
! 16389: * S->quit to FTW_SKR, then no more files in the current directory
! 16390: * will be visited. (The current directory is the one containing
! 16391: * the object being visited.) If the third parameter to fn is
! 16392: * FTW_D and the caller sets S->quit to FTW_SKD, then this directory
! 16393: * (the one named in the first parameter to fn) will be skipped.
! 16394: *
! 16395: * Other components pointed to by the fourth parameter S are
! 16396: * the current recursion level S->level (top level = 0) and
! 16397: * the offset S->base in the pathname of the current object
! 16398: * (the first parameter to fn) of the object's base name.
! 16399: * By expanding the definition of struct FTW given below and
! 16400: * including the files included below, one can arrange for
! 16401: * S to point to a larger structure, components of which can
! 16402: * be initialized (for example) on calls to fn with third
! 16403: * parameter FTW_D.
! 16404: *
! 16405: * If fn returns nonzero, ftw stops and returns the same value
! 16406: * to its caller. Ftw only initiates a nonzero return if malloc
! 16407: * fails; in this case ftw sets errno to ENOMEM and returns -1.
! 16408: *
! 16409: * The third argument to ftw does not limit the depth to which
! 16410: * ftw will go. Rather, it limits the depth to which ftw will
! 16411: * go before it starts recycling file descriptors. In general,
! 16412: * it is necessary to use a file descriptor for each level of the
! 16413: * tree, but they can be recycled for deep trees by saving the position,
! 16414: * closing, re-opening, and seeking. It is possible to start
! 16415: * recycling file descriptors by sensing when we have run out, but
! 16416: * in general this will not be terribly useful if fn expects to be
! 16417: * able to open files. We could also figure out how many file descriptors
! 16418: * are available and guarantee a certain number to fn, but we would not
! 16419: * know how many to guarantee, and we do not want to impose the extra
! 16420: * overhead on a caller who knows how many are available without
! 16421: * having to figure it out.
! 16422: *
! 16423: * It is possible for ftw to die with a memory fault in the event
! 16424: * of a file system so deeply nested that the stack overflows.
! 16425: */
! 16426:
! 16427: #include <sys/types.h>
! 16428: #include <sys/stat.h>
! 16429: #include "myftw.h" /* not <ftw.h>, for portability to Suns */
! 16430: /*
! 16431: * Struct FTW (whose definition starts at the end of ftw.h) must
! 16432: * must include at least the integers quit, base, and level.
! 16433: */
! 16434:
! 16435: #define FTW_PATHLEN0 1000
! 16436: #define FTW_PATHINC 1000
! 16437: #ifndef S_IFLNK
! 16438: #define lstat stat
! 16439: #endif
! 16440: #ifdef S_IFSOCK
! 16441: #include <sys/dir.h>
! 16442: #else
! 16443: #include "ndir.h"
! 16444: #endif
! 16445: #ifndef ENOMEM
! 16446: #include <errno.h>
! 16447: #endif
! 16448:
! 16449: extern int errno;
! 16450:
! 16451: /*
! 16452: * Each generation of ftw1 (the real ftw) allocates one copy, R, of the
! 16453: * following structure; it passes a pointer to this structure when it
! 16454: * recursively invokes itself. These structures are chained together,
! 16455: * so that if it becomes necessary to recycle file descriptors, then
! 16456: * the oldest descriptor (the one at the shallowest depth still open)
! 16457: * can be recycled.
! 16458: */
! 16459:
! 16460: struct FTW_rec {
! 16461: struct FTW_rec *prev;
! 16462: long here; /* seek to here when reopening at this level */
! 16463: DIR *fd; /* file descriptor at this level */
! 16464: };
! 16465:
! 16466: /*
! 16467: * One instance, T, of the following structure is allocated by ftw; a
! 16468: * pointer to it is passed to all generations of ftw1 (the real ftw).
! 16469: * T could often be a global variable, but this way the parameter fn
! 16470: * can invoke ftw for an independent tree walk.
! 16471: * Component T->path points to storage for the object path-names;
! 16472: * this storage may be relocated by realloc if T->path needs to be
! 16473: * more than T->pathlast characters long.
! 16474: * T->path[T->pathnext] is the next free character in the pathnames.
! 16475: * T->depth = parameter depth to ftw. T->lastout is the deepest level at
! 16476: * which a file descriptor has been recycled.
! 16477: */
! 16478:
! 16479: struct FTW_top {
! 16480: int (*fn)();
! 16481: char *path;
! 16482: unsigned pathlast, pathnext;
! 16483: int lastout;
! 16484: int depth;
! 16485: };
! 16486:
! 16487: static ftw_1_();
! 16488:
! 16489: int
! 16490: ftw (path, fn, depth)
! 16491: char *path;
! 16492: int (*fn)();
! 16493: int depth;
! 16494: {
! 16495: struct FTW_top T;
! 16496: struct FTW_rec R;
! 16497: struct FTW S;
! 16498: int rc;
! 16499: char *malloc(), *strcpy();
! 16500:
! 16501: T.depth = depth;
! 16502: T.lastout = -1;
! 16503: T.fn = fn;
! 16504: S.quit = 0;
! 16505: S.level = -1;
! 16506:
! 16507: /* initialize S.base, T.pathnext... */
! 16508: {
! 16509: register char c, *p, *q;
! 16510: for (p = q = path; c = *p; p++) if (c == '/') q = p + 1;
! 16511: S.base = q - path;
! 16512: T.pathnext = p - path;
! 16513: }
! 16514:
! 16515: T.pathlast = T.pathnext + FTW_PATHLEN0;
! 16516: T.path = malloc(T.pathlast);
! 16517: if (!T.path) { errno = ENOMEM; return -1; }
! 16518: strcpy(T.path, path);
! 16519: rc = ftw_1_(&R, &T, 0, &S);
! 16520: free(T.path);
! 16521: return rc;
! 16522: }
! 16523:
! 16524: int
! 16525: static
! 16526: ftw_1_ (R, T, level, S1)
! 16527: register struct FTW_rec *R;
! 16528: register struct FTW_top *T;
! 16529: int level;
! 16530: struct FTW *S1;
! 16531: {
! 16532: int rc, n;
! 16533: DIR *fd;
! 16534: struct direct *dirp;
! 16535: char *component, *path;
! 16536: struct stat sb;
! 16537: struct FTW_rec mr;
! 16538: unsigned nextsave;
! 16539: struct FTW S;
! 16540: char *realloc();
! 16541: long lseek();
! 16542:
! 16543: mr.prev = R;
! 16544: path = T->path;
! 16545: S.level = level;
! 16546: S.quit = 0;
! 16547: S.base = S1->base;
! 16548:
! 16549: /* Try to get file status. If unsuccessful, errno will say why. */
! 16550: if (lstat(path, &sb) < 0) {
! 16551: rc = (*T->fn) (path, &sb, FTW_NS, &S);
! 16552: S1->quit = S.quit;
! 16553: return rc;
! 16554: };
! 16555:
! 16556: /*
! 16557: * The stat succeeded, so we know the object exists.
! 16558: * If not a directory, call the user function and return.
! 16559: */
! 16560: #ifdef S_IFLNK
! 16561: if ((sb.st_mode & S_IFMT) == S_IFLNK) {
! 16562: rc = (*T->fn) (path, &sb, FTW_SL, &S);
! 16563: S1->quit = S.quit;
! 16564: if (rc || S.quit == FTW_SKR) return rc;
! 16565: if (S.quit != FTW_FOLLOW) return 0;
! 16566: S1->quit = S.quit = 0;
! 16567: if (stat(path, &sb) < 0) {
! 16568: rc = (*T->fn) (path, &sb, FTW_NSL, &S);
! 16569: S1->quit = S.quit;
! 16570: return rc;
! 16571: };
! 16572: }
! 16573: #endif
! 16574:
! 16575: if ((sb.st_mode & S_IFMT) != S_IFDIR) {
! 16576: rc = (*T->fn) (path, &sb, FTW_F, &S);
! 16577: S1->quit = S.quit;
! 16578: return rc;
! 16579: }
! 16580:
! 16581: /*
! 16582: * The object was a directory.
! 16583: *
! 16584: * Open a file to read the directory
! 16585: */
! 16586: mr.fd = fd = opendir(path);
! 16587:
! 16588: /*
! 16589: * Call the user function, telling it whether
! 16590: * the directory can be read. If it can't be read
! 16591: * call the user function or indicate an error,
! 16592: * depending on the reason it couldn't be read.
! 16593: */
! 16594: if (!fd) {
! 16595: rc = (*T->fn) (path, &sb, FTW_DNR, &S);
! 16596: S1->quit = S.quit;
! 16597: return rc;
! 16598: }
! 16599:
! 16600: /* We could read the directory. Call user function. */
! 16601: rc = (*T->fn) (path, &sb, FTW_D, &S);
! 16602: if (rc != 0)
! 16603: goto rtrn;
! 16604: if (S.quit == FTW_SKD) goto rtrn;
! 16605: if (S.quit == FTW_SKR) {S1->quit = FTW_SKR; goto rtrn;}
! 16606:
! 16607: /* Make sure path is big enough to hold generated pathnames. */
! 16608:
! 16609: n = nextsave = T->pathnext;
! 16610: if (n + MAXNAMLEN + 1 >= T->pathlast) {
! 16611: T->pathlast += FTW_PATHINC;
! 16612: path = T->path = realloc(T->path, T->pathlast);
! 16613: if (!path) {
! 16614: errno = ENOMEM;
! 16615: rc = -1;
! 16616: goto rtrn;
! 16617: }
! 16618: }
! 16619:
! 16620: /* Create a prefix to which we will append component names */
! 16621:
! 16622: if (n > 0 && path[n-1] != '/') path[n++] = '/';
! 16623: component = path + n;
! 16624:
! 16625: /*
! 16626: * Read the directory one component at a time.
! 16627: * We must ignore "." and "..", but other than that,
! 16628: * just create a path name and call self to check it out.
! 16629: */
! 16630: while (dirp = readdir(fd)) {
! 16631: if (dirp->d_ino != 0
! 16632: && strcmp (dirp->d_name, ".") != 0
! 16633: && strcmp (dirp->d_name, "..") != 0) {
! 16634: int i;
! 16635: struct FTW_rec *pr;
! 16636:
! 16637: /* Append the component name to the working path */
! 16638: strcpy(component, dirp->d_name);
! 16639: T->pathnext = n + strlen(dirp->d_name);
! 16640:
! 16641: /*
! 16642: * If we are about to exceed our depth,
! 16643: * remember where we are and close the file.
! 16644: */
! 16645: if (level - T->lastout >= T->depth) {
! 16646: pr = &mr;
! 16647: i = T->lastout++;
! 16648: while (++i < level) pr = pr->prev;
! 16649: pr->here = telldir(pr->fd);
! 16650: closedir(pr->fd);
! 16651: }
! 16652:
! 16653: /*
! 16654: * Do a recursive call to process the file.
! 16655: */
! 16656: S.quit = 0;
! 16657: S.base = n;
! 16658: rc = ftw_1_(&mr, T, level+1, &S);
! 16659: if (rc != 0 || S.quit == FTW_SKR) {
! 16660: if (level > T->lastout) closedir(fd);
! 16661: T->pathnext = nextsave;
! 16662: return rc;
! 16663: }
! 16664:
! 16665: /*
! 16666: * If we closed the file, try to reopen it.
! 16667: */
! 16668: if (level <= T->lastout) {
! 16669: char c = path[nextsave];
! 16670: path[nextsave] = 0;
! 16671: T->lastout = level - 1;
! 16672: mr.fd = fd = opendir(path);
! 16673: if (!fd) {
! 16674: rc = (*T->fn) (path, &sb, FTW_DNR, &S);
! 16675: S1->quit = S.quit;
! 16676: T->pathnext = nextsave;
! 16677: return rc;
! 16678: }
! 16679: path[nextsave] = c;
! 16680: seekdir(fd, mr.here);
! 16681: }
! 16682: }
! 16683: }
! 16684: T->pathnext = nextsave;
! 16685: path[nextsave] = 0;
! 16686:
! 16687: /*
! 16688: * We got out of the subdirectory loop. Call the user
! 16689: * function again at the end and clean up.
! 16690: */
! 16691:
! 16692: rc = (*T->fn) (path, &sb, FTW_DP, &S);
! 16693: S1->quit = S.quit;
! 16694: rtrn:
! 16695: closedir(fd);
! 16696: return rc;
! 16697: }
! 16698: 0707070035350320551006640007620000050000010263640476773367300001000000002137myftw.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 16699: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 16700: /* The copyright notice does not imply actual or intended publication. */
! 16701: /* AUTHORS: */
! 16702: /* H. S. Baird - ATT-BL MH - first versions */
! 16703: /*
! 16704: * Codes for the third argument to the user-supplied function
! 16705: * which is passed as the second argument to ftw...
! 16706: */
! 16707:
! 16708: #define FTW_F 0 /* file */
! 16709: #define FTW_D 1 /* directory */
! 16710: #define FTW_DNR 2 /* directory without read permission */
! 16711: #define FTW_NS 3 /* unknown type, stat failed */
! 16712: #define FTW_DP 4 /* directory, postorder visit */
! 16713: #define FTW_SL 5 /* symbolic link */
! 16714: #define FTW_NSL 6 /* stat failed (errno = ENOENT) on symbolic link */
! 16715:
! 16716: /* Values the user-supplied function may wish to assign to
! 16717: component quit of struct FTW...
! 16718: */
! 16719:
! 16720: #define FTW_SKD 1 /* skip this directory (2nd par = FTW_D) */
! 16721: #define FTW_SKR 2 /* skip rest of current directory */
! 16722: #define FTW_FOLLOW 3 /* follow symbolic link */
! 16723:
! 16724: struct FTW { int quit, base, level;
! 16725: #ifndef FTW_more_to_come
! 16726: };
! 16727: #endif
! 16728: 0707070035350320571006640007620000050000010263660476773367300000600000003730pic.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 16729: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 16730: /* The copyright notice does not imply actual or intended publication. */
! 16731: /* AUTHORS: */
! 16732: /* H. S. Baird - ATT-BL MH - first versions */
! 16733:
! 16734: /* pic.h - picture files. See man page for picfile(5).
! 16735: They have an ascii header, terminated by \n\n; see PIC_hdr for its data fields.
! 16736: The rest is binary scanner data. Each `PIC_hdr.bpl' bytes holds one scan-line's
! 16737: pixels, 1 bit/pixel. A `1' bit means black. The order of the bytes in a line
! 16738: is left-to-right across the page. The low-order bit in a byte is the left-most.
! 16739: Conventionally, X-coordinates start at 0, at the left of the page, and
! 16740: increase to the right. Y-coordinates start at 0 at the top of the page,
! 16741: and increase down.
! 16742: NOTE: must be preceded by #include "Coord.h"
! 16743: */
! 16744:
! 16745: typedef struct PIC_hdr {
! 16746: /* Contents of picfile ASCII header (or other structure) */
! 16747: char type[40]; /* "rle" "dump" "binary" "ccitt-g4" "imdir" etc */
! 16748: Bbx bx; /* WINDOW (bounding box) */
! 16749: short res_x; /* resolution in pixels/inch (x,y may differ) */
! 16750: short res_y;
! 16751: char *parms; /* PARMS= string */
! 16752: char *misc; /* all other unexpected header lines, catenated */
! 16753: /* the following are used by I/O routines */
! 16754: FILE *fp;
! 16755: long seek; /* current seek address */
! 16756: int bpl; /* bytes per line (in file) */
! 16757: unsigned char *line; /* one line of picture (malloc space) */
! 16758: unsigned char *pline; /* prior line of picture (malloc space) */
! 16759: Scoor cy; /* index no. of *line */
! 16760: } PIC_hdr;
! 16761: #define Init_PIC_hdr {"",Init_Bbx,0,0,NULL,NULL,NULL,0L,0,NULL,NULL,0}
! 16762: #if MAIN
! 16763: PIC_hdr empty_PIC_hdr = Init_PIC_hdr;
! 16764: #else
! 16765: extern PIC_hdr empty_PIC_hdr;
! 16766: #endif
! 16767:
! 16768: /* these functions are in /usr/hsb/ocr/piclib.c */
! 16769: PIC_hdr *alloc_PIC_hdr();
! 16770: int PIC_get_hdr();
! 16771: PIC_put_hdr();
! 16772: err_PIC_line();
! 16773: PIC_skip();
! 16774: int PIC_rline();
! 16775: int PIC_wline();
! 16776: char *PIC_hdr_toa();
! 16777: 0707070035350320561006640007620000050000010263700476773367300001100000044413piclib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 16778: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 16779: /* The copyright notice does not imply actual or intended publication. */
! 16780: /* AUTHORS: */
! 16781: /* H. S. Baird - ATT-BL MH - first versions */
! 16782:
! 16783: /* piclib.c - picture-file public functions.
! 16784: alloc_PIC_hdr() - allocate initialized PIC_hdr, associate with FILE *
! 16785: free_PIC_hdr() - free PIC_hdr & all malloc'ed fields
! 16786: PIC_get_hdr() - get picture-file header
! 16787: PIC_rline() - read one line of picture data
! 16788: PIC_put_hdr() - get picture-file header
! 16789: PIC_wline() - write one line of picture data
! 16790: err_PIC_Line() - print line on stderr
! 16791: PIC_hdr_toa() - PIC_hdr to ascii printable string
! 16792: (PIC_* functions use system I/O, for speed)
! 16793: */
! 16794:
! 16795: #include <stdio.h>
! 16796: #include <math.h>
! 16797: #include <string.h>
! 16798: #include "boole.h"
! 16799: #include "limits.h" /* numeric extreme values */
! 16800: #include "Units.h"
! 16801: #include "Coord.h"
! 16802: #include "pic.h"
! 16803:
! 16804: #define PIC_debug (0)
! 16805: double atof();
! 16806:
! 16807: PIC_hdr *alloc_PIC_hdr( fp )
! 16808: FILE *fp; /* already-open file descr */
! 16809: { PIC_hdr *h;
! 16810: if((h=(PIC_hdr *)malloc(sizeof(PIC_hdr)))==NULL)
! 16811: abort("piclib: alloc_PIC_hdr: can't alloc");
! 16812: *h = empty_PIC_hdr;
! 16813: h->fp = fp;
! 16814: return(h);
! 16815: }
! 16816:
! 16817: free_PIC_hdr( h )
! 16818: PIC_hdr *h;
! 16819: { if(h->parms!=NULL) free(h->parms);
! 16820: if(h->line!=NULL) free(h->line);
! 16821: if(h->pline!=NULL) free(h->pline);
! 16822: if(h->misc!=NULL) free(h->misc);
! 16823: free(h);
! 16824: }
! 16825:
! 16826: /* system I/O variation on fgets(3), except it replaces \n with \0,
! 16827: and returns the number of chars read (including \0) */
! 16828: int PIC_fgets(bf,max,fd)
! 16829: char *bf;
! 16830: int max;
! 16831: int fd;
! 16832: { char *cp;
! 16833: int stat,mny;
! 16834: cp=bf; mny=0;
! 16835: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
! 16836: if(stat!=1) return(stat);
! 16837: else if(mny>=max) return(-1);
! 16838: *cp='\0';
! 16839: return(mny);
! 16840: }
! 16841:
! 16842: /* Read picture file header from file descr fileno(h->fp), set up the rest of the
! 16843: header, and return status: 1 OK, 0 EOF, <0 error */
! 16844: int PIC_get_hdr( h )
! 16845: PIC_hdr *h;
! 16846: #define HL_MAX 300
! 16847: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
! 16848: { char *cp,*parm,hline[HL_MAX],oline[HL_MAX],*hl;
! 16849: int status,nrd,ch,mny;
! 16850: /* synchronize FILE * ptr with file descr ptr */
! 16851: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
! 16852: hline[0]='\0';
! 16853: if((mny=read(fileno(h->fp),hline,5))!=5)
! 16854: return(0);
! 16855: if(!(hline[0]=='T' && hline[1]=='Y' && hline[2]=='P'
! 16856: && hline[3]=='E' && hline[4]=='=')) {
! 16857: /* no "TYPE=" header; don't accept */
! 16858: if(0) /* don't accept */ {
! 16859: if(PIC_debug)
! 16860: err("PIC_get_hdr: can't find TYPE=... header");
! 16861: return(-1);
! 16862: }
! 16863: else /* accept as bitfile format (OBSOLESCENT) */ {
! 16864: strcpy(h->type,"bitfile");
! 16865: h->res_x = h->res_y = 0;
! 16866: fseek(h->fp,h->seek+2L,0); /* back up to byte no. 2 */
! 16867: /* read window */
! 16868: if((ch=getc(h->fp))!=EOF) { h->bx.a.x = ch;
! 16869: if((ch=getc(h->fp))!=EOF) { h->bx.a.x += (ch<<8);
! 16870: if((ch=getc(h->fp))!=EOF) { h->bx.a.y = ch;
! 16871: if((ch=getc(h->fp))!=EOF) { h->bx.a.y += (ch<<8);
! 16872: if((ch=getc(h->fp))!=EOF) { h->bx.b.x = ch;
! 16873: if((ch=getc(h->fp))!=EOF) { h->bx.b.x += (ch<<8);
! 16874: if((ch=getc(h->fp))!=EOF) { h->bx.b.y = ch;
! 16875: if((ch=getc(h->fp))!=EOF) { h->bx.b.y += (ch<<8); }}}}}}}}
! 16876: else return(0/*EOF*/);
! 16877: h->bx.b.x--; h->bx.b.y--;
! 16878: /* synchronize file descr ptr with FILE * ptr */
! 16879: lseek(fileno(h->fp),h->seek = ftell(h->fp),0);
! 16880: };
! 16881: }
! 16882: else {
! 16883: if((status=PIC_fgets(hline+5,HL_MAX-5,fileno(h->fp)))<=0)
! 16884: return(status);
! 16885: strcpy(oline,hline);
! 16886: hl=hline; while(*hl==' ') hl++; /* strip initial blanks */
! 16887: while(strlen(hl)>1) {
! 16888: if(PIC_debug) err("PIC_get_hdr: hl \"%s\"",hl);
! 16889: parm=strtok(hl,HTERM);
! 16890: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
! 16891: if((parm=strtok(0,HTERM))!=NULL) {
! 16892: strcpy(h->type,parm);
! 16893: if( (strcmp(h->type,"dump")==0)
! 16894: || (strcmp(h->type,"pico")==0)
! 16895: || (strcmp(h->type,"rle")==0)
! 16896: || (strcmp(h->type,"binary")==0)
! 16897: || (strcmp(h->type,"bitmap")==0)
! 16898: || (strcmp(h->type,"dim")==0)
! 16899: || (strcmp(h->type,"document-image")==0)
! 16900: || (strcmp(h->type,"ccitt-g31")==0)
! 16901: || (strcmp(h->type,"ccitt-g32")==0)
! 16902: || (strcmp(h->type,"ccitt-g4")==0)
! 16903: || (strcmp(h->type,"cdf")==0)
! 16904: || (strcmp(h->type,"tiff")==0)
! 16905: ) /* these types are expected */ {
! 16906: if(PIC_debug)
! 16907: err("PIC_get_hdr: good TYPE=\"%s\"",h->type);
! 16908: }
! 16909: else { if(PIC_debug)
! 16910: err("PIC_get_hdr: unexpected TYPE=\"%s\"",h->type);
! 16911: return(-1);
! 16912: };
! 16913: }
! 16914: else { if(PIC_debug)
! 16915: err("PIC_get_hdr: 1st line must be TYPE=...");
! 16916:
! 16917: return(-1);
! 16918: };
! 16919: }
! 16920: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
! 16921: if((parm=strtok(0,HTERM))!=NULL) h->bx.a.x=atoi(parm);
! 16922: else return(-1);
! 16923: if((parm=strtok(0,HTERM))!=NULL) h->bx.a.y=atoi(parm);
! 16924: else return(-1);
! 16925: if((parm=strtok(0,HTERM))!=NULL) h->bx.b.x=atoi(parm)-1;
! 16926: else return(-1);
! 16927: if((parm=strtok(0,HTERM))!=NULL) h->bx.b.y=atoi(parm)-1;
! 16928: else return(-1);
! 16929: }
! 16930: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
! 16931: if((parm=strtok(0,HTERM))!=NULL)
! 16932: h->res_x=(int)(atof(parm)+0.5);
! 16933: else return(-1);
! 16934: if((parm=strtok(0,HTERM))!=NULL)
! 16935: h->res_y=(int)(atof(parm)+0.5);
! 16936: else return(-1);
! 16937: }
! 16938: else if(parm!=NULL&&strcmp(parm,"NCHAN")==0) {
! 16939: int nchan;
! 16940: if((parm=strtok(0,HTERM))!=NULL) nchan=atoi(parm);
! 16941: else return(-1);
! 16942: if(nchan!=1) {
! 16943: err("PIC_get_hdr: NCHAN=%d illegal: must be 1",nchan);
! 16944: return(-1);
! 16945: };
! 16946: }
! 16947: else if(parm!=NULL&&strcmp(parm,"PARMS")==0) {
! 16948: int nchan;
! 16949: if((parm=strtok(0,"\n"))!=NULL) {
! 16950: h->parms = strdup(parm);
! 16951: }
! 16952: else return(-1);
! 16953: }
! 16954: else if(parm!=NULL) {
! 16955: char *cat;
! 16956: /* save all header lines with unexpected keywords */
! 16957: if(h->misc==NULL) h->misc=(char *)malloc(strlen(oline)+2);
! 16958: else { cat=(char *)malloc(strlen(h->misc)+strlen(oline)+2);
! 16959: strcpy(cat,h->misc);
! 16960: free(h->misc);
! 16961: h->misc=cat;
! 16962: };
! 16963: strcat(h->misc,oline);
! 16964: strcat(h->misc,"\n");
! 16965: }
! 16966: else return(-1);
! 16967: if((status=PIC_fgets(hline,HL_MAX,fileno(h->fp)))<=0)
! 16968: return(status);
! 16969: strcpy(oline,hline);
! 16970: hl=hline; while(*hl==' ') hl++; /* strip initial blanks */
! 16971: };
! 16972: };
! 16973:
! 16974: if(strcmp(h->type,"cdf")==0) {
! 16975: int stat;
! 16976: /* Compund Document Format has binary header */
! 16977: /* synchronize FILE * ptr with file descr ptr */
! 16978: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
! 16979: if((stat=CDF_get_hdr(h)) != 1) return(stat);
! 16980: };
! 16981:
! 16982: if(strcmp(h->type,"tiff")==0) {
! 16983: int stat;
! 16984: /* Tagged Image File Format has abinary header */
! 16985: /* synchronize FILE * ptr with file descr ptr */
! 16986: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
! 16987: if((stat=TIFF_get_hdr(h)) != 1) return(stat);
! 16988: };
! 16989:
! 16990: /* may want to allocate a line buffer here */
! 16991: h->bpl = bbx_wid(&(h->bx));
! 16992: if(strcmp(h->type,"binary")==0)
! 16993: h->bpl = (h->bpl+7)/8; /* round up to byte boundary */
! 16994: else if(strcmp(h->type,"bitfile")==0)
! 16995: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
! 16996: else if(strcmp(h->type,"bitmap")==0)
! 16997: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
! 16998: else if( strcmp(h->type,"rle")==0
! 16999: || strcmp(h->type,"dim")==0
! 17000: || strcmp(h->type,"document-image")==0
! 17001: || strcmp(h->type,"cdf")==0
! 17002: || strcmp(h->type,"cdf-mrlc")==0
! 17003: || strcmp(h->type,"cdf-g31")==0
! 17004: || strcmp(h->type,"cdf-g32")==0
! 17005: || strcmp(h->type,"cdf-g4")==0
! 17006: || strcmp(h->type,"tiff")==0 )
! 17007: h->bpl = 0;
! 17008: if(h->bpl==0) h->line = NULL;
! 17009: else { /* allocate one extra byte in line buffer as a favor to RLE */
! 17010: if((h->line = (unsigned char *) malloc(h->bpl+1))==NULL) {
! 17011: fprintf(stderr,
! 17012: "piclib: PIC_get_hdr: can't alloc h->line (%d bytes) - abort\n",
! 17013: h->bpl+1);
! 17014: return(-1);
! 17015: };
! 17016: memset(h->line,'\0',h->bpl);
! 17017: if(strcmp(h->type,"bitfile")==0) {
! 17018: if((h->pline = (unsigned char *) malloc(h->bpl+1))==NULL) {
! 17019: fprintf(stderr,
! 17020: "piclib: PIC_get_hdr: can't alloc h->pline (%d bytes) - abort\n",
! 17021: h->bpl+1);
! 17022: return(-1);
! 17023: };
! 17024: };
! 17025: };
! 17026: h->cy = h->bx.a.y-1; /* just prior to 1st line */
! 17027: /* synchronize FILE * ptr with file descr ptr */
! 17028: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
! 17029: return(1);
! 17030: }
! 17031:
! 17032: /* Read next page from AT&T Image Director file header from file descr
! 17033: fileno(h->fp), set up the rest of the header, and return status:
! 17034: 1 OK, 0 EOF, <0 error */
! 17035: int CDF_next_page( h )
! 17036: PIC_hdr *h;
! 17037: { return(-1); /* unimplemented */
! 17038: }
! 17039:
! 17040: #define HASHEADER(h) ((strcmp((h)->type,"postscript")!=0&&strcmp((h)->type,"sunraster")!=0))
! 17041:
! 17042: /* Read AT&T Image Director file header from file descr fileno(h->fp),
! 17043: set up the rest of the header, and return status: 1 OK, 0 EOF, <0 error */
! 17044: int CDF_get_hdr( h )
! 17045: PIC_hdr *h;
! 17046: { char *cp,*parm,hline[HL_MAX];
! 17047: int status,nrd,ch,mny;
! 17048: #define dbg_cdf (0)
! 17049: typedef struct CDF_file {
! 17050: unsigned char raw[16];
! 17051: unsigned char op,np,at;
! 17052: unsigned int l1,l2,len;
! 17053: } CDF_file;
! 17054: typedef struct CDF_page {
! 17055: unsigned char raw[16];
! 17056: unsigned char op,pn,at;
! 17057: unsigned char f1,f2,f3,f4;
! 17058: unsigned int ptr;
! 17059: } CDF_page;
! 17060: typedef struct CDF_recd {
! 17061: unsigned char raw[16];
! 17062: unsigned char op,a1,a2,a3;
! 17063: unsigned int len;
! 17064: Bbx bx;
! 17065: } CDF_recd;
! 17066: CDF_file fh;
! 17067: CDF_page ph;
! 17068: CDF_recd rh;
! 17069:
! 17070: if(dbg_cdf) err("CDF_get_hdr: enter %s",PIC_hdr_toa(h));
! 17071: /* synchronize FILE * ptr with file descr ptr */
! 17072: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
! 17073: strcpy(h->type,"cdf");
! 17074:
! 17075: /* Read CDF File header */
! 17076: if(fread(fh.raw,1,16,h->fp)!=16) return(0);
! 17077: fh.op = fh.raw[0];
! 17078: fh.np = fh.raw[1];
! 17079: fh.at = fh.raw[2];
! 17080: fh.l1 = fh.raw[4]+256*fh.raw[5];
! 17081: fh.l2 = fh.raw[6]+256*fh.raw[7];
! 17082: fh.len = fh.raw[12]+256*(fh.raw[13]+256*(fh.raw[14]+256*fh.raw[15]));
! 17083: if(dbg_cdf) err("CDF_get_hdr: file hdr: op0x%x p%d at0x%x lim1:%u lim2:%u len%u",
! 17084: fh.op,fh.np,fh.at,fh.l1,fh.l2,fh.len);
! 17085: if(fh.op!=0xA0&&fh.op!=0xAF) abort("CDF_get_hdr: file must be CDF type");
! 17086: if(fh.np!=1) err("CDF_get_hdr: file has %d pages - ignore all but 1st",fh.np);
! 17087: switch(fh.at>>4) {
! 17088: case 0: h->res_x = h->res_y = 100; break;
! 17089: case 1: h->res_x = h->res_y = 200; break;
! 17090: case 2: h->res_x = h->res_y = 300; break;
! 17091: default: err("CDF_get_hdr: file has unknown resolution nibble 0x%x -- assume 400 dpi",fh.at>>4);
! 17092: h->res_x = h->res_y = 400;
! 17093: break;
! 17094: };
! 17095: h->bx.a.x = h->bx.a.y = 0;
! 17096: h->bx.b.x = fh.l1;
! 17097: h->bx.b.y = fh.l2;
! 17098: if(fh.op==0xAF) {
! 17099: abort("CDF_get_hdr: file has continuation header");
! 17100: };
! 17101:
! 17102: /* Read 1st page table entry */
! 17103: if(fread(ph.raw,1,16,h->fp)!=16) return(0);
! 17104: ph.op = ph.raw[0];
! 17105: ph.pn = ph.raw[1];
! 17106: ph.at = ph.raw[2];
! 17107: ph.ptr = ph.raw[12]+256*(ph.raw[13]+256*(ph.raw[14]+256*ph.raw[15]));
! 17108: if(dbg_cdf) err("CDF_get_hdr: page hdr: op0x%x p%d at0x%x ptr%u",
! 17109: ph.op,ph.pn,ph.at,ph.ptr);
! 17110: if(ph.op!=0x80&&ph.op!=0x8F)
! 17111: abort("CDF_get_hdr: page opcode 0x%x is peculiar",ph.op);
! 17112: if(ph.pn!=1) err("CDF_get_hdr: page %d out of order - read anyway",ph.pn);
! 17113: switch(ph.at&0x0F) { /* low nibble */
! 17114: case 0: /* portrait */ break;
! 17115: case 1: /* landscape */
! 17116: default: err("CDF_get_hdr: page has peculiar format nibble 0x%x -- assume 40portrait",ph.at&0x0F);
! 17117: break;
! 17118: };
! 17119: switch(ph.at>>4) { /* high nibble */
! 17120: case 0xF: /* background is white */ break;
! 17121: default: err("CDF_get_hdr: page has peculiar color nibble 0x%x -- assume white",ph.at>>4);
! 17122: break;
! 17123: };
! 17124: /* seek top of Page */
! 17125: fseek(h->fp,h->seek+=ph.ptr,0);
! 17126:
! 17127: /* Read CDF Record header */
! 17128: if(fread(rh.raw,1,16,h->fp)!=16) return(0);
! 17129: rh.op = rh.raw[0];
! 17130: rh.a1 = rh.raw[1];
! 17131: rh.a2 = rh.raw[2];
! 17132: rh.a3 = rh.raw[3];
! 17133: rh.len = rh.raw[4]+256*rh.raw[5];
! 17134: rh.bx.a.x = rh.raw[8]+256*rh.raw[9];
! 17135: rh.bx.a.y = rh.raw[10]+256*rh.raw[11];
! 17136: rh.bx.b.x = rh.raw[12]+256*rh.raw[13];
! 17137: rh.bx.b.y = rh.raw[14]+256*rh.raw[15];
! 17138: if(dbg_cdf) err("CDF_get_hdr: record hdr: op0x%x a0x%x,0x%x,0x%x len%u bx%s",
! 17139: rh.op,rh.a1,rh.a2,rh.a3,rh.len,bbx_toa(&rh.bx));
! 17140: switch(rh.op) {
! 17141: case 0x20: /* Image */ break;
! 17142: case 0x01: /* End of Page */
! 17143: case 0x10: /* Text */
! 17144: case 0x1F: /* Text + cont. */
! 17145: case 0x50: /* Text Document */
! 17146: case 0x5F: /* Text Document + cont. */
! 17147: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44:
! 17148: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4A:
! 17149: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
! 17150: /* Graphics */
! 17151: default:
! 17152: abort("CDF_get_hdr: record not Image");
! 17153: };
! 17154: if(rh.a2!=0x01) err("CDF_get_hdr: record not opaque - assume opaque");
! 17155: switch(rh.a3&0x0F) { /* compression algorithm */
! 17156: case 1: /* modified run-length code */
! 17157: strcat(h->type,"-mrlc");
! 17158: break;
! 17159: case 0: /* raw */
! 17160: abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
! 17161: break;
! 17162: case 2: /* ccitt_g31 */
! 17163: strcat(h->type,"-g31");
! 17164: abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
! 17165: break;
! 17166: case 3: /* ccitt_g32 or ccitt_g4 */
! 17167: strcat(h->type,"-g32");
! 17168: abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
! 17169: break;
! 17170: default:
! 17171: abort("CDF_get_hdr: record compression 0x%x is peculiar",rh.a3&0x0F);
! 17172: break;
! 17173: };
! 17174: switch(rh.a3>>4) { /* resolution */
! 17175: case 0:
! 17176: h->res_y = 100;
! 17177: break;
! 17178: case 1:
! 17179: h->res_y = 200;
! 17180: break;
! 17181: case 2:
! 17182: h->res_y = 300;
! 17183: break;
! 17184: default:
! 17185: err("CDF_get_hdr: record vert resolution peculiar 0x%x - assume 200 dpi",
! 17186: rh.a3>>4);
! 17187: h->res_y = 200;
! 17188: break;
! 17189: };
! 17190: /* synchronize file descr ptr with FILE * ptr */
! 17191: lseek(fileno(h->fp),h->seek = ftell(h->fp),0);
! 17192: if(dbg_cdf) err("CDF_get_hdr: normal exit %s",PIC_hdr_toa(h));
! 17193: return(1);
! 17194: }
! 17195:
! 17196: /* Read Tagged Image Format File (TIFF) header, from file descr fileno(h->fp),
! 17197: set up the rest of the PIC header, and return status: 1 OK, 0 EOF, <0 error */
! 17198: int TIFF_get_hdr( h )
! 17199: PIC_hdr *h;
! 17200: { err("TIFF not yet supported");
! 17201: return(-1);
! 17202: }
! 17203:
! 17204: /* Write header to picture file, to file descriptor fileno(h->fp), and initialize
! 17205: line buffer and cy. */
! 17206: PIC_put_hdr( h )
! 17207: PIC_hdr *h;
! 17208: { char *cp,*parm,hline[HL_MAX];
! 17209: int status,nrd;
! 17210: unsigned short s;
! 17211: #define put_ushort(S) { s=(S); putc(s&0377,h->fp); putc(s>>8,h->fp); }
! 17212:
! 17213: /* write type header */
! 17214: if( strcmp(h->type,"bitfile")==0 ) { /* bitfile header */
! 17215: put_ushort(0);
! 17216: }
! 17217: else if(HASHEADER(h)) {
! 17218: sprintf(hline,"TYPE=%s\n",h->type);
! 17219: write(fileno(h->fp),hline,strlen(hline));
! 17220: };
! 17221: if(strcmp(h->type,"pico")==0
! 17222: || strcmp(h->type,"dump")==0) {
! 17223: sprintf(hline,"NCHAN=1\n");
! 17224: write(fileno(h->fp),hline,strlen(hline));
! 17225: };
! 17226:
! 17227: /* write window */
! 17228: h->bpl = bbx_wid(&(h->bx));
! 17229: if(strcmp(h->type,"binary")!=0
! 17230: && strcmp(h->type,"bitfile")!=0
! 17231: && strcmp(h->type,"bitmap")!=0
! 17232: && HASHEADER(h)) {
! 17233: sprintf(hline,"WINDOW=%d %d %d %d\n",
! 17234: h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
! 17235: write(fileno(h->fp),hline,strlen(hline));
! 17236: }
! 17237: else if(strcmp(h->type,"binary")==0) {
! 17238: h->bpl = (h->bpl+7)/8; /* round up to byte boundary */
! 17239: sprintf(hline,"WINDOW=%d %d %d %d\n",
! 17240: h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
! 17241: write(fileno(h->fp),hline,strlen(hline));
! 17242: }
! 17243: else if(strcmp(h->type,"bitmap")==0) {
! 17244: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
! 17245: sprintf(hline,"WINDOW=%d %d %d %d\n",
! 17246: h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
! 17247: write(fileno(h->fp),hline,strlen(hline));
! 17248: }
! 17249: else if(strcmp(h->type,"sunraster")!=0 ) { /* bitfile window */
! 17250: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
! 17251: put_ushort(h->bx.a.x); put_ushort(h->bx.a.y);
! 17252: put_ushort(h->bx.b.x+1); put_ushort(h->bx.b.y+1);
! 17253: fflush(h->fp);
! 17254: };
! 17255: if( ((h->res_x!=0||h->res_y!=0)) && (HASHEADER(h))
! 17256: && strcmp(h->type,"bitfile")!=0 ) {
! 17257: sprintf(hline,"RES=%d %d\n",h->res_x,h->res_y);
! 17258: write(fileno(h->fp),hline,strlen(hline));
! 17259: };
! 17260: if(h->parms!=NULL && strlen(h->parms)>0 && strcmp(h->type,"bitfile")!=0 ) {
! 17261: sprintf(hline,"PARMS=%s\n",h->parms);
! 17262: write(fileno(h->fp),hline,strlen(hline));
! 17263: };
! 17264: if(h->misc!=NULL && strlen(h->misc)>0 && strcmp(h->type,"bitfile")!=0 ) {
! 17265: write(fileno(h->fp),h->misc,strlen(h->misc));
! 17266: };
! 17267: /* terminating blank line */
! 17268: if( HASHEADER(h) && strcmp(h->type,"bitfile")!=0 ) {
! 17269: hline[0] = '\n';
! 17270: write(fileno(h->fp),hline,1);
! 17271: };
! 17272:
! 17273: if(strcmp(h->type,"rle")==0) { h->bpl = 0; h->line = NULL; }
! 17274: else { /* allocate one extra byte in line buffer as a favor to RLE */
! 17275: if((h->line = (unsigned char *) malloc(h->bpl+1))==NULL) {
! 17276: fprintf(stderr,
! 17277: "piclib: PIC_put_hdr: can't alloc h->line (%d bytes) - abort\n",
! 17278: h->bpl+1);
! 17279: return(-1);
! 17280: };
! 17281: if(strcmp(h->type,"bitfile")==0) {
! 17282: memset(h->line,'\0',h->bpl);
! 17283: if((h->pline = (unsigned char *) malloc(h->bpl+1))==NULL) {
! 17284: fprintf(stderr,
! 17285: "piclib: PIC_put_hdr: can't alloc h->pline (%d bytes) - abort\n",
! 17286: h->bpl+1);
! 17287: return(-1);
! 17288: };
! 17289: };
! 17290: };
! 17291: h->cy = h->bx.a.y-1; /* just prior to 1st line */
! 17292: /* synchronize FILE * ptr with file descr ptr */
! 17293: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
! 17294: }
! 17295:
! 17296: err_PIC_line(h,sl)
! 17297: PIC_hdr *h;
! 17298: char *sl;
! 17299: #define BPL 20 /* bytes to display per line */
! 17300: { char *cp,*ep;
! 17301: int bpl; /* bytes per display line */
! 17302: bpl=0;
! 17303: for(cp=sl,ep=sl+h->bpl; cp!=ep; cp++) {
! 17304: fprintf(stderr,"%o ",0377&(*cp));
! 17305: if((++bpl)%BPL==0) fprintf(stderr,"\n ");
! 17306: };
! 17307: if((bpl)%BPL!=0)fprintf(stderr,"\n");
! 17308: }
! 17309:
! 17310: /* Skip `y' lines of PIC file */
! 17311: PIC_skip(h,y)
! 17312: PIC_hdr *h;
! 17313: int y;
! 17314: { lseek(fileno(h->fp),(long)(y*h->bpl),1);
! 17315: h->seek += y*h->bpl;
! 17316: h->cy += y;
! 17317: }
! 17318:
! 17319: /* Read next full line of picture data, and if OK update line & cy;
! 17320: return status: 1 OK, 0 EOF, -1 ERR.
! 17321: Free buffer in header on EOF. */
! 17322: int PIC_rline(h,lbpp)
! 17323: PIC_hdr *h;
! 17324: unsigned char **lbpp;
! 17325: { int stat;
! 17326: if( (stat=read(fileno(h->fp),h->line,h->bpl)) == h->bpl) {
! 17327: *lbpp=h->line;
! 17328: h->seek += h->bpl;
! 17329: h->cy++;
! 17330: if(PIC_debug) err("read %d bytes from fileno(h->fp) - OK",stat);
! 17331: return(1);
! 17332: }
! 17333: else { /* EOF or ERR */
! 17334: *lbpp=NULL;
! 17335: free(h->line); h->line = NULL;
! 17336: if(PIC_debug) err("read from fileno(h->fp) stat%d",stat);
! 17337: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
! 17338: else return(-1);
! 17339: };
! 17340: }
! 17341:
! 17342: /* write a full line of picture data, returning status: 1 OK, 0 EOF, -1 ERR */
! 17343: int PIC_wline(h,line)
! 17344: PIC_hdr *h;
! 17345: unsigned char *line;
! 17346: { int stat;
! 17347: if( (stat=write(fileno(h->fp),line,h->bpl)) == h->bpl) {
! 17348: h->seek += h->bpl;
! 17349: h->cy++;
! 17350: if(PIC_debug) err("wrote %d bytes to fd%d - OK",stat,fileno(h->fp));
! 17351: return(1);
! 17352: }
! 17353: else { /* ERR */
! 17354: err("write to fd%d stat%d",fileno(h->fp),stat);
! 17355: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
! 17356: else return(-1);
! 17357: };
! 17358: }
! 17359:
! 17360: char *PIC_hdr_toa(h)
! 17361: PIC_hdr *h;
! 17362: { static char s[120];
! 17363: sprintf(s,"{type=%s bx%s res%d,%d bpl%d cy%d sk%d}",
! 17364: h->type,
! 17365: bbx_toa(&(h->bx)),
! 17366: h->res_x,h->res_y,
! 17367: h->bpl,
! 17368: h->cy,
! 17369: h->seek
! 17370: );
! 17371: return(s);
! 17372: }
! 17373: 0707070035351135641006640007620000050000010264030476773367300001200000032256postlib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 17374: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 17375: /* The copyright notice does not imply actual or intended publication. */
! 17376: /* AUTHORS: */
! 17377: /* T. Thompson - ATT-BL HO - first versions */
! 17378: /* Routines for generating PostScript from RLE. */
! 17379: /* The routines at the bottom of this file, which */
! 17380: /* do the actual conversion to postscript, were */
! 17381: /* hacked out of 'sun2ps'. The original header */
! 17382: /* giving credit to its authors is there. */
! 17383:
! 17384: /* The 'binary' version of the output is collected in a */
! 17385: /* temporary file, which is then fed back to the routines */
! 17386: /* that generate postscript in a run-length-encoded form. */
! 17387: /* Ideally it should just convert the original run-length */
! 17388: /* encoding directly, but the REAL bottleneck is the */
! 17389: /* PostScript printer, of course. Printing an 800 by 800 */
! 17390: /* pixel image takes 5 minutes. */
! 17391:
! 17392: #include <stdio.h>
! 17393: #include <math.h>
! 17394: #include <string.h>
! 17395: #include "CPU.h"
! 17396: #include "boole.h"
! 17397: #include "limits.h" /* numeric extreme values */
! 17398: #include "Units.h"
! 17399: #include "Coord.h"
! 17400: #include "pic.h"
! 17401:
! 17402: FILE *Fp, *tmpfile();
! 17403: int Raswidth;
! 17404: int Raslength;
! 17405: int Rasbytes; /* bytes per row */
! 17406: int Inv = 0;
! 17407: int Aspect = 1; /* if non-zero, retain original aspect ratio */
! 17408: int Land = 0; /* if non-zero, print in landscape mode */
! 17409: char Revbyte[256];
! 17410: /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
! 17411: char Revnib[16] = {
! 17412: 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
! 17413: };
! 17414:
! 17415: void
! 17416: POST_start(h)
! 17417: PIC_hdr *h;
! 17418: {
! 17419: int n, v;
! 17420:
! 17421: /* build a table of reversed bytes */
! 17422: for ( n=0; n<256; n++ )
! 17423: Revbyte[n] = Revnib[(n>>4)&0xf] | Revnib[n&0xf]<<4;
! 17424:
! 17425: h->bpl = (h->bpl+7)/8;
! 17426: Rasbytes = h->bpl;
! 17427: Raslength = h->bpl * h->bx.b.y;
! 17428: Raswidth = h->bx.b.x;
! 17429: postmain(1,NULL,Raswidth,h->bx.b.y);
! 17430: #if CPU==SUN
! 17431: Fp = tmpfile();
! 17432: #else
! 17433: Fp = fopen("tmp.postlib.0","rw");
! 17434: #endif
! 17435: }
! 17436:
! 17437: void
! 17438: POST_end()
! 17439: {
! 17440: int c;
! 17441: rewind(Fp);
! 17442: (VOID) Encode(Raslength, Inv);
! 17443: PrintPostScriptClosing();
! 17444: fclose(Fp);
! 17445: }
! 17446:
! 17447: /* write a full line of picture data, returning status: 1 OK, 0 EOF, -1 ERR */
! 17448: int POST_wline(h,line)
! 17449: PIC_hdr *h;
! 17450: unsigned char *line;
! 17451: { int stat;
! 17452: if( (stat=fwrite(line,1,h->bpl,Fp)) == h->bpl) {
! 17453: h->seek += h->bpl;
! 17454: h->cy++;
! 17455: return(1);
! 17456: }
! 17457: else { /* ERR */
! 17458: err("write to fd%d stat%d",fileno(h->fp),stat);
! 17459: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
! 17460: else return(-1);
! 17461: };
! 17462: }
! 17463:
! 17464: /******************************************************************************
! 17465: * *
! 17466: * File: sun2ps.c *
! 17467: * Author: Glenn Boysko *
! 17468: * Organization: Case Western Reserve University *
! 17469: * EMail: {decvax, sun}!mandrill!boysko *
! 17470: * [email protected] *
! 17471: * Created: Wed Mar 23 9:25pm *
! 17472: * Contents: Sun Rasterfile to PostScript image (using a run-length *
! 17473: * encoding scheme.) *
! 17474: * *
! 17475: * (Adapted from "postimage" filter by J. R. Bammi.) *
! 17476: * *
! 17477: * @(#)sun2ps.c 1.8
! 17478: ******************************************************************************/
! 17479:
! 17480: /*
! 17481: * Usage:
! 17482: * sun2ps [-s sizex sizey] [-t transx transy] [-r rot] [-l] [-i] [-a] file ...
! 17483: *
! 17484: * -s sizex sizey = size of postscript image - default 7.5 x 10 inches.
! 17485: * -t transx transy = translate image - default 0.5 0.5 inches
! 17486: * -r rotate = rotate image - default 0 degress
! 17487: * -l = landscape (overrides *all* settings.)
! 17488: * -i = inverse image - default no inverse
! 17489: * (Inverse enabled implies white on black.)
! 17490: * -a = maintain correct aspect ratio - default none.
! 17491: *
! 17492: */
! 17493:
! 17494: /* Sun standard raster file format (as obtained by screendump(1)).
! 17495: *
! 17496: * Header (8 16-bit quantities)
! 17497: * Color Map
! 17498: * Image
! 17499: *
! 17500: */
! 17501:
! 17502: /* Header Format:
! 17503: *
! 17504: * ras_magic (int) Raster Magic number 0x59a66a95
! 17505: * ras_width (int) Width of image in pixels.
! 17506: * ras_height (int) Height of image in pixels.
! 17507: * ras_depth (int) Bits per pixel. Either 1 or 8 bits.
! 17508: * ras_length (int) Length of image in bytes.
! 17509: * ras_type (int) Type of file. Assumed to be RT_STANDARD (1) if
! 17510: * produced by a screendump command.
! 17511: * ras_maptype (int) Type of color map.
! 17512: * ras_maplength (int) Length of color map in bytes.
! 17513: *
! 17514: */
! 17515:
! 17516: /* Ras_maplength bytes of Color map data. */
! 17517:
! 17518: /* Ras_length bytes of Image data. */
! 17519:
! 17520: /* Buffer and Input Modes... */
! 17521: #define LITERAL 0
! 17522: #define COPY 1
! 17523: #define IGNORE 2
! 17524:
! 17525: /* Transmission Variables. */
! 17526: int BufCount;
! 17527:
! 17528: unsigned char Buffer[128],
! 17529: CurrByte,
! 17530: NextByte,
! 17531: *BufferP = Buffer;
! 17532:
! 17533: /* Diagnostic Variables. */
! 17534: int DiagNLongRuns = 0,
! 17535: DiagMaxRunLength = 0,
! 17536: DiagNumRuns = 0;
! 17537: double DiagSumRunLength = 0;
! 17538:
! 17539: postmain(argc,argv,width,height)
! 17540: int argc;
! 17541: char **argv;
! 17542: int width, height;
! 17543: {
! 17544: char *filename;
! 17545: double sizex, sizey, transx, transy, rotate;
! 17546:
! 17547: extern double atof();
! 17548:
! 17549: filename = "STDIN";
! 17550: sizex = 7.5;
! 17551: sizey = 10.0;
! 17552: transx = transy = 0.5;
! 17553: rotate = 0.0;
! 17554:
! 17555: while(--argc > 0)
! 17556: {
! 17557: ++argv;
! 17558: if((*argv)[0] == '-')
! 17559: {
! 17560: switch((*argv)[1])
! 17561: {
! 17562: case 'l':
! 17563: case 'L':
! 17564: Land = 1;
! 17565: break;
! 17566:
! 17567: case 's':
! 17568: case 'S':
! 17569: sizex = atof(*++argv);
! 17570: sizey = atof(*++argv);
! 17571: argc -= 2;
! 17572: break;
! 17573:
! 17574: case 't':
! 17575: case 'T':
! 17576: transx = atof(*++argv);
! 17577: transy = atof(*++argv);
! 17578: argc -= 2;
! 17579: break;
! 17580:
! 17581: case 'r':
! 17582: case 'R':
! 17583: rotate = atof(*++argv);
! 17584: argc--;
! 17585: break;
! 17586:
! 17587: case 'I':
! 17588: case 'i':
! 17589: Inv = 1;
! 17590: break;
! 17591:
! 17592: case 'A':
! 17593: case 'a':
! 17594: Aspect = 1;
! 17595: break;
! 17596:
! 17597: default:
! 17598: fprintf(stderr,"Illegal switch %c - ignored\n",
! 17599: (*argv)[1]);
! 17600: }
! 17601: }
! 17602: }
! 17603: if (Land)
! 17604: {
! 17605: transx = 8.0;
! 17606: transy = 0.5;
! 17607: sizex = 10.0;
! 17608: sizey = 7.5;
! 17609: rotate = 90.0;
! 17610: }
! 17611: if (Aspect) {
! 17612: if ((sizex / width) < (sizey / height)) {
! 17613: sizey = sizex * (height * 1.0 / width);
! 17614: }
! 17615: else {
! 17616: sizex = sizey * (width * 1.0 / height);
! 17617: }
! 17618: }
! 17619: PrintPostScriptRoutines(height, width, 1 /*depth*/ ,
! 17620: transx, transy, sizex, sizey, rotate);
! 17621: }
! 17622:
! 17623: /******************************************************************************
! 17624: * I/O Routines. *
! 17625: ******************************************************************************/
! 17626: int
! 17627: gb() /* Get a byte from Fp. */
! 17628: {
! 17629: int byte;
! 17630:
! 17631: if (!feof(Fp))
! 17632: byte = getc(Fp);
! 17633: else
! 17634: Error("Premature EOF.\n");
! 17635: if (ferror(Fp))
! 17636: Error("I/O Error.\n");
! 17637: return(Revbyte[byte]);
! 17638: }
! 17639:
! 17640: SendHex(Byte) /* Send a Hex char to Stdout. */
! 17641: unsigned char Byte;
! 17642: {
! 17643: static int LineCount = 0;
! 17644:
! 17645: printf("%02x", 0xff & Byte);
! 17646: if (++LineCount == Rasbytes)
! 17647: {
! 17648: putchar('\n');
! 17649: LineCount = 0;
! 17650: }
! 17651: }
! 17652:
! 17653: int
! 17654: SendBuffer(Inv) /* Send a buffer to Stdout. Return BytesSent. */
! 17655: int Inv;
! 17656: {
! 17657: int i, BytesSent;
! 17658:
! 17659: if (BufferMode() == LITERAL)
! 17660: {
! 17661: SendHex( (unsigned char) 0xff & BufCount );
! 17662: for (i = 0; i < BufCount+1; i++)
! 17663: {
! 17664: SendHex( (Inv) ? Buffer[i] : ~Buffer[i]);
! 17665: }
! 17666: BytesSent = BufCount+2;
! 17667: }
! 17668: else if (BufferMode() == COPY)
! 17669: {
! 17670: SendHex( (unsigned char) 0xff & (0x100 + BufCount) );
! 17671: SendHex( (Inv) ? Buffer[0] : ~Buffer[0]);
! 17672: BytesSent = 2;
! 17673: DiagRecLRun(mag(BufCount)+1);
! 17674: }
! 17675: return(BytesSent);
! 17676: }
! 17677:
! 17678: /******************************************************************************
! 17679: * Utility Routines. *
! 17680: ******************************************************************************/
! 17681: int
! 17682: mag(Byte) /* Magitude of a signed char. */
! 17683: int Byte;
! 17684: {
! 17685: if (Byte & 0x80)
! 17686: {
! 17687: /* Signed */
! 17688: Byte = ~(--Byte);
! 17689: }
! 17690: return( 0xff & Byte );
! 17691: }
! 17692:
! 17693: /******************************************************************************
! 17694: * Buffer Management Routines. *
! 17695: ******************************************************************************/
! 17696: int
! 17697: InputMode()
! 17698: {
! 17699: if (CurrByte == NextByte)
! 17700: return(COPY);
! 17701: return(LITERAL);
! 17702: }
! 17703:
! 17704: int
! 17705: BufferMode()
! 17706: {
! 17707: if (BufCount >= 0 && BufCount <= 127)
! 17708: return(LITERAL);
! 17709: else if (BufCount >= -127 && BufCount <= -1)
! 17710: return(COPY);
! 17711: return(IGNORE);
! 17712: }
! 17713:
! 17714: InitLitMode(NBytes, Inv)
! 17715: int *NBytes, Inv;
! 17716: {
! 17717: BufferP = Buffer;
! 17718: BufCount = -1;
! 17719: ContLitMode(NBytes, Inv);
! 17720: }
! 17721:
! 17722: ContLitMode(NBytes, Inv)
! 17723: int *NBytes, Inv;
! 17724: {
! 17725: if (BufCount == 127)
! 17726: {
! 17727: SendBuffer(Inv);
! 17728: BufferP = Buffer;
! 17729: BufCount = -1;
! 17730: }
! 17731: *BufferP++ = CurrByte;
! 17732: BufCount++;
! 17733: CurrByte = NextByte;
! 17734: NextByte = (unsigned char) gb();
! 17735: (*NBytes)--;
! 17736: }
! 17737:
! 17738: InitCopyMode(NBytes, Inv)
! 17739: int *NBytes, Inv;
! 17740: {
! 17741: BufferP = Buffer;
! 17742: *BufferP++ = CurrByte;
! 17743: BufCount = -1;
! 17744: CurrByte = (unsigned char) gb();
! 17745: NextByte = (unsigned char) gb();
! 17746: *NBytes -= 2;
! 17747: }
! 17748:
! 17749: ContCopyMode(NBytes, Inv)
! 17750: int *NBytes, Inv;
! 17751: {
! 17752: if (BufCount == -127)
! 17753: {
! 17754: SendBuffer(Inv);
! 17755: InitCopyMode(NBytes, Inv);
! 17756: DiagNLongRuns++;
! 17757: }
! 17758: BufCount--;
! 17759: CurrByte = NextByte;
! 17760: NextByte = gb();
! 17761: (*NBytes)--;
! 17762: }
! 17763:
! 17764: /******************************************************************************
! 17765: * Encoding Algorithm. *
! 17766: ******************************************************************************/
! 17767: int
! 17768: Encode(NBytes, Inv)
! 17769: int NBytes, Inv;
! 17770: {
! 17771: int BytesSent = 0;
! 17772:
! 17773: /* Initialize Buffer, BufCount, NextByte, CurrByte */
! 17774: CurrByte = (unsigned char) gb();
! 17775: NextByte = (unsigned char) gb();
! 17776: if (InputMode() == LITERAL)
! 17777: {
! 17778: InitLitMode(&NBytes, Inv);
! 17779: }
! 17780: else
! 17781: {
! 17782: InitCopyMode(&NBytes, Inv);
! 17783: }
! 17784: while (NBytes > 3)
! 17785: {
! 17786: switch(BufferMode())
! 17787: {
! 17788: case LITERAL:
! 17789: if (InputMode() == COPY)
! 17790: {
! 17791: BytesSent += SendBuffer(Inv);
! 17792: InitCopyMode(&NBytes, Inv);
! 17793: }
! 17794: else
! 17795: {
! 17796: ContLitMode(&NBytes, Inv);
! 17797: }
! 17798: break;
! 17799: case COPY:
! 17800: if (CurrByte == Buffer[0])
! 17801: {
! 17802: ContCopyMode(&NBytes, Inv);
! 17803: }
! 17804: else
! 17805: {
! 17806: BytesSent += SendBuffer(Inv);
! 17807: if (InputMode() == COPY)
! 17808: {
! 17809: InitCopyMode(&NBytes, Inv);
! 17810: }
! 17811: else
! 17812: {
! 17813: InitLitMode(&NBytes, Inv);
! 17814: }
! 17815: }
! 17816: break;
! 17817: default:
! 17818: Error("Bad Buffer Mode... Sorry\n");
! 17819: break;
! 17820: }
! 17821: }
! 17822: BytesSent += SendBuffer(Inv);
! 17823: /* Send out rem'g 2-3 bytes in LITERAL mode. */
! 17824: Buffer[0] = CurrByte;
! 17825: Buffer[1] = NextByte;
! 17826: if (NBytes == 3)
! 17827: Buffer[2] = gb();
! 17828: BufCount = NBytes-1;
! 17829: BytesSent += SendBuffer(Inv);
! 17830: return(BytesSent);
! 17831: }
! 17832:
! 17833: /******************************************************************************
! 17834: * Diagnostic Routines. *
! 17835: ******************************************************************************/
! 17836: DiagRecLRun(Rlength)
! 17837: int Rlength;
! 17838: {
! 17839: #ifdef DIAGS
! 17840: if (Rlength > DiagMaxRunLength)
! 17841: DiagMaxRunLength = Rlength;
! 17842: DiagSumRunLength += Rlength;
! 17843: DiagNumRuns++;
! 17844: #endif
! 17845: }
! 17846:
! 17847: Diags()
! 17848: {
! 17849: #ifdef DIAGS
! 17850: fprintf(stderr, "Longest Run (<= 128) = %d\n", DiagMaxRunLength);
! 17851: fprintf(stderr, "Number of Runs over 128 = %d\n", DiagNLongRuns);
! 17852: fprintf(stderr, "Average Run Length of %d. (%d Runs)\n",
! 17853: (int) DiagSumRunLength / DiagNumRuns, DiagNumRuns);
! 17854: #endif
! 17855: }
! 17856:
! 17857: /******************************************************************************
! 17858: * PostScript Output Routines. *
! 17859: ******************************************************************************/
! 17860: PrintPostScriptRoutines(ras_h, ras_w, ras_d, tx, ty, sx, sy, rot)
! 17861: int ras_h, ras_w, ras_d;
! 17862: double tx, ty, sx, sy, rot;
! 17863: {
! 17864: printf("%%!\n/inch {72 mul} def\n");
! 17865: printf("/bpp %d def\n", ras_d);
! 17866: printf("/scanlines %d def\n", ras_h);
! 17867: printf("/scansize %d def\n", ras_w);
! 17868: printf("/bitmapx\n{");
! 17869: printf(" %d %d %d [%d 0 0 %d 0 %d] ", ras_w, ras_h, ras_d, ras_w,
! 17870: -ras_h, ras_h);
! 17871: printf("{currentfile readrlehexstring pop } image\n} def\n");
! 17872: printf("gsave\n");
! 17873: printf("%f inch %f inch translate\n",tx, ty);
! 17874: printf("%f rotate\n", rot );
! 17875: printf("%f inch %f inch scale\n", sx, sy);
! 17876: printf("/readrlehexstring\t%% rle_file => decoded_string boolean\n");
! 17877: printf("{\n\t/fileptr exch def\n\tfileptr 1 string readhexstring {");
! 17878: printf("\n\t\t0 get dup 128 and 0 eq\n");
! 17879: printf("\t\t{ 1 add /Buffer exch string def\n");
! 17880: printf("\t\t\tfileptr Buffer readhexstring\n\t\t}\n\t\t{");
! 17881: printf(" 256 exch sub /BufCount exch def\n");
! 17882: printf("\t\t\t/Buffer BufCount 1 add string def\n");
! 17883: printf("\t\t\t/RunInt fileptr 1 string readhexstring");
! 17884: printf(" pop 0 get def\n");
! 17885: printf("\t\t\t0 1 BufCount { RunInt Buffer 3 1 roll put } for\n");
! 17886: printf("\t\t\tBuffer true\n\t\t} ifelse\n\t}\n\t{ false } ifelse\n");
! 17887: printf("} def\n");
! 17888: printf("/clipathx\n{\tnewpath\n\t0 0 moveto\n\t%f inch 0", sx);
! 17889: printf(" lineto\n\t%f inch %f inch lineto\n\t0 %f inch lineto\n",
! 17890: sx, sy, sy);
! 17891: printf("\tclosepath\n} def\nclipathx clip\n");
! 17892: printf("bitmapx\n");
! 17893: }
! 17894:
! 17895: PrintPostScriptClosing()
! 17896: {
! 17897: printf("\ngrestore\n");
! 17898: printf("showpage\n");
! 17899: }
! 17900:
! 17901: /******************************************************************************
! 17902: * Error Routine. *
! 17903: ******************************************************************************/
! 17904: Error(S1, S2, S3)
! 17905: char *S1, *S2, *S3;
! 17906: {
! 17907: fprintf(stderr, S1, S2, S3);
! 17908: exit(-1);
! 17909: }
! 17910: 0707070035351136011006640007620000050000010264130476773367300001200000005002rastlib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 17911: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 17912: /* The copyright notice does not imply actual or intended publication. */
! 17913: /* AUTHORS: */
! 17914: /* T. Thompson - ATT-BL HO - first version */
! 17915: /* Routines for generating PostScript from RLE. */
! 17916: /* The routines at the bottom of this file, which */
! 17917: /* do the actual conversion to postscript, were */
! 17918: /* take from 'sun2ps'. The original header */
! 17919: /* giving credit to its authors is there. */
! 17920:
! 17921: /* The 'binary' version of the output is collected in a */
! 17922: /* temporary file, which is then fed back to the routines */
! 17923: /* that generate postscript in a run-length-encoded form. */
! 17924: /* Ideally it should just convert the original run-length */
! 17925: /* encoding directly, but this is just a hack. The REAL */
! 17926: /* bottleneck is the PostScript printer, of course. */
! 17927: /* Printing an 800 by 800 pixel image takes 5 minutes. */
! 17928:
! 17929: #include <stdio.h>
! 17930: #include <math.h>
! 17931: #include <string.h>
! 17932: #include "CPU.h"
! 17933: #include "boole.h"
! 17934: #include "limits.h" /* numeric extreme values */
! 17935: #include "Units.h"
! 17936: #include "Coord.h"
! 17937: #include "pic.h"
! 17938: #include <sys/types.h>
! 17939: #include <suntool/sunview.h>
! 17940: #include <pixrect/pixrect.h>
! 17941: #include <pixrect/pr_io.h>
! 17942:
! 17943: int Raswidth;
! 17944: int Raslength;
! 17945: extern char Revbyte[256];
! 17946: extern char Revnib[16];
! 17947:
! 17948: static FILE *fout;
! 17949:
! 17950: void
! 17951: RAST_start(h)
! 17952: PIC_hdr *h;
! 17953: {
! 17954: int n, v;
! 17955: struct rasterfile rh;
! 17956:
! 17957: /* build a table of reversed bytes */
! 17958: for ( n=0; n<256; n++ )
! 17959: Revbyte[n] = Revnib[(n>>4)&0xf] | Revnib[n&0xf]<<4;
! 17960:
! 17961: fout = h->fp;
! 17962: h->bpl = (h->bpl+7)/8;
! 17963: Raslength = h->bpl * h->bx.b.y;
! 17964: Raswidth = h->bx.b.x;
! 17965:
! 17966: rh.ras_magic = RAS_MAGIC;
! 17967: rh.ras_width = h->bx.b.x;
! 17968: rh.ras_height = h->bx.b.y;
! 17969: rh.ras_depth = 1;
! 17970: rh.ras_length = Raslength;
! 17971: rh.ras_type = RT_STANDARD;
! 17972: rh.ras_maptype = RMT_NONE;
! 17973: rh.ras_maplength = 0;
! 17974: pr_dump_header(fout,&rh,(colormap_t*)0);
! 17975: }
! 17976:
! 17977: void
! 17978: RAST_end()
! 17979: {
! 17980: }
! 17981:
! 17982: /* write a full line of picture data, returning status: 1 OK, 0 EOF,
! 17983: -1 ERR */
! 17984: int RAST_wline(h,line)
! 17985: PIC_hdr *h;
! 17986: unsigned char *line;
! 17987: { int stat;
! 17988: int n;
! 17989:
! 17990: for ( n=h->bpl; n>0; n-- ) {
! 17991: if ( putc(Revbyte[*line++],fout) == EOF )
! 17992: break;
! 17993: }
! 17994: if ( n == 0 ) {
! 17995: h->seek += h->bpl;
! 17996: h->cy++;
! 17997: return(1);
! 17998: }
! 17999: else { /* ERR */
! 18000: err("write to fd%d stat%d",fileno(h->fp),stat);
! 18001: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
! 18002: else return(-1);
! 18003: };
! 18004: }
! 18005: 0707070035351135651006640007620000050000010264150476773367300000600000003030ric.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 18006: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 18007: /* The copyright notice does not imply actual or intended publication. */
! 18008: /* AUTHORS: */
! 18009: /* H. S. Baird - ATT-BL MH - first versions */
! 18010: /* ric.h - Ricoh IS-30 scanner constants, typedefs, function declarations
! 18011: The scanner program `rscan' creates a file (typically >1Mbyte).
! 18012: It has an ascii header, terminated by \n\n -- see RIC_hdr for its data fields.
! 18013: The rest is binary scanner data. Each `RIC_hdr.bpl' bytes holds one scan-line's
! 18014: pixels, 1 bit/pixel. A `1' bit means black. The order of the bytes in a line
! 18015: is left-to-right across the page. The low-order bit in a byte is the left-most.
! 18016: Conventionally, X-coordinates start at 0, at the left of the page, and
! 18017: increase to the right. Y-coordinates start at 0 at the top of the page,
! 18018: and increase down.
! 18019:
! 18020: REQUIRES: prior #include "Coord.h"
! 18021: */
! 18022:
! 18023: typedef struct { /* Scanner file header */
! 18024: short res_x,res_y; /* resolution in pixels/inch (x,y may differ) */
! 18025: short bpl; /* bytes per scan line */
! 18026: Bbx bx; /* bounding box (pixel indices 0,1,...) */
! 18027: } RIC_hdr;
! 18028:
! 18029: /* these routines are found in /usr/hsb/ricoh/riclib.c */
! 18030: int RIC_get_hdr(); /* args: fd, (RIC_hdr *); returns: 1==OK, 0==EOF, -1=ERR */
! 18031: int RIC_line(); /* arg: (char **); returns: 1==OK, 0==EOF, -1==ERR */
! 18032: RIC_skip(); /* arg: int no. lines to skip */
! 18033: char *S_hdr_toa(); /* RIC_hdr in printable-string form */
! 18034:
! 18035: 0707070035351135321006640007620000050000010264160476773367300001100000011466riclib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 18036: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 18037: /* The copyright notice does not imply actual or intended publication. */
! 18038: /* AUTHORS: */
! 18039: /* H. S. Baird - ATT-BL MH - first versions */
! 18040: /* riclib.c - Ricoh scanner-file public functions:
! 18041:
! 18042: RIC_* functions use system I/O, for speed...
! 18043: int RIC_get_hdr(fd,RIC_hdr *) - get scanner-file header
! 18044: int RIC_line(char **) - read one line of scanner data
! 18045: err_RIC_Line(char *,RIC_hdr) - print on stderr
! 18046: int RIC_oline(char **) - write one line of scanner data
! 18047: char *RIC_hdr_toa() - RIC_hdr to ascii printable string
! 18048: */
! 18049:
! 18050: #include <stdio.h>
! 18051: #include <math.h>
! 18052: #include <string.h>
! 18053: #include "CPU.h"
! 18054: #include "stdocr.h"
! 18055:
! 18056: #define RIC_debug 0
! 18057:
! 18058: /* treated as local static: */
! 18059: int RIC_fd; /* file descr. */
! 18060: int RIC_bpl; /* bytes per line */
! 18061: char *RIC_bf = NULL; /* (malloc space *) holds one line of scanner data */
! 18062:
! 18063: /* system I/O variation on fgets(3), except it replaces \n with \0,
! 18064: and returns the number of chars read (including \0) */
! 18065: int RIC_fgets(bf,max,fd)
! 18066: char *bf;
! 18067: int max;
! 18068: int fd;
! 18069: { char *cp;
! 18070: int stat,mny;
! 18071: cp=bf; mny=0;
! 18072: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
! 18073: if(stat!=1) return(stat);
! 18074: else if(mny>=max) return(-1);
! 18075: *cp='\0';
! 18076: return(mny);
! 18077: }
! 18078:
! 18079: /* read header from scanner file, return status: 1 OK, 0 EOF, -1 error */
! 18080: int RIC_get_hdr( fd, hp )
! 18081: int fd; /* should have been open'ed earlier */
! 18082: RIC_hdr *hp;
! 18083: #define HL_MAX 80
! 18084: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
! 18085: { char *cp,*parm,hline[HL_MAX];
! 18086: int status,nrd;
! 18087: RIC_fd = fd;
! 18088: if((status=RIC_fgets(hline,HL_MAX,RIC_fd))<=0) return(status);
! 18089: while(strlen(hline)>1) {
! 18090: if(RIC_debug) err("hline \"%s\"",hline);
! 18091: parm=strtok(hline,HTERM);
! 18092: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
! 18093: if((parm=strtok(0,HTERM))!=NULL
! 18094: &&strcmp(parm,"binary")==0) ;
! 18095: else return(-1);
! 18096: }
! 18097: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
! 18098: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.x=atoi(parm);
! 18099: else return(-1);
! 18100: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.y=atoi(parm);
! 18101: else return(-1);
! 18102: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.x=atoi(parm)-1;
! 18103: else return(-1);
! 18104: hp->bpl=(hp->bx.b.x-hp->bx.a.x+1+7)/8;
! 18105: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.y=atoi(parm)-1;
! 18106: else return(-1);
! 18107: }
! 18108: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
! 18109: if((parm=strtok(0,HTERM))!=NULL) hp->res_x=atoi(parm);
! 18110: else return(-1);
! 18111: if((parm=strtok(0,HTERM))!=NULL) hp->res_y=atoi(parm);
! 18112: else return(-1);
! 18113: }
! 18114: else return(-1);
! 18115: if((status=RIC_fgets(hline,HL_MAX,RIC_fd))<=0) return(status);
! 18116: };
! 18117: RIC_bpl=hp->bpl;
! 18118: /* allocate one extra byte in scanner buffer as a favor to RLE */
! 18119: if((RIC_bf = (char *) malloc(RIC_bpl+1))==NULL) {
! 18120: fprintf(stderr,
! 18121: "riclib: can't alloc RIC_bf (%d bytes) - abort\n",
! 18122: RIC_bpl+1);
! 18123: return(-1);
! 18124: };
! 18125: return(1);
! 18126: }
! 18127:
! 18128: /* write header to scanner file */
! 18129: RIC_put_hdr( fd, hp )
! 18130: int fd; /* should have been open'ed earlier */
! 18131: RIC_hdr *hp;
! 18132: { char *cp,*parm,hline[HL_MAX];
! 18133: int status,nrd;
! 18134: sprintf(hline,"TYPE=binary\n");
! 18135: write(fd,hline,strlen(hline));
! 18136: sprintf(hline,"WINDOW=%d %d %d %d\n",
! 18137: hp->bx.a.x,hp->bx.a.y,hp->bpl,hp->bx.b.y+1);
! 18138: write(fd,hline,strlen(hline));
! 18139: sprintf(hline,"RES=%d %d\n\n",hp->res_x,hp->res_y);
! 18140: write(fd,hline,strlen(hline));
! 18141: }
! 18142:
! 18143: err_RIC_line(sl,shdr)
! 18144: char *sl;
! 18145: RIC_hdr shdr;
! 18146: #define BPL 20 /* bytes to display per line */
! 18147: { char *cp,*ep;
! 18148: int bpl; /* bytes per display line */
! 18149: bpl=0;
! 18150: for(cp=sl,ep=sl+shdr.bpl; cp!=ep; cp++) {
! 18151: fprintf(stderr,"%o ",0377&(*cp));
! 18152: if((++bpl)%BPL==0) fprintf(stderr,"\n ");
! 18153: };
! 18154: if((bpl)%BPL!=0)fprintf(stderr,"\n");
! 18155: }
! 18156:
! 18157: /* skip `y' lines, starting from current read pointer */
! 18158: RIC_skip(y)
! 18159: int y;
! 18160: { lseek(RIC_fd,(long)(y*RIC_bpl),1);
! 18161: }
! 18162:
! 18163: /* read next full line of scanner data, return status: 1 OK, 0 EOF, -1 ERR */
! 18164: int RIC_line(lbpp)
! 18165: char **lbpp;
! 18166: { int stat;
! 18167: if( (stat=read(RIC_fd,RIC_bf,RIC_bpl)) == RIC_bpl) {
! 18168: *lbpp=RIC_bf;
! 18169: if(RIC_debug) err("read %d bytes from RIC_fd - OK",stat);
! 18170: return(1);
! 18171: }
! 18172: else { /* EOF or ERR */
! 18173: *lbpp=NULL;
! 18174: free(RIC_bf);
! 18175: if(RIC_debug) err("read from RIC_fd stat%d",stat);
! 18176: if((stat>=0)&&(stat<RIC_bpl)) return(0 /*EOF*/);
! 18177: else return(-1);
! 18178: };
! 18179: }
! 18180:
! 18181: /* write a full line of scanner data, returning status: 1 OK, 0 EOF, -1 ERR */
! 18182: int RIC_oline(fd,bf)
! 18183: int fd;
! 18184: char *bf;
! 18185: { int stat;
! 18186: if( (stat=write(fd,bf,RIC_bpl)) == RIC_bpl) {
! 18187: if(RIC_debug) err("wrote %d bytes to fd%d - OK",stat,fd);
! 18188: return(1);
! 18189: }
! 18190: else { /* ERR */
! 18191: err("write to fd%d stat%d",fd,stat);
! 18192: if((stat>=0)&&(stat<RIC_bpl)) return(0 /*EOF*/);
! 18193: else return(-1);
! 18194: };
! 18195: }
! 18196:
! 18197: char *RIC_hdr_toa(hp)
! 18198: RIC_hdr *hp;
! 18199: { static char s[40];
! 18200: sprintf(s,"{res%d,%d bpl%d bx%s}\n",
! 18201: hp->res_x,hp->res_y,
! 18202: hp->bpl,
! 18203: bbx_toa(&(hp->bx)));
! 18204: return(s);
! 18205: }
! 18206:
! 18207: 0707070035351135311006640007620000050000010264170476773367400000600000007317rle.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 18208: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 18209: /* The copyright notice does not imply actual or intended publication. */
! 18210: /* AUTHORS: */
! 18211: /* H. S. Baird - ATT-BL MH - first versions */
! 18212: /* A rle file consists of any number of:
! 18213: `scan_line's, each of which has the form:
! 18214: (short) bytes_mny, followed by bytes_mny bytes in the form:
! 18215: (packed short) runs_mny
! 18216: if >0, then followed by runs_mny runs
! 18217: else if ==0, then followed by:
! 18218: (packed short) blank_lines_mny skipped, -1
! 18219: (packed short) runs_mny (>0), then...
! 18220: ...runs_mny runs
! 18221: A `run' is two (packed short) oxs,oxe which are
! 18222: both offset counts >=0 from the prior `?x?' (starts at 0 at left margin).
! 18223: Suppose that xs, xe are the corresponding accumulated pixel indices,
! 18224: then xs is the pixel index of the first black pixel of the run,
! 18225: and xe the pixel index of the first white pixel following the run.
! 18226: A `packed short' is a byte if its value is <128, else two bytes `HIGH' & `LOW'
! 18227: with the 0200 bit of its HIGH byte set.
! 18228: */
! 18229:
! 18230: #define HIGH(A) ((A>>8)&0177)
! 18231: #define LOW(A) (A&0377)
! 18232:
! 18233: /* run-length-encoding constants, typedefs */
! 18234:
! 18235: /* The following assumes a worst case page width of 17 inches (Legal page, >ISO A2)
! 18236: and worst case digitizing resolution of 400 pixels/inch (e.g. CCITT Group 4),
! 18237: for a maximum of 6800 pixels/line */
! 18238: #define RLE_RUNS 3401 /* maximum no. runs in a line */
! 18239: #define RLE_BYTES 6800 /* maximum no. data bytes in a rle line (enough?) */
! 18240:
! 18241: typedef struct RLE_Run {
! 18242: short xs; /* x-coord of first pixel in run */
! 18243: short xe; /* x-coord of last pixel in run (NOT first following) */
! 18244: } RLE_Run;
! 18245: #define Init_RLE_Run {0,0}
! 18246:
! 18247: typedef struct DRLE_Run {
! 18248: short xs; /* x-coord of first pixel in run */
! 18249: short xe; /* x-coord of last pixel in run (NOT first following) */
! 18250: struct DRLE_Run *next;
! 18251: } DRLE_Run;
! 18252:
! 18253: typedef struct RLE_Yrun {
! 18254: short y,xs,xe;
! 18255: } RLE_Yrun;
! 18256: #define Init_RLE_Yrun {0,0,0}
! 18257:
! 18258: typedef struct RLE_Line {
! 18259: short y; /* y-coord of line */
! 18260: short len; /* length of line in pixels (white+black) */
! 18261: short runs; /* no. of runs */
! 18262: RLE_Run r[RLE_RUNS];
! 18263: } RLE_Line;
! 18264: #define Init_RLE_Line {0,0,0,Init_RLE_Run}
! 18265:
! 18266:
! 18267: typedef struct DRLE_Line { /* dynamically allocated version */
! 18268: DRLE_Run *r; /* first run */
! 18269: DRLE_Run *lastr; /* last run */
! 18270: } DRLE_Line;
! 18271: #define Init_DRLE_Line {0,0}
! 18272:
! 18273: typedef struct RLE_Lines {
! 18274: int mny;
! 18275: RLE_Line *rla; /* array of RLE_Lines */
! 18276: } RLE_Lines;
! 18277: #define Init_RLE_Lines {0,NULL}
! 18278: #if MAIN
! 18279: RLE_Lines empty_RLE_Lines = Init_RLE_Lines;
! 18280: #else
! 18281: extern RLE_Lines empty_RLE_Lines;
! 18282: #endif
! 18283:
! 18284: typedef struct Transform_rlel_arg {
! 18285: boolean ident; /* if T, then no change (speed-optimization) */
! 18286: Bbx tr; /* trim: select just this window of input */
! 18287: Sp off; /* offset: translate by off.x,off.y */
! 18288: Pp scl; /* scale: X & Y expansion factors (about 0,0) */
! 18289: Sp wh; /* truncate: exact maximum output width,height */
! 18290: Radians rot; /* rotate: angle (multiple of PI/4) */
! 18291: boolean rev; /* reverse: swap black and white */
! 18292: int sy; /* next integer line no. to write */
! 18293: double dy; /* next real line no. to write */
! 18294: } Transform_rlel_arg;
! 18295: #define Init_Transform_rlel_arg {T,Init_Bbx,Init_Zero_Sp,{1.0,1.0},Init_Zero_Sp,0.0,F,0,0.0}
! 18296: #if MAIN
! 18297: Transform_rlel_arg empty_Transform_rlel_arg = Init_Transform_rlel_arg;
! 18298: #else
! 18299: extern Transform_rlel_arg empty_Transform_rlel_arg;
! 18300: #endif
! 18301:
! 18302: #ifdef MAIN
! 18303: /* these routines are found in rlelib.c */
! 18304:
! 18305: boolean RLE_open(); /* arg: (FILE *) */
! 18306: RLE_Line *RLE_line(); /* args: l,r - left,right interval */
! 18307: RLE_Line *RLE_get_Line(); /* args: l,r - left,right interval */
! 18308: int RLE_run(); /* arg: (RLE_Run *) */
! 18309: fwrb_rlines(); /* args: (FILE *), (RLE_Lines *) */
! 18310: insert_rlel();
! 18311: #endif
! 18312: 0707070035351135301006640007620000050000010264210476773367400001100000047356rlelib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 18313: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 18314: /* The copyright notice does not imply actual or intended publication. */
! 18315: /* AUTHORS: */
! 18316: /* T. Pavlidis - ATT-BL MH - first versions */
! 18317: /* H. S. Baird - ATT-BL MH - first versions */
! 18318:
! 18319: /* rlelib.c - subroutines for writing/reading run-length-encoded format files.
! 18320: BUG: Uses system I/O for speed, but sacrifices machine-independence:
! 18321: should use fioi.h macroes instead.
! 18322: See rle.h for summary of rle file and format of public functions.
! 18323: Writing a rle file:
! 18324: fd=creat()
! 18325: RLE_put_hdr(fd,hp) - once: allocate buffers, write header
! 18326: RLE_put_Line(fd,lp) - repeatedly
! 18327: RLE_close(fd) - once: flush and deallocate buffers
! 18328: Reading a rle file:
! 18329: fd=open()
! 18330: RLE_open(fd,hp) - once: read header, 1st line into buffer
! 18331: RLE_get_Line(l,r) - repeatedly (on EOF, deallocates buffer)
! 18332: The user can read line-at-a-time or run-at-a-time, but should not intermix them:
! 18333: line-at-a-time:
! 18334: (RLE_Line *) RLE_get_Line(l,r) - return ptr to next line with some run
! 18335: in the interval [l,r];
! 18336: read from opened file (NULL if EOF, abort on error)
! 18337: allocates large buffer and frees it when done
! 18338: run-at-a-time:
! 18339: int RLE_get_Run(&R) - read next run into (RLE_Run) R
! 18340: returns the line number (-1 for EOF, abort on ERROR)
! 18341: does not allocate large buffer;
! 18342: if only a few runs will be used, can be faster
! 18343: */
! 18344:
! 18345: #include <stdio.h>
! 18346: #define LIBC_INCL 1
! 18347: #include "CPU.h"
! 18348: #include "stdocr.h"
! 18349: #include "rle.h"
! 18350:
! 18351: #define RLE_dbg F
! 18352: #define dbg_rd F
! 18353: #define dbg_wr F
! 18354:
! 18355: /* Treated as local static: */
! 18356: typedef struct RLE_global {
! 18357: int fd; /* rle file descriptor */
! 18358: boolean eof;
! 18359: int cy, cx; /* current line no., x-coord */
! 18360: short runs, nrun; /* no. runs, next run in current line */
! 18361: RLE_Line *lp; /* pointer to line (malloc space) */
! 18362: int bpl; /* maximum no. bytes in packed rle line */
! 18363: char *bf; /* I/O buffer (malloc space) */
! 18364: int bfsize; /* size of buffer */
! 18365: char *cp; /* cur. ptr, into bf */
! 18366: } RLE_global;
! 18367: #define Init_RLE_global {0,F,-1,-1,0,0,NULL,0,NULL,0,NULL}
! 18368: RLE_global _RLE = Init_RLE_global;
! 18369:
! 18370: RLE_put_hdr( fd, rhp, bufn )
! 18371: int fd;
! 18372: RIC_hdr *rhp;
! 18373: int bufn; /* minimum number of lines to buffer locally */
! 18374: { char hdr[100];
! 18375: int stat;
! 18376: sprintf(hdr,"TYPE=rle\nWINDOW=%d %d %d %d\nRES=%d %d\n\n",
! 18377: /* use half-open WINDOW convention: l&t closed, r&b open*/
! 18378: rhp->bx.a.x,rhp->bx.a.y,rhp->bx.b.x+1,rhp->bx.b.y+1,
! 18379: rhp->res_x,rhp->res_y);
! 18380: if((stat=write(fd,hdr,strlen(hdr)))!=strlen(hdr)) {
! 18381: abort("rlelib: can't put hdr, stat %d",stat);
! 18382: };
! 18383: _RLE.fd = fd;
! 18384: _RLE.cy = rhp->bx.a.y-1;
! 18385: _RLE.bpl = rhp->bx.b.x-rhp->bx.a.x+9; /* maximum bytes per line */
! 18386: _RLE.bfsize = bufn*_RLE.bpl;
! 18387: if((_RLE.bf=(char *)malloc(_RLE.bfsize))==NULL)
! 18388: abort("can't alloc _RLE.bf[%d]",_RLE.bfsize);
! 18389: _RLE.cp = _RLE.bf;
! 18390: }
! 18391:
! 18392: #define PUT(A,B) { if((A)<128) *(B)++ = (A); \
! 18393: else { *(B)++ = HIGH(A) | 0200; *(B)++ = LOW(A); } \
! 18394: }
! 18395:
! 18396: /* write out a non-blank line of runs */
! 18397: RLE_put_Line(fd,rlp)
! 18398: int fd; /* file descr (already open) */
! 18399: RLE_Line *rlp;
! 18400: { register char *bp;
! 18401: short blank_lines_mny; /* the number of preceding blank lines, minus 1 */
! 18402: register RLE_Run *rp,*ep;
! 18403: Scoor xsofar;
! 18404: short bytes_mny;
! 18405: int stat; /* I/O status */
! 18406: if((_RLE.bfsize-(_RLE.cp-_RLE.bf)) < _RLE.bpl) {
! 18407: /* not enough room left in buffer for worst-case line */
! 18408: RLE_flush();
! 18409: };
! 18410: /* leave space for (short) bytes_mny count */
! 18411: bp=_RLE.cp+sizeof(short);
! 18412: if((blank_lines_mny=(rlp->y-_RLE.cy-1))>0) /* blank lines were skipped */ {
! 18413: PUT(0,bp); /* ``0 runs'' signals blank lines */
! 18414: PUT(blank_lines_mny,bp);
! 18415: };
! 18416: _RLE.cy=rlp->y;
! 18417: PUT(rlp->runs,bp);
! 18418: xsofar=0;
! 18419: for(rp=rlp->r,ep=rp+rlp->runs; rp!=ep; rp++) {
! 18420: PUT(rp->xs-xsofar,bp); xsofar = rp->xs;
! 18421: PUT(rp->xe-xsofar+1,bp); xsofar = rp->xe+1;
! 18422: };
! 18423: /* go back & write no. bytes at top of line */
! 18424: *((short *) _RLE.cp) = bp-_RLE.cp-sizeof(short);
! 18425: _RLE.cp = bp;
! 18426: if(dbg_wr) err("RLE_put_Line y%d nh%d",_RLE.cy,bytes_mny-2);
! 18427: };
! 18428:
! 18429: /* write out a set of runs */
! 18430: RLE_put_Lines(fd,rlsp)
! 18431: int fd; /* file descr (already open) */
! 18432: RLE_Lines *rlsp;
! 18433: { int i;
! 18434: RLE_Line *rlp;
! 18435: for(i=0,rlp=rlsp->rla; i<rlsp->mny; i++,rlp++)
! 18436: RLE_put_Line(fd,rlp);
! 18437: }
! 18438:
! 18439: RLE_flush()
! 18440: { int bytes;
! 18441: int stat;
! 18442: if((bytes=(_RLE.cp-_RLE.bf))>0)
! 18443: if(stat=write(_RLE.fd,_RLE.bf,bytes)!=bytes)
! 18444: abort("can't write _RLE.bf[%d], status %d",bytes,stat);
! 18445: _RLE.cp = _RLE.bf;
! 18446: }
! 18447:
! 18448: RLE_close(fd)
! 18449: int fd;
! 18450: { RLE_flush();
! 18451: if(_RLE.bf!=NULL) free(_RLE.bf);
! 18452: _RLE.bf = _RLE.cp = NULL;
! 18453: _RLE.bfsize = 0;
! 18454: }
! 18455:
! 18456: /* ``open'' RLE_file for reading:
! 18457: save filedes, read header, and read first line into buffer */
! 18458: boolean RLE_open( fd, hp )
! 18459: int fd;
! 18460: RIC_hdr *hp;
! 18461: { _RLE.fd = fd;
! 18462: /* read header */
! 18463: RLE_get_hdr( fd, hp );
! 18464: if(_RLE.bf!=NULL) free(_RLE.bf);
! 18465: _RLE.bfsize = _RLE.bpl;
! 18466: if((_RLE.bf=(char *)malloc(_RLE.bfsize))==NULL)
! 18467: abort("can't alloc _RLE.bf[%d]",_RLE.bfsize);
! 18468: /* read first non-blank line */
! 18469: _RLE.cy = hp->bx.a.y-1;
! 18470: if (!RLE_rdbf()) return(F);
! 18471: _RLE.eof = F;
! 18472: return(T);
! 18473: }
! 18474:
! 18475: /* read next short from rle-line buffer, updating arg ptr */
! 18476: short RLE_gshort(p)
! 18477: char **p;
! 18478: { register n;
! 18479: register char *q;
! 18480: q = *p;
! 18481: if((*q)&0200) {
! 18482: n = (((*q & 0177)<<8)&077400) | (*(q+1) & 0377);
! 18483: (*p)++;
! 18484: }
! 18485: else n = *q;
! 18486: (*p)++;
! 18487: return(n);
! 18488: }
! 18489:
! 18490: /* system I/O variation on fgets(3), except it replaces \n with \0,
! 18491: and returns the number of chars read (including \0) */
! 18492: int RLE_fgets(bf,max,fd)
! 18493: char *bf;
! 18494: int max;
! 18495: int fd;
! 18496: { char *cp;
! 18497: int stat,mny;
! 18498: cp=bf; mny=0;
! 18499: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
! 18500: if(stat!=1) return(stat);
! 18501: else if(mny>=max) return(-1);
! 18502: *cp='\0';
! 18503: return(mny);
! 18504: }
! 18505:
! 18506: /* read ascii header from rle file, convert to RIC_hdr,
! 18507: return status: 1 OK, 0 EOF, -1 error */
! 18508: int RLE_get_hdr( fd, hp )
! 18509: int fd; /* should have been open'ed earlier */
! 18510: RIC_hdr *hp;
! 18511: #define HL_MAX 80
! 18512: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
! 18513: { char *cp,*parm,hline[HL_MAX];
! 18514: int status,nrd;
! 18515: if((status=RLE_fgets(hline,HL_MAX,fd))<=0) return(status);
! 18516: while(strlen(hline)>1) {
! 18517: if(RLE_dbg) err("hline \"%s\"",hline);
! 18518: parm=strtok(hline,HTERM);
! 18519: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
! 18520: if((parm=strtok(0,HTERM))!=NULL
! 18521: &&strcmp(parm,"rle")==0) ;
! 18522: else return(-1);
! 18523: }
! 18524: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
! 18525: /* assume half-open WINDOW: l&t closed, r&b open */
! 18526: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.x=atoi(parm);
! 18527: else return(-1);
! 18528: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.y=atoi(parm);
! 18529: else return(-1);
! 18530: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.x=atoi(parm)-1;
! 18531: else return(-1);
! 18532: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.y=atoi(parm)-1;
! 18533: else return(-1);
! 18534: }
! 18535: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
! 18536: if((parm=strtok(0,HTERM))!=NULL) hp->res_x=atoi(parm);
! 18537: else return(-1);
! 18538: if((parm=strtok(0,HTERM))!=NULL) hp->res_y=atoi(parm);
! 18539: else return(-1);
! 18540: }
! 18541: else return(-1);
! 18542: if((status=RLE_fgets(hline,HL_MAX,fd))<=0) return(status);
! 18543: };
! 18544: /* maximum possible no. bytes in a packed rle line */
! 18545: _RLE.bpl = hp->bpl = hp->bx.b.x-hp->bx.a.x+9;
! 18546: if(dbg_rd) fprintf(stderr,"rlelib: RLE_get_hdr: %s\n",RIC_hdr_toa(hp));
! 18547: return(1);
! 18548: }
! 18549:
! 18550: /* read the next run into *Rp, and return line number
! 18551: (-1 for EOF, abort on error) */
! 18552: int RLE_get_Run( Rp )
! 18553: RLE_Run *Rp;
! 18554: { if(_RLE.nrun >= _RLE.runs) { /* no more, try to read next line */
! 18555: if (!RLE_rdbf()) /* EOF */ return(-1);
! 18556: };
! 18557: /* another run */
! 18558: Rp->xs = (_RLE.cx += RLE_gshort(&_RLE.cp));
! 18559: Rp->xe = (_RLE.cx += RLE_gshort(&_RLE.cp)) - 1;
! 18560: _RLE.nrun++;
! 18561: return(_RLE.cy);
! 18562: }
! 18563:
! 18564: /* Return ptr to the next line with at least one run overlapping the margins
! 18565: [lm,rm]. The reported runs are not trimmed to fit exactly within margins.
! 18566: If no more lines, return NULL. On error, abort */
! 18567: RLE_Line *RLE_get_Line(lm,rm)
! 18568: int lm, rm; /* left, right margins */
! 18569: { register int rr; /* runs read */
! 18570: register RLE_Run *rp; /* write ptr */
! 18571:
! 18572: do { if(_RLE.eof) {
! 18573: free(_RLE.lp); _RLE.lp = NULL;
! 18574: free(_RLE.bf); _RLE.bf = NULL;
! 18575: return(NULL);
! 18576: };
! 18577: if(_RLE.lp==NULL) { /* allocate space for RLE_Line */
! 18578: _RLE.lp = (RLE_Line *) malloc(sizeof(RLE_Line));
! 18579: if(_RLE.lp==NULL) {
! 18580: abort("rlelib: can't malloc RLE_Line (%d bytes)",
! 18581: sizeof(RLE_Line));
! 18582: };
! 18583: };
! 18584: _RLE.lp->y = _RLE.cy;
! 18585: /* guaranteed to be at least one run in line */
! 18586: rr=0; rp=_RLE.lp->r; _RLE.lp->runs=0;
! 18587: /* skip runs that are outside left margin */
! 18588: do RLE_get_Run(rp);
! 18589: while((rr++ < _RLE.runs) && (rp->xe < lm));
! 18590: /* accept runs until cross right margin */
! 18591: while(rp->xs <= rm) {
! 18592: _RLE.lp->runs++; /* count accepted runs */
! 18593: if(rr++ >= _RLE.runs) break;
! 18594: RLE_get_Run(++rp);
! 18595: };
! 18596: /* look ahead to next line */
! 18597: if (!RLE_rdbf()) /* EOF */ _RLE.eof=T;
! 18598: }
! 18599: while(_RLE.lp->runs==0); /* as result of margins, some lines may empty */
! 18600: return(_RLE.lp);
! 18601: }
! 18602:
! 18603: /* read next line buffer - return F if EOF, abort on error
! 18604: sideffects: sets up _RLE.cp, _RLE.cy, _RLE.cx, _RLE.runs, _RLE.nrun */
! 18605: boolean RLE_rdbf()
! 18606: { short nh;
! 18607: if(dbg_rd) err("enter RLE_rdbf");
! 18608: /* get number of bytes holding RLE of a scan line */
! 18609: if( read(_RLE.fd,&nh,sizeof(short)) != sizeof(short)) {
! 18610: return(F); /* normal EOF */
! 18611: };
! 18612: if( Readvax )
! 18613: nh = swapshortin( nh );
! 18614: if(dbg_rd) err("rlelib: RLE_rdbf: nh %d",nh);
! 18615: if(nh > _RLE.bpl) {
! 18616: abort("rlelib: too many bytes in line: %d > %d(_RLE.bpl)",
! 18617: nh,_RLE.bpl);
! 18618: };
! 18619:
! 18620: /* get those bytes */
! 18621: if( read(_RLE.fd,_RLE.bf,nh) != nh) {
! 18622: abort("rlelib: rle line truncated");
! 18623: };
! 18624: if(dbg_rd) {
! 18625: int bi;
! 18626: err("rlelib: RLE_rdbf: _RLE.bf[0-%d] octal:",nh-1);
! 18627: for(bi=0;bi<nh;bi++)
! 18628: fprintf(stderr," 0%o",0377&(_RLE.bf[bi]));
! 18629: fprintf(stderr,"\n");
! 18630: };
! 18631:
! 18632: /* decode the bytes */
! 18633: _RLE.cp = _RLE.bf;
! 18634: _RLE.runs = RLE_gshort(&_RLE.cp);
! 18635: if(dbg_rd) err("rlelib: _RLE.runs %d",_RLE.runs);
! 18636: if(_RLE.runs==0) { /* blank lines seen */
! 18637: _RLE.cy += RLE_gshort(&_RLE.cp);
! 18638: _RLE.runs = RLE_gshort(&_RLE.cp);
! 18639: if(dbg_rd)
! 18640: err("rlelib: _RLE.cy %d _RLE.runs %d",_RLE.cy,_RLE.runs);
! 18641: };
! 18642: if(_RLE.runs>RLE_RUNS || _RLE.runs<1) {
! 18643: abort("rlelib: illegal no. runs %d in line",_RLE.runs);
! 18644: };
! 18645: _RLE.cy++;
! 18646: if(dbg_rd) err("rlelib: RLE_rdbf: _RLE.runs %d _RLE.cy %d",_RLE.runs,_RLE.cy);
! 18647: _RLE.cx = _RLE.nrun = 0; /* next run will be first */
! 18648: if(dbg_rd) err("rlelib: RLE_rdbf: T exit");
! 18649: return(T);
! 18650: }
! 18651:
! 18652: /* brrl - compute a binary raster line from a run-length-encoded scanline.
! 18653: runa[] is an array of shorts, grouped in pairs (xs,xe) to describe the starting
! 18654: and ending index (inclusive) of each run of black pixels (1 bits).
! 18655: xe >= xs > xe. The runs are in strictly ascending order on xs.
! 18656: lm & rm are the left and right margin indices of pixels, outside of which the
! 18657: pixels are forced to be white. rm >= lm. The `lm'th pixel is written
! 18658: into the `olm'th bit of the output raster (olm>=0).
! 18659: rasp[] is a raser line of chars; on entry, it is assumed to have been zeroed
! 18660: out. rasp[0] holds the leftmost byte in the line and the 001 bit of each
! 18661: byte is the leftmost bit in that byte.
! 18662: The user must ensure that rasp[] is at least (rm-lm+olm+9)/8 bytes long.
! 18663: Returns the number of black pixels in the raster line.
! 18664: NOTE: this uses the ``little-endian'' convention, in which the leftmost pixel
! 18665: in a byte is placed in the least-significant bit (0x01). See `brrlb()' below
! 18666: for the alternative ``big-endian'' version.
! 18667: */
! 18668: int brrl(runs,runa,lm,rm,olm,rasp)
! 18669: int runs; /* number of run-segments in runa[] */
! 18670: short runa[]; /* array of run-segments [xs,xe] (pairs of short) */
! 18671: int lm,rm; /* left,right margin bit indices within raster */
! 18672: int olm; /* `lm'th input pixel will be written to `olm'th bit */
! 18673: char unsigned rasp[]; /* binary raster line (zeroed out on entry) */
! 18674: { int pixels,bi;
! 18675: RLE_Run r,*rp,*re;
! 18676: pixels = 0;
! 18677: re = (rp = (RLE_Run *) runa) + runs;
! 18678: while(rp<re && rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
! 18679: while(rp<re && rp->xs<=rm) {
! 18680: /* truncate to margins */
! 18681: if((r.xs = rp->xs)<lm) r.xs = lm;
! 18682: if((r.xe = rp->xe)>rm) r.xe = rm;
! 18683: /* shift to output indices */
! 18684: r.xs += olm-lm; r.xe += olm-lm;
! 18685: /** SLOW **/
! 18686: for(bi=r.xs; bi<=r.xe; bi++) rasp[bi/8] |= (01)<<(bi%8);
! 18687: pixels += r.xe-r.xs+1;
! 18688: rp++;
! 18689: };
! 18690: return(pixels);
! 18691: }
! 18692:
! 18693: /* ``big-endian'' version of brrl: bits are packed so that the leftmost
! 18694: pixel is placed in the high-order bit (0x80) of each byte.
! 18695: */
! 18696: int brrlb(runs,runa,lm,rm,olm,rasp)
! 18697: int runs;
! 18698: short runa[];
! 18699: int lm,rm,olm;
! 18700: char unsigned rasp[];
! 18701: { int pixels,bi;
! 18702: RLE_Run r,*rp,*re;
! 18703: pixels = 0;
! 18704: re = (rp = (RLE_Run *) runa) + runs;
! 18705: while(rp<re && rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
! 18706: while(rp<re && rp->xs<=rm) {
! 18707: /* truncate to margins */
! 18708: if((r.xs = rp->xs)<lm) r.xs = lm;
! 18709: if((r.xe = rp->xe)>rm) r.xe = rm;
! 18710: /* shift to output indices */
! 18711: r.xs += olm-lm; r.xe += olm-lm;
! 18712: /** SLOW **/
! 18713: for(bi=r.xs; bi<=r.xe; bi++) rasp[bi/8] |= (0200)>>(bi%8);
! 18714: pixels += r.xe-r.xs+1;
! 18715: rp++;
! 18716: };
! 18717: return(pixels);
! 18718: }
! 18719:
! 18720: /* crrl - compute a character raster line from a run-length-encoded scanline.
! 18721: runa[] is an array of shorts, grouped in pairs (xs,xe) to describe the starting
! 18722: and ending index (inclusive) of each run of black pixels (1 bits): xs<=xe.
! 18723: The runs are in strictly ascending order on xs. lm & rm are the left and
! 18724: right margin indices, outside of which pixels are forced to be white. rm >= lm.
! 18725: rasp[] is a raster line, one unsigned char per pixel; rasp[0] holds the
! 18726: leftmost pixel. The user must ensure that rasp[] is at least (rm-lm+1)
! 18727: bytes long. Black pixels are encoded as 0, white as 255. Returns the number
! 18728: of black pixels in the raster line.
! 18729: */
! 18730: #define WHITE_pel 0377
! 18731: #define BLACK_pel 0000
! 18732: int crrl(runs,runa,lm,rm,rasp)
! 18733: int runs; /* number of run-segments in runa[] */
! 18734: short runa[]; /* array of run-segments [xs,xe] (pairs of short) */
! 18735: int lm,rm; /* left,right margin bit indices within raster */
! 18736: unsigned char rasp[]; /* char raster line */
! 18737: { int pixels,bi,wid;
! 18738: RLE_Run r,*rp,*re;
! 18739: unsigned char *cp,*ep;
! 18740: wid=rm-lm+1;
! 18741: memset(rasp,WHITE_pel,wid);
! 18742: re = (rp = (RLE_Run *) runa) + runs;
! 18743: while(rp<re&&rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
! 18744: if(rp>=re) return(0);
! 18745:
! 18746: r = *rp; r.xs -= lm; r.xe -= lm;
! 18747: pixels = 0;
! 18748: do { /* truncate left,right margin */
! 18749: if(r.xs<0) r.xs = 0;
! 18750: if(r.xe>(wid-1)) r.xe = wid-1;
! 18751: /* write r into raster line */
! 18752: pixels += (r.xe-r.xs+1);
! 18753: for(cp=rasp+r.xs,ep=rasp+r.xe; cp<=ep; cp++) *cp = BLACK_pel;
! 18754: /* step to next run */
! 18755: r = *(++rp); r.xs -= lm; r.xe -= lm;
! 18756: }
! 18757: while(r.xs<=(wid-1)&&rp<re);
! 18758: return(pixels);
! 18759: }
! 18760:
! 18761: /* trcr - threshold & run-length-encode a char raster line. `rasp' is a raster
! 18762: line, one unsigned char per pixel: rasp[0] is the leftmost pixel in the line.
! 18763: Pixels with value < 'thresh' are translated to black, else white.
! 18764: Analyzes the line into a series of runs of `1's, placing them into array
! 18765: `runs'. Observes margins: starts at `lm' bit and continues through `rm';
! 18766: bits outside the margins are assumed 0. A `run' is two shorts (the starting &
! 18767: ending indices of the run of `1's, inclusive). The indices are shifted
! 18768: so that the `lm'th pixel goes to run index `olm'. Returns the number of runs.
! 18769: NOTE: The user must ensure that: (1) margins fall within `rasp[]';
! 18770: (2) `runp[]' is big enough to hold the worst-case no. of runs that can result
! 18771: ((rm-lm+2)/2). The contents of the raster-line are unmodified.
! 18772: */
! 18773: int trcr(rasp,lm,rm,olm,thresh,runp)
! 18774: char unsigned rasp[]; /* binary raster line (with 1 extra byte at end) */
! 18775: int lm,rm; /* left,right margin indices within raster */
! 18776: int olm; /* `lm' pixel goes to `olm' run index */
! 18777: int thresh;
! 18778: short runp[]; /* array of run-segments [xs,xe] (pairs of short) */
! 18779: #define dbg_trcr (T)
! 18780: { unsigned char *cp,*ep;
! 18781: short x,*xp;
! 18782: int cv,pv; /* current,prior binary pixel value */
! 18783: ep=(cp=rasp+lm)+rm; x=olm; xp=runp;
! 18784: pv=0; /* assume pixels left of 'lm' are 0 */
! 18785: while (cp<=ep) {
! 18786: if((*cp)<thresh) {
! 18787: /* black pixel */
! 18788: cv=1;
! 18789: if(pv==0) { *xp = x; xp++; };
! 18790: }
! 18791: else { /* white pixel */
! 18792: cv=0;
! 18793: if(pv==1) { *xp = x-1; xp++; };
! 18794: };
! 18795: pv=cv; x++;
! 18796: cp++;
! 18797: };
! 18798: if(pv==1) { *xp = x-1; xp++; }; /* assume pixels right of 'rm' is 0 */
! 18799: return((xp-runp)/2);
! 18800: }
! 18801:
! 18802: /* Transform a sequence of rle-lines using trimming, offsetting, scaling,
! 18803: truncation, and reverse-video. Scaling may lead to interpolation or
! 18804: decimation of lines, so an input line may be mapped into 0, 1, or more
! 18805: output lines.
! 18806: Input lines may be buffered, and there may be latency. To flush buffers,
! 18807: this must be called with NULL argument at end of the sequence. Each output
! 18808: line will be passed to function `sink()', which returns 1 if OK and 0 to quit. Quits are passed back immediately with no latency. Sink's 1st arg RLE_Line
! 18809: *l is a line of runs in output coordinates, whose `len' is the maximum length
! 18810: of the line. l==NULL means end of sequence.
! 18811: Return 1 if OK, 0 to quit. A copy of *l is passed to sink().
! 18812: a->sy is incremented for every line written to the sink, and is attached to
! 18813: the output lines as *.y.
! 18814: */
! 18815: int transform_rlel(l,a,sink,sa)
! 18816: RLE_Line *l; /* NULL if end of sequence */
! 18817: Transform_rlel_arg *a;
! 18818: int (*sink)(); /* takes args: (RLE_Line *), and int */
! 18819: VOID *sa; /* passed to sink() as 2nd arg */
! 18820: { RLE_Line m,r;
! 18821: register RLE_Run *rp,*ep,*mp;
! 18822: RLE_Run mr,mm,rr;
! 18823: int rm;
! 18824: int o_a_x,o_b_x; /* maximum output index */
! 18825: if(l==NULL) {
! 18826: sink(NULL,sa);
! 18827: return(1);
! 18828: };
! 18829: m.len = l->len;
! 18830: m.runs = l->runs;
! 18831: if(a->ident) {
! 18832: if(m.runs>0) memcpy(m.r,l->r,2*m.runs*sizeof(short));
! 18833: m.y = a->sy;
! 18834: if(sink(&m,sa)==0) return(0);
! 18835: else { a->sy++;
! 18836: return(1);
! 18837: };
! 18838: };
! 18839: /* maximum permissable output bounds */
! 18840: o_a_x = (int)((a->tr.a.x + a->off.x)*a->scl.x);
! 18841: o_b_x = o_a_x + a->wh.x - 1;
! 18842: if(a->sy<=((int)a->dy)) {
! 18843: /* compute runs to be ouput: rp - input runs; mp - output runs*/
! 18844: mp=(m.r - 1);
! 18845: for(ep=(rp=l->r)+l->runs; rp<ep; rp++) {
! 18846: /* trim using a->tr */
! 18847: mr = *rp;
! 18848: if(mr.xe < a->tr.a.x) /* off left margin */ continue;
! 18849: if(mr.xs > a->tr.b.x) /* off right margin */ break;
! 18850: if(mr.xs < a->tr.a.x) /* extends left too far */
! 18851: mr.xs=a->tr.a.x;
! 18852: if(mr.xe > a->tr.b.x) /* extends right too far */
! 18853: mr.xe=a->tr.b.x;
! 18854:
! 18855: /* offset using a->off */
! 18856: mr.xs += a->off.x;
! 18857: mr.xe += a->off.x;
! 18858:
! 18859: /* expand using a->scl */
! 18860: mr.xs = (int)(mr.xs*a->scl.x);
! 18861: mr.xe = ((int)((mr.xe+1)*a->scl.x))-1;
! 18862: if(mr.xe<mr.xs) mr.xe=mr.xs;
! 18863:
! 18864: /* truncate to maximum output width */
! 18865: if(mr.xe<o_a_x) /* off left margin */ continue;
! 18866: if(mr.xs>o_b_x) /* off right margin */ break;
! 18867: if(mr.xs<o_a_x) /* extends left too far */ mr.xs=o_a_x;
! 18868: if(mr.xe>o_b_x) /* extends right too far */ mr.xe=o_b_x;
! 18869: /* store */
! 18870: if(mp < m.r) /* first */ *(++mp) = mr;
! 18871: else /* can merge with prior run? */ {
! 18872: if(mp->xe >= (mr.xs-1)) /* yes */ mp->xe = mr.xe;
! 18873: else /* no */ *(++mp) = mr;
! 18874: };
! 18875: };
! 18876: m.runs = mp - m.r + 1;
! 18877: m.len = a->wh.x;
! 18878: do { m.y = a->sy;
! 18879: if(a->rev) {
! 18880: /* r = reverse-video(m) */
! 18881: rp=r.r; rr.xs=o_a_x;
! 18882: for(ep=(mp=m.r)+m.runs; mp<ep; mp++) {
! 18883: if(rr.xs<mp->xs) {
! 18884: rr.xe=mp->xs-1;
! 18885: *(rp++)=rr;
! 18886: };
! 18887: rr.xs=mp->xe+1;
! 18888: };
! 18889: if(rr.xs<=o_b_x) {
! 18890: rr.xe=o_b_x;
! 18891: *(rp++)=rr;
! 18892: };
! 18893: r.runs = rp-r.r;
! 18894: r.len = m.len;
! 18895: r.y = m.y;
! 18896: if(sink(&r,sa)==0) return(0);
! 18897: }
! 18898: else { if(sink(&m,sa)==0) return(0); };
! 18899: a->sy++;
! 18900: }
! 18901: while(a->sy<=((int)a->dy));
! 18902: };
! 18903: a->dy += a->scl.y;
! 18904: return(1);
! 18905: }
! 18906:
! 18907: /* Insert a (copy of) the given RLE_Line in the RLE_Lines */
! 18908: insert_rlel(rlp,rlsp)
! 18909: RLE_Line *rlp;
! 18910: RLE_Lines *rlsp;
! 18911: { abort("insert_rlel: unimplemented");
! 18912: }
! 18913:
! 18914: err_RLE_line(s,rl)
! 18915: char *s; /* name */
! 18916: RLE_Line *rl;
! 18917: { RLE_Run *r;
! 18918: int ri;
! 18919: if(rl==NULL) fprintf(stderr,"RLEL %10s NULL\n",s);
! 18920: else { fprintf(stderr,"RLEL %10s y%d r%d l%d: ",
! 18921: s,rl->y,rl->runs,rl->len);
! 18922: for(ri=0,r=rl->r;ri<rl->runs;ri++,r++)
! 18923: fprintf(stderr,"[%d,%d] ",r->xs,r->xe);
! 18924: fprintf(stderr,"\n");
! 18925: };
! 18926: }
! 18927:
! 18928: 0707070035351135271006640007620000050000010264220476773367400001100000047346stdocr.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 18929: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 18930: /* The copyright notice does not imply actual or intended publication. */
! 18931: /* AUTHORS: */
! 18932: /* H. S. Baird - ATT-BL MH - first versions */
! 18933: /* stdocr.h -- conventional OCGR constants, typedefs, and file formats
! 18934: NOTE: sensitive to prior:
! 18935: `#define MAIN 1'
! 18936: `#define CPU ?'
! 18937: `#define OS ?' */
! 18938:
! 18939: extern int errno; /* UNIX system call error number */
! 18940:
! 18941: #ifndef MAIN
! 18942: #define MAIN 0
! 18943: #endif
! 18944:
! 18945: #define FWRI (T) /* use machine-independent format for dim-file writes */
! 18946: #define FRDI (T) /* use machine-independent format for dim-file reads */
! 18947:
! 18948: #ifndef PI
! 18949: #define PI 3.1415926535
! 18950: #endif
! 18951:
! 18952: extern int Readvax; /* T. Thompson flag: see Coord.c */
! 18953:
! 18954: #include "limits.h" /* machine-dependent numeric extreme values */
! 18955: #include "fioi.h" /* machine-independent types and binary I/O */
! 18956: #include "boole.h" /* boolean type */
! 18957: #include "Units.h" /* OCR-specific units */
! 18958: #include "Coord.h" /* scanner coordinates & basic geometry */
! 18959: #include "ric.h" /* ricoh scanner page & file formats */
! 18960:
! 18961: /* 5620 dimensions, in dots */
! 18962: #define Width5620 800
! 18963: #define Height5620 1024
! 18964:
! 18965: /* used (in clc.c) to compute absolute maximum value of natural
! 18966: log values used in Bayesian binary weights */
! 18967: #define LOG_ABS_MAX 3.0
! 18968:
! 18969: #define Merit float /* heuristic ``merit'' takes on values in [0,1] */
! 18970: /* machine-independent I/O: range [0.0-1.0], precision .0000153 */
! 18971: #define fwri_Merit(F,V) fwri_uint2((F),((V)*USHRT_MAX))
! 18972: #define frdi_Merit(F) (frdi_uint2(F)/(Merit)USHRT_MAX)
! 18973:
! 18974: #define Prob float /* ``probability'' takes on values in [0,1] */
! 18975: /* machine-independent I/O: range [0.0-1.0], precision .0000153 */
! 18976: #define fwri_Prob(F,V) fwri_uint2((F),((V)*USHRT_MAX))
! 18977: #define frdi_Prob(F) (frdi_uint2(F)/(Prob)USHRT_MAX)
! 18978:
! 18979: #define Pts float /* text-size units: ``points'' (1/72) inch */
! 18980: /* machine-independent I/O: range [0,655.36], precision 0.01 ([0,9.1] inches) */
! 18981: #define fwri_Pts(F,V) fwri_uint2((F),((V)*100.0))
! 18982: #define frdi_Pts(F) (frdi_uint2(F)/100.0)
! 18983:
! 18984: #define Ems float /* em-space units */
! 18985: /* machine-independent I/O: range [-32.768,32.767], precision 0.001 */
! 18986: #define fwri_Ems(F,V) fwri_int2((F),((V)*1000.0))
! 18987: #define frdi_Ems(F) (frdi_int2(F)/1000.0)
! 18988:
! 18989: /* class name - long enough to be a unix file name */
! 18990: #define Cln_len (14) /* maximum no. chars (DIRSIZ in some UNIX's) */
! 18991: #define Cln_lenp (Cln_len+1) /* maximum size of array */
! 18992: typedef char Cln[Cln_lenp];
! 18993: #define fwri_Cln(F,S) fwri_str((F),(S))
! 18994: #define frdi_Cln(F,S) frdi_strn((F),(S),Cln_lenp)
! 18995:
! 18996: /* font name */
! 18997: #define Fontn_len (Cln_len) /* maximum no. chars */
! 18998: #define Fontn_lenp (Cln_lenp) /* maximum size of array */
! 18999: typedef char Fontn[Fontn_lenp];
! 19000: #define fwri_Fontn(F,S) fwri_str((F),(S))
! 19001: #define frdi_Fontn(F,S) frdi_strn((F),(S),Fontn_lenp)
! 19002:
! 19003: typedef struct ClassId {
! 19004: Fontn f; /* font name */
! 19005: Pts s; /* size in points */
! 19006: Cln c; /* printable symbol name (``class-name'') */
! 19007: short v; /* symbol variant no. 0,1,... */
! 19008: } ClassId;
! 19009:
! 19010: #define Init_ClassId {"",0.0,"",0}
! 19011: #if MAIN
! 19012: ClassId empty_ClassId = Init_ClassId;
! 19013: #else
! 19014: extern ClassId empty_ClassId;
! 19015: #endif
! 19016: char *classid_toa(); /* in chcln.c */
! 19017: #define eq_classid(a,b) ((!strcmp((a).f,(b).f))&&((a).s==(b).s)&&(!strcmp((a).c,(b).c))&&((a).v==(b).v))
! 19018:
! 19019: #define fwri_ClassId(F,P) { \
! 19020: fwri_Fontn((F),(P)->f); \
! 19021: fwri_Pts((F),(P)->s); \
! 19022: fwri_Cln((F),(P)->c); \
! 19023: fwri_uint1((F),(P)->v); \
! 19024: }
! 19025: #define frdi_ClassId(F,P) ( feof(F)? 0: ( \
! 19026: frdi_Fontn((F),(P)->f), \
! 19027: (P)->s=frdi_Pts(F), \
! 19028: frdi_Cln((F),(P)->c), \
! 19029: (P)->v=frdi_uint1(F), \
! 19030: (ferror(F)? -errno: 1) ) )
! 19031:
! 19032: /* Convert variant no. to ASCII character, and vice versa */
! 19033: #define vtoc(V) (((V)<=9)?('0'+(V)):(((V)<=35)?('a'+((V)-10)):('A'+((V)-36))))
! 19034: #define ctov(C) ((((C)>='0')&&((C)<='9'))?((C)-'0'):((((C)>='a')&&((C)<='z'))?(10+((C)-'a')):(36+((C)-'A'))))
! 19035:
! 19036: /* parametric values: */
! 19037: #define Pval float
! 19038: /* machine-independent I/O: precision 0.0001 & range [-838.8608,838.8607] */
! 19039: #define fwri_Pval(F,V) fwri_int4((F),(V)*1000.0)
! 19040: #define frdi_Pval(F) (frdi_int4(F)/1000.0)
! 19041:
! 19042: typedef struct { /* parametric point */
! 19043: Pval x;
! 19044: Pval y;
! 19045: } Pp;
! 19046:
! 19047: #define Init_Zero_Pp {0.0,0.0}
! 19048: #if MAIN
! 19049: Pp zero_Pp = Init_Zero_Pp;
! 19050: #else
! 19051: extern Pp zero_Pp;
! 19052: #endif
! 19053:
! 19054: #define fwri_Pp(F,P) { fwri_Pval((F),(P)->x); fwri_Pval((F),(P)->y); }
! 19055: #define frdi_Pp(F,P) ( feof(F)? 0: ( \
! 19056: (P)->x=frdi_Pval(F), \
! 19057: (P)->y=frdi_Pval(F), \
! 19058: (ferror(F)? -errno: 1) ) )
! 19059:
! 19060: /* metrics: ABSS, EUCL, MAXV */
! 19061: #define ABSS 'a'
! 19062: #define EUCL 'e'
! 19063: #define MAXV 'm'
! 19064: typedef short Metric;
! 19065:
! 19066: #define fwri_Metric(F,V) fwri_ch((F),(V))
! 19067: #define frdi_Metric(F) (frdi_ch(F))
! 19068:
! 19069: /* a vectorized blob file is a sequence of blob-descriptions.
! 19070: a blob-description is a sequence of "vector" records; there are two
! 19071: types of blob descriptions:
! 19072: DOT:
! 19073: 'D'-vector (with bounding box)
! 19074: CHAR:
! 19075: 'C'-vector, followed by:
! 19076: one 'B'-vector (bounding-box), and
! 19077: any number of: 'S' (stroke),
! 19078: 'G' (edge),
! 19079: 'O' (hole),
! 19080: 'A' (arc),
! 19081: 'C' (corner),
! 19082: 'P' (end-point), and
! 19083: 'V' & 'W' (boundary angles - 1 each),
! 19084: and terminated with one 'E' vector (giving classname)
! 19085: */
! 19086:
! 19087: #define Vrec_len 5
! 19088: typedef short Vrec[Vrec_len];
! 19089:
! 19090: /* subshape values */
! 19091: /* #define U 0 uninitialized */
! 19092: #define NA (SHRT_MAX) /* deliberately not-assigned (classifier failure) */
! 19093:
! 19094: #define Dim short /* specifies dimension 1,..,MaxDim */
! 19095: #define MaxDim 4
! 19096:
! 19097: #define fwri_Dim(F,V) fwri_uint1((F),(V))
! 19098: #define frdi_Dim(F) (frdi_uint1(F))
! 19099:
! 19100: #define Seq int /* sequence nos; indices into tables */
! 19101: #define FISeq 0 /* first value */
! 19102: #define NLSeq -1 /* conventional NULL value */
! 19103: #define S1Seq 0200000000 /* special bit 1 of Seq */
! 19104: #define S2Seq 0100000000 /* special bit 2 of Seq */
! 19105: #define NSSeq 0077777777 /* non-special bits */
! 19106:
! 19107: #define fwri_Seq(F,V) fwri_int4((F),(V))
! 19108: #define frdi_Seq(F) (frdi_int4(F))
! 19109:
! 19110: typedef short Liv; /* limit value: scaled and truncated from floating-pt */
! 19111: #define Liv_MAX (SHRT_MAX)
! 19112: #define Liv_MIN (SHRT_MIN)
! 19113:
! 19114: #define fwri_Liv(F,V) fwri_int2((F),(V))
! 19115: #define frdi_Liv(F) (frdi_int2(F))
! 19116:
! 19117: typedef short Lit; /* limit type, two flavors: */
! 19118: #define MN 0 /* min: MN < v */
! 19119: #define MX 1 /* max: v <= MX */
! 19120:
! 19121: typedef Liv Ivl[2]; /* interval: ( Ivl[MN], Ivl[MX] ] */
! 19122:
! 19123: typedef Ivl Rec[MaxDim]; /* rectangular parallelopiped of limits in DIM-space */
! 19124:
! 19125: /* a normalized blob file is a sequence of:
! 19126: Nb_h header, followed by Nb_h.ss of:
! 19127: Nb_s contour shapes */
! 19128: typedef struct {
! 19129: ClassId ci; /* class name */
! 19130: Bbx bb; /* bounding box */
! 19131: Pval rsz; /* raw character size (Ems) */
! 19132: Pval bht; /* height-above-baseline (Ems) */
! 19133: Pval rwd; /* width (Ems) */
! 19134: Pval rar; /* area (square-Ems) */
! 19135: Pval rpe; /* perimiter (Ems) */
! 19136: Pval asp; /* aspect ratio (h/w) */
! 19137: Pval blk; /* fraction of Bbx area that is black */
! 19138: Pval per; /* perimeter of blob as multiple of Bbx perim */
! 19139: Pval gale; /* Gale's feature: incl. angle 'tween 2 longest sides */
! 19140: short ss; /* no. of shapes to follow */
! 19141: } Nb_h;
! 19142:
! 19143: #define MAX_SHAPES_EACH 1024 /* Max no. shapes per Blob/Char/item */
! 19144:
! 19145: /* Shape is tiny (below threshold, may be pruned): a flag ORed into shape type */
! 19146: #define Sh_tiny (0x80)
! 19147:
! 19148: /* Shape types: */
! 19149: #define U 0 /* uninitialized */
! 19150: #define Sh_FI 1 /* first shape no. */
! 19151: #define Sh_B 1 /* blob (connected black region) */
! 19152: #define Sh_H 2 /* hole (connected white region) */
! 19153: #define Sh_S 3 /* stroke (undirected line-segment) */
! 19154: #define Sh_E 4 /* edge (directed line-segment along boundary) */
! 19155: #define Sh_C 5 /* concavity (intrusion from convex hull): its `cover' edge */
! 19156: #define Sh_D 6 /* direction and depth of concavity */
! 19157: #define Sh_A 7 /* locally-maximal convex arc (encloses black) */
! 19158: #define Sh_V 8 /* locally-maximal concave arc (encloses white) */
! 19159: #define Sh_P 9 /* endpoint (0-junction) */
! 19160: #define Sh_T 10 /* detail (left- and right-facing ticks) */
! 19161: #define Sh_X 11 /* crossing (X) */
! 19162: #define Sh_Y 12 /* global scalar variables, combined */
! 19163: #define Sh_Z 13 /* more global scalar variables, combined */
! 19164: #define Sh_LA 13 /* last of variable-no-of-occurences shape-types */
! 19165: #define Sh_MNY (Sh_LA+1)
! 19166: #define SHS_MNY (Sh_MNY)
! 19167:
! 19168: #if (MAIN)
! 19169: /* shape-names, given shape-type */
! 19170: char Sh_nam[SHS_MNY] =
! 19171: {'U', 'B', 'H', 'S', 'E', 'C', 'D', 'A', 'V', 'P', 'T', 'X', 'Y', 'Z'};
! 19172: /* "dimension" -- no parameters in normalized form */
! 19173: short Sh_dim[SHS_MNY] =
! 19174: { 0, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 3, 1};
! 19175: /* absolute minimum parametric values possible -- must be >= -1.0
! 19176: (see norm.c & fiodict.c) */
! 19177: Pval Sh_MN[SHS_MNY][MaxDim]
! 19178: = { { 0.0, 0.0, 0.0, 0.0}, /* U */
! 19179: {-0.5, -0.5, -0.5/*see mkd*/}, /* B */
! 19180: {-0.5, -0.5, -0.5/*see mkd*/}, /* H */
! 19181: {-0.5, -0.5, -0.5, -0.5}, /* S */
! 19182: {-0.5, -0.5, -0.5, -0.5}, /* E */
! 19183: {-0.5, -0.5, -0.5, -0.5}, /* C */
! 19184: {-0.5, -0.5, -0.5, -0.5}, /* D */
! 19185: {-0.5, -0.5, -0.5, -0.5}, /* A */
! 19186: {-0.5, -0.5, -0.5, -0.5}, /* V */
! 19187: {-0.5, -0.5, -0.5, -0.5}, /* P */
! 19188: {-0.5, -0.5, -0.5}, /* T */
! 19189: {-0.5, -0.5}, /* X */
! 19190: {-0.5, -0.5, -0.5}, /* Y */
! 19191: {-0.5} /* Z */
! 19192: };
! 19193: /* absolute maximum parametric value possible -- must be <= 1.0
! 19194: (see norm.c & fiodict.c) */
! 19195: Pval Sh_MX[SHS_MNY][MaxDim]
! 19196: = { { 0.0, 0.0, 0.0, 0.0}, /* U */
! 19197: {0.5, 0.5, 1.0/*see mkd*/}, /* B */
! 19198: {0.5, 0.5, 1.0/*see mkd*/}, /* H */
! 19199: {0.5, 0.5, 0.5, 0.5}, /* S */
! 19200: {0.5, 0.5, 0.5, 0.5}, /* E */
! 19201: {0.5, 0.5, 0.5, 0.5}, /* C */
! 19202: {0.5, 0.5, 0.5, 0.5}, /* D */
! 19203: {0.5, 0.5, 0.5, 0.5}, /* A */
! 19204: {0.5, 0.5, 0.5, 0.5}, /* V */
! 19205: {0.5, 0.5, 0.5, 0.5}, /* P */
! 19206: {0.5, 0.5, 0.5}, /* T */
! 19207: {0.5, 0.5}, /* X */
! 19208: {0.5, 0.5, 0.5}, /* Y */
! 19209: {0.5} /* Z */
! 19210: };
! 19211: /* minimum magnitude of (r,i) part of certain shapes */
! 19212: Pval A_ri_minmag = 0.25;
! 19213: Pval P_ri_minmag = 0.25;
! 19214: #else
! 19215: extern char Sh_nam[];
! 19216: extern short Sh_dim[];
! 19217: extern Pval Sh_MN[][MaxDim];
! 19218: extern Pval Sh_MX[][MaxDim];
! 19219: extern Pval A_ri_minmag;
! 19220: extern Pval P_ri_minmag;
! 19221: #endif
! 19222:
! 19223: #define MIN_SD 0.001 /* minimum std-dev permitted */
! 19224:
! 19225: typedef Pval Spar[MaxDim]; /* shape parameters */
! 19226:
! 19227: typedef struct Nb_s {
! 19228: short t; /* shape type: one of U S O A C etc, perhaps |Sh_tiny */
! 19229: Spar p; /* parametric values */
! 19230: } Nb_s;
! 19231:
! 19232: /* indices into parametric values */
! 19233: /* blobs */
! 19234: #define B_x 0 /* (x,y) location of dot wrt bounding-box */
! 19235: #define B_y 1
! 19236: #define B_r 2 /* size of dot */
! 19237: /* holes */
! 19238: #define H_x 0 /* (x,y) location of center wrt bounding-box */
! 19239: #define H_y 1
! 19240: #define H_r 2 /* size of hole */
! 19241: /* strokes */
! 19242: #define S_x 0 /* (x,y) location of stroke center wrt bounding box */
! 19243: #define S_y 1
! 19244: #define S_r 2 /* (r,i) real-imag parts of rotation-length vector; */
! 19245: #define S_i 3 /* rotation angle *2 since strokes have only [0,PI] range */
! 19246: /* edges */
! 19247: #define E_x 0 /* (x,y) location of edge center wrt bounding box */
! 19248: #define E_y 1
! 19249: #define E_r 2 /* (r,i) real-imag parts of direction-length vector */
! 19250: #define E_i 3
! 19251: /* concavity hull edge */
! 19252: #define C_x 0 /* (x,y) location of center of hull-bdy edge wrt bounding-box */
! 19253: #define C_y 1
! 19254: #define C_r 2 /* (r,i) real-imag parts of hull-bdy edge */
! 19255: #define C_i 3
! 19256: /* concavity depth & direction */
! 19257: #define D_x 0 /* (x,y) location of center of depth & direction vector */
! 19258: #define D_y 1
! 19259: #define D_r 2 /* (r,i) real-imag parts of depth & direction vector */
! 19260: #define D_i 3
! 19261: /* locally-maximal convex arc */
! 19262: #define A_x 0 /* (x,y) location of center of enclosed area */
! 19263: #define A_y 1
! 19264: #define A_r 2 /* (r,i) real-imag parts of `incompleteness' vector */
! 19265: #define A_i 3
! 19266: /* locally-maximal concave arc */
! 19267: #define V_x 0 /* (x,y) location of center of enclosed area */
! 19268: #define V_y 1
! 19269: #define V_r 2 /* (r,i) real-imag parts of `incompleteness' vector */
! 19270: #define V_i 3
! 19271: /* endpoint */
! 19272: #define P_x 0 /* (x,y) location of center of hull-bdy wrt bounding-box */
! 19273: #define P_y 1
! 19274: #define P_r 2 /* (r,i) real-imag parts of direction-depth vector */
! 19275: #define P_i 3
! 19276: /* ticks: left-, right-, top-, & bottom-facing extrema near ends */
! 19277: #define T_x 0 /* signed distance from centroid along principal axis */
! 19278: #define T_y 1 /* signed perpendicular distance from axis */
! 19279: #define T_a 2 /* angle of principal axis, within worst-case range */
! 19280: /* crossings */
! 19281: #define X_x 0 /* (x,y) location of crossing wrt bounding-box */
! 19282: #define X_y 1
! 19283: /* global scalars, combined */
! 19284: #define Y_a 0 /* log(aspect_ratio=hgt/wid) */
! 19285: #define Y_b 1 /* ratio of area to bbx_area */
! 19286: #define Y_p 2 /* ratio of perimeter to bbx_perimeter */
! 19287: /* global scalars, combined (more) */
! 19288: #define Z_g 0 /* Gale's feature: included angle between two longest bdy edges */
! 19289:
! 19290: /* scalar features field indices */
! 19291: #define SF_RSZ 0 /* relative size (height in ems) */
! 19292: #define SF_BHT 1 /* height above baseline (ems) */
! 19293: #define SF_RWD 2 /* relative width (ems) */
! 19294: #define SF_RAR 3 /* relative area (square-ems) */
! 19295: #define SF_RPE 4 /* relative perimeter (ems) */
! 19296: #define SF_ASP 5 /* aspect-ratio */
! 19297: #define SF_BLK 6 /* fraction of Bbx that is black */
! 19298: #define SF_PER 7 /* ratio of perimeter to BBx per */
! 19299: #define SF_GALE 8 /* Gale's feature: incl. ang. between 2 longest edges */
! 19300: #define SF_N 8 /* index of last var that's not an occurrence-count */
! 19301: #define SF_MNY (SF_N+Sh_LA+1)
! 19302:
! 19303: #if MAIN
! 19304: /* ``Is this feature available early enough to be used in fast scalar-
! 19305: feature preclassifier?'' (Must not depend on shape analysis.) */
! 19306: boolean SFfeature[SF_MNY] = {
! 19307: F, F, F, F, F, T, T, T, F,
! 19308: T, T, T, T, T, T, T, T, T, T, T, F, F };
! 19309: /* ``Is this feature discrete (integer-valued)?'' (Affects construction
! 19310: of scalar-decision tree preclassifier.) */
! 19311: boolean SFdiscrete[SF_MNY] = {
! 19312: F, F, F, F, F, F, F, F, F,
! 19313: T, T, T, T, T, T, T, T, T, T, T, T, T };
! 19314: #else
! 19315: extern boolean SFfeature[];
! 19316: extern boolean SFdiscrete[];
! 19317: #endif
! 19318:
! 19319: typedef Pval SFv[SF_MNY];
! 19320:
! 19321: /* blob tracer (boundary angles) features field indices */
! 19322: #define TR_MNY 8
! 19323:
! 19324: typedef Pval TRv[TR_MNY];
! 19325:
! 19326: /* tracer decision-tree header */
! 19327: typedef struct TRtr {
! 19328: struct SFdnode *TRd; /* array of decision-nodes */
! 19329: struct Cl ***clist; /* list of (class-ptr)-lists */
! 19330: } TRtr;
! 19331:
! 19332: /* Ss - sub-shape list-item */
! 19333: typedef struct Ss {
! 19334: Seq seq; /* globally unique sequence no */
! 19335: Seq shs; /* shape-hdr seq no */
! 19336: Seq cls; /* class sequence no */
! 19337: short no; /* sub-shape number (0,1,2..., NA) */
! 19338: float focc; /* fraction of training set w/ >=1 occurrence */
! 19339: float fdup; /* fraction of training set w/ >=2 occurrence */
! 19340: Spar me; /* mean parameters */
! 19341: Spar sd; /* std-dev parameters */
! 19342: Spar min; /* min limits (for fast checking) */
! 19343: Spar max; /* max limits (for fast checking) */
! 19344: Rec r; /* rectangular parallelopiped in Liv space */
! 19345: Pval fr; /* fraction of training set covered */
! 19346: short nuse; /* for current blob, no. uses */
! 19347: float nocc; /* occurrences: no. blobs with >=1 of these */
! 19348: float ndup; /* duplicates: no. blobs with >=2 of these */
! 19349: float mind; /* minimum scaled distance from cluster among uses */
! 19350: float merit; /* merit score resulting from 'nuse' matches to this */
! 19351: struct Ss *ne; /* ptr to next in list */
! 19352: } Ss;
! 19353:
! 19354: #define MAX_SS 8192 /* see 'kdt.h' for reasons */
! 19355:
! 19356: /* BMask: 1-d, variable-length packed bitstring (N = no. bits). The string
! 19357: is stored in an array of (unsigned int). It is often accessed via a fast
! 19358: ascending sequence of 'short' pointers (unsigned short *) or (unsigned char *):
! 19359: in these cases, enough are used to completely cover all the (unsigned int)s,
! 19360: even though that may be more than enough, to ensure that the result is
! 19361: insensitive to machine-dependent short-order-in-ints and char-order-in-shorts.
! 19362: BMask_ni(N) no. unsigned ints holding bit-data
! 19363: BMask_si(N) no. unsigned shorts covering bit-data (exactly 2x _ni)
! 19364: BMask_ci(N) no. unsigned chars covering bit-data (exactly 4x _ni)
! 19365: BMask_size(N) total no. bytes in, or pointed to by BMask:
! 19366: sizeof(n) + sizeof(mny) + sizeof(r) + sizeof(malloc space)
! 19367: */
! 19368: #define BMask_ni(N) (((N)+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))
! 19369: #define BMask_si(N) (2*BMask_ni(N))
! 19370: #define BMask_ci(N) (4*BMask_ni(N))
! 19371: #define BMask_size(N) (3*sizeof(unsigned int)+(BMask_ci((N))))
! 19372:
! 19373: typedef struct BMask {
! 19374: unsigned int n; /* no. of bits stored (==N above) */
! 19375: unsigned int mny; /* no. bits set to 1 */
! 19376: unsigned int r; /* represents `r' BMasks altogether */
! 19377: union { /* packed bits: 0th bit is 01 */
! 19378: unsigned int *i; /* malloc space: int [Bmask_ni] */
! 19379: unsigned short *s; /* malloc space: short [Bmask_si] */
! 19380: int ii; /* index into (unsigned int)[] array */
! 19381: int si; /* index into (unsigned short)[] array */
! 19382: } u;
! 19383: } BMask;
! 19384:
! 19385: #define Init_BMask {0,0,0,}
! 19386: #if MAIN
! 19387: BMask empty_BMask = Init_BMask;
! 19388: #else
! 19389: extern BMask empty_BMask;
! 19390: #endif
! 19391:
! 19392:
! 19393: typedef struct BMasks {
! 19394: unsigned short mny; /* no. BMasks */
! 19395: unsigned short r; /* represents `r' BMasks altogether */
! 19396: unsigned short shallow; /* 0 <= shallow <= mny */
! 19397: unsigned short alloc; /* no. items allocated in .a[] */
! 19398: union { BMask *a; /* array[mny] of BMasks */
! 19399: int bi; /* index into (BMask)[] array */
! 19400: } u;
! 19401: } BMasks;
! 19402:
! 19403: #define Init_BMasks {0,0,0,0,}
! 19404: #if MAIN
! 19405: BMasks empty_BMasks = Init_BMasks;
! 19406: #else
! 19407: extern empty_BMasks;
! 19408: #endif
! 19409:
! 19410: /* Sh - shape list-item */
! 19411: typedef struct Sh {
! 19412: Seq seq; /* unique sequence no. */
! 19413: short t; /* shape type: S, H, X, etc */
! 19414: short nss; /* no. sub-shapes in the list */
! 19415: float mess; /* mean no. sub-shapes in training set */
! 19416: float sdss; /* std-dev of sub-shapes in training set */
! 19417: float NAocc; /* prob at least one shape not-assigned */
! 19418: float NAdup; /* prob more than one not-assigned */
! 19419: Ss NAss; /* "not-assigned" data */
! 19420: Ss *fi; /* first sub-shape */
! 19421: Ss *la; /* last sub-shape */
! 19422: struct Sh *ne; /* next shape */
! 19423: } Sh;
! 19424:
! 19425: /* Cl - class list-item */
! 19426: typedef struct Cl {
! 19427: Seq seq; /* unique sequence no. 0,1,... */
! 19428: Cln c; /* class name */
! 19429: float shNA; /* fraction of shapes unassigned */
! 19430: float blDP; /* fraction of blobs w/ >=1 duplicate shape-match*/
! 19431: float blAL; /* average extra alternate shape-matches / blob */
! 19432: SFv sf_me; /* scalar-features: means, std-devs */
! 19433: SFv sf_sd;
! 19434: BMask bm; /* canonical BMask */
! 19435: BMasks bms; /* additional representative BMask records */
! 19436: Sh *sha[Sh_MNY]; /* table of pointers to shape-types */
! 19437: Sh *fi; /* first owned shape */
! 19438: Sh *la; /* last owned shape */
! 19439: short unmat[Sh_MNY]; /* counts of unmatched shapes/shape-type */
! 19440: struct Ssm *ssmfi; /* first sub-shape match for this class */
! 19441: TRtr *tr; /* pointer to tracer decision tree (if any) */
! 19442: TRv tr_me; /* tracer-features: means, std-devs */
! 19443: TRv tr_sd;
! 19444: float m_me; /* mean, std-err of merit (in training set) */
! 19445: float m_sd;
! 19446: float bayes; /* Bayesian merit: a posteriori log-probability */
! 19447: Merit m01; /* Haming, etc. merit in range [0,1] */
! 19448: Merit merit; /* sort and truncate based on this merit */
! 19449: short pass; /* the last classification method this class passed */
! 19450: int ch_mny; /* No. Chars of this class in a subset */
! 19451: int ss_mny; /* No. Chars with given feature */
! 19452: boolean force_reseg; /* forcibly resegment Chars of this Class */
! 19453: struct Cl *ne; /* next class */
! 19454: } Cl;
! 19455:
! 19456: /* MAX_CL (max no. of classes) is defined in CPU.h */
! 19457: #define MAX_SH (MAX_CL*SH_MNY)
! 19458:
! 19459: typedef struct Classes {
! 19460: int mny; /* number of items in array */
! 19461: Cl **clpa; /* Cl *clpa[cl_mny+1]: NULL-term'd array of ptrs */
! 19462: } Classes;
! 19463: #define Init_Classes {0,NULL}
! 19464: #if MAIN
! 19465: Classes empty_Classes = Init_Classes;
! 19466: #else
! 19467: extern Classes empty_Classes;
! 19468: #endif
! 19469:
! 19470: typedef struct Ssm { /* sub-shape match record */
! 19471: Seq isn; /* input shape sequence no (w/in blob) */
! 19472: Cl *clp; /* owning class, shape, sub-shape... */
! 19473: Sh *shp;
! 19474: Ss *ssp;
! 19475: float mind; /* distance to closest assigned sub-shape */
! 19476: boolean alt; /* T if this is an alternative (not the first) */
! 19477: struct Ssm *ne; /* next, prior ptrs in list */
! 19478: struct Ssm *pr;
! 19479: } Ssm;
! 19480:
! 19481: /* return pathname of OCR directory; if environment variable OCRDIR
! 19482: is set, it is used; otherwise #defined variable OCRDIR is used. */
! 19483: #if MAIN
! 19484: char *getenv();
! 19485: char *ocrdir()
! 19486: { char *ocrdir_ev;
! 19487: if((ocrdir_ev=getenv("OCRDIR"))!=NULL) {
! 19488: return(ocrdir_ev);
! 19489: }
! 19490: else return(OCRDIR);
! 19491: }
! 19492: #else
! 19493: char *ocrdir();
! 19494: #endif
! 19495: 0707070035351135261006640007620000050000010264330476773367400001100000033171sunlib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
! 19496: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
! 19497: /* The copyright notice does not imply actual or intended publication. */
! 19498: /* AUTHORS: */
! 19499: /* T. Thompson - ATT-BL HO - first versions */
! 19500: #include <stdio.h>
! 19501: #include <sys/types.h>
! 19502: #include <sys/stat.h>
! 19503: #include <sys/ioctl.h>
! 19504: #include <pixrect/pixrect.h>
! 19505: #include <pixrect/pixfont.h>
! 19506: #include <suntool/sunview.h>
! 19507: #include <suntool/canvas.h>
! 19508: #include "met.h"
! 19509: #include "boole.h"
! 19510: #include "Coord.h"
! 19511:
! 19512: #define XYSCALE(x,y) (x=(x-obotx)*scx+botx),(y=(y-oboty)*scy+boty)
! 19513:
! 19514: struct pixrect *source_pixrect;
! 19515:
! 19516: Frame Mainframe;
! 19517: Canvas Win;
! 19518: int Winfd;
! 19519: Pixwin *Pw;
! 19520: int Key = -1;
! 19521: int Mousex;
! 19522: int Mousey;
! 19523: int Colorval;
! 19524:
! 19525: /* CMAPSIZE MUST BE A POWER OF 2 (restriction in sun colormap stuff)*/
! 19526: #define CMAPSIZE 8
! 19527:
! 19528: #define DEFAULTCOLOR (CMAPSIZE-1)
! 19529:
! 19530: #define S_WHITE 0
! 19531: #define S_RED 1
! 19532: #define S_GREEN 2
! 19533: #define S_BLUE 3
! 19534: #define S_GREY 4
! 19535: #define S_AQUA 5
! 19536: #define S_YELLOW 6
! 19537: #define S_BLACK 7
! 19538:
! 19539: int mycolors[CMAPSIZE][3] = {
! 19540: 255, 255, 255, /* white */
! 19541: 230, 0, 75, /* red */
! 19542: 0, 200, 0, /* green */
! 19543: 0, 0, 200, /* blue */
! 19544: 200, 200, 200, /* grey */
! 19545: 0, 160, 170, /* aqua */
! 19546: 250, 220, 0, /* yellow */
! 19547: 0,0,0 /* foreground (black) */
! 19548: };
! 19549:
! 19550:
! 19551: void domouse();
! 19552:
! 19553: extern int Debug;
! 19554:
! 19555: extern event_proc();
! 19556:
! 19557: static int
! 19558: boty = 32767, /* screen bottom y */
! 19559: botx = 0, /* screen bottom x */
! 19560: topx = 32767, /* screen top x */
! 19561: topy = 0, /* screen top y */
! 19562: oboty = 0, /* user's bottom y */
! 19563: obotx = 0, /* user's bottom x */
! 19564: otopy = 32767, /* user's top y */
! 19565: otopx = 32767; /* user's top x */
! 19566:
! 19567: static double
! 19568: scx = 1.0, /* scale factor x */
! 19569: scy = 1.0 /* scale factor y */
! 19570: ;
! 19571: static int lastx = 0;
! 19572: static int lasty = 0;
! 19573: static int lmode = 3; /* drawing mode (default is xor)*/
! 19574:
! 19575: int Prevlmode = 3;
! 19576:
! 19577: #define signof(x) ((x)>=0.0?(1):(-1))
! 19578: #define absof(x) ((x)>=0.0?(x):(-x))
! 19579:
! 19580: void flushout() { }
! 19581:
! 19582: short bsy_pixrect_data[] = {
! 19583: /* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
! 19584: */
! 19585: 0x7FFE,0x4002,0x200C,0x1A38,0x0FF0,0x07E0,0x03C0,0x0180,
! 19586: 0x0180,0x0240,0x0520,0x0810,0x1108,0x23C4,0x47E2,0x7FFE
! 19587: };
! 19588: mpr_static(busy_pixrect, 16, 16, 1, bsy_pixrect_data);
! 19589:
! 19590: int childpid;
! 19591:
! 19592: Rect sweeparect();
! 19593:
! 19594: om_open()
! 19595: {
! 19596: Rect r;
! 19597:
! 19598: r = sweeparect();
! 19599:
! 19600: notify_errno = NOTIFY_OK;
! 19601:
! 19602: Mainframe = window_create((Window)NULL, FRAME,
! 19603: FRAME_LABEL, "ocr",
! 19604: 0 );
! 19605: Win = window_create(Mainframe, CANVAS, 0);
! 19606: Pw = canvas_pixwin(Win);
! 19607:
! 19608: window_set(Mainframe, WIN_X, r.r_left,
! 19609: WIN_Y, r.r_top, 0);
! 19610: window_set(Win, WIN_WIDTH, r.r_width,
! 19611: WIN_HEIGHT, r.r_height, 0);
! 19612:
! 19613: window_fit(Win);
! 19614: window_fit(Mainframe);
! 19615:
! 19616: window_set(Mainframe, WIN_SHOW, TRUE, 0);
! 19617:
! 19618: Winfd = (int) window_get(Win, WIN_FD);
! 19619:
! 19620: if ( notify_errno != NOTIFY_OK ) {
! 19621: notify_perror("ocr");
! 19622: exit(1);
! 19623: }
! 19624:
! 19625: setcolormap();
! 19626:
! 19627: set_color(DEFAULTCOLOR);
! 19628: linemod("solid");
! 19629:
! 19630: window_set(Win,
! 19631: WIN_CONSUME_PICK_EVENTS,
! 19632: WIN_NO_EVENTS,
! 19633: WIN_ASCII_EVENTS,
! 19634: WIN_MOUSE_BUTTONS,
! 19635: LOC_MOVE,
! 19636: /* LOC_DRAG, */
! 19637: LOC_WINEXIT, LOC_WINENTER,
! 19638: LOC_RGNEXIT, LOC_RGNENTER, 0,
! 19639: 0);
! 19640:
! 19641: window_set(Win, WIN_EVENT_PROC, event_proc, 0);
! 19642:
! 19643: space(0,0,M_WID,M_HGT);
! 19644: interact();
! 19645: }
! 19646:
! 19647: /***********************************************************/
! 19648: /* The code below was taken from the 'dumpregion' program. */
! 19649: /***********************************************************/
! 19650:
! 19651: /*
! 19652: * Copyright Richard Tobin 1987. You may freely copy, modify and distribute
! 19653: * this program in source form provided this comment remains intact.
! 19654: *
! 19655: * Richard Tobin, JANET: [email protected]
! 19656: * AI Applications Institute, ARPA: R.Tobin%[email protected]
! 19657: * Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
! 19658: */
! 19659:
! 19660: #include <sys/file.h>
! 19661: #include <suntool/fullscreen.h>
! 19662:
! 19663: short nwdata[] = {
! 19664: #include </usr/include/images/stretchNW.cursor>
! 19665: };
! 19666: mpr_static(nwpixrect, 16, 16, 1, nwdata);
! 19667:
! 19668: short sedata[] = {
! 19669: #include </usr/include/images/stretchSE.cursor>
! 19670: };
! 19671: mpr_static(sepixrect, 16, 16, 1, sedata);
! 19672:
! 19673: Rect rect = {0,0,0,0};
! 19674:
! 19675: Rect
! 19676: sweeparect()
! 19677: {
! 19678: int wfd, n;
! 19679: struct fullscreen *fs;
! 19680: Event event;
! 19681: Pixwin *pw;
! 19682: int left, right, top, bottom, temp;
! 19683: Window win;
! 19684: double w;
! 19685: Rect r;
! 19686:
! 19687: win = window_create(0, FRAME,
! 19688: FRAME_OPEN_RECT, &rect,
! 19689: WIN_CONSUME_PICK_EVENTS,
! 19690: WIN_ASCII_EVENTS,
! 19691: LOC_MOVE, WIN_MOUSE_BUTTONS, 0,
! 19692: 0);
! 19693:
! 19694: wfd = (int)window_get(win, WIN_FD);
! 19695: fs = fullscreen_init(wfd);
! 19696: pw = fs->fs_pixwin;
! 19697:
! 19698: window_set(win,
! 19699: WIN_CURSOR, cursor_create(CURSOR_IMAGE, &nwpixrect,
! 19700: CURSOR_XHOT, 0, CURSOR_YHOT, 0,
! 19701: 0),
! 19702: 0);
! 19703:
! 19704: for ( ;; ) {
! 19705: n = window_read_event(win, &event);
! 19706: if ( n < 0 )
! 19707: continue;
! 19708: if ( event_is_ascii(&event) ) {
! 19709: if ( event_id(&event) == 'F' ) {
! 19710: r.r_left = 10;
! 19711: r.r_top = 10;
! 19712: r.r_width = 900;
! 19713: r.r_height = 900;
! 19714: }
! 19715: else {
! 19716: r.r_left = 542;
! 19717: r.r_top = 0;
! 19718: r.r_width = 540;
! 19719: r.r_height = 512;
! 19720: }
! 19721: goto getout;
! 19722: }
! 19723: if ( event_is_down(&event) && event_is_button(&event) )
! 19724: break;
! 19725: }
! 19726:
! 19727: right = left = event_x(&event);
! 19728: bottom = top = event_y(&event);
! 19729:
! 19730: window_set(win,
! 19731: WIN_CURSOR, cursor_create(CURSOR_IMAGE, &sepixrect,
! 19732: CURSOR_XHOT, 15, CURSOR_YHOT, 15,
! 19733: 0),
! 19734: 0);
! 19735:
! 19736: drawbox(pw, left, top, right, bottom);
! 19737:
! 19738: while(window_read_event(win, &event) == -1 ||
! 19739: !event_is_up(&event) ||
! 19740: !event_is_button(&event))
! 19741: {
! 19742: drawbox(pw, left, top, right, bottom);
! 19743: right = event_x(&event);
! 19744: bottom = event_y(&event);
! 19745: drawbox(pw, left, top, right, bottom);
! 19746: }
! 19747:
! 19748: drawbox(pw, left, top, right, bottom);
! 19749:
! 19750: if(right < left)
! 19751: {
! 19752: temp = right;
! 19753: right = left;
! 19754: left = temp;
! 19755: }
! 19756: if(bottom < top)
! 19757: {
! 19758: temp = bottom;
! 19759: bottom = top;
! 19760: top = temp;
! 19761: }
! 19762: r.r_left = left;
! 19763: r.r_top = top;
! 19764: r.r_width = (right-left);
! 19765: r.r_height = (bottom-top);
! 19766: getout:
! 19767: fullscreen_destroy(fs);
! 19768:
! 19769: window_set(win, FRAME_NO_CONFIRM, TRUE, 0);
! 19770: window_destroy(win);
! 19771: return r;
! 19772: }
! 19773:
! 19774: drawbox(pw, left, top, right, bottom)
! 19775: Pixwin *pw;
! 19776: int left, top, right, bottom;
! 19777: {
! 19778: fullscreen_pw_vector(pw, left, top, right, top, PIX_NOT(PIX_DST), 0);
! 19779: fullscreen_pw_vector(pw, right, top, right, bottom, PIX_NOT(PIX_DST), 0);
! 19780: fullscreen_pw_vector(pw, right, bottom, left, bottom, PIX_NOT(PIX_DST), 0);
! 19781: fullscreen_pw_vector(pw, left, bottom, left, top, PIX_NOT(PIX_DST), 0);
! 19782: }
! 19783:
! 19784: ttygets(buff,len)
! 19785: char *buff;
! 19786: {
! 19787: int x, y, n, key;
! 19788: char *p = buff;
! 19789:
! 19790: for ( n=0; n<(len-1); n++ ) {
! 19791: while ( (key=mouseorkey(&x,&y)) < 0 )
! 19792: ;
! 19793: if ( key == '\r' ) /* just in case */
! 19794: key = '\n';
! 19795: *p++ = key;
! 19796: if ( key == '\n' || key == '\0' )
! 19797: break;
! 19798: }
! 19799: *p++ = '\0';
! 19800: }
! 19801:
! 19802: int mouseorkey(x,y)
! 19803: int* x;
! 19804: int* y;
! 19805: {
! 19806: Event anevent;
! 19807: char c;
! 19808: int n;
! 19809:
! 19810: Key = -1;
! 19811:
! 19812: notify_do_dispatch();
! 19813: n = read(0,&c,1);
! 19814: notify_no_dispatch();
! 19815: if ( n == 1 ) {
! 19816: /* character was typed in text (original) window */
! 19817: /* ie. stdin */
! 19818: Key = c;
! 19819: *x = Mousex;
! 19820: *y = Mousey;
! 19821: xyunscale(x,y);
! 19822: }
! 19823: else if ( Key >= 0 ) {
! 19824: /* character was typed in graphics window */
! 19825: /* so it must be echoed. */
! 19826: putchar(Key);
! 19827: if ( Key == '\r' )
! 19828: putchar('\n');
! 19829: fflush(stdout);
! 19830: *x = Mousex;
! 19831: *y = Mousey;
! 19832: xyunscale(x,y);
! 19833: }
! 19834: return(Key);
! 19835: }
! 19836:
! 19837: interact()
! 19838: {
! 19839: (void) notify_dispatch();
! 19840: }
! 19841:
! 19842: setcolormap()
! 19843: {
! 19844: u_char red[CMAPSIZE], green[CMAPSIZE], blue[CMAPSIZE];
! 19845: int n;
! 19846:
! 19847: for(n=0;n<CMAPSIZE;n++) {
! 19848: red[n] = mycolors[n][0];
! 19849: green[n] = mycolors[n][1];
! 19850: blue[n] = mycolors[n][2];
! 19851: }
! 19852: pw_setcmsname(Pw,"showcolor");
! 19853: pw_putcolormap(Pw, 0, CMAPSIZE, red, green, blue);
! 19854: }
! 19855:
! 19856: /*ARGSUSED*/
! 19857: wait_proc(window,event,arg)
! 19858: Window window;
! 19859: Event *event;
! 19860: caddr_t arg;
! 19861: {
! 19862: int id = event_id(event);
! 19863:
! 19864: if ( event_is_ascii(event) && id == 'q' )
! 19865: notify_stop(0);
! 19866: }
! 19867:
! 19868: om_close()
! 19869: {
! 19870: window_set(Win, WIN_EVENT_PROC, wait_proc, 0);
! 19871: if ( fork() == 0 ) {
! 19872: close(0);
! 19873: close(1);
! 19874: close(2);
! 19875: /* This stuff doesn't seem to work. I'm trying to */
! 19876: /* get the window to be able to repaint itself when */
! 19877: /* uncovered. */
! 19878: sleep(1);
! 19879: window_main_loop(Mainframe);
! 19880: exit(0);
! 19881: }
! 19882: }
! 19883:
! 19884: space(x0,y0,x1,y1)
! 19885: int x0, y0, x1, y1;
! 19886: {
! 19887: int tx, ty;
! 19888:
! 19889: obotx = x0;
! 19890: oboty = y0;
! 19891: otopx = x1;
! 19892: otopy = y1;
! 19893:
! 19894: boty = 0;
! 19895: botx = 0;
! 19896: tx = (int) window_get(Win,WIN_WIDTH);
! 19897: ty = (int) window_get(Win,WIN_HEIGHT);
! 19898: topx = tx;
! 19899: topy = ty;
! 19900: scx = (double)(topx-botx)/(otopx-obotx);
! 19901: scy = (double)(topy-boty)/(otopy-oboty);
! 19902: }
! 19903:
! 19904: #ifdef OLDSTUFF
! 19905: xyscale(x, y)
! 19906: int *x, *y;
! 19907: {
! 19908: *x = (*x-obotx)*scx+botx;
! 19909: *y = (*y-oboty)*scy+boty;
! 19910: }
! 19911: #endif
! 19912:
! 19913: xyunscale(x, y)
! 19914: int *x, *y;
! 19915: {
! 19916: /* map from device coordinates to space() coordinates */
! 19917:
! 19918: *x = ( (*x - botx)/scx + obotx );
! 19919: *y = ( (*y - boty)/scy + oboty );
! 19920: }
! 19921:
! 19922: wline(x1,y1,x2,y2)
! 19923: int x1, y1, x2, y2;
! 19924: {
! 19925: lastx = x2;
! 19926: lasty = y2;
! 19927:
! 19928: XYSCALE(x1, y1);
! 19929: XYSCALE(x2, y2);
! 19930:
! 19931: arawline(x1,y1,x2,y2);
! 19932: }
! 19933:
! 19934: wrect(x1,y1,x2,y2)
! 19935: int x1, y1, x2, y2;
! 19936: {
! 19937: lastx = x2;
! 19938: lasty = y2;
! 19939:
! 19940: XYSCALE(x1, y1);
! 19941: XYSCALE(x2, y2);
! 19942:
! 19943: arawbox(x1,y1,x2,y2);
! 19944: }
! 19945:
! 19946: arawbox(x1,y1,x2,y2)
! 19947: int x1, y1, x2, y2;
! 19948: {
! 19949: arawline(x1,y1,x2,y1);
! 19950: arawline(x2,y1,x2,y2);
! 19951: arawline(x2,y2,x1,y2);
! 19952: arawline(x1,y2,x1,y1);
! 19953: }
! 19954:
! 19955: arawline(x1,y1,x2,y2)
! 19956: int x1, y1, x2, y2;
! 19957: {
! 19958: int op, col;
! 19959:
! 19960: currentopcol(&op,&col);
! 19961: /* fprintf(stderr,"calling pw_vector, %d,%d %d,%d currentop=%d Colorval=%d Pw=%ld\n",x1,y1,x2,y2,op,col,Pw); */
! 19962: pw_vector(Pw, (int)x1,(int)y1, (int)x2,(int)y2, op, col);
! 19963: interact();
! 19964: }
! 19965:
! 19966: currentopcol(aop,acol)
! 19967: int *aop, *acol;
! 19968: {
! 19969: if ( lmode == 1 && Colorval == S_WHITE ) {
! 19970: *aop = (PIX_NOT(PIX_SRC) & PIX_DST);
! 19971: *acol = S_BLACK;
! 19972: }
! 19973: else {
! 19974: *acol = Colorval;
! 19975: switch (lmode) {
! 19976: case 0:
! 19977: *aop = (PIX_NOT(PIX_SRC) & PIX_DST);
! 19978: break;
! 19979: case 1:
! 19980: case 2:
! 19981: /* *aop = (PIX_SRC | PIX_DST); */
! 19982: *aop = PIX_SRC;
! 19983: break;
! 19984: case 3:
! 19985: *aop = (PIX_SRC ^ PIX_DST);
! 19986: break;
! 19987: default:
! 19988: *aop = (PIX_SRC | PIX_DST);
! 19989: break;
! 19990: }
! 19991: }
! 19992: }
! 19993:
! 19994: wt(s,scl,left,top,right,bot)
! 19995: char *s;
! 19996: {
! 19997: int op, col;
! 19998: /* fprintf(stderr,"wt() called, s=%s lastxy=%d,%d scl=%d left-top=%d,%d\n",
! 19999: s,left,top,scl,left,top); */
! 20000: currentopcol(&op,&col);
! 20001: XYSCALE(left, top);
! 20002: pw_ttext(Pw,(int)left,(int)top,op,NULL,s);
! 20003: }
! 20004:
! 20005: Sp *
! 20006: set_font(n)
! 20007: {
! 20008: static Sp chsz;
! 20009: struct pr_size prs;
! 20010: int x, y;
! 20011:
! 20012: prs = pf_textwidth(1,pf_default(),"x");
! 20013: x = prs.x;
! 20014: y = prs.y;
! 20015: xyunscale(&x,&y);
! 20016: chsz.x = ++x;
! 20017: chsz.y = y;
! 20018: return &chsz;
! 20019: }
! 20020:
! 20021: #ifdef OLDSTUFF
! 20022: textwidth(s)
! 20023: {
! 20024: struct pr_size prs;
! 20025:
! 20026: prs = pf_textwidth(bound,strlen(s),pf_default(),s);
! 20027:
! 20028:
! 20029: prs = pf_textwidth(1,pf_default(),"x");
! 20030: *ax = prs.x;
! 20031: *ay = prs.y;
! 20032: xyunscale(ax,ay);
! 20033: }
! 20034: #endif
! 20035:
! 20036: amove(x,y)
! 20037: int x,y;
! 20038: {
! 20039: lastx = x;
! 20040: lasty = y;
! 20041: }
! 20042:
! 20043: cont(x,y)
! 20044: int x,y;
! 20045: {
! 20046: wline(lastx,lasty,x,y);
! 20047: /* last[xy] are then updated by line */
! 20048: }
! 20049:
! 20050:
! 20051: set_color(n)
! 20052: int n;
! 20053: {
! 20054: switch(n){
! 20055: case M_WHITE:
! 20056: n = S_WHITE; break;
! 20057: case M_PALE_GREY:
! 20058: case M_GREY_7:
! 20059: n = S_GREY; break;
! 20060: case M_BLACK:
! 20061: n = S_BLACK; break;
! 20062: case M_YELLOW_13:
! 20063: case M_YELLOW_11:
! 20064: n = S_YELLOW; break;
! 20065: case M_MAGENTA:
! 20066: case M_CYAN:
! 20067: case M_CYAN_14:
! 20068: n = S_AQUA; break;
! 20069: case M_GREEN:
! 20070: case M_GREEN_7:
! 20071: n = S_GREEN; break;
! 20072: case M_BLUE:
! 20073: n = S_BLUE; break;
! 20074: case M_RED:
! 20075: n = S_RED; break;
! 20076: default:
! 20077: fprintf(stderr,"Unknown color in set_color (%d)\n",n);
! 20078: n = S_WHITE;
! 20079: break;
! 20080: }
! 20081: Colorval = n;
! 20082: /* fprintf(stderr,"set_color = (sun#) %d\n",n); */
! 20083: }
! 20084:
! 20085: linemod(s)
! 20086: char *s;
! 20087: {
! 20088: if ( strcmp(s,"erase")==0 )
! 20089: lmode = 0;
! 20090: else if ( strcmp(s,"dotted")==0 || strcmp(s,"hilight")==0 )
! 20091: lmode = 2;
! 20092: else if ( strcmp(s,"xor")==0 )
! 20093: lmode = 3;
! 20094: else { /* everything, including "solid" defaults to this */
! 20095: lmode = 1;
! 20096: }
! 20097: }
! 20098:
! 20099: aerase()
! 20100: {
! 20101: pw_writebackground(Pw,0,0,(int)topx,(int)topy,PIX_SRC);
! 20102: }
! 20103:
! 20104: wfrect(x1,y1,x2,y2)
! 20105: int x1, y1, x2, y2;
! 20106: {
! 20107: int op, col;
! 20108: int t;
! 20109:
! 20110: XYSCALE(x1, y1);
! 20111: XYSCALE(x2, y2);
! 20112:
! 20113: currentopcol(&op,&col);
! 20114:
! 20115: if ( x1 > x2 ) {
! 20116: t = x1;
! 20117: x1 = x2;
! 20118: x2 = t;
! 20119: }
! 20120: if ( y1 > y2 ) {
! 20121: t = y1;
! 20122: y1 = y2;
! 20123: y2 = t;
! 20124: }
! 20125: /* fprintf(stderr,"wfrect(%d,%d to %d,%d lmode=%d op=%d col=%d)\n",
! 20126: x1,y1,x2,y2,lmode,op,col); */
! 20127: for ( t=y1; t<=y2; t++ ) {
! 20128: pw_vector(Pw, x1,t, x2,t, op, col);
! 20129: }
! 20130: interact();
! 20131: }
! 20132:
! 20133: /*ARGSUSED*/
! 20134: event_proc(window,event,arg)
! 20135: Window window;
! 20136: Event *event;
! 20137: caddr_t arg;
! 20138: {
! 20139: int id = event_id(event);
! 20140:
! 20141: if ( event_is_ascii(event) ) {
! 20142: Key = id;
! 20143: notify_stop(0);
! 20144: return;
! 20145: }
! 20146: }
! 20147:
! 20148: /* trim a Metheus X coordinate to fit on screen */
! 20149: int M_trimX(x)
! 20150: int x;
! 20151: { if(x<0) return(0);
! 20152: else if(x>(topx-1)) return((topx-1));
! 20153: return(x);
! 20154: }
! 20155:
! 20156: /* trim a Metheus Y coordinate to fit on screen */
! 20157: int M_trimY(y)
! 20158: int y;
! 20159: { if(y<0) return(0);
! 20160: else if(y>(topy-1)) return((topy-1));
! 20161: return(y);
! 20162: }
! 20163:
! 20164: /* show Sp (Metheus coordinates) on Metheus,
! 20165: enlarged to a `dot'-sided square */
! 20166: sh_Mp(mpp,dot)
! 20167: Sp *mpp;
! 20168: int dot;
! 20169: { int half_dot;
! 20170: if(dot==1)
! 20171: wfrect(mpp->x,mpp->y,mpp->x,mpp->y);
! 20172: else {
! 20173: half_dot=dot/2;
! 20174: if((dot%2)==0)
! 20175: wfrect( M_trimX(mpp->x-half_dot+1),
! 20176: M_trimY(mpp->y-half_dot+1),
! 20177: M_trimX(mpp->x+half_dot),
! 20178: M_trimY(mpp->y+half_dot) );
! 20179: else wfrect( M_trimX(mpp->x-half_dot),
! 20180: M_trimY(mpp->y-half_dot),
! 20181: M_trimX(mpp->x+half_dot),
! 20182: M_trimY(mpp->y+half_dot) );
! 20183: };
! 20184: }
! 20185:
! 20186:
! 20187: om_force(){}
! 20188:
! 20189: /* write "thick" line, two pixels wide */
! 20190: wtline(x1,y1,x2,y2)
! 20191: { int absdx, absdy;
! 20192: wline(x1,y1,x2,y2);
! 20193: absdx = (x1-x2)>=0 ? x1-x2 : x2-x1;
! 20194: absdy = (y1-y2)>=0 ? y1-y2 : y2-y1;
! 20195: if(absdx>absdy)
! 20196: /* more horizontal -- thicken vertically */
! 20197: wline(x1,M_trimY(y1+1),x2,M_trimY(y2+1));
! 20198: else
! 20199: /* more vertical -- thicken horizontally */
! 20200: wline(M_trimX(x1+1),y1,M_trimX(x2+1),y2);
! 20201: }
! 20202:
! 20203: /* write "fat" line, three pixels wide */
! 20204: wfline(x1,y1,x2,y2)
! 20205: { register int absdx, absdy;
! 20206:
! 20207: wline(x1,y1,x2,y2);
! 20208: absdx = (x1-x2)>=0 ? x1-x2 : x2-x1;
! 20209: absdy = (y1-y2)>=0 ? y1-y2 : y2-y1;
! 20210: if(absdx>absdy) {
! 20211: /* more horizontal -- thicken vertically */
! 20212: wline(x1,M_trimY(y1+1),x2,M_trimY(y2+1));
! 20213: wline(x1,M_trimY(y1-1),x2,M_trimY(y2-1));
! 20214: }
! 20215: else {
! 20216: /* more vertical -- thicken horizontally */
! 20217: wline(M_trimX(x1+1),y1,M_trimX(x2+1),y2);
! 20218: wline(M_trimX(x1-1),y1,M_trimX(x2-1),y2);
! 20219: };
! 20220: }
! 20221:
! 20222:
! 20223: om_wrpix()
! 20224: {
! 20225: printf("om_wrpix called\n");
! 20226: }
! 20227:
! 20228: om_buffer(n) { }
! 20229:
! 20230: rreset() { }
! 20231: 0707070035351136761006640007620000050000011476070476773366200001100000004314makefile # for all OS --
! 20232: OPT = -O
! 20233: PROF = -p
! 20234: PI = -g
! 20235:
! 20236: PRODUCTION = $(OPT)
! 20237: DEBUG = $(PROF) $(PI)
! 20238:
! 20239: # -- for UNIX 9th Ed --
! 20240: CFLAGS = $(PRODUCTION)
! 20241: LIBS = -lY3610 -lY
! 20242: PORTLIB = -lport
! 20243: LDFLAGS =
! 20244: F77LIBS = $(LIBS)
! 20245: MLIB =
! 20246: REGEX =
! 20247: FTW =
! 20248: METLIB = mlib.o
! 20249: RASTLIB =
! 20250: POSTLIB =
! 20251: GRAPHICLIBS =
! 20252:
! 20253: # -- For Sun OS 4.x --
! 20254: ##GRAPHICLIBS = -lsuntool -lsunwindow -lpixrect
! 20255: ##MLIB = -lm
! 20256: ##LIBS = $(GRAPHICLIBS) $(MLIB)
! 20257: ##PORTLIB = /usr/lib/libport3.a
! 20258: ##F77LIBS = -lF77 -lI77 -lc $(MLIB) $(GRAPHICLIBS)
! 20259: ##REGEX = regexec.o regcomp.o regerror.o
! 20260: ##FTW = myftw.o
! 20261: ##LDFLAGS = $(PROF) -fswitch
! 20262: ##CFLAGS = $(PROF) -fswitch -Bstatic
! 20263: ##METLIB = sunlib.o
! 20264: ##RASTLIB = rastlib.o
! 20265: ##POSTLIB = postlib.o
! 20266:
! 20267: all: bcp
! 20268: touch bcp
! 20269: clean:
! 20270: rm -rf *.[cho15] bcp bcp.cpio *.srcs makefile
! 20271:
! 20272: # the next three targets are for use in 1127 software distribution on bowell
! 20273:
! 20274: install: /usr/bin/bcp
! 20275: cp bcp.1 /usr/man/man1
! 20276:
! 20277: /usr/bin/bcp: bcp
! 20278: strip bcp
! 20279: cp bcp /usr/bin
! 20280:
! 20281: ship: /usr/bin/bcp
! 20282: ship /usr/bin/bcp
! 20283:
! 20284: # If you want to use UNIX FILE_TREEs:
! 20285: Path.o: Path.c CPU.h myftw.h Path.h
! 20286: cc $(CFLAGS) -c Path.c
! 20287: FTREE=Path.o
! 20288:
! 20289: # If you DON'T want to use FILE_TREEs:
! 20290: ##FTREE=
! 20291:
! 20292: bcp: bcp.o CCITT.o rlelib.o riclib.o Coord.o piclib.o jslr.o Text.o $(FTREE) $(POSTLIB) $(RASTLIB)
! 20293: cc $(CFLAGS) bcp.o CCITT.o rlelib.o riclib.o Coord.o piclib.o jslr.o Text.o $(FTREE) $(POSTLIB) $(RASTLIB) $(MLIB) $(GRAPHICLIBS) -o bcp
! 20294: bcp.o: bcp.c CPU.h stdocr.h rle.h CCITT.h bitio.h pic.h Path.h Bitmap.h Text.h abort.h
! 20295: cc $(CFLAGS) $(MLIB) $(GRAPHICLIBS) -c bcp.c
! 20296:
! 20297: stdocr.h: boole.h limits.h Units.h ric.h fioi.h
! 20298: touch stdocr.h
! 20299: CCITT.o: CCITT.c CPU.h stdocr.h rle.h Bitmap.h CCITT.h bitio.h
! 20300: cc $(CFLAGS) -c CCITT.c
! 20301: rlelib.o: rlelib.c CPU.h stdocr.h rle.h ric.h
! 20302: cc $(CFLAGS) -c rlelib.c
! 20303: riclib.o: riclib.c CPU.h stdocr.h
! 20304: cc $(CFLAGS) -c riclib.c
! 20305: Coord.o: Coord.c CPU.h boole.h Units.h Coord.h
! 20306: cc $(CFLAGS) -c Coord.c
! 20307: Text.o: Text.c font.h Bfeats.h stdocr.h
! 20308: cc $(CFLAGS) -c Text.c
! 20309: piclib.o: piclib.c CPU.h boole.h limits.h Units.h Coord.h pic.h
! 20310: cc $(CFLAGS) -c piclib.c
! 20311: jslr.o: jslr.c
! 20312: cc $(CFLAGS) -c jslr.c
! 20313: rastlib.o: rastlib.c
! 20314: cc $(CFLAGS) $(MLIB) $(GRAPHICLIBS) -c rastlib.c
! 20315: postlib.o: postlib.c
! 20316: cc $(CFLAGS) -c postlib.c
! 20317: sunlib.o: sunlib.c
! 20318: cc $(CFLAGS) -c sunlib.c
! 20319: myftw.o: myftw.c myftw.h
! 20320: cc $(CFLAGS) -c myftw.c
! 20321: 0707070035350335411006640007620000050000010556240457561704600000700000001365README Copy bcp.cpio.z into an empty directory, cd there, and...
! 20322: unpack bcp.cpio.z
! 20323: cpio -ic <bcp.cpio
! 20324: If your cpu is not a VAX or your OS is not research UNIX:
! 20325: edit CPU.h to specify SUN, CRAY, 3B, etc (and specify OS too)
! 20326: edit makefile to enable SUN, CRAY, 3B, etc compilation options
! 20327: Next, defeat the UNIX file-tree code (later, you may decide you want this; but
! 20328: it seldom ports easily), by taking these steps:
! 20329: 1) in CPU.h, change this line to:
! 20330: #define FILE_TREE 0
! 20331: 2) in makefile, remove all references to Path.c Path.o (this is
! 20332: spelled out in the comments).
! 20333: Then say:
! 20334: make
! 20335: and hope for the best, which is a working `bcp'.
! 20336: Bcp.1 and picfile.5 are man pages; print them using `troff -man'.
! 20337: More detailed documentation can be found in source bcp.c.
! 20338: 0707070035351136771006640007620000050000011476110476773366300000600000011432bcp.1