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

#include "internalfile.h"
#include "internal.h"
#include "psignal.h"

void _imp_readbyte(unsigned char *dest) {
  int num;
  //fprintf(stderr, "{_imp_readbyte}");
  check_instream(__PRETTY_FUNCTION__);
  if (dest == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  int rc = fscanf(_imp_InFile, "%d", &num);
  int terminator = _imp_getchar(_imp_InFile); // actually read the ' ' or '\n' that terminated the read, to help with prompting.
  if (rc != 1) {
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  // first do a range check for 0:255 (or possibly -128:127 or even -128:255)
  *dest = num;
  (void)rc;
}

void _imp_readshort(short int *dest) {
  int num;
  //fprintf(stderr, "{_imp_readshort}");
  check_instream(__PRETTY_FUNCTION__);
  if (dest == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  int rc = fscanf(_imp_InFile, "%hd", dest);
  int terminator = _imp_getchar(_imp_InFile); // actually read the ' ' or '\n' that terminated the read, to help with prompting.
  if (rc != 1) {
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  // first do a range check for 0x8000 to 0x7FFF
  (void)rc;
}

void _imp_readint(int *dest) {
  int num;
  //fprintf(stderr, "{_imp_readint}");
  check_instream(__PRETTY_FUNCTION__);
  if (dest == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  // Imp %integer is really 'long int' in C but it's too complicated to retool i2c to use long everywhere so *not* using %ld below.
  // Only matters for targets like 6809 where int would default to 16 bits (or worse, in Vide for the vectrex, 8 bits).
  int rc = fscanf(_imp_InFile, "%d", dest);
  int terminator = _imp_getchar(_imp_InFile); //fprintf(stderr, "[t=%d val=%d]", terminator, *dest); // actually read the ' ' or '\n' that terminated the read, to help with prompting.
  if (rc != 1) {
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  // first do a range check for 0x80000000 to 0x7FFFFFFF
  (void)rc;
}

void _imp_readlong(long long int *dest) {
  //fprintf(stderr, "{_imp_readlong}");
  check_instream(__PRETTY_FUNCTION__);
  if (dest == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  int rc = fscanf(_imp_InFile, "%lld", dest);
  int terminator = _imp_getchar(_imp_InFile); // actually read the ' ' or '\n' that terminated the read, to help with prompting.
  if (rc != 1) {
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  (void)rc;
}

void _imp_readfloat(float *dest) {
  //fprintf(stderr, "{_imp_readfloat}");
  check_instream(__PRETTY_FUNCTION__);
  if (dest == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  int rc = fscanf(_imp_InFile, "%f", dest);
  int terminator = _imp_getchar(_imp_InFile); //fprintf(stderr, "[t=%d val=%f]", terminator, *dest); // actually read the ' ' or '\n' that terminated the read, to help with prompting.
  if (rc != 1) {
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  // possible warning for loss of precision?
  (void)rc;
}

void _imp_readdouble(double *dest) {
  //fprintf(stderr, "{_imp_readdouble}");
  check_instream(__PRETTY_FUNCTION__);
  if (dest == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  int rc = fscanf(_imp_InFile, "%lf", dest);
  int terminator = _imp_getchar(_imp_InFile); // actually read the ' ' or '\n' that terminated the read, to help with prompting.
  if (rc != 1) {
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  (void)rc;
}

void _imp_readitem(_imp_string *S) {
  
  // I think READITEM(S) is like readch except that it returns a 1-character
  // string via its %name parameter.
  
  // It may not be the correct call for reading a string with READ() - we may
  // need to examine old IMP implementations to see what they actually did...

  //fprintf(stderr, "{_imp_readitem}");
  check_instream(__PRETTY_FUNCTION__);
  if (S == NULL) { /* to do - report NULL %name parameter was given */ }
  _imp_issue_prompt();
  _imp_string chs;
  int ch = _imp_getchar(_imp_InFile);
  if (ch == EOF) {
    chs.length = 0;
    *S = chs;
    _imp_signal(3,1,0,"");
    exit(EXIT_FAILURE);
  }
  chs.charno[1] = ch; chs.length = 1;
  *S = chs;
}
