/*
 * mktexmf.c (Borrowed from Fabrice)
 * (2006 --ak)
 *
*/

#include <kpathsea/kpathsea.h>

#include "dirutil.h"
#include "getdestdir.h"
#include "mktexupd.h"

#define SBUF 256

char *progname;

static int
test_file(char c, char * name)
{
/*
 * c= 'z', 'f', 'd', 'r'
 *     
*/
  FILE *fp;

  if (c == 'z') {
    if (name == NULL) return 1;
    else if (*name == '\0') return 1;
    else if (_access(name, 0) != 0) return 1;
    else if ((fp = (FILE *)fopen(name, "r")) == NULL) return 1;
    else if (_filelength(_fileno(fp)) == 0L) {
      fclose(fp);
      return 1;
    }
    else {
      fclose(fp);
      return 0;
    }
  }
  else if (c == 'f') {
    if (name == NULL) return 0;
    else if (*name == '\0') return 0;
    else if (_access(name, 0) != 0) return 0;
    else return 1;
  }
  else if (c == 'd') {
    if (is_dir(name)) return 1;
    else return 0;
  }
  else if (c == 'r') {
    if (_access(name, 4) == 0) return 1;
    else return 0;
  }
  return 0;
}

static void
usage(void)
{
  fprintf(stderr, "Usage : mktexmf FONT.\n\n");
  fprintf(stderr, "Makes the Metafont source file for FONT,"
	  " if possible. For example,\n");
  fprintf(stderr, "`ecr12' or `cmr11'.\n");
}

/*
 * Split a .mf name into root part and point size part.
 * Root and point size are optional (may be NULL).
 */

static void
split_mf_name(string name, string *base, string *root, string *ptsize)
{
  string p, q;
  /* name = basename $1 .mf */
  p = strrchr (name, '.');
  if (p) {
    if (stricmp (p, ".mf") == 0) *p = '\0';
  }
  p = name;

  if (base)
    *base = xstrdup(p);
  /* rootname = `echo $name | sed 's/[0-9]*$//'` */
  for (q = p + strlen(p);  q > p && isdigit(q[-1]); q--);
  /* ptsize = `echo $name | sed 's/^$rootname//'` */
  if (ptsize)
    *ptsize = xstrdup(q);
  *q = '\0';
  if (root)
    *root = p;
  else
    free(p);
}

static void
relmem (char **v)
{
  int j;
  for (j = 0; j < 4; j++)
    free (v[j]);
  return;
}

