1 #ifndef lint
2 static char sccsid[] = "@(#)rdata.c	1.3 (CWI) 93/07/27";
3 #endif lint
4 
5 
6 /*
7  * read data for table
8  */
9 
10 #include "defs.h"
11 #include "ext.h"
12 #include <signal.h>
13 
14 gettbl(){
15 	int icol, ch;
16 	extern interr();
17 	extern char *chspace();
18 	extern char *maknew();
19 	extern int *alocv();
20 	extern char *gettext();
21 	sig_t savsign;
22 
23 	cstore = cspace = chspace();
24 	textflg = 0;
25 	for(nlin = nslin = 0; gets1(cstore); nlin++){
26 		stynum[nlin] = nslin;
27 		if(prefix(".TE", cstore)){
28 			leftover = 0;
29 			break;
30 		}
31 		if(prefix(".TC", cstore) || prefix(".T&", cstore)){
32 			readspec();
33 			nslin++;
34 		}
35 		if(nlin >= MAXLIN){
36 			leftover = (int)cstore;
37 			break;
38 		}
39 		fullbot[nlin] = 0;
40 		if(cstore[0] == '.' && !isdigit(cstore[1])){
41 			instead[nlin] = cstore;
42 			while(*cstore++)
43 				;
44 			continue;
45 		} else
46 			instead[nlin] = 0;
47 		if(nodata(nlin)){
48 			if(ch = oneh(nlin))
49 				fullbot[nlin] = ch;
50 #ifdef FIX
51 	This FIX didn't work, so commented out for the time being,
52 	problem temporarily solved with signal catching...
53 dprint(".\\\" FIX nlin = %d\n", nlin);
54 dprint(".\\\" FIXgettbl: alocv %d\n", (ncol + 2) * sizeof(table[0][0]));
55 			/*
56 			 * start of FIX?
57 			 *
58 			 * Need to allocate pointers as well, in case
59 			 * of vertical spanning.
60 			 * I hope this works
61 			 */
62 			table[nlin] = (struct colstr *) alocv((ncol + 2) *
63 							sizeof(*table[0]));
64 			/*
65 			 * Does alocv clears the pointers?
66 			 */
67 		{	int tmp;
68 			for( tmp = 0; tmp < ncol +2; tmp++) {
69 		table[nlin][tmp].col = "";
70 		table[nlin][tmp].rcol = (char*)0;
71 printf(".\\\"FIX table[%d][%d].col: <%s>\n", nlin, tmp, table[nlin][tmp].col);
72 printf(".\\\"FIX table[%d][%d].rcol: <%s>\n", nlin, tmp, table[nlin][tmp].rcol);
73 			}
74 		}
75 			/*
76 			 * End of FIX
77 			 */
78 #endif FIX
79 			nlin++;
80 			nslin++;
81 			instead[nlin] = (char *) 0;
82 			fullbot[nlin] = 0;
83 dprint(".\\\" gettbl continue, due to nodata\n");
84 		}
85 		table[nlin] = (struct colstr *) alocv((ncol + 2) *
86 							sizeof(*table[0]));
87 		if(cstore[1] == 0) {
88 			switch(cstore[0]){
89 
90 			case '_':
91 				fullbot[nlin] = '-';
92 				continue;
93 			case '=':
94 				fullbot[nlin] = '=';
95 				continue;
96 			}
97 		}
98 		stynum[nlin] = nslin;
99 		nslin = min(nslin + 1, nclin - 1);
100 		for(icol = 0; icol < ncol; icol++){
101 			table[nlin][icol].col = cstore;
102 			table[nlin][icol].rcol = (char*)0;
103 			ch = 1;
104 			if(strcmp(cstore, "T{") == 0) {
105 				/*
106 				 * text follows
107 				 */
108 				table[nlin][icol].col =
109 						gettext(cstore, nlin, icol,
110 						font[stynum[nlin]][icol],
111 						csize[stynum[nlin]][icol]);
112 			} else {
113 				for(; (ch = *cstore) != '\0' && ch != tab; cstore++)
114 					;
115 				*cstore++ = '\0';
116 				switch(ctype(nlin, icol)){
117  					/*
118 					 * numerical or alpha, subcol
119 					 */
120 				case 'n':
121 					table[nlin][icol].rcol = maknew(table[nlin][icol].col);
122 					break;
123 				case 'a':
124 					table[nlin][icol].rcol = table[nlin][icol].col;
125 					table[nlin][icol].col = "";
126 					break;
127 				}
128 			}
129 			while(ctype(nlin, icol + 1) == 's'){
130 				/*
131 				 * spanning
132 				 */
133 				table[nlin][++icol].col = "";
134 			}
135 			if(ch == '\0')
136 				break;
137 		}
138 		while(++icol < ncol + 2){
139 			table[nlin][icol].col = "";
140 			table[nlin][icol].rcol = (char*)0;
141 		}
142 		while(*cstore != '\0')
143 			cstore++;
144 		if(cstore - cspace > MAXCHS)
145 			cstore = cspace = chspace();
146 	}
147 	last = cstore;
148 	/*
149 	 * the next example is weird & legal tbl input.
150 	 * however, it generates a bus error.
151 .TS
152 linesize(24) tab(@);
153 ct| c cf3
154 ^ | _ _
155 ^ | cf3 cf3
156 ^ | c s.
157 0,0@0,1@0,2
158 @1,1@1,2
159 @2,1@2,2
160 .TE
161 	 * This works:
162 .TS
163 linesize(24) tab(@);
164 ct| c cf3
165 ^ | cf3 cf3
166 ^ | c s.
167 0,0@0,1@0,2
168 @1,1@1,2
169 @2,1@2,2
170 .TE
171 	 * So it is the vertical spanning of an empty column which
172 	 * cuases problems
173 	 */
174 	savsign = signal(SIGBUS, interr);
175 	permute();
176 	signal(SIGBUS, savsign);
177 	if(textflg)
178 		untext();
179 	return;
180 }
181 
182 /*
183  * return 1 if no type of column specified for this line
184  */
185 nodata(il){
186 	int c;
187 
188 	for(c = 0; c < ncol; c++){
189 		switch(ctype(il, c)){
190 
191 		case 'c':
192 		case 'n':
193 		case 'r':
194 		case 'l':
195 		case 's':
196 		case 'a':
197 			return(0);
198 		}
199 	}
200 	return(1);
201 }
202 
203 /*
204  * returns the type of heading if they are all the same for the table
205  * line?
206  */
207 oneh(lin){
208 	int k, icol;
209 
210 	k = ctype(lin, 0);
211 	for(icol = 1; icol < ncol; icol++){
212 		if(k != ctype(lin, icol))
213 			return(0);
214 	}
215 	return(k);
216 }
217 
218 #define SPAN "\\^"
219 
220 permute(){
221 	register int irow, jcol, is;
222 	char *start, *strig;
223 
224 	for(jcol = 0; jcol < ncol; jcol++){
225 		for(irow = 1; irow < nlin; irow++){
226 			if(vspand(irow, jcol, 0)){
227 				is = prev(irow);
228 				if(is < 0)
229 					error("Vertical spanning in first row not allowed");
230 				start = table[is][jcol].col;
231 				strig = table[is][jcol].rcol;
232 				while(irow < nlin && vspand(irow, jcol, 0)){
233 					irow++;
234 				}
235 				table[--irow][jcol].col = start;
236 				table[irow][jcol].rcol = strig;
237 				while(is < irow){
238 					table[is][jcol].col = SPAN;
239 					table[is][jcol].rcol = (char*)0;
240 					is = next(is);
241 				}
242 			}
243 		}
244 	}
245 }
246 
247 /*
248  * return 1 if vertical spanning is row ir, column ij, from position ifrom
249  */
250 vspand(ir, ij, ifform)
251 {
252 	if(ir < 0)
253 		return(0);
254 	if(ir >= nlin)
255 		return(0);
256 	if(instead[ir])
257 		return(0);
258 	if(ifform == 0 && ctype(ir, ij) == '^'){
259 		return(1);
260 	}
261 	if(table[ir][ij].rcol != (char*)0)
262 		return(0);
263 	if(fullbot[ir])
264 		return(0);
265 	return(vspen(table[ir][ij].col));
266 }
267 
268 /*
269  * return 1 if the string is the same as SPAN
270  */
271 vspen(s)
272 char   *s;
273 {
274 	if(s == 0)
275 		return(0);
276 	if(!point(s))
277 		return(0);
278 	return(strcmp(s, SPAN) == 0);
279 }
280 
281 static
282 interr()
283 {
284 	error("internal tbl error -- function: permute");
285 }
286