#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define WBUFSIZ 81
#define MAXRL 200
#define SPDIF(A) ((A)!=' ' && (A)!=9 && (A)!=10 && (A)!=13)
#define IGNORE(A) do A = getc(f); while (! SPDIF(i))
#define FMTERR do { fputs("Error: Bad source format.\n",stderr); exit(-1); } while(0)

#define OB_TR 1
#define OB_TH 2
#define OB_TD 3

#define OB_ALLIGN 10
#define OB_VALLIGN 11
#define OB_ROWSPAN 12
#define OB_COLSPAN 13

#define OB_UNKNOWN 0

#define LEFT 1
#define RIGHT 2
#define CENTER 3
#define TOP 4
#define BOTTOM 5
#define MIDDLE 6

#define MAXSTR 200

FILE *f, *g, *wf1, *wf2;
int TAB_x=80,a,w,b;
char wordbuf[WBUFSIZ],i, pass;
int lbptr, lbfull,
    TAB_rwsp,
    TAB_colsp,
    TAB_alig=LEFT,
    TAB_valig=TOP;
int x, y, cmd, alig, valig, rwsp, colsp, strn0=0, strn=1, lp, sl, rl[MAXRL];
char lwd[MAXSTR];
int rr[7],rc;

int GetStr(char *s, int m)
{
  int j=0;
  IGNORE(i);
  if (m) { /* cmd */
    while ( !feof(f) && ((i>=65 && i<=90) || (i>=0x30 && i<=0x39)) ) { s[j++]=i; i=getc(f); }
    ungetc(i,f);
    s[j]=0;
    IGNORE(i);
    }
  else { /* word */
    while (SPDIF(i) && i!='<' && !(feof(f))) { s[j]=i; i=getc(f); }
    s[j]=0;
    IGNORE(i);
    }
  ungetc(i,f);
  strupr(s);
  return(feof(f));
  }

int ReadObject (int m)
{
  GetStr(wordbuf,m); /* get command */
  if (m) { /* cmd */
    if (strcmp(wordbuf,"TH")==0) return OB_TH;
    if (strcmp(wordbuf,"TD")==0) return OB_TD;
    if (strcmp(wordbuf,"TR")==0) return OB_TR;
    if (strcmp(wordbuf,"ALLIGN")==0) return OB_ALLIGN;
    if (strcmp(wordbuf,"VALLIGN")==0) return OB_VALLIGN;
    if (strcmp(wordbuf,"ROWSPAN")==0) return OB_ROWSPAN;
    if (strcmp(wordbuf,"COLSPAN")==0) return OB_COLSPAN;
    return OB_UNKNOWN;
    }
  else { /* words */
    return OB_UNKNOWN;
    }
  }

void RdCommand(int *cmd, int *alig, int *rwsp, int *colsp, int *valig)
{
  IGNORE(i);    /* spcs */
  if (i!='<') {  /* no command - ret string */

    }
  switch(ReadObject(1)) {      /* read command */
    case OB_TR: *cmd = OB_TR; break;
    case OB_TD: *cmd = OB_TD; *valig = TOP;
			      *alig  = LEFT;
			      *rwsp  = 1;
			      *colsp = 1;
			      break;
    case OB_TH: *cmd = OB_TD; *valig = MIDDLE;
			      *alig  = CENTER;
			      *rwsp  = 1;
			      *colsp = 1;
			      break;
    default   : FMTERR;
    }
  for (pass=1; pass; )
    switch(ReadObject(1)) {
      case OB_ALLIGN: if (getc(f)!='=') FMTERR;  /* = */
		      if (ReadObject(1)) FMTERR;  /* num */
		      *alig = atoi (wordbuf);
		      break;
      case OB_VALLIGN: if (getc(f)!='=') FMTERR;  /* = */
		       if (ReadObject(1)) FMTERR;  /* num */
		       *valig = atoi (wordbuf);
		       break;
      case OB_ROWSPAN: if (getc(f)!='=') FMTERR;  /* = */
		       if (ReadObject(1)) FMTERR;  /* num */
		       *colsp = atoi (wordbuf);
		       break;
      case OB_COLSPAN: if (getc(f)!='=') FMTERR;  /* = */
		       if (ReadObject(1)) FMTERR;  /* num */
		       *rwsp = atoi (wordbuf);
		       break;
      default        : pass=0;
      }
  if (getc(f)!='>') FMTERR; /* must be TR > ... */
  }
/*
int MakeLine (void)
{
  RdCommand (&cmd, &alig, &rwsp, &colsp, &valig);

  }
  */
