/* -*- mode: C -*-
 *
 * Copyright (c) 2007-2011, 2013, 2014, 2015 The University of Utah
 * All rights reserved.
 *
 * This file is part of `csmith', a random generator of C programs.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef NO_PRINTF
int putchar (int);
#else
extern int printf (const char *, ...);
#endif

// FIXME-- need more versions, and a way to figure out which is needed
#include "custom_stdint_x86.h"

#include "custom_limits.h"

#define STATIC static

#define UNDEFINED(__val) (__val)

#define LOG_INDEX

#define LOG_EXEC

#define FUNC_NAME(x) (safe_##x)

// FIXME
#define assert(x)

#if defined (USE_MATH_MACROS_NOTMP)
#include "safe_math_macros_notmp.h"
#elif defined (USE_MATH_MACROS)
#include "safe_math_macros.h"
#else
#define FUNC_NAME(x) (safe_##x)
#include "safe_math.h"
#undef FUNC_NAME
#endif

static inline void platform_main_begin(void)
{
}

static inline void crc32_gentab (void)
{
}

#define _CSMITH_BITFIELD(x) ((x>32)?(x%32):x)

uint64_t crc32_context;

#ifdef TCC
int strcmp (const char *s1, const char *s2)
{
  for(; *s1 == *s2; ++s1, ++s2)
    if(*s1 == 0)
      return 0;
  return *(unsigned char *)s1 < *(unsigned char *)s2 ? -1 : 1;
}
#else
extern int strcmp (const char *, const char *);
#endif

static inline void 
transparent_crc (uint64_t val, char* vname, int flag)
{
#ifndef NO_PRINTF
  if (flag) printf ("%s %d\n", vname, val);
#endif
  crc32_context += val;
}

static void 
transparent_crc_bytes (char *ptr, int nbytes, char* vname, int flag)
{
  int i;
  for (i=0; i<nbytes; i++) {
    crc32_context += ptr[i];
  }
#ifndef NO_PRINTF
  if (flag) {
    printf("...checksum after hashing %s : %lX\n", vname, crc32_context ^ 0xFFFFFFFFUL);
  }
#endif
}

#ifdef NO_PRINTF
void my_puts (char *p)
{
  int i = 0;
  while (p[i]) {
    putchar (p[i]);
    i++;
  }
}

void put_hex (int x)
{
  switch (x) {
  case 0x0: putchar ('0'); break;
  case 0x1: putchar ('1'); break;
  case 0x2: putchar ('2'); break;
  case 0x3: putchar ('3'); break;
  case 0x4: putchar ('4'); break;
  case 0x5: putchar ('5'); break;
  case 0x6: putchar ('6'); break;
  case 0x7: putchar ('7'); break;
  case 0x8: putchar ('8'); break;
  case 0x9: putchar ('9'); break;
  case 0xa: putchar ('a'); break;
  case 0xb: putchar ('b'); break;
  case 0xc: putchar ('c'); break;
  case 0xd: putchar ('d'); break;
  case 0xe: putchar ('e'); break;
  case 0xf: putchar ('f'); break;
  }
}
#endif

static inline void
platform_main_end (uint64_t x, int flag)
{
#ifndef NOT_PRINT_CHECKSUM
  if (!flag) {
#ifdef NO_PRINTF
    int i;
    my_puts ("checksum = ");
    for (i=0; i<16; i++) {
      put_hex (x & 0xf);
      x >>= 4;
    }
    putchar ('\n');
#else
    printf ("checksum = %llx\n", x);
#endif
  }
#endif
}
