Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* t4.c: read table specification */
2
# include "t.h"
3
int	oncol;
4
 
5
void
6
getspec(void)
7
{
8
	int	icol, i;
9
 
10
	qcol = findcol() + 1;/* must allow one extra for line at right */
11
	garray(qcol);
12
	sep[-1] = -1;
13
	for (icol = 0; icol < qcol; icol++) {
14
		sep[icol] = -1;
15
		evenup[icol] = 0;
16
		cll[icol][0] = 0;
17
		for (i = 0; i < MAXHEAD; i++) {
18
			csize[icol][i][0] = 0;
19
			vsize[icol][i][0] = 0;
20
			font[icol][i][0] = lefline[icol][i] = 0;
21
			flags[icol][i] = 0;
22
			style[icol][i] = 'l';
23
		}
24
	}
25
	for (i = 0; i < MAXHEAD; i++)
26
		lefline[qcol][i] = 0;	/* fixes sample55 looping */
27
	nclin = ncol = 0;
28
	oncol = 0;
29
	left1flg = rightl = 0;
30
	readspec();
31
	Bprint(&tabout, ".rm");
32
	for (i = 0; i < ncol; i++)
33
		Bprint(&tabout, " %2s", reg(i, CRIGHT));
34
	Bprint(&tabout, "\n");
35
}
36
 
37
 
