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