// Create a new, empty table with a specified structure

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "dbftable.h"

const int MAXNAMESIZE = 10;

static char HELP[] =
  "\n"
  "dbfcreate  <structure filepecs>  <table filespecs>\n"
  "\n"
  "creates an empty dBase table with the fields specified in the\n"
  "structure file.\n";

static FILE *structure;
static int c;

static void readchar(void)
{
  if (c != EOF) c = getc(structure);
  if (c != EOF) c = toupper(c);
}

static bool space_or_tab(void)
{
  return c == ' ' || c == '\t';
}

static void scan_spaces_and_tabs()
{
  while (space_or_tab()) readchar();
}

static int readnum()
{
  int n = 0;
  bool overflow = false;
  scan_spaces_and_tabs();
  while (isdigit(c))
  {
    n = 10 * n + c - '0';
    if (n >= 100) overflow = true;
    readchar();
  }
  return overflow ? 0 : n;
}

int main(int argc, char **argv)
{
  if (argc < 3)
  {
    puts(HELP);
    return 1;
  }
  dbf_table table;
  if (!table.open(argv[2], DBF_WRITE))
  {
    fprintf(stderr, "Can't open dBase table file %s\n", argv[2]);
    return 1;
  }
  structure = fopen(argv[1], "r");
  if (structure == NULL)
  {
    fprintf(stderr, "Can't open structure file %s\n", argv[1]);
    return 1;
  }
  readchar();
  while (true)
  {
    scan_spaces_and_tabs();
    if (c == EOF) break;
    if (c == '\n') {readchar(); continue;}
    if (c != 'C' && c != 'N' && c != 'D' && c != 'L')
    {
      fprintf(stderr, "type %c is invalid\n", c);
      return 1;
    }
    int type = c;
    readchar(); scan_spaces_and_tabs();
    char name[MAXNAMESIZE+1];
    {
      int n = 0;
      while (c != ' ' && c != '\n' && c != EOF)
      {
        if (n < MAXNAMESIZE)
        {
          name[n++] = c;
          readchar();
        }
        else
        {
          fprintf(stderr, "Field name more than %d characters long\n",
            MAXNAMESIZE);
          return 1;
        }
        name[n] = 0;
      }
      if (name[0] == 0)
      {
        fprintf(stderr, "Missing field name\n");
        return 1;
      }
      {
        for (const char *s = name; *s != 0; s++)
        {
          if (!isalnum(*s) && *s != '_')
          {
            fprintf(stderr, "Illegal character '%c' in field name\n", *s);
            return 1;
          }
        }
      }
    }
    int width, precision;
    if (type == 'C' || type == 'N')
    {
      width = readnum();
      if (type == 'N')
        precision = readnum();
    }
    if (table.add_field(type, name, width, precision) == NULL)
    {
      fprintf(stderr, "Field %s is invalid\n", name);
      return 1;
    }
    while (strlen(name) < MAXNAMESIZE) strcat(name, " ");
    printf("%c  %s", type, name);
    if (type == 'C' || type == 'N')
      printf("  %2d", width);
    if (type == 'N')
      printf("  %2d", precision);
    putchar('\n');
    while (c != '\n' && c != EOF) readchar();
    if (c == EOF) break;
    readchar();
  }
  table.close();
  return 0;
}


