#
# define ever (;;)
# define MAXCHS 2000
main(argc,argv)
	char *argv[];
{
char line[200];
extern int cin;
extern char *cspace;
	cspace = getvec(MAXCHS + 100);
for ever
{
	if (argc>1)
	{
	argc--;
	argv++;
	if (match(*argv, "-ms"))
		*argv = "/usr/lib/tmac.s";
	cin = copen(*argv, 'r');
	if (cin < 0)
		{
		printf(2,"where is input file %s\n",*argv);
		cexit();
		}
	}
while (gets(line))
	if (match(line, ".TS"))
		tableput();
	else
		puts(line);
if (argc <= 1) break;
}
cexit();
}
# define MAXCOL 35
# define MAXLIN 220
# define ONELINE 250
char *tabentry[MAXLIN][MAXCOL];
char extra[MAXCHS];
char *cspace, *cstore;
char *exstore extra;
int sep[MAXCOL], dwide[MAXCOL];
char *instead[MAXLIN];
int newtab[MAXLIN];
char *style[MAXCOL];
tableput()
{
/* read input, write output, make tables on the way */
char st[ONELINE], *format;
int ilin, nlin, icol, ncol, k, ch, ws, cs, ns;
int maxchnge, ct;
printf(".TS\n");
/* get command line */
cstore = cspace;
exstore = extra;
ncol = 0;
for (ilin=0; ilin<MAXLIN; ilin++)
	newtab[ilin]=0;
gets (st);
for (k=0; k<ONELINE && st[k] != '\0'; k++)
	if (!space(st[k]))
		{
		style[ncol] = st+k;
		dwide[ncol] =0;
		for(; letter(st[k]); k++)
			{
			if ((st[k]=='n' || st[k] == 'N') &&
				!dwide[ncol])
				{
				dwide[ncol]=1;
				sep[ncol++] = 0;
				style[ncol] = style[ncol-1];
				dwide [ncol] = 0;
				}
			}
		if (digit(st[k]))
			sep[ncol] = numb(st+k);
		else
			sep[ncol] = 3;
		ncol++;
		while (digit(st[k]))
			st[k++] = '\0';
		if (st[k] == '\0')
			break;
		st[k] = '\0';
		}
/* now get input lines */
for (nlin=0; gets(cstore) && !match(cstore, ".TE"); nlin++)
	{
	if (cstore[0] == '.' && letter(cstore[1]))
		{
		instead[nlin] = cstore;
		while (*cstore) cstore++;
		}
	else instead[nlin] = 0;
	for (icol = 0; icol <ncol; icol++)
		{
		tabentry[nlin][icol] = cstore;
		for(; (ch= *cstore) != '\0' && ch != '\t'; cstore++)
				;
		*cstore++ = '\0';
		if (dwide[icol] )
			if (broken(style[icol],nlin))
				{
				tabentry[nlin][icol+1]=maknew(tabentry[nlin][icol]);
				icol++;
				if (tabentry[nlin][icol] ==0)
					newtab[nlin]=newtab[nlin+1]=1;
				}
			else
				tabentry[nlin][++icol] = 0;
		while (span(style[icol+1],nlin) )
			tabentry[nlin][++icol] = "";
		if (ch == '\0') break;
		}
	while (++icol <ncol)
		tabentry[nlin][icol] = "";
	while (*cstore != '\0')
		 *cstore++;
	if (cstore-cspace > MAXCHS)
		cstore = cspace  = getvec(MAXCHS+100);
	}
/* find longest command string */
for (icol=maxchnge=0; icol<ncol; icol++)
	if (slen(style[icol]) >maxchnge)
		maxchnge = slen(style[icol]);
/* set tab stops */
printf(".nr 49 0\n");
for (icol = 0; icol<ncol; icol++)
	{
	ct = 1 + (icol>0 ? sep[icol-1] : 0);
	printf(".nr %2d 0\n", icol+50);
	for (ilin=0; ilin < nlin; ilin++)
		{
		if (icol>0 && dwide[icol-1]>0 && tabentry[ilin][icol]==0)
			{
			printf(".nr 48 \\n(%2d+\\w'%s'+%dn\n",
				icol+48, tabentry[ilin][icol-1], sep[icol-1]);
			printf(".if \\n(48-\\n(%2d .nr %2d \\n(48\n",
				icol+50,icol+50);
			}
		if ( !span(style[icol],ilin) && /* not part of span */
		   (dwide[icol] == 0 || tabentry[ilin][icol+1]!= 0)
				/* not a double item */
		     && (!span(style[icol+1],ilin) || icol==ncol))
			{
			printf(".nr 47 \\n(%2d+\\w'%s'+%dn\n",
			icol+49,tabentry[ilin][icol], ct);
			printf(".if \\n(47-\\n(%2d .nr %2d \\n(47\n",
				icol+50,icol+50);
			}
		}
	/* clean up spanned headings */
	for(ilin=0; ilin<maxchnge; ilin++)
		{
		if( !(span(style[icol],ilin)) &&
		  (icol ==1 || dwide[icol-1] == 0) &&
		  span(style[icol+(dwide[icol]?2:1)],ilin))
			printf(".nr %d \\n(%2d+\\w'%s'+%dn\n",
			  ilin+30, icol+49, tabentry[ilin][icol], ct);
		else if (span(style[icol],ilin) &&
		  (icol+1==ncol || !span(style[icol+1],ilin)))
			printf(".if \\n(%d-\\n(%d .nr %d \\n(%d\n",
				30+ilin, icol+50, icol+50, ilin+30);
		}
	}
/* run out table, put field characters in */
printf (".fc  @\n");
for (ilin=0; ilin<nlin; ilin++)
	{
	if (instead[ilin])
		{
		printf("%s\n",instead[ilin]);
		continue;
		}
	/* is a new set of tab stops needed */
	if (ilin < maxchnge || newtab[ilin])
		settab(ncol, ilin);
	for (icol=0; icol<ncol; icol++)
		{
		switch ( ylet(style[icol],ilin))
			{
			default:
			case 'L': case 'l':
				format = "%s@"; break;
			case 'R': case 'r':
				format= "@%s"; break;
			case 'n': case 'N':
				if (!dwide[icol] || tabentry[ilin][icol+1] != 0)
					{
					format=dwide[icol]? "@%s" : "%s@";
					break;
					}
			case 'c': case 'C':
				format = "@%s@"; break;
			case 's':  case 'S':
				format= "";
				break;
			}
		if (! (dwide [icol-1]>0 && tabentry[ilin][icol] == 0 ))
		printf(format, tabentry[ilin][icol]);
		if (!span(style[icol+1],ilin))
			for (k=sep[icol]; k>0; k--)
				printf(" ");
		}
	printf("\n");
	}
printf(".fc\n");
printf(".TE\n");
}
match (s1, s2)
	char *s1, *s2;
{
	while (*s1 == *s2)
		if (*s1++ == '\0')
			return(1);
		else
			*s2++;
	return(0);
}
slen(str)
	char *str;
{
	int k;
	for (k=0; *str++ != '\0'; k++);
	return(k);
}
space(ch)
	{
	switch (ch)
		{
		case ' ': case '\t':
			return(1);
	}
	return(0);
	}
