/*

This is the program that writes the file INT.h that is included in all the C
sections that consistitue the BCPL Cintcode system.  INT.h contains C #define
statements for macros such as BCPLINT32 and BCPLINT64 for the architecture that
this program is running on.  If the current (not the target) architecture uses 64
bit pointers, it adds a #define for PTR64.

*/

#include <stdio.h>

int main() {
  printf("/* This file was generated by mkint-h */\n\n");

  if (sizeof(int)==4) {
    printf("#define BCPLINT32 int\n");
    printf("#define BCPLUINT32 unsigned int\n");
  } else if (sizeof(long)==4) {
    printf("#define BCPLINT32 long\n");
    printf("#define BCPLUINT32 unsigned long\n");
  }

  if (sizeof(int)==8){
    printf("#define BCPLINT64 int\n");
    printf("#define BCPLUINT64 unsigned int\n");
  } else if (sizeof(long)==8) {
    printf("#define BCPLINT64 long\n");
    printf("#define BCPLUINT64 unsigned long\n");
  } else if (sizeof(long long)==8) {
    printf("#define BCPLINT64 long long\n");
    printf("#define BCPLUINT64 unsigned long long\n");
  }

  // Conditionally define CURRENT64
  if (sizeof(void*)==8){
    printf("#define CURRENT64\n");
    printf("#define ADDRINT BCPLINT64\n");
  }
  else
    printf("#define ADDRINT BCPLINT32\n");

  // Define FLOAT32 and FLOAT64
  printf("#define FLOAT32 float\n");
  printf("#define FLOAT64 double\n");

  if(sizeof(float)!=4) printf("SYSTEM ERROR: sizeof(float) in not 4\n");
  if(sizeof(double)!=8) printf("SYSTEM ERROR: sizeof(double) in not 8\n");

  // TARGET64 is conditionally defined elsewhere depending on the BCPL word
  // length of the target system. BCPLFLOAT will be defined as FLOAT64 or
  // FLOAT32 depending on whether TARGET64 is defined or not. Thus BCPL
  // floating point numbers have the same size as the BCPL word.

  // Discover whether char is signed or unsigned in this implementation
  
  { // It is really difficult to write code to determined whether char
    // is signed or unsigned without a strict C compiler generating a
    // warning message.
    // Here is my attempt, but see below.
    /*
    union cu {
      char c;
      unsigned char u;
      signed char s;
    } t;
    int i;
    t.u = 0xFF;
    i = t.c;
    printf("// i=%8X t.u=%8X t.c=%8X t.s=%8X\n", i, t.u, t.c, t.s); 
    if(t.c==t.s) {
      //printf("#define BCPLCHAR char\n");
      printf("#define BCPLCHAR signed char\n");
      printf("#define UBCPLCHAR unsigned char\n");
    } else {
      printf("#define BCPLCHAR signed char\n");
      //printf("#define UBCPLCHAR char\n");
      printf("#define UBCPLCHAR unsigned char\n");
    }
  */
  }
  // In an uncharacteristic burst of inspiration I have just realised
  // that it is not necessary to know whether char is signed or not.
  printf("#define BCPLCHAR signed char\n");
  printf("#define UBCPLCHAR unsigned char\n");
  return 0;
}
