//    GMPAda, binding to the Ada Language for the GNU MultiPrecision library.
//    Copyright (C) 2009-2017 Nicolas Boulenguez <nicolas.boulenguez@free.fr>
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

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


// The size of the result of sizeof(...) and of some integer constants
// depends of the architecture. We convert all values to long so that
// printf is not confused.
void print_s (const char * name,
              const char * value) {
  printf ("   %-25s : constant String := \"%s\";\n", name, value); }
void print_i (const char * name,
              signed long int value) {
  printf ("   %-25s : constant := %li;\n", name, value); }
void print_u (const char * name,
              unsigned long int value) {
  printf ("   %-25s : constant := %lu;\n", name, value); }


int main (int argc, char* argv[])
{
  const __mpz_struct z;

  if (argc != 1) {
    fprintf (stderr,"no argument expected.\n");
    exit (EXIT_FAILURE);
  }
  if (sizeof(z._mp_alloc) != sizeof(int)        ||
      sizeof(z._mp_size)  != sizeof(int)        ||
      sizeof(z._mp_d)     != sizeof(mp_limb_t*) ||
      sizeof(z._mp_alloc)+sizeof(z._mp_size)+sizeof(z._mp_d) != sizeof(mpz_t))
    {
      fprintf (stderr, "\n\
An incompatible change of mpz_t has been detected in gmp.h.\n\
Please report this to the Ada binding author.\n");
      exit (EXIT_FAILURE);
    }
  printf ("--  Generated by the C program %s.c.\n", argv[0]);
  printf ("--  Do not edit this file directly.\n");
  printf ("--  The values provided here may vary on your system.\n");
  printf ("\n");
  printf ("package GMP.Constants is\n");
  printf ("   pragma Pure;\n");

  print_s ("Gmp_Version", gmp_version);
  print_i ("Mp_Bits_Per_Limb", mp_bits_per_limb);
  print_u ("Gnu_Mp_Version", __GNU_MP_VERSION);
  print_u ("Gnu_Mp_Version_Minor", __GNU_MP_VERSION_MINOR);
  print_u ("Gnu_Mp_Version_Patchlevel", __GNU_MP_VERSION_PATCHLEVEL);
  print_u ("Mp_Exp_T_Size", 8*sizeof(mp_exp_t));
  print_u ("Mp_Size_T_Size", 8*sizeof(mp_size_t));
  print_u ("Mp_Limb_T_Size", 8*sizeof(mp_limb_t));
  print_u ("Mpz_Alloc_Start", (char*)&z._mp_alloc - (char*)&z);
  print_u ("Mpz_Alloc_Length", 8 * sizeof (z._mp_alloc));
  print_u ("Mpz_Size_Start", (char*)&z._mp_size  - (char*)&z);
  print_u ("Mpz_Size_Length", 8 * sizeof (z._mp_size));
  print_u ("Mpz_D_Start", (char*)&z._mp_d     - (char*)&z);
  print_u ("Mpz_D_Length", 8 * sizeof (z._mp_d));
  print_u ("Sizeof_Mpq_T", sizeof(mpq_t));
  print_u ("Sizeof_Mpf_T", sizeof(mpf_t));
  print_u ("Sizeof_Gmp_Randstate_T", sizeof(gmp_randstate_t));

  printf ("end GMP.Constants;\n");
  exit (EXIT_SUCCESS);
}
