MiniUnix/usr/source/s2/tbl.c
#
# 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");
}