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