/*
   File: process_var.c
*/

#include <stdio.h>
#include <stdlib.h>

#define MAX_VAR_LENGTH 64 /* Maximum length of variable names in matrix file */

struct fifo {
   long j;
   char *x;
   struct fifo *next;
};
typedef struct fifo fifo_item;
typedef struct fifo *fifo_link;

typedef struct {
   fifo_link front, rear;
} queue; 


FILE *nice_fopen(char *name, char *mode)
{
  FILE *file;

  file = fopen(name, mode);
  if(file == NULL) {
    fprintf(stderr, "File %s could not be opened\n", name);
    exit(1);
  }
  return(file);
}

int is_empty(queue q)
{ return(q.front == NULL); }

void dequeue(queue *q, long *j, char **x)
{
   fifo_link temp = q->front;

   *j = temp->j;
   *x = temp->x;
    q->front = temp->next;
    free(temp);
}

void enqueue(queue *q, long j, char *x)
{
   fifo_link temp;

   temp = malloc(sizeof(fifo_item));
   temp->j = j;
   temp->x = x;
   temp->next = NULL;
   if(is_empty(*q))
      q->front = q->rear = temp;
   else {
      q->rear->next = temp;
      q->rear = temp;
   }
}


int main(int argc, char *argv[])
{
  long prev_i, i, j;
  char *var;
  char eoln;
  long size;
  FILE *diag, *offd, *matrix_f;
  queue *rows;

  if(argc != 3) {
    printf("Process a var file\n");
    printf("Usage: %s matrix-var-file matrix-size\n", argv[0]);
    return(EXIT_SUCCESS);
  }

  /* Get matrix size */
  sscanf(argv[2], "%ld", &size);
  /* Open the matrix file for input */
  matrix_f = nice_fopen (argv[1], "r");
  /* Open the diagonal entries file for writing */
  diag = nice_fopen ("pwbsolve.dia.var", "w");
  /* Open the off-diagonal entries for writing */
  offd = nice_fopen ("pwbsolve.off.var", "w");

  rows = (queue *)calloc(size+1, sizeof(queue));
  prev_i = 0;

  while(getc(matrix_f) != EOF) {
    var = malloc(MAX_VAR_LENGTH * sizeof(char));  /* Get new mem for var */
    fscanf(matrix_f, "%i%i%s%c", &i, &j, var, &eoln); /* read entry */
/*     fprintf(stderr, "read variable name %s\n", var); */
    
    if(prev_i != i) {   /* We have started a new row so do diag */
/*         if(i != 1) putc('\n', diag); */
        if(prev_i != 0) putc('\n', diag);
        fprintf(diag, "\t%i\t%i", i, i);
    }
    fprintf(diag, "\t%s", var);
    if(j != size) enqueue(&rows[j], i, var);
    prev_i = i;
  }

  /* The last diagonal, just set to 1.0 cos it's gonna be anyway */
  fprintf(diag, "\n\t%i\t%i\t%lf\n", size, size, 1.0);
  fclose(diag);

  for(i=1; i<=size; i++)
     while(!is_empty(rows[i])) {
        dequeue(&rows[i], &j, &var);
	/* gcla - is this a bug (transposition)? */
        /* this is the original */
	/* gcla - does this make a difference? */
/* 	if (! (i == j)) { */
	fprintf(offd, "\t%li\t%li\t%s\n", i, j, var);
/* 	}	 */
	/*         fprintf(offd, "\t%li\t%li\t%s\n", j, i, var); */
     }

  /* Now spit out 1.0s for last row */
  for(i=1; i<size; i++)
      fprintf(offd, "\t%li\t%li\t%lf\n", size, i, 1.0);
  
  fprintf(stderr, "Finished processing .var file.\n");
}