int main (char argc, char **argv)
{
  char pass=0;
  if (argc<3) {
    puts("Usage: 09tab [-<n>] <table_description> <formatted_table>");
    puts("(c) 1996 by Martin Drab");
    }
  if (argv[1][0]=='-' || argv[1][0]=='/') {
    if ((TAB_x = atoi (argv[1]+1))==0) { fputs("Error: Bad 1st arg or -0 arg.\n",stderr); return -1; }
    pass=1;
    }

  if (!pass) {
    f=fopen(argv[1],"rt");
    g=fopen(argv[2],"wt");
    }
  else {
    f=fopen(argv[2],"rt");
    g=fopen(argv[3],"wt");
    }

  wf1=fopen("09tmp1.wrk","wb"); /* cmds */
  wf2=fopen("09tmp2.wrk","wt"); /* strs */
  rc=0;
  while (!feof(f)) {
    RdCommand (&cmd, &alig, &rwsp, &colsp, &valig);
    switch (cmd) {
      case OB_TR: fwrite(&cmd,2,1,wf1);   fflush(wf1);
		  fwrite(&strn0,2,1,wf1);  fflush(wf1);
		  fwrite(&strn0,2,1,wf1);  fflush(wf1);
		  fwrite(&strn0,2,1,wf1); fflush(wf1);
		  fwrite(&strn0,2,1,wf1); fflush(wf1);
		  fwrite(&strn0,2,1,wf1); fflush(wf1);
		  fwrite(&strn0,2,1,wf1); fflush(wf1);
		  rc++;
		  break;
      case OB_TD: fwrite(&cmd,2,1,wf1); fflush(wf1);
		  fwrite(&alig,2,1,wf1); fflush(wf1);
		  fwrite(&rwsp,2,1,wf1); fflush(wf1);
		  fwrite(&colsp,2,1,wf1); fflush(wf1);
		  fwrite(&valig,2,1,wf1); fflush(wf1);
		  fwrite(&strn,2,1,wf1); fflush(wf1);
		  lp=0;
		  while (!feof(f) && (i=getc(f))!='<') {
		    switch (i) {
		      case ' ':
		      case 9  :
		      case 10 :
		      case 13 :
			lwd[lp++]=32;
			while (i==' ' || i==9 || i==10 || i==13) i=getc(f);
			ungetc(i,f);
			break;
		      default: lwd[lp++]=i;
		      }
		    }
		  if (lwd[lp--]!=32) lp++;
		  lwd[lp]=0;
		  fprintf(wf2,"%s\n",lwd);
		  sl=strlen(lwd);
		  fwrite(&sl,2,1,wf1); fflush(wf1);
		  if (!feof(f)) ungetc(i,f);
		  strn++;
		  break;
      }
    }

  fclose(wf1); fclose(wf2);
  wf1=fopen("09tmp1.wrk","rb"); /* cmds */
  wf2=fopen("09tmp2.wrk","rt"); /* strs */

  for (a=0; a<rc; rl[a++]=0);
  while (!feof(wf1)) {
    fread(rr,2,7,wf1);
    if (rr[0]==OB_TR) x=0;
    else {
      if (rl[x]<rr[6])
	rl[x]=rr[6];
      x++;
      }
    }
  x--;  /* ?? */

  fclose (wf1);
  w=0;
  for (a=0; a<x; w+=rl[a++]+3);
  w++;
  if (TAB_x<w) { fputs("Error: Table is too long to fit line.",stderr); return -1; }
  wf1=fopen("09tmp1.wrk","rb"); /* cmds */
  while (!feof(wf1)) {
    fread(rr,2,7,wf1);
    if (rr[0]==OB_TR) {
      for (b=0; b<x; b++){
	fputs("+",g);
	for (a=0; a<rl[b]+2; a++) fputs("-",g);
	}
	fputs("+\n",g);
      }
    else {
      for (b=0; b<x; b++){
	fputs("| ",g);
	fscanf(wf2,"%s",lwd);
	fprintf(g,"%s",lwd);
	for (a=strlen(lwd)+1; a<rl[b]+2; a++) fputs(" ",g);
	}
	fputs("|\n",g);
      }
    }
      for (b=0; b<x; b++){
	fputs("+",g);
	for (a=0; a<rl[b]+2; a++) fputs("-",g);
	}
	fputs("+\n",g);
  fclose (wf1);
  fclose (wf2);


  /* calculating the columns * /

  while (!foef(f)) {
    RdCommand (&cmd, &alig, &rwsp, &colsp, &valig);
    if (cmd != OB_TR) FMTERR;
    y=0;

    RdCommand (&cmd, &alig, &rwsp, &colsp, &valig);

    for (x=0; cmd != OB_TR; x++) {
      if (cmd != OB_TD) FMTERR;
      lwd[x]
      while (getc(f) != '<') {
	Read_Object(0);

      }

    }                          */

  fclose(f); fclose(g);
  return 0;
  }
