125073Sjaap #ifndef lint
2*64045Sbostic static char sccsid[] = "@(#)rdata.c	1.3 (CWI) 93/07/27";
325073Sjaap #endif lint
425073Sjaap 
525073Sjaap 
625091Sjaap /*
725091Sjaap  * read data for table
825091Sjaap  */
925073Sjaap 
1025073Sjaap #include "defs.h"
1125073Sjaap #include "ext.h"
1225073Sjaap #include <signal.h>
1325073Sjaap 
gettbl()1425073Sjaap gettbl(){
1525073Sjaap 	int icol, ch;
1625073Sjaap 	extern interr();
1725073Sjaap 	extern char *chspace();
1825073Sjaap 	extern char *maknew();
1925073Sjaap 	extern int *alocv();
2025073Sjaap 	extern char *gettext();
21*64045Sbostic 	sig_t savsign;
2225073Sjaap 
2325073Sjaap 	cstore = cspace = chspace();
2425073Sjaap 	textflg = 0;
2525073Sjaap 	for(nlin = nslin = 0; gets1(cstore); nlin++){
2625073Sjaap 		stynum[nlin] = nslin;
2725073Sjaap 		if(prefix(".TE", cstore)){
2825073Sjaap 			leftover = 0;
2925073Sjaap 			break;
3025073Sjaap 		}
3125073Sjaap 		if(prefix(".TC", cstore) || prefix(".T&", cstore)){
3225073Sjaap 			readspec();
3325073Sjaap 			nslin++;
3425073Sjaap 		}
3525073Sjaap 		if(nlin >= MAXLIN){
3625073Sjaap 			leftover = (int)cstore;
3725073Sjaap 			break;
3825073Sjaap 		}
3925073Sjaap 		fullbot[nlin] = 0;
4025073Sjaap 		if(cstore[0] == '.' && !isdigit(cstore[1])){
4125073Sjaap 			instead[nlin] = cstore;
4225073Sjaap 			while(*cstore++)
4325073Sjaap 				;
4425073Sjaap 			continue;
4525073Sjaap 		} else
4625073Sjaap 			instead[nlin] = 0;
4725073Sjaap 		if(nodata(nlin)){
4825073Sjaap 			if(ch = oneh(nlin))
4925073Sjaap 				fullbot[nlin] = ch;
5025073Sjaap #ifdef FIX
5125073Sjaap 	This FIX didn't work, so commented out for the time being,
5225073Sjaap 	problem temporarily solved with signal catching...
5325091Sjaap dprint(".\\\" FIX nlin = %d\n", nlin);
5425091Sjaap dprint(".\\\" FIXgettbl: alocv %d\n", (ncol + 2) * sizeof(table[0][0]));
5525073Sjaap 			/*
5625073Sjaap 			 * start of FIX?
5725073Sjaap 			 *
5825073Sjaap 			 * Need to allocate pointers as well, in case
5925073Sjaap 			 * of vertical spanning.
6025073Sjaap 			 * I hope this works
6125073Sjaap 			 */
6225073Sjaap 			table[nlin] = (struct colstr *) alocv((ncol + 2) *
6325073Sjaap 							sizeof(*table[0]));
6425073Sjaap 			/*
6525073Sjaap 			 * Does alocv clears the pointers?
6625073Sjaap 			 */
6725073Sjaap 		{	int tmp;
6825073Sjaap 			for( tmp = 0; tmp < ncol +2; tmp++) {
6925073Sjaap 		table[nlin][tmp].col = "";
7025073Sjaap 		table[nlin][tmp].rcol = (char*)0;
7125073Sjaap printf(".\\\"FIX table[%d][%d].col: <%s>\n", nlin, tmp, table[nlin][tmp].col);
7225073Sjaap printf(".\\\"FIX table[%d][%d].rcol: <%s>\n", nlin, tmp, table[nlin][tmp].rcol);
7325073Sjaap 			}
7425073Sjaap 		}
7525073Sjaap 			/*
7625073Sjaap 			 * End of FIX
7725073Sjaap 			 */
7825073Sjaap #endif FIX
7925073Sjaap 			nlin++;
8025073Sjaap 			nslin++;
8125073Sjaap 			instead[nlin] = (char *) 0;
8225073Sjaap 			fullbot[nlin] = 0;
8325091Sjaap dprint(".\\\" gettbl continue, due to nodata\n");
8425073Sjaap 		}
8525073Sjaap 		table[nlin] = (struct colstr *) alocv((ncol + 2) *
8625073Sjaap 							sizeof(*table[0]));
8725073Sjaap 		if(cstore[1] == 0) {
8825073Sjaap 			switch(cstore[0]){
8925073Sjaap 
9025073Sjaap 			case '_':
9125073Sjaap 				fullbot[nlin] = '-';
9225073Sjaap 				continue;
9325073Sjaap 			case '=':
9425073Sjaap 				fullbot[nlin] = '=';
9525073Sjaap 				continue;
9625073Sjaap 			}
9725073Sjaap 		}
9825073Sjaap 		stynum[nlin] = nslin;
9925073Sjaap 		nslin = min(nslin + 1, nclin - 1);
10025073Sjaap 		for(icol = 0; icol < ncol; icol++){
10125073Sjaap 			table[nlin][icol].col = cstore;
10225073Sjaap 			table[nlin][icol].rcol = (char*)0;
10325073Sjaap 			ch = 1;
10425073Sjaap 			if(strcmp(cstore, "T{") == 0) {
10525073Sjaap 				/*
10625073Sjaap 				 * text follows
10725073Sjaap 				 */
10825073Sjaap 				table[nlin][icol].col =
10925073Sjaap 						gettext(cstore, nlin, icol,
11025073Sjaap 						font[stynum[nlin]][icol],
11125073Sjaap 						csize[stynum[nlin]][icol]);
11225073Sjaap 			} else {
11325073Sjaap 				for(; (ch = *cstore) != '\0' && ch != tab; cstore++)
11425073Sjaap 					;
11525073Sjaap 				*cstore++ = '\0';
11625073Sjaap 				switch(ctype(nlin, icol)){
11725073Sjaap  					/*
11825073Sjaap 					 * numerical or alpha, subcol
11925073Sjaap 					 */
12025073Sjaap 				case 'n':
12125073Sjaap 					table[nlin][icol].rcol = maknew(table[nlin][icol].col);
12225073Sjaap 					break;
12325073Sjaap 				case 'a':
12425073Sjaap 					table[nlin][icol].rcol = table[nlin][icol].col;
12525073Sjaap 					table[nlin][icol].col = "";
12625073Sjaap 					break;
12725073Sjaap 				}
12825073Sjaap 			}
12925073Sjaap 			while(ctype(nlin, icol + 1) == 's'){
13025073Sjaap 				/*
13125073Sjaap 				 * spanning
13225073Sjaap 				 */
13325073Sjaap 				table[nlin][++icol].col = "";
13425073Sjaap 			}
13525073Sjaap 			if(ch == '\0')
13625073Sjaap 				break;
13725073Sjaap 		}
13825073Sjaap 		while(++icol < ncol + 2){
13925073Sjaap 			table[nlin][icol].col = "";
14025073Sjaap 			table[nlin][icol].rcol = (char*)0;
14125073Sjaap 		}
14225073Sjaap 		while(*cstore != '\0')
14325073Sjaap 			cstore++;
14425073Sjaap 		if(cstore - cspace > MAXCHS)
14525073Sjaap 			cstore = cspace = chspace();
14625073Sjaap 	}
14725073Sjaap 	last = cstore;
14825091Sjaap 	/*
14925091Sjaap 	 * the next example is weird & legal tbl input.
15025091Sjaap 	 * however, it generates a bus error.
15125091Sjaap .TS
15225091Sjaap linesize(24) tab(@);
15325091Sjaap ct| c cf3
15425091Sjaap ^ | _ _
15525091Sjaap ^ | cf3 cf3
15625091Sjaap ^ | c s.
15725091Sjaap 0,0@0,1@0,2
15825091Sjaap @1,1@1,2
15925091Sjaap @2,1@2,2
16025091Sjaap .TE
16125091Sjaap 	 * This works:
16225091Sjaap .TS
16325091Sjaap linesize(24) tab(@);
16425091Sjaap ct| c cf3
16525091Sjaap ^ | cf3 cf3
16625091Sjaap ^ | c s.
16725091Sjaap 0,0@0,1@0,2
16825091Sjaap @1,1@1,2
16925091Sjaap @2,1@2,2
17025091Sjaap .TE
17125091Sjaap 	 * So it is the vertical spanning of an empty column which
17225091Sjaap 	 * cuases problems
17325091Sjaap 	 */
17425073Sjaap 	savsign = signal(SIGBUS, interr);
17525073Sjaap 	permute();
17625073Sjaap 	signal(SIGBUS, savsign);
17725073Sjaap 	if(textflg)
17825073Sjaap 		untext();
17925073Sjaap 	return;
18025073Sjaap }
18125073Sjaap 
18225073Sjaap /*
18325073Sjaap  * return 1 if no type of column specified for this line
18425073Sjaap  */
18525073Sjaap nodata(il){
18625073Sjaap 	int c;
18725073Sjaap 
18825073Sjaap 	for(c = 0; c < ncol; c++){
18925073Sjaap 		switch(ctype(il, c)){
19025073Sjaap 
19125073Sjaap 		case 'c':
19225073Sjaap 		case 'n':
19325073Sjaap 		case 'r':
19425073Sjaap 		case 'l':
19525073Sjaap 		case 's':
19625073Sjaap 		case 'a':
19725073Sjaap 			return(0);
19825073Sjaap 		}
19925073Sjaap 	}
20025073Sjaap 	return(1);
20125073Sjaap }
20225073Sjaap 
20325073Sjaap /*
20425073Sjaap  * returns the type of heading if they are all the same for the table
20525073Sjaap  * line?
20625073Sjaap  */
20725073Sjaap oneh(lin){
20825073Sjaap 	int k, icol;
20925073Sjaap 
21025073Sjaap 	k = ctype(lin, 0);
21125073Sjaap 	for(icol = 1; icol < ncol; icol++){
21225073Sjaap 		if(k != ctype(lin, icol))
21325073Sjaap 			return(0);
21425073Sjaap 	}
21525073Sjaap 	return(k);
21625073Sjaap }
21725073Sjaap 
21825073Sjaap #define SPAN "\\^"
21925073Sjaap 
22025073Sjaap permute(){
22125073Sjaap 	register int irow, jcol, is;
22225073Sjaap 	char *start, *strig;
22325073Sjaap 
22425073Sjaap 	for(jcol = 0; jcol < ncol; jcol++){
22525073Sjaap 		for(irow = 1; irow < nlin; irow++){
22625073Sjaap 			if(vspand(irow, jcol, 0)){
22725073Sjaap 				is = prev(irow);
22825073Sjaap 				if(is < 0)
22925073Sjaap 					error("Vertical spanning in first row not allowed");
23025073Sjaap 				start = table[is][jcol].col;
23125073Sjaap 				strig = table[is][jcol].rcol;
23225073Sjaap 				while(irow < nlin && vspand(irow, jcol, 0)){
23325073Sjaap 					irow++;
23425073Sjaap 				}
23525073Sjaap 				table[--irow][jcol].col = start;
23625073Sjaap 				table[irow][jcol].rcol = strig;
23725073Sjaap 				while(is < irow){
23825073Sjaap 					table[is][jcol].col = SPAN;
23925073Sjaap 					table[is][jcol].rcol = (char*)0;
24025073Sjaap 					is = next(is);
24125073Sjaap 				}
24225073Sjaap 			}
24325073Sjaap 		}
24425073Sjaap 	}
24525073Sjaap }
24625073Sjaap 
24725073Sjaap /*
24825073Sjaap  * return 1 if vertical spanning is row ir, column ij, from position ifrom
24925073Sjaap  */
25025073Sjaap vspand(ir, ij, ifform)
25125073Sjaap {
25225073Sjaap 	if(ir < 0)
25325073Sjaap 		return(0);
25425073Sjaap 	if(ir >= nlin)
25525073Sjaap 		return(0);
25625073Sjaap 	if(instead[ir])
25725073Sjaap 		return(0);
25825073Sjaap 	if(ifform == 0 && ctype(ir, ij) == '^'){
25925073Sjaap 		return(1);
26025073Sjaap 	}
26125073Sjaap 	if(table[ir][ij].rcol != (char*)0)
26225073Sjaap 		return(0);
26325073Sjaap 	if(fullbot[ir])
26425073Sjaap 		return(0);
26525073Sjaap 	return(vspen(table[ir][ij].col));
26625073Sjaap }
26725073Sjaap 
26825073Sjaap /*
26925073Sjaap  * return 1 if the string is the same as SPAN
27025073Sjaap  */
27125073Sjaap vspen(s)
27225073Sjaap char   *s;
27325073Sjaap {
27425073Sjaap 	if(s == 0)
27525073Sjaap 		return(0);
27625073Sjaap 	if(!point(s))
27725073Sjaap 		return(0);
27825073Sjaap 	return(strcmp(s, SPAN) == 0);
27925073Sjaap }
28025073Sjaap 
28125073Sjaap static
28225073Sjaap interr()
28325073Sjaap {
28425073Sjaap 	error("internal tbl error -- function: permute");
28525073Sjaap }
286