38
void
39
readspec(void)
40
{
41
	int	icol, c, sawchar, stopc, i;
42
	char	sn[10], *snp, *temp;
43
 
44
	sawchar = icol = 0;
45
	while (c = get1char()) {
46
		switch (c) {
47
		default:
48
			if (c != tab) {
49
				char buf[64];
50
				sprint(buf, "bad table specification character %c", c);
51
				error(buf);
52
			}
53
		case ' ': /* note this is also case tab */
54
			continue;
55
		case '\n':
56
			if (sawchar == 0) 
57
				continue;
58
		case ',':
59
		case '.': /* end of table specification */
60
			ncol = max(ncol, icol);
61
			if (lefline[ncol][nclin] > 0) {
62
				ncol++; 
63
				rightl++;
64
			};
65
			if (sawchar)
66
				nclin++;
67
			if (nclin >= MAXHEAD)
68
				error("too many lines in specification");
69
			icol = 0;
70
			if (ncol == 0 || nclin == 0)
71
				error("no specification");
72
			if (c == '.') {
73
				while ((c = get1char()) && c != '\n')
74
					if (c != ' ' && c != '\t')
75
						error("dot not last character on format line");
76
				/* fix up sep - default is 3 except at edge */
77
				for (icol = 0; icol < ncol; icol++)
78
					if (sep[icol] < 0)
79
						sep[icol] =  icol + 1 < ncol ? 3 : 2;
80
				if (oncol == 0)
81
					oncol = ncol;
82
				else if (oncol + 2 < ncol)
83
					error("tried to widen table in T&, not allowed");
84
				return;
85
			}
86
			sawchar = 0;
87
			continue;
88
		case 'C': 
89
		case 'S': 
90
		case 'R': 
91
		case 'N': 
92
		case 'L':  
93
		case 'A':
94
			c += ('a' - 'A');
95
		case '_': 
96
			if (c == '_') 
97
				c = '-';
98
		case '=': 
99
		case '-':
100
		case '^':
101
		case 'c': 
102
		case 's': 
103
		case 'n': 
104
		case 'r': 
105
		case 'l':  
106
		case 'a':
107
			style[icol][nclin] = c;
108
			if (c == 's' && icol <= 0)
109
				error("first column can not be S-type");
110
			if (c == 's' && style[icol-1][nclin] == 'a') {
111
				Bprint(&tabout, ".tm warning: can't span a-type cols, changed to l\n");
112
				style[icol-1][nclin] = 'l';
113
			}
114
			if (c == 's' && style[icol-1][nclin] == 'n') {
115
				Bprint(&tabout, ".tm warning: can't span n-type cols, changed to c\n");
116
				style[icol-1][nclin] = 'c';
117
			}
118
			icol++;
119
			if (c == '^' && nclin <= 0)
120
				error("first row can not contain vertical span");
121
			if (icol > qcol)
122
				error("too many columns in table");
123
			sawchar = 1;
124
			continue;
125
		case 'b': 
126
		case 'i':
127
			c += 'A' - 'a';
128
		case 'B': 
129
		case 'I':
130
			if (icol == 0) 
131
				continue;
132
			snp = font[icol-1][nclin];
133
			snp[0] = (c == 'I' ? '2' : '3');
134
			snp[1] = 0;
135
			continue;
136
		case 't': 
137
		case 'T':
138
			if (icol > 0)
139
				flags[icol-1][nclin] |= CTOP;
140
			continue;
141
		case 'd': 
142
		case 'D':
143
			if (icol > 0)
144
				flags[icol-1][nclin] |= CDOWN;
145
			continue;
146
		case 'f': 
147
		case 'F':
148
			if (icol == 0) 
149
				continue;
150
			snp = font[icol-1][nclin];
151
			snp[0] = snp[1] = stopc = 0;
152
			for (i = 0; i < 2; i++) {
153
				c = get1char();
154
				if (i == 0 && c == '(') {
155
					stopc = ')';
156
					c = get1char();
157
				}
158
				if (c == 0) 
159
					break;
160
				if (c == stopc) {
161
					stopc = 0; 
162
					break;
163
				}
164
				if (stopc == 0)  
165
					if (c == ' ' || c == tab ) 
166
						break;
167
				if (c == '\n' || c == '|') {
168
					un1getc(c); 
169
					break;
170
				}
171
				snp[i] = c;
172
				if (c >= '0' && c <= '9') 
173
					break;
174
			}
175
			if (stopc) 
176
				if (get1char() != stopc)
177
					error("Nonterminated font name");
178
			continue;
179
		case 'P': 
180
		case 'p':
181
			if (icol <= 0) 
182
				continue;
183
			temp = snp = csize[icol-1][nclin];
184
			while (c = get1char()) {
185
				if (c == ' ' || c == tab || c == '\n') 
186
					break;
187
				if (c == '-' || c == '+')
188
					if (snp > temp)
189
						break;
190
					else
191
						*snp++ = c;
192
				else if (digit(c))
193
					*snp++ = c;
194
				else 
195
					break;
196
				if (snp - temp > 4)
197
					error("point size too large");
198
			}
199
			*snp = 0;
200
			if (atoi(temp) > 36)
201
				error("point size unreasonable");
202
			un1getc (c);
203
			continue;
204
		case 'V': 
205
		case 'v':
206
			if (icol <= 0) 
207
				continue;
208
			temp = snp = vsize[icol-1][nclin];
209
			while (c = get1char()) {
210
				if (c == ' ' || c == tab || c == '\n') 
211
					break;
212
				if (c == '-' || c == '+')
213
					if (snp > temp)
214
						break;
215
					else
216
						*snp++ = c;
217
				else if (digit(c))
218
					*snp++ = c;
219
				else 
220
					break;
221
				if (snp - temp > 4)
222
					error("vertical spacing value too large");
223
			}
224
			*snp = 0;
225
			un1getc(c);
226
			continue;
227
		case 'w': 
228
		case 'W':
229
			snp = cll [icol-1];
230
			/* Dale Smith didn't like this check - possible to have two text blocks
231
		   of different widths now ....
232
			if (*snp)
233
				{
234
				Bprint(&tabout, "Ignored second width specification");
235
				continue;
236
				}
237
		/* end commented out code ... */
238
			stopc = 0;
239
			while (c = get1char()) {
240
				if (snp == cll[icol-1] && c == '(') {
241
					stopc = ')';
242
					continue;
243
				}
244
				if ( !stopc && (c > '9' || c < '0'))
245
					break;
246
				if (stopc && c == stopc)
247
					break;
248
				*snp++ = c;
249
			}
250
			*snp = 0;
251
			if (snp - cll[icol-1] > CLLEN)
252
				error ("column width too long");
253
			if (!stopc)
254
				un1getc(c);
255
			continue;
256
		case 'e': 
257
		case 'E':
258
			if (icol < 1) 
259
				continue;
260
			evenup[icol-1] = 1;
261
			evenflg = 1;
262
			continue;
263
		case 'z': 
264
		case 'Z': /* zero width-ignre width this item */
265
			if (icol < 1) 
266
				continue;
267
			flags[icol-1][nclin] |= ZEROW;
268
			continue;
269
		case 'u': 
270
		case 'U': /* half line up */
271
			if (icol < 1) 
272
				continue;
273
			flags[icol-1][nclin] |= HALFUP;
274
			continue;
275
		case '0': 
276
		case '1': 
277
		case '2': 
278
		case '3': 
279
		case '4':
280
		case '5': 
281
		case '6': 
282
		case '7': 
283
		case '8': 
284
		case '9':
285
			sn[0] = c;
286
			snp = sn + 1;
287
			while (digit(*snp++ = c = get1char()))
288
				;
289
			un1getc(c);
290
			sep[icol-1] = max(sep[icol-1], numb(sn));
291
			continue;
292
		case '|':
293
			lefline[icol][nclin]++;
294
			if (icol == 0) 
295
				left1flg = 1;
296
			continue;
297
		}
298
	}
299
	error("EOF reading table specification");
300
}
301
 
