/* qi_make - convert a sequential file to a format suitable for a qi build */

/* 1993/08/30 release for beta testing */
/* 1993/09/13 added long input records & fields, "\n" newline token in fields */

#include stdio
#include string
#include ctype
#include "qi.h"

#define MAX_PARAMS 100

int recsz, fldsz;

struct param {
   int pos;
   int size;
   int field;
   int cap;
   int bz;
   char *pre;
   char *post;
} params[MAX_PARAMS + 1];

void cap(char *);
void trim(char *);


main(int argc, char *argv[])
{

   FILE *in, *out;
   char *record, *field, *new_field;
   char filename[256], temp[256], *cp, *fld;
   int pidx, index, sequence;

   if (argc < 3) {
       printf("Usage: make input output [base]\n");
       exit();
   }

   strcpy(filename, argv[1]);
   if (cp = strchr(filename, '.')) *cp = '\0';
   strcat(filename, ".qi_make");

   if (read_params(filename) == FALSE) {
       sprintf(temp, "can't open parameter file %s", filename);
       perror(temp);
       exit();
   }
   record = malloc(++recsz);
   field = malloc(fldsz);
   new_field = malloc(fldsz);

   if ((in = fopen(argv[1], "r")) == NULL) {
       perror("Can't open input file");
       exit();
   }
   if ((out = fopen(argv[2], "w")) == NULL) {
       perror("Can't open output file");
       exit();
   }
   if (argc == 4)
       index = atoi(argv[3]);
   else
       index = 0;

   printf("Convert qi data from %s to %s\n", argv[1], argv[2]);

   printf("ID base set to %d\n", index);

   while (fgets(record, recsz, in)) {
       index++;  /* it really starts at 1 */
       if ((index % 100) == 0) printf("%d\n", index);
       for (pidx = 0; params[pidx].size >= 0; pidx++) {
           strncpy(field, "", fldsz);
           strncpy(field, record + params[pidx].pos, params[pidx].size);
           if (params[pidx].cap) cap(field);
           trim(field);
           if ((params[pidx].size == 0) ||
               ((strlen(field) > 0) &&
                (!params[pidx].bz ||
                 (atoi(field) > 0)))) {
               strcpy(new_field, params[pidx].pre);
               strcat(new_field, field);
               strcat(new_field, params[pidx].post);
               sequence = 0;
               fld = new_field;
               for (;;) {
                   if (cp = strstr(fld, "\\n"))
                       *cp = '\0';
                   fprintf(out, "%0*d%0*d%0*d%0*d%s\n",
                       ID_SIZE, index,
                       FIELD_SIZE, params[pidx].field,
                       SEQ_SIZE, sequence++, ATTR_SIZE, 0, fld);
                   if (cp == NULL)
                       break;
                   fld = cp + 2;
               }
           }
       }
   }
   fclose(in);
   fclose(out);
}


void strxcpy(char *dest, char *src, int cnt)
{
   if (cnt == 0) return;

   for (;*src; src++) {
       if ((*src != '\\') || (*(src + 1) != ','))
           *dest++ = *src;
       if (--cnt == 0)
           break;
   }
}


int read_params(char *name)
{
   FILE *fp;
   int ind = 0;
   char *cp, *cp2, val[10], line[256];

   fp = fopen(name, "r");

   if (fp == NULL) return (FALSE);

   while (fgets(line, sizeof(line), fp)) {
       if (line[0] == '#') continue;
       cp = line;
       cp2 = strchr(cp,',');
       strncpy(val, "", sizeof(val));
       strncpy(val, cp, cp2 - cp);
       params[ind].pos = atoi(val) - 1;  /* origin 0 into field */
       cp = cp2 + 1;

       cp2 = strchr(cp,',');
       strncpy(val, "", sizeof(val));
       strncpy(val, cp, cp2 - cp);
       params[ind].size = atoi(val);
       cp = cp2 + 1;

       cp2 = strchr(cp,',');
       strncpy(val, "", sizeof(val));
       strncpy(val, cp, cp2 - cp);
       params[ind].field = atoi(val);
       cp = cp2 + 1;

       cp2 = strchr(cp,',');
       if (cp2 == NULL)
           cp2 = strchr(cp, '\0');
       strncpy(val, "", sizeof(val));
       strncpy(val, cp, cp2 - cp);
       params[ind].cap = atoi(val);
       cp = cp2 + 1;

       cp2 = strchr(cp,',');
       if (cp2 == NULL)
           cp2 = strchr(cp, '\0');
       strncpy(val, "", sizeof(val));
       strncpy(val, cp, cp2 - cp);
       params[ind].bz = atoi(val);
       cp = cp2 + 1;

       /* find comma, but skip over '\,' */
       for (cp2 = cp; *cp2; cp2++)
           if ((*cp2 == '\\') && (*(cp2 + 1) == ','))
               cp2++;
           else if (*cp2 == ',')
               break;
       params[ind].pre = calloc((cp2 - cp) + 1, sizeof(char));
       strxcpy(params[ind].pre, cp, cp2 - cp);
       cp = cp2 + 1;

       for (cp2 = cp; *cp2; cp2++)
           if ((*cp2 == '\\') && (*(cp2 + 1) == ','))
               cp2++;
           else if (*cp2 == ',')
               break;
       params[ind].post = calloc((cp2 - cp) + 1, sizeof(char));
       strxcpy(params[ind].post, cp, cp2 - cp);
       cp = cp2 + 1;

       if (recsz < (params[ind].pos + params[ind].size + 1))
           recsz = (params[ind].pos + params[ind].size + 1);
       if (fldsz < (params[ind].size + strlen(params[ind].pre) + strlen(params[ind].post) + 1))
           fldsz = (params[ind].size + strlen(params[ind].pre) + strlen(params[ind].post) + 1);

       if (++ind == MAX_PARAMS) {
           printf("Parameter file contains more than %d rules\n", MAX_PARAMS);
           break;
       }
   }
   params[ind].size = -1;

   fclose(fp);
   return (TRUE);
}

void trim(char *s)
{
   while ((strlen(s) > 0) && (s[strlen(s)-1] == ' '))
       s[strlen(s)-1] = '\0';
}

void cap(char *s)
{
   char *ptr;

   *s = _toupper(*s);
   for (ptr = s + 1; *ptr; ptr++) {
       *ptr = _tolower(*ptr);
       if (*ptr == ',') *ptr = ' ';
       if (!isalnum(*(ptr - 1)))
           *ptr = _toupper(*ptr);
       if ((*(ptr - 1) == 'I') && (*ptr == 'i'))
           *ptr = _toupper(*ptr);
   }
}