plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

t4.c (8288B)


      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 }