int
main (int argc, char **argv)
{
  string rootname, pointsize;
  const_string realsize;
  string name;
  string sauterroot, rootfile;
  string destdir = NULL;
  FILE *f;
  size_t ptsz_len;
  char font[SBUF];
  char mfname[SBUF];
  char *arg[4];
  int  i;
  char *ptr;

  progname = argv[0];
  kpse_set_program_name (progname, NULL);
  if (argc != 2) {
    usage();
    return 0;
  }

  for (i=0; i < 4; i++) {
    arg[i] = (char *)malloc(SBUF);
  }

  if(strlen(argv[1]) > SBUF - 1) {
    fprintf(stderr, "\nToo long a font name.\n");
    return 100;
  }

  strcpy (font, argv[1]);

  split_mf_name(font, &name, &rootname, &pointsize);


  fprintf(stderr, "name = %s, rootname = %s, pointsize = %s\n",
	  name, rootname, pointsize);      


  sauterroot = kpse_find_file(concat3("b-", rootname, ".mf"),
			      kpse_mf_format, false);

  if (sauterroot && *sauterroot) {
    rootfile = sauterroot;
    rootname = concat("b-", rootname);
    strcpy (arg[0], "Dummy");
    strcpy (arg[1], "source");
    strcpy (arg[2], sauterroot);
    if (!(ptr = getdestdir (3, arg))) {
      fprintf(stderr, "Cannot get destination directory name.\n");
      relmem (arg);
      return 100;
    }
    destdir = ptr;
  }
  else if (strlen(name) == 8
	   && FILESTRNCASEEQ(name, "csso12", 6)
	   && (name[6] >= '0' && name[6] <= '5')
	   && isdigit(name[7])) {
    rootfile = xstrdup("");
  }
  else if (FILESTRNCASEEQ(rootname, "cs", 2)
	   || FILESTRNCASEEQ(rootname, "lcsss", 5)
	   || FILESTRNCASEEQ(rootname, "icscsc", 6)
	   || FILESTRNCASEEQ(rootname, "icstt", 5)
	   || FILESTRNCASEEQ(rootname, "ilcsss", 6)
	   ) {
    rootfile = kpse_find_file("cscode.mf",
			      kpse_mf_format, false);
  }
  else if (strlen(rootname) >= 3
	   && ((FILESTRNCASEEQ(rootname, "wn", 2)
		&& strchr("bBcCdDfFiIrRsStTuUvV", rootname[2]))
	       || (FILESTRNCASEEQ(rootname, "rx", 2)
		   && strchr("bBcCdDfFiIoOrRsStTuUvVxX", rootname[2])
		   && strlen(rootname) >= 4
		   && strchr("bBcCfFhHiIlLmMoOsStTxX", rootname[3]))
	       || ((rootname[0] == 'l' || rootname[0] == 'L')
		   && strchr("aAbBcCdDhHlL", rootname[1])
		   && strchr("bBcCdDfFiIoOrRsStTuUvVxX", rootname[2])))) {
    char lhprefix[64];
    strncpy(lhprefix, name, 2);
    lhprefix[2] = '\0';
    strcat(lhprefix, "codes.mf");
    rootfile = kpse_find_file(lhprefix, kpse_mf_format, false);
  }
  else {
    string tem;
    rootfile = kpse_find_file(tem = concat(rootname, ".mf"),
			      kpse_mf_format, false);
    free(tem);
  }

  if (test_file('z', rootfile)) {
    fprintf (stderr, "%s: empty or non-existent rootfile!\n", progname);
    relmem (arg);
    return 1;
  }
  if (!test_file('f', rootfile)) {
    fprintf (stderr, "%s: rootfile %s does not exist!\n", progname, rootfile);
    relmem (arg);
    return 1;
  }

  if (!destdir) {
    if (rootfile && *rootfile) {
      strcpy (arg[0], "Dummy");
      strcpy (arg[1], "source");
      strcpy (arg[2], rootfile);
      if (!(ptr = getdestdir (3, arg))) {
	fprintf(stderr, "Cannot get destination directory name.\n");
	relmem (arg);
	return 1;
      }
      destdir = ptr;
    }
  }

  if (!test_file('d', destdir)) {
    relmem (arg);
    return 1;
  }

  ptsz_len = strlen(pointsize);
  if (ptsz_len == 0) {
    fprintf(stderr, "%s: no pointsize.\n", progname);
    relmem (arg);
    return 1;
  } else if (ptsz_len == 2) {
    if (pointsize[0] == '1' && pointsize[1] == '1')
      realsize = "10.95";		/* \magstephalf */
    else if (pointsize[0] == '1' && pointsize[1] == '4')
      realsize = "14.4";		/* \magstep2 */
    else if (pointsize[0] == '1' && pointsize[1] == '7')
      realsize = "17.28";		/* \magstep3 */
    else if (pointsize[0] == '2' && pointsize[1] == '0')
      realsize = "20.74";		/* \magstep4 */
    else if (pointsize[0] == '2' && pointsize[1] == '5')
      realsize = "24.88";		/* \magstep5 */
    else if (pointsize[0] == '3' && pointsize[1] == '0')
      realsize = "29.86";		/* \magstep6 */
    else if (pointsize[0] == '3' && pointsize[1] == '6')
      realsize = "35.83";		/* \magstep7 */
    else
      realsize = pointsize;
  }
  /* The new convention is to have three or four letters for the
     font name and four digits for the pointsize. The number is
     pointsize * 100. We effectively divide by 100 by inserting a
     dot before the last two digits.  */
  else if (ptsz_len == 4 || ptsz_len == 5) {
    /* realsize=`echo "$pointsize" | sed 's/\(..\)$/.\1/'` */
    string tempsize = (string)xmalloc(ptsz_len + 2);
    strcpy(tempsize, pointsize);
    /* The script doesn't check for last chars being digits, but we do!  */
    if (isdigit(tempsize[ptsz_len-1])
	&& isdigit(tempsize[ptsz_len-2])) {
      tempsize[ptsz_len+1] = '\0';
      tempsize[ptsz_len]   = tempsize[ptsz_len-1];
      tempsize[ptsz_len-1] = tempsize[ptsz_len-2];
      tempsize[ptsz_len-2] = '.';
      free(pointsize);
    }
    realsize = tempsize;
  } else realsize = pointsize;

/* mfname is the full name */
  strcpy (mfname, destdir);
  i = strlen (mfname);
  if (mfname[i-1] != '/') {
    mfname[i] = '/';
    mfname[i+1] = '\0';
  }

  strcat (mfname, name);
  strcat (mfname, ".mf");

  if (test_file('r', mfname)) {
    fprintf(stderr, "%s: %s already exists.\n", progname, mfname);
    fprintf(stdout, "%s\n", mfname);
    if (destdir) free (destdir);
    relmem (arg);
    return 0;
  }

  if ((f = fopen(mfname, "wb")) == NULL) {
    fprintf(stderr, "%s: can't write into the file %s/%s.\n",
	    progname, destdir, name);
    if (destdir) free (destdir);
    relmem (arg);
    return 1;
  }

  if (FILESTRNCASEEQ(name, "ec", 2)
      || FILESTRNCASEEQ(name, "tc", 2)) {
    fprintf(f, "if unknown exbase: input exbase fi;\n");
    fprintf(f, "gensize:=%s;\ngenerate %s;\n", realsize, rootname);
  }
  else if (FILESTRNCASEEQ(name, "dc", 2)) {
    fprintf(f, "if unknown dxbase: input dxbase fi;\n");
    fprintf(f, "gensize:=%s;\ngenerate %s;\n", realsize, rootname);

  }
  else if (FILESTRNCASEEQ(name, "cs", 2)
	   || FILESTRNCASEEQ(name, "lcsss", 5)
	   || FILESTRNCASEEQ(name, "icscsc", 6)
	   || FILESTRNCASEEQ(name, "icstt", 5)
	   || FILESTRNCASEEQ(name, "ilcsss", 6)
	   ) {
    fprintf(f, "input cscode\nuse_driver;\n");
  }
  else if (strlen(name) >= 3
	   && ((FILESTRNCASEEQ(name, "wn", 2)
		&& strchr("bBcCdDfFiIrRsStTuUvV", name[2]))
	       || (FILESTRNCASEEQ(name, "rx", 2)
		   && strchr("bBcCdDfFiIoOrRsStTuUvVxX", name[2])
		   && strlen(name) >= 4
		   && strchr("bBcCfFhHiIlLmMoOsStTxX", name[3]))
	       || ((name[0] == 'l' || name[0] == 'L')
		   && strchr("aAbBcCdDhHlL", name[1])
		   && strchr("bBcCdDfFiIoOrRsStTuUvVxX", name[2])))) {
    fprintf(f, "input fikparm;\n");
  }
  else if (strlen(name) >= 4 && strchr("gG", name[0])
	   && strchr("lLmMoOrRsStT", name[1]) 
	   && strchr("bBiIjJmMtTwWxX", name[2]) 
	   && strchr("cCiIlLnNoOrRuU", name[3])) {
    /* A small superset of the names of the cbgreek fonts:
       pattern `g[lmorst][bijmtwx][cilnou]*'. 
       This is only slightly more general than the exact set of patterns.
     */
    fprintf(f, "gensize:=%s;\ninput %s;\n", realsize, rootname);
  }
  else {
    /* FIXME: this was in the previous versions */
    /* fprintf(f, "if unknown %s: input %s fi;\n", base, base); */
      fprintf(f, "design_size := %s;\ninput %s;\n",
	      realsize, rootname);
  }

  fclose(f);
  fprintf(stdout, "%s\n", mfname);
  fprintf(stderr, "%s: %s: successfully generated.\n", progname, mfname);
  mktexupd (mfname);
  if (destdir) free (destdir);
  relmem (arg);
  return 0;
}
