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