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