xref: /illumos-gate/usr/src/cmd/tbl/t4.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * Copyright 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  /* t4.c: read table specification */
17 # include "t..c"
18 int oncol;
19 
20 void	readspec(void);
21 
22 void
23 getspec(void)
24 {
25 int icol, i;
26 for(icol=0; icol<MAXCOL; icol++)
27 	{
28 	sep[icol]= -1;
29 	evenup[icol]=0;
30 	cll[icol][0]=0;
31 	for(i=0; i<MAXHEAD; i++)
32 		{
33 		csize[i][icol][0]=0;
34 		vsize[i][icol][0]=0;
35 		font[i][icol][0] = lefline[i][icol] = 0;
36 		ctop[i][icol]=0;
37 		style[i][icol]= 'l';
38 		}
39 	}
40 nclin=ncol=0;
41 oncol =0;
42 left1flg=rightl=0;
43 readspec();
44 fprintf(tabout, ".rm");
45 for(i=0; i<ncol; i++)
46 	fprintf(tabout, " %02d", 80+i);
47 fprintf(tabout, "\n");
48 }
49 
50 void
51 readspec(void)
52 {
53 int icol, c, sawchar, stopc, i;
54 char sn[10], *snp, *temp;
55 sawchar=icol=0;
56 while (c=get1char())
57 	{
58 	switch(c)
59 		{
60 		default:
61 			if (c != tab)
62 			error(gettext("bad table specification character"));
63 			/* FALLTHROUGH */
64 		case ' ': /* note this is also case tab */
65 			continue;
66 		case '\n':
67 			if(sawchar==0) continue;
68 			/* FALLTHROUGH */
69 		case ',':
70 		case '.': /* end of table specification */
71 			ncol = max(ncol, icol);
72 			if (lefline[nclin][ncol]>0) {ncol++; rightl++;};
73 			if(sawchar)
74 				nclin++;
75 			if (nclin>=MAXHEAD)
76 				error(gettext("too many lines in specification"));
77 			icol=0;
78 			if (ncol==0 || nclin==0)
79 				error(gettext("no specification"));
80 			if (c== '.')
81 				{
82 				while ((c=get1char()) && c != '\n')
83 					if (c != ' ' && c != '\t')
84 						error(gettext("dot not last character on format line"));
85 				/* fix up sep - default is 3 except at edge */
86 				for(icol=0; icol<ncol; icol++)
87 					if (sep[icol]<0)
88 						sep[icol] =  icol+1<ncol ? 3 : 1;
89 				if (oncol == 0)
90 					oncol = ncol;
91 				else if (oncol +2 <ncol)
92 					error(gettext("tried to widen table in T&, not allowed"));
93 				return;
94 				}
95 			sawchar=0;
96 			continue;
97 		case 'C': case 'S': case 'R': case 'N': case 'L':  case 'A':
98 			c += ('a'-'A');
99 			/* FALLTHROUGH */
100 		case '_': if (c=='_') c= '-';
101 			/* FALLTHROUGH */
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 				error(gettext("first column can not be S-type"));
108 			if (c=='s' && style[nclin][icol-1] == 'a')
109 				{
110 				fprintf(tabout, ".tm warning: can't span a-type cols, changed to l\n");
111 				style[nclin][icol-1] = 'l';
112 				}
113 			if (c=='s' && style[nclin][icol-1] == 'n')
114 				{
115 				fprintf(tabout, ".tm warning: can't span n-type cols, changed to c\n");
116 				style[nclin][icol-1] = 'c';
117 				}
118 			icol++;
119 			if (c=='^' && nclin<=0)
120 				error(gettext("first row can not contain vertical span"));
121 			if (icol>=MAXCOL)
122 				error(gettext("too many columns in table"));
123 			sawchar=1;
124 			continue;
125 		case 'b': case 'i':
126 			c += 'A'-'a';
127 			/* FALLTHRU */
128 		case 'B': case 'I':
129 			if (sawchar == 0)
130 				continue;
131 			if (icol==0) continue;
132 			snp=font[nclin][icol-1];
133 			snp[0]= (c=='I' ? '2' : '3');
134 			snp[1]=0;
135 			continue;
136 		case 't': case 'T':
137 			if (sawchar == 0) {
138 				continue;
139 			}
140 			if (icol>0)
141 			ctop[nclin][icol-1] = 1;
142 			continue;
143 		case 'd': case 'D':
144 			if (sawchar == 0)
145 				continue;
146 			if (icol>0)
147 			ctop[nclin][icol-1] = -1;
148 			continue;
149 		case 'f': case 'F':
150 			if (sawchar == 0)
151 				continue;
152 			if (icol==0) continue;
153 			snp=font[nclin][icol-1];
154 			snp[0]=snp[1]=stopc=0;
155 			for(i=0; i<2; i++)
156 				{
157 				c = get1char();
158 				if (i==0 && c=='(')
159 					{
160 					stopc=')';
161 					c = get1char();
162 					}
163 				if (c==0) break;
164 				if (c==stopc) {stopc=0; break;}
165 				if (stopc==0)  if (c==' ' || c== tab ) break;
166 				if (c=='\n'){un1getc(c); break;}
167 				snp[i] = c;
168 				if (c>= '0' && c<= '9') break;
169 				}
170 			if (stopc) if (get1char()!=stopc)
171 				error(gettext("Nonterminated font name"));
172 			continue;
173 		case 'P': case 'p':
174 			if (sawchar == 0)
175 				continue;
176 			if (icol<=0) continue;
177 			temp = snp = csize[nclin][icol-1];
178 			while (c = get1char())
179 				{
180 				if (c== ' ' || c== tab || c=='\n') break;
181 				if (c=='-' || c == '+')
182 					if (snp>temp)
183 						break;
184 					else
185 						*snp++=c;
186 				else
187 				if (digit(c))
188 					*snp++ = c;
189 				else break;
190 				if (snp-temp>4)
191 					error(gettext("point size too large"));
192 				}
193 			*snp = 0;
194 			if (atoi(temp)>36)
195 				error(gettext("point size unreasonable"));
196 			un1getc (c);
197 			continue;
198 		case 'V': case 'v':
199 			if (sawchar == 0)
200 				continue;
201 			if (icol<=0) continue;
202 			temp = snp = vsize[nclin][icol-1];
203 			while (c = get1char())
204 				{
205 				if (c== ' ' || c== tab || c=='\n') break;
206 				if (c=='-' || c == '+')
207 					if (snp>temp)
208 						break;
209 					else
210 						*snp++=c;
211 				else
212 				if (digit(c))
213 					*snp++ = c;
214 				else break;
215 				if (snp-temp>4)
216 					error(
217 					gettext("vertical spacing value too large")
218 					);
219 				}
220 			*snp=0;
221 			un1getc(c);
222 			continue;
223 		case 'w': case 'W':
224 			if (sawchar == 0) {
225 				/*
226 				 * This should be an error case.
227 				 * However, for the backward-compatibility,
228 				 * treat as if 'c' was specified.
229 				 */
230 				style[nclin][icol] = 'c';
231 				icol++;
232 				if (icol >= MAXCOL) {
233 					error(gettext(
234 						  "too many columns in table"));
235 				}
236 				sawchar = 1;
237 			}
238 
239 			snp = cll [icol-1];
240 		/* Dale Smith didn't like this check
241 		 * possible to have two text blocks
242 		 *  of different widths now ....
243 			if (*snp)
244 				{
245 				fprintf(tabout,
246 				gettext("Ignored second width specification"));
247 				continue;
248 				}
249 		* end commented out code ... */
250 			stopc=0;
251 			while (c = get1char())
252 				{
253 				if (snp==cll[icol-1] && c=='(')
254 					{
255 					stopc = ')';
256 					continue;
257 					}
258 				if ( !stopc && (c>'9' || c< '0'))
259 					break;
260 				if (stopc && c== stopc)
261 					break;
262 				*snp++ =c;
263 				}
264 			*snp=0;
265 			if (snp-cll[icol-1]>CLLEN)
266 				error (gettext("column width too long"));
267 			if (!stopc)
268 				un1getc(c);
269 			continue;
270 		case 'e': case 'E':
271 			if (sawchar == 0)
272 				continue;
273 			if (icol<1) continue;
274 			evenup[icol-1]=1;
275 			evenflg=1;
276 			continue;
277 		case '0': case '1': case '2': case '3': case '4':
278 		case '5': case '6': case '7': case '8': case '9':
279 			sn[0] = c;
280 			snp=sn+1;
281 			while (digit(*snp++ = c = get1char()))
282 				;
283 			un1getc(c);
284 			sep[icol-1] = max(sep[icol-1], numb(sn));
285 			continue;
286 		case '|':
287 			lefline[nclin][icol]++;
288 			if (icol==0) left1flg=1;
289 			continue;
290 		}
291 	}
292 error(gettext("EOF reading table specification"));
293 }
294