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