1 /*
2  * Copyright 1983-2003 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
7 /*	  All Rights Reserved  	*/
8 
9 
10 /*
11  * Copyright (c) 1980 Regents of the University of California.
12  * All rights reserved. The Berkeley software License Agreement
13  * specifies the terms and conditions for redistribution.
14  */
15 
16 /*	from OpenSolaris "t4.c	1.10	05/06/02 SMI"	*/
17 
18 /*
19  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
20  * Portions Copyright (c) 2015 Carsten Kunze
21  *
22  * Sccsid @(#)t4.c	1.7 (gritter) 9/8/06
23  */
24 
25  /* t4.c: read table specification */
26 # include "t..c"
27 # include <stdlib.h>
28 # include <string.h>
29 int oncol;
30 static int morecols(int);
31 static int moreheads(int);
32 static void initspec(int);
33 static void inithead(int, int);
34 
35 int
getspec(void)36 getspec(void) {
37 	int i;
38 	moreheads(0);
39 	morecols(0);
40 	initspec(0);
41 	nclin=ncol=0;
42 	oncol =0;
43 	left1flg=rightl=0;
44 	if (readspec())
45 		return -1;
46 	fprintf(tabout, ".rm");
47 	for(i=0; i<ncol; i++)
48 		fprintf(tabout, " %02d", 80+i);
49 	fprintf(tabout, "\n");
50 	return 0;
51 }
52 
53 int
readspec(void)54 readspec(void)
55 {
56 	int icol, c, sawchar, stopc, i;
57 	char sn[10], *snp, *temp;
58 	sawchar=icol=0;
59 	while ((c=get1char()))
60 	{
61 		switch(c)
62 		{
63 		default:
64 			if (c != tab)
65 				return error("bad table specification character");
66 		case ' ': /* note this is also case tab */
67 			continue;
68 		case '\n':
69 			if(sawchar==0) continue;
70 		case ',':
71 		case '.': /* end of table specification */
72 			ncol = max(ncol, icol);
73 			if (lefline[nclin][ncol]>0) {ncol++; rightl++;};
74 			if(sawchar)
75 				nclin++;
76 			if (nclin>=MAXHEAD && !moreheads(nclin))
77 				return error("too many lines in specification");
78 			icol=0;
79 			if (ncol==0 || nclin==0)
80 				return error("no specification");
81 			if (c== '.')
82 			{
83 				while ((c=get1char()) && c != '\n')
84 					if (c != ' ' && c != '\t')
85 						return error(
86 						    "dot not last character on format line");
87 				/* fix up sep - default is 3 except at edge */
88 				for(icol=0; icol<ncol; icol++)
89 					if (sep[icol]<0)
90 						sep[icol] =  icol+1<ncol ? 3 : 1;
91 				if (oncol == 0)
92 					oncol = ncol;
93 				else if (oncol +2 <ncol)
94 					return error("tried to widen table in T&, not allowed");
95 				return 0;
96 			}
97 			sawchar=0;
98 			continue;
99 		case 'C': case 'S': case 'R': case 'N': case 'L':  case 'A':
100 			c += ('a'-'A');
101 		case '_': if (c=='_') c= '-';
102 		case '=': case '-':
103 		case '^':
104 		case 'c': case 's': case 'n': case 'r': case 'l':  case 'a':
105 			style[nclin][icol]=c;
106 			if (c== 's' && icol<=0)
107 				return error("first column can not be S-type");
108 			if (c=='s' && style[nclin][icol-1] == 'a')
109 			{
110 				fprintf(tabout,
111 				    ".tm warning: can't span a-type cols, changed to l\n");
112 				style[nclin][icol-1] = 'l';
113 			}
114 			if (c=='s' && style[nclin][icol-1] == 'n')
115 			{
116 				fprintf(tabout,
117 				    ".tm warning: can't span n-type cols, changed to c\n");
118 				style[nclin][icol-1] = 'c';
119 			}
120 			icol++;
121 			if (c=='^' && nclin<=0)
122 				return error("first row can not contain vertical span");
123 			if (icol>=MAXCOL && !morecols(icol))
124 				return error("too many columns in table");
125 			sawchar=1;
126 			continue;
127 		case 'b': case 'i':
128 			c += 'A'-'a';
129 			/* FALLTHRU */
130 		case 'B': case 'I':
131 			if (sawchar == 0)
132 				continue;
133 			if (icol==0) continue;
134 			snp=font[nclin][icol-1];
135 			snp[0]= (c=='I' ? '2' : '3');
136 			snp[1]=0;
137 			continue;
138 		case 't': case 'T':
139 			if (sawchar == 0) {
140 				continue;
141 			}
142 			if (icol>0)
143 			ctop[nclin][icol-1] = 1;
144 			continue;
145 		case 'd': case 'D':
146 			if (sawchar == 0)
147 				continue;
148 			if (icol>0)
149 			ctop[nclin][icol-1] = -1;
150 			continue;
151 		case 'f': case 'F':
152 			if (sawchar == 0)
153 				continue;
154 			if (icol==0) continue;
155 			snp=font[nclin][icol-1];
156 			snp[0]=snp[1]=stopc=0;
157 			for(i=0; i<CLLEN; i++)
158 			{
159 				if (stopc==0 && i==2) break;
160 				do
161 					c = get1char();
162 				while (i==0 && c==' ');
163 				if (i==0 && c=='(')
164 				{
165 					stopc=')';
166 					c = get1char();
167 				}
168 				if (c==0) break;
169 				if (c==stopc) {stopc=0; break;}
170 				if (stopc==0)  if (c==' ' || c== tab ) break;
171 				if (c=='.'){un1getc(c); break;}
172 				if (c=='\n'){un1getc(c); break;}
173 				snp[i] = c;
174 				if (c>= '0' && c<= '9') break;
175 			}
176 			if (stopc) if (get1char()!=stopc)
177 				return error("Nonterminated font name");
178 			continue;
179 		case 'P': case 'p':
180 			if (sawchar == 0)
181 				continue;
182 			if (icol<=0) continue;
183 			temp = snp = csize[nclin][icol-1];
184 			while ((c = get1char()))
185 			{
186 				if (c== ' ' || c== tab || c=='\n') break;
187 				if (c=='-' || c == '+')
188 					if (snp>temp)
189 						break;
190 					else
191 						*snp++=c;
192 				else
193 				if (digit(c))
194 					*snp++ = c;
195 				else break;
196 				if (snp-temp>20)
197 					return error("point size too large");
198 			}
199 			*snp = 0;
200 			if (atoi(temp)>36)
201 				return error("point size unreasonable");
202 			un1getc (c);
203 			continue;
204 		case 'V': case 'v':
205 			if (sawchar == 0)
206 				continue;
207 			if (icol<=0) continue;
208 			temp = snp = vsize[nclin][icol-1];
209 			while ((c = get1char()))
210 			{
211 				if (c== ' ' || c== tab || c=='\n') break;
212 				if (c=='-' || c == '+')
213 					if (snp>temp)
214 						break;
215 					else
216 						*snp++=c;
217 				else
218 				if (digit(c))
219 					*snp++ = c;
220 				else break;
221 				if (snp-temp>20)
222 					return error(
223 					"vertical spacing value too large");
224 			}
225 			*snp=0;
226 			un1getc(c);
227 			continue;
228 		case 'w': case 'W':
229 			if (sawchar == 0) {
230 				/*
231 				 * This should be an error case.
232 				 * However, for the backward-compatibility,
233 				 * treat as if 'c' was specified.
234 				 */
235 				style[nclin][icol] = 'c';
236 				icol++;
237 				if (icol >= MAXCOL && !morecols(icol)) {
238 					return error("too many columns in table");
239 				}
240 				sawchar = 1;
241 			}
242 
243 			snp = cll [icol-1];
244 			/* Dale Smith didn't like this check
245 			 * possible to have two text blocks
246 			 *  of different widths now ....
247 			if (*snp)
248 				{
249 				fprintf(tabout,
250 				"Ignored second width specification");
251 				continue;
252 				}
253 			* end commented out code ... */
254 			stopc=0;
255 			while ((c = get1char()))
256 			{
257 				if (snp==cll[icol-1] && c==' ')
258 					continue;
259 				if (snp==cll[icol-1] && c=='(')
260 				{
261 					stopc = ')';
262 					continue;
263 				}
264 				if ( !stopc && (c>'9' || c< '0'))
265 					break;
266 				if (stopc && c== stopc)
267 					break;
268 				if (snp-cll[icol-1]>CLLEN)
269 					return error ("column width too long");
270 				*snp++ =c;
271 			}
272 			*snp=0;
273 			if (!stopc)
274 				un1getc(c);
275 			continue;
276 		case 'x': case 'X':
277 			if (!sawchar || icol < 1) break;
278 			xcol[icol-1] = 1;
279 			xcolflg++;
280 			expflg = 0;
281 			break;
282 		case 'e': case 'E':
283 			if (sawchar == 0)
284 				continue;
285 			if (icol<1) continue;
286 			evenup[icol-1]=1;
287 			evenflg=1;
288 			continue;
289 		case '0': case '1': case '2': case '3': case '4':
290 		case '5': case '6': case '7': case '8': case '9':
291 			sn[0] = c;
292 			snp=sn+1;
293 			while (digit(*snp++ = c = get1char()))
294 				;
295 			un1getc(c);
296 			sep[icol-1] = max(sep[icol-1], numb(sn));
297 			continue;
298 		case '|':
299 			lefline[nclin][icol]++;
300 			if (icol==0) left1flg=1;
301 			continue;
302 		}
303 	}
304 	return error("EOF reading table specification");
305 }
306 
307 static int
morecols(int n)308 morecols(int n)
309 {
310 	int i, j, inc = 10, maxcol;
311 	void *vp;
312 	if (n < MAXCOL) return(1);
313 	while ((maxcol = MAXCOL + inc) < n) inc *= 2;
314 	for (i=0; i<MAXHEAD; i++)
315 	{
316 		if ((vp = realloc(style[i], maxcol * sizeof **style)) == NULL)
317 			return(0);
318 		style[i] = vp;
319 		if ((vp = realloc(ctop[i], maxcol * sizeof **ctop)) == NULL)
320 			return(0);
321 		ctop[i] = vp;
322 		if ((vp = realloc(font[i], maxcol * sizeof **font)) == NULL)
323 			return(0);
324 		font[i] = vp;
325 		if ((vp = realloc(csize[i], maxcol * sizeof **csize)) == NULL)
326 			return(0);
327 		csize[i] = vp;
328 		if ((vp = realloc(vsize[i], maxcol * sizeof **vsize)) == NULL)
329 			return(0);
330 		vsize[i] = vp;
331 		if ((vp = realloc(lefline[i], maxcol * sizeof **lefline)) == NULL)
332 			return(0);
333 		lefline[i] = vp;
334 		for (j=MAXCOL; j<maxcol; j++)
335 		{
336 			if ((font[i][j] = calloc(CLLEN, sizeof ***font)) == NULL)
337 				return(0);
338 			if ((csize[i][j] = calloc(20, sizeof ***csize)) == NULL)
339 				return(0);
340 			if ((vsize[i][j] = calloc(20, sizeof ***vsize)) == NULL)
341 				return(0);
342 		}
343 	}
344 	if ((vp = realloc(cll, maxcol * sizeof *cll)) == NULL)
345 		return(0);
346 	cll = vp;
347 	for (j=MAXCOL; j<maxcol; j++)
348 		if ((cll[j] = calloc(CLLEN, sizeof **cll)) == NULL)
349 			return(0);
350 	if ((vp = realloc(xcol, maxcol * sizeof(*xcol))) == NULL)
351 		return 0;
352 	xcol = vp;
353 	if ((vp = realloc(evenup, maxcol * sizeof *evenup)) == NULL)
354 		return(0);
355 	evenup = vp;
356 	if ((vp = realloc(sep, maxcol * sizeof *sep)) == NULL)
357 		return(0);
358 	sep = vp;
359 	if ((vp = realloc(used, maxcol * sizeof *used)) == NULL)
360 		return(0);
361 	used = vp;
362 	if ((vp = realloc(lused, maxcol * sizeof *lused)) == NULL)
363 		return(0);
364 	lused = vp;
365 	if ((vp = realloc(rused, maxcol * sizeof *rused)) == NULL)
366 		return(0);
367 	rused = vp;
368 	if ((vp = realloc(topat, maxcol * sizeof *topat)) == NULL)
369 		return(0);
370 	topat = vp;
371 	MAXCOL = maxcol;
372 	initspec(MAXCOL - inc);
373 	return(1);
374 }
375 static int
moreheads(int n)376 moreheads(int n)
377 {
378 	int i, j, inc = 10, maxhead;
379 	void *vp;
380 	if (n<MAXHEAD) return(1);
381 	while ((maxhead = MAXHEAD + inc) < n) inc *= 2;
382 	if ((vp = realloc(style, maxhead * sizeof *style)) == NULL)
383 		return(0);
384 	style = vp;
385 	if ((vp = realloc(ctop, maxhead * sizeof *ctop)) == NULL)
386 		return(0);
387 	ctop = vp;
388 	if ((vp = realloc(font, maxhead * sizeof *font)) == NULL)
389 		return(0);
390 	font = vp;
391 	if ((vp = realloc(csize, maxhead * sizeof *csize)) == NULL)
392 		return(0);
393 	csize = vp;
394 	if ((vp = realloc(vsize, maxhead * sizeof *vsize)) == NULL)
395 		return(0);
396 	vsize = vp;
397 	if ((vp = realloc(lefline, maxhead * sizeof *lefline)) == NULL)
398 		return(0);
399 	lefline = vp;
400 	if (MAXCOL == 0)
401 	{
402 		memset(style, 0, maxhead * sizeof *style);
403 		memset(ctop, 0, maxhead * sizeof *ctop);
404 		memset(font, 0, maxhead * sizeof *font);
405 		memset(csize, 0, maxhead * sizeof *csize);
406 		memset(vsize, 0, maxhead * sizeof *vsize);
407 		memset(lefline, 0, maxhead * sizeof *lefline);
408 	}
409 	if (MAXCOL) for (i=MAXHEAD; i<maxhead; i++)
410 	{
411 		if ((vp = calloc(MAXCOL, sizeof **style)) == NULL)
412 			return(0);
413 		style[i] = vp;
414 		if ((vp = calloc(MAXCOL, sizeof **ctop)) == NULL)
415 			return(0);
416 		ctop[i] = vp;
417 		if ((vp = calloc(MAXCOL, sizeof **font)) == NULL)
418 			return(0);
419 		font[i] = vp;
420 		if ((vp = calloc(MAXCOL, sizeof **csize)) == NULL)
421 			return(0);
422 		csize[i] = vp;
423 		if ((vp = calloc(MAXCOL, sizeof **vsize)) == NULL)
424 			return(0);
425 		vsize[i] = vp;
426 		if ((vp = calloc(MAXCOL, sizeof **lefline)) == NULL)
427 			return(0);
428 		lefline[i] = vp;
429 		for (j=0; j<MAXCOL; j++)
430 		{
431 			if ((vp = calloc(CLLEN, sizeof ***font)) == NULL)
432 				return(0);
433 			font[i][j] = vp;
434 			if ((vp = calloc(20, sizeof ***csize)) == NULL)
435 				return(0);
436 			csize[i][j] = vp;
437 			if ((vp = calloc(20, sizeof ***vsize)) == NULL)
438 				return(0);
439 			vsize[i][j] = vp;
440 		}
441 	}
442 	MAXHEAD = maxhead;
443 	for (j=0; j<MAXCOL; j++)
444 		inithead(MAXHEAD-inc, j);
445 	return(1);
446 }
447 static void
initspec(int scol)448 initspec(int scol)
449 {
450 	int icol;
451 	for(icol=scol; icol<MAXCOL; icol++)
452 	{
453 		sep[icol]= -1;
454 		evenup[icol]=0;
455 		cll[icol][0]=0;
456 		xcol[icol] = 0;
457 		inithead(0, icol);
458 	}
459 	xcolflg = 0;
460 }
461 static void
inithead(int shead,int icol)462 inithead(int shead, int icol)
463 {
464 int i;
465 for(i=shead; i<MAXHEAD; i++)
466 	{
467 	csize[i][icol][0]=0;
468 	vsize[i][icol][0]=0;
469 	font[i][icol][0] = lefline[i][icol] = 0;
470 	ctop[i][icol]=0;
471 	style[i][icol]= 'l';
472 	}
473 }
474