302
 
303
int
304
findcol(void)
305
{
306
# define FLNLIM 200
307
	/* this counts the number of columns and then puts the line back*/
308
	char	*s, line[FLNLIM+2], *p;
309
	int	c, n = 0, inpar = 0;
310
 
311
	while ((c = get1char()) != 0 && c == ' ')
312
		;
313
	if (c != '\n')
314
		un1getc(c);
315
	for (s = line; *s = c = get1char(); s++) {
316
		if (c == ')') 
317
			inpar = 0;
318
		if (inpar) 
319
			continue;
320
		if (c == '\n' || c == 0 || c == '.' || c == ',')
321
			break;
322
		else if (c == '(')
323
			inpar = 1;
324
		else if (s >= line + FLNLIM)
325
			error("too long spec line");
326
	}
327
	for (p = line; p < s; p++)
328
		switch (*p) {
329
		case 'l': 
330
		case 'r': 
331
		case 'c': 
332
		case 'n': 
333
		case 'a': 
334
		case 's':
335
		case 'L': 
336
		case 'R': 
337
		case 'C': 
338
		case 'N': 
339
		case 'A': 
340
		case 'S':
341
		case '-': 
342
		case '=': 
343
		case '_':
344
			n++;
345
		}
346
	while (p >= line)
347
		un1getc(*p--);
348
	return(n);
349
}
350
 
351
 
352
void
353
garray(int qcol)
354
{
355
	style =  (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int));
356
	evenup = (int *) getcore(qcol, sizeof(int));
357
	lefline = (int (*)[]) getcore(MAXHEAD * (qcol + 1), sizeof (int)); /*+1 for sample55 loop - others may need it too*/
358
	font = (char (*)[][2]) getcore(MAXHEAD * qcol, 2);
359
	csize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4);
360
	vsize = (char (*)[MAXHEAD][4]) getcore(MAXHEAD * qcol, 4);
361
	flags =  (int (*)[]) getcore(MAXHEAD * qcol, sizeof(int));
362
	cll = (char (*)[])getcore(qcol, CLLEN);
363
	sep = (int *) getcore(qcol + 1, sizeof(int));
364
	sep++; /* sep[-1] must be legal */
365
	used = (int *) getcore(qcol + 1, sizeof(int));
366
	lused = (int *) getcore(qcol + 1, sizeof(int));
367
	rused = (int *) getcore(qcol + 1, sizeof(int));
368
	doubled = (int *) getcore(qcol + 1, sizeof(int));
369
	acase = (int *) getcore(qcol + 1, sizeof(int));
370
	topat = (int *) getcore(qcol + 1, sizeof(int));
371
}
372
 
373
 
374
char	*
375
getcore(int a, int b)
376
{
377
	char	*x;
378
	x = calloc(a, b);
379
	if (x == 0)
380
		error("Couldn't get memory");
381
	return(x);
382
}
383
 
384
 
385
void
386
freearr(void)
387
{
388
	free(style);
389
	free(evenup);
390
	free(lefline);
391
	free(flags);
392
	free(font);
393
	free(csize);
394
	free(vsize);
395
	free(cll);
396
	free(--sep);	/* netnews says this should be --sep because incremented earlier! */
397
	free(used);
398
	free(lused);
399
	free(rused);
400
	free(doubled);
401
	free(acase);
402
	free(topat);
403
}
404
 
405