t4.c (8288B)
1 /* t4.c: read table specification */ 2 # include "t.h" 3 int oncol; 4 5 void 6 getspec(void) 7 { 8 int icol, i; 9 10 qcol = findcol() + 1;/* must allow one extra for line at right */ 11 garray(qcol); 12 sep[-1] = -1; 13 for (icol = 0; icol < qcol; icol++) { 14 sep[icol] = -1; 15 evenup[icol] = 0; 16 cll[icol][0] = 0; 17 for (i = 0; i < MAXHEAD; i++) { 18 csize[icol][i][0] = 0; 19 vsize[icol][i][0] = 0; 20 font[icol][i][0] = lefline[icol][i] = 0; 21 flags[icol][i] = 0; 22 style[icol][i] = 'l'; 23 } 24 } 25 for (i = 0; i < MAXHEAD; i++) 26 lefline[qcol][i] = 0; /* fixes sample55 looping */ 27 nclin = ncol = 0; 28 oncol = 0; 29 left1flg = rightl = 0; 30 readspec(); 31 Bprint(&tabout, ".rm"); 32 for (i = 0; i < ncol; i++) 33 Bprint(&tabout, " %2s", reg(i, CRIGHT)); 34 Bprint(&tabout, "\n"); 35 } 36 37 38 void 39 readspec(void) 40 { 41 int icol, c, sawchar, stopc, i; 42 char sn[10], *snp, *temp; 43 44 sawchar = icol = 0; 45 while (c = get1char()) { 46 switch (c) { 47 default: 48 if (c != tab) { 49 char buf[64]; 50 sprint(buf, "bad table specification character %c", c); 51 error(buf); 52 } 53 case ' ': /* note this is also case tab */ 54 continue; 55 case '\n': 56 if (sawchar == 0) 57 continue; 58 case ',': 59 case '.': /* end of table specification */ 60 ncol = max(ncol, icol); 61 if (lefline[ncol][nclin] > 0) { 62 ncol++; 63 rightl++; 64 }; 65 if (sawchar) 66 nclin++; 67 if (nclin >= MAXHEAD) 68 error("too many lines in specification"); 69 icol = 0; 70 if (ncol == 0 || nclin == 0) 71 error("no specification"); 72 if (c == '.') { 73 while ((c = get1char()) && c != '\n') 74 if (c != ' ' && c != '\t') 75 error("dot not last character on format line"); 76 /* fix up sep - default is 3 except at edge */ 77 for (icol = 0; icol < ncol; icol++) 78 if (sep[icol] < 0) 79 sep[icol] = icol + 1 < ncol ? 3 : 2; 80 if (oncol == 0) 81 oncol = ncol; 82 else if (oncol + 2 < ncol) 83 error("tried to widen table in T&, not allowed"); 84 return; 85 } 86 sawchar = 0; 87 continue; 88 case 'C': 89 case 'S': 90 case 'R': 91 case 'N': 92 case 'L': 93 case 'A': 94 c += ('a' - 'A'); 95 case '_': 96 if (c == '_') 97 c = '-'; 98 case '=': 99 case '-': 100 case '^': 101 case 'c': 102 case 's': 103 case 'n': 104 case 'r': 105 case 'l': 106 case 'a': 107 style[icol][nclin] = c; 108 if (c == 's' && icol <= 0) 109 error("first column can not be S-type"); 110 if (c == 's' && style[icol-1][nclin] == 'a') { 111 Bprint(&tabout, ".tm warning: can't span a-type cols, changed to l\n"); 112 style[icol-1][nclin] = 'l'; 113 } 114 if (c == 's' && style[icol-1][nclin] == 'n') { 115 Bprint(&tabout, ".tm warning: can't span n-type cols, changed to c\n"); 116 style[icol-1][nclin] = 'c'; 117 } 118 icol++; 119 if (c == '^' && nclin <= 0) 120 error("first row can not contain vertical span"); 121 if (icol > qcol) 122 error("too many columns in table"); 123 sawchar = 1; 124 continue; 125 case 'b': 126 case 'i': 127 c += 'A' - 'a'; 128 case 'B': 129 case 'I': 130 if (icol == 0) 131 continue; 132 snp = font[icol-1][nclin]; 133 snp[0] = (c == 'I' ? '2' : '3'); 134 snp[1] = 0; 135 continue; 136 case 't': 137 case 'T': 138 if (icol > 0) 139 flags[icol-1][nclin] |= CTOP; 140 continue; 141 case 'd': 142 case 'D': 143 if (icol > 0) 144 flags[icol-1][nclin] |= CDOWN; 145 continue; 146 case 'f': 147 case 'F': 148 if (icol == 0) 149 continue; 150 snp = font[icol-1][nclin]; 151 snp[0] = snp[1] = stopc = 0; 152 for (i = 0; i < 2; i++) { 153 c = get1char(); 154 if (i == 0 && c == '(') { 155 stopc = ')'; 156 c = get1char(); 157 } 158 if (c == 0) 159 break; 160 if (c == stopc) { 161 stopc = 0; 162 break; 163 } 164 if (stopc == 0) 165 if (c == ' ' || c == tab ) 166 break; 167 if (c == '\n' || c == '|') { 168 un1getc(c); 169 break; 170 } 171 snp[i] = c; 172 if (c >= '0' && c <= '9') 173 break; 174 } 175 if (stopc) 176 if (get1char() != stopc) 177 error("Nonterminated font name"); 178 continue; 179 case 'P': 180 case 'p': 181 if (icol <= 0) 182 continue; 183 temp = snp = csize[icol-1][nclin]; 184 while (c = get1char()) { 185 if (c == ' ' || c == tab || c == '\n') 186 break; 187 if (c == '-' || c == '+') 188 if (snp > temp) 189 break; 190 else 191 *snp++ = c; 192 else if (digit(c)) 193 *snp++ = c; 194 else 195 break; 196 if (snp - temp > 4) 197 error("point size too large"); 198 } 199 *snp = 0; 200 if (atoi(temp) > 36) 201 error("point size unreasonable"); 202 un1getc (c); 203 continue; 204 case 'V': 205 case 'v': 206 if (icol <= 0) 207 continue; 208 temp = snp = vsize[icol-1][nclin]; 209 while (c = get1char()) { 210 if (c == ' ' || c == tab || c == '\n') 211 break; 212 if (c == '-' || c == '+') 213 if (snp > temp) 214 break; 215 else 216 *snp++ = c; 217 else if (digit(c)) 218 *snp++ = c; 219 else 220 break; 221 if (snp - temp > 4) 222 error("vertical spacing value too large"); 223 } 224 *snp = 0; 225 un1getc(c); 226 continue; 227 case 'w': 228 case 'W': 229 snp = cll [icol-1]; 230 /* Dale Smith didn't like this check - possible to have two text blocks 231 of different widths now .... 232 if (*snp) 233 { 234 Bprint(&tabout, "Ignored second width specification"); 235 continue; 236 } 237 /* end commented out code ... */ 238 stopc = 0; 239 while (c = get1char()) { 240 if (snp == cll[icol-1] && c == '(') { 241 stopc = ')'; 242 continue; 243 } 244 if ( !stopc && (c > '9' || c < '0')) 245 break; 246 if (stopc && c == stopc) 247 break; 248 *snp++ = c; 249 } 250 *snp = 0; 251 if (snp - cll[icol-1] > CLLEN) 252 error ("column width too long"); 253 if (!stopc) 254 un1getc(c); 255 continue; 256 case 'e': 257 case 'E': 258 if (icol < 1) 259 continue; 260 evenup[icol-1] = 1; 261 evenflg = 1; 262 continue; 263 case 'z': 264 case 'Z': /* zero width-ignre width this item */ 265 if (icol < 1) 266 continue; 267 flags[icol-1][nclin] |= ZEROW; 268 continue; 269 case 'u': 270 case 'U': /* half line up */ 271 if (icol < 1) 272 continue; 273 flags[icol-1][nclin] |= HALFUP; 274 continue; 275 case '0': 276 case '1': 277 case '2': 278 case '3': 279 case '4': 280 case '5': 281 case '6': 282 case '7': 283 case '8': 284 case '9': 285 sn[0] = c; 286 snp = sn + 1; 287 while (digit(*snp++ = c = get1char())) 288 ; 289 un1getc(c); 290 sep[icol-1] = max(sep[icol-1], numb(sn)); 291 continue; 292 case '|': 293 lefline[icol][nclin]++; 294 if (icol == 0) 295 left1flg = 1; 296 continue; 297 } 298 } 299 error("EOF reading table specification"); 300 } 301 302 303 int 304 findcol(void) 305 { 306 # define FLNLIM 200 307 /* this counts the number of columns and then puts the line back*/ 308 char *s, line[FLNLIM+2], *p; 309 int c, n = 0, inpar = 0; 310 311 while ((c = get1char()) != 0 && c == ' ') 312 ; 313 if (c != '\n') 314 un1getc(c); 315 for (s = line; *s = c = get1char(); s++) { 316 if (c == ')') 317 inpar = 0; 318 if (inpar) 319 continue; 320 if (c == '\n' || c == 0 || c == '.' || c == ',') 321 break; 322 else if (c == '(') 323 inpar = 1; 324 else if (s >= line + FLNLIM) 325 error("too long spec line"); 326 } 327 for (p = line; p < s; p++) 328 switch (*p) { 329 case 'l': 330 case 'r': 331 case 'c': 332 case 'n': 333 case 'a': 334 case 's': 335 case 'L': 336 case 'R': 337 case 'C': 338 case 'N': 339 case 'A': 340 case 'S': 341 case '-': 342 case '=': 343 case '_': 344 n++; 345 } 346 while (p >= line) 347 un1getc(*p--); 348 return(n); 349 } 350 351 352 void 353 garray(int qcol) 354 { 355 style = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int)); 356 evenup = (int *) getcore(qcol, sizeof(int)); 357 lefline = (int (*)[]) getcore(MAXHEAD * (qcol + 1), sizeof (int)); /*+1 for sample55 loop - others may need it too*/ 358 font = (char (*)[][2]) getcore(MAXHEAD * qcol, 2); 359 csize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4); 360 vsize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4); 361 flags = (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int)); 362 cll = (char (*)[])getcore(qcol, CLLEN); 363 sep = (int *) getcore(qcol + 1, sizeof(int)); 364 sep++; /* sep[-1] must be legal */ 365 used = (int *) getcore(qcol + 1, sizeof(int)); 366 lused = (int *) getcore(qcol + 1, sizeof(int)); 367 rused = (int *) getcore(qcol + 1, sizeof(int)); 368 doubled = (int *) getcore(qcol + 1, sizeof(int)); 369 acase = (int *) getcore(qcol + 1, sizeof(int)); 370 topat = (int *) getcore(qcol + 1, sizeof(int)); 371 } 372 373 374 char * 375 getcore(int a, int b) 376 { 377 char *x; 378 x = calloc(a, b); 379 if (x == 0) 380 error("Couldn't get memory"); 381 return(x); 382 } 383 384 385 void 386 freearr(void) 387 { 388 free(style); 389 free(evenup); 390 free(lefline); 391 free(flags); 392 free(font); 393 free(csize); 394 free(vsize); 395 free(cll); 396 free(--sep); /* netnews says this should be --sep because incremented earlier! */ 397 free(used); 398 free(lused); 399 free(rused); 400 free(doubled); 401 free(acase); 402 free(topat); 403 }