letter (ch)
	{
	if (ch >= 'a' && ch <= 'z')
		return(1);
	if (ch >= 'A' && ch <= 'Z')
		return(1);
	return(0);
	}
numb(str)
	char *str;
	{
	/* convert to integer */
	int k;
	for (k=0; *str >= '0' && *str <= '9'; str++)
		k = k*10 + *str - '0';
	return(k);
	}
broken(str, nlin)
	{
	switch(ylet(str,nlin))
		{
		case 'n': case 'N':
			return(1);
		}
	return(0);
	}
ylet (str, k)
	char *str;
{
	k++;
	while (*str &&k--)
		str++;
	return(*--str);
}
span(str, k)
	{
	switch(ylet(str,k))
		{
		case 's': case 'S':
			return(1);
		}
	return(0);
	}
maknew(str)
	char *str;
{
	/* make two numerical fields */
	int point;
	char *p, *q;
	p = str;
	for (point=0; *str; str++)
		if (*str=='.')
			point=1;
	if (!point && *(str-1)== '$')
		return(0);
	for(; str>p; str--)
		if ( (point && *str == '.') ||
		    (!point && digit(*(str-1)) ) )
			break;
	if (!point && p==str) /* not numerical, don't split */
		return(0);
	p= str;
	q = exstore;
	while (*exstore++ = *str++);
	*p = 0;
	return(q);
	}
digit(x)
	{
	return(x>= '0' && x<= '9');
	}
settab(ncol, ilin)
{
	int k, icol;
	printf(".ta ");
	for (icol = 0; icol<ncol; icol++)
	   if ((dwide[icol] == 0 || tabentry[ilin][icol+1] != 0)
		&& !span(style[icol+1],ilin))
		printf("\\n(%du ",icol+50);
	printf("\n");
}
