#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

typedef enum {
  st_ok,
  st_in_string,
  st_in_string_bsl,
  st_tag_open,
  st_sst_tag_open,
  st_in_expression,
  st_in_expression_percent,
  st_in_schemelet,
  st_in_schemelet_percent
} parse_state;

int ssp_compile(const char *infile, const char *outfile) {
  struct stat stat1, stat2;
  FILE *inf, *outf;
  int c;
  parse_state pst;
  parse_state saved_pst;
  int count;

  if(stat(infile,&stat1)!=0) {
    return 0;
  }

  if(stat(outfile,&stat2)==0) {
    if(difftime(stat1.st_mtime,stat2.st_mtime)<0) {
      return 1; /* No recompilation needed */
    }
  }
  
  inf=fopen(infile,"r");
  outf=fopen(outfile,"w");
  if(inf==0 || outf==0) {
    if(inf!=0) {
      fclose(inf);
    }    
    if(outf!=0) {
      fclose(outf);
    }    
    return 0;
  }

  pst=st_ok;
  count=0;

  while((c=fgetc(inf))!=EOF) {
    switch(pst) {
    case st_ok:
      if(count==0) {
	fputs("(display \"",outf);
      } else if(count==256) {
	fputs("\")\n(display \"",outf);
	count=0;
      }
      if(c=='<') {
	pst=st_tag_open;
      } else if(c=='\n') {
	fputs("\n",outf);
	count++;
      } else {
	if(c=='"') {
	  saved_pst=pst;
	  pst=st_in_string;
	  fputc('\\',outf);
	} 
	fputc(c,outf);
	count++;
      }
      break;

    case st_in_schemelet:
      if(c=='%') {
	pst=st_in_schemelet_percent;
      } else {
	if(c=='"') {
	  saved_pst=pst;
	  pst=st_in_string;
	}
	fputc(c,outf);
      } 
      break;
    case st_in_schemelet_percent:
      if(c=='>') {
	pst=st_ok;
	count=0;
      } else {
	fputc('%',outf);
	fputc(c,outf);
	pst=st_in_schemelet;
      }
      break;

    case st_tag_open:
      if(c=='%') {
	fputs("\")\n",outf);
	pst=st_sst_tag_open;
      } else {
	pst=st_ok;
	fputc('<',outf);
	fputc(c,outf);
	count+=2;
      }
      break;
    case st_sst_tag_open:
      if(c=='=') {
	pst=st_in_expression;
	fputs("(display ",outf);
      } else {
	pst=st_in_schemelet;
      }
      break;

    case st_in_expression:
      if(c=='%') {
	pst=st_in_expression_percent;
      } else {
	if(c=='"') {
	  saved_pst=pst;
	  pst=st_in_string;
	} 
	fputc(c,outf);
      }
      break;
    case st_in_expression_percent:
      if(c=='>') {
	fputs(")\n",outf);
	pst=st_ok;
	count=0;
      } else {
	fputc('%',outf);
	fputc(c,outf);
	pst=st_in_expression;
      }
      break;

    case st_in_string:
      if(c=='\\') {
	pst=st_in_string_bsl;
      } else if(c=='"') {
	pst=saved_pst;
	if(pst==st_ok) {
	  fputc('\\',outf);
	  count++;
	}
	fputc(c,outf);
      } else {
	fputc(c,outf);
      }
      break;
    case st_in_string_bsl:
      fputc('\\',outf);
      pst=st_in_string;
      fputc(c,outf);
      break;
    }
  }

  if(pst==st_ok && count!=0) {
    fputs("\")\n",outf);
  } else {
    /* ??? */
  }

  fclose(inf);
  fclose(outf);

  return 1;
}


#ifdef SSP_COMPILER_MAIN
int main(int argc, char **argv) {
  char outfile[1024];
  if(argc<2 || access(argv[1],R_OK)!=0) {
    printf("Usage: ssp_compiler <infile> [<outfile>]\n");
    return 1;
  }
  if(argv[2]==0) {
    strcpy(outfile,argv[1]);
    argv[2]=outfile;
  }
  ssp_compile(argv[1],argv[2]);
}
#endif




