/*
** fileio.c
*/

#include <stdio.h>
#include "peek.h"

/*
** get_source()
** gets source of input for object info, either from file, in which case
** it returns a file pointer, or from stdin, in which case it returns
** NULL.
** pesters user until a valid filename is given.
*/
FILE *
get_source() {
  FILE *file;
  char filename[32];
  int c;
  
  do {
    printf("name of file to read from? ");
    scanf("%s", filename); 
    file = fopen(filename, "r");
  } while(NULL == file);
  return (file);
}

/*
** get_output()
** returns file pointer of file that something is to be saved to
** won't quit pestering user until a valid filename is put it.
*/
FILE *
get_output(char *s) {
  FILE *file;
  char filename[32];
  int c;
  
  do {
    printf("name of file to write %s to? ", s);
    scanf("%s", filename);
    file = fopen(filename, "w");
  } while(NULL == file);
  return(file);
}

/* 
** skip()
** reads past all comments and whitespace, leaving file pointer on first 
** thing that is not comment or whitespace. Returns EOF if hits EOF in 
** process of looking.
*/
int
skip(FILE *file) {
  static char whites[5] = {' ', '\t', '\n', '\r', '\0'};
  char c;
  int done = 0;

  while (!done) {
    while (strchr(whites, (c=fgetc(file))));
    if (EOF == c) {
      return(EOF);
    }
    fseek(file, -1, SEEK_CUR);  /* we got to character past all whites */
    if (COMMCH == (c=fgetc(file))) {
      while ('\n' != (c=fgetc(file))) {
	if (EOF == c) {
	  return(EOF);
	}
      }
    }
    else {
      done = 1;
      fseek(file, -1, SEEK_CUR); /* we had to read this character to see
				    if it was COMMCH */
    }
  }
  return(0);
}

/*
** get_int()
** gets an integer from file, reading past comments (beginning with COMMCH)
** if there is some error, returns EOF; returns ENDLIST if it hits a ENDLCH.
*/
int
get_int(FILE *file, int *d) {
  char 
    c, 
    intstr[MAXINTLEN], 
    valid_int_str[12] = {'-', '0', '1', '2', '3', '4', 
			   '5', '6', '7', '8', '9', '\0'};
  int i = 0, num;

  if (EOF == skip(file)) {
    sprintf(err, "get_float: Couldn't skip\n");
    return(EOF);
  }

  if (ENDLCH == (c=getc(file))) {
    return(ENDLIST);
  }
  else
    fseek(file, -1, SEEK_CUR);

  while (strchr(valid_int_str, (c=getc(file)))) {
    if (i < MAXINTLEN - 1) {
      intstr[i++] = c;
    }
    else {
      intstr[i++] = 0;
      sprintf(err, "get_int: Int string |%s| too long\n", intstr);
      return(EOF);
    }
  }
  fseek(file, -1, SEEK_CUR);
  intstr[i++] = '\0';
  if (EOF == sscanf(intstr, "%d", &num)) {
    sprintf(err, "get_int: Invalid integer format encountered\n");
    return(EOF);
  }
  *d = num;
  return(0);
}

/*
** get_float()
** gets a float from file, reading past comments (beginning with COMMCH)
** if there is some error, returns EOF; returns ENDLIST if it hits a ENDLCH.
*/
int
get_float(FILE *file, float *f) {
  char 
    c, 
    floatstr[MAXFLOATLEN], 
    valid_float_str[13] = {'-', '.', '0', '1', '2', '3', 
			     '4', '5', '6', '7', '8', '9', '\0'};
  int i = 0;
  float num;

  if (EOF == skip(file)) {
    sprintf(err, "get_float: Couldn't skip\n");
    return(EOF);
  }

  if (ENDLCH == (c=getc(file))) {
    return(ENDLIST);
  }
  else
    fseek(file, -1, SEEK_CUR);

  while (strchr(valid_float_str, (c=getc(file)))) {
    if (i < MAXFLOATLEN - 1) {
      floatstr[i++] = c;
    }
    else {
      floatstr[i++] = 0;
      sprintf(err, "get_float: float string %s too long\n", floatstr);
      return(EOF);
    }
  }
  fseek(file, -1, SEEK_CUR);
  floatstr[i++] = '\0';
  if (EOF == sscanf(floatstr, "%g", &num)) {
    sprintf(err, "get_float: Invalid float format %s encountered\n",
	    floatstr);
    return(EOF);
  }
  *f = num;
  return(0);
}

/*
** next_sect()
** reads past everything to next SECTCH in file, leaves file pointer on character
** following SECTCH. If it hits EOF, returns -1.
*/
int
next_sect(FILE *file) {
  char c;
  
  while(SECTCH != (c=fgetc(file)));
  if (EOF == c) {
    sprintf(err, "next_sect: encountered EOF when looking for next section\n");
    return(-1);
  }
  return(0);
}





