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
gettbl()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