#ifdef DIAGNOSTICS

static void SHOW_NUM(char *dest, long num) { // left-aligned
#define show_digit(x) *dest++ = (char)((x)+'0')
  int8_t digit, zeroes;

  // This replaces code that used divide by 10 and modulo 10.  Much faster.

  // handles full 16 bit range of -32768:32767  -  Uses negative numbers to avoid the issue of negating -32768

  if (num >= 0) num = -num; else *dest++ = '-';
  digit = 0;
  zeroes = 1; // CLRing is shorter
  // max 11 add/subtracts...
  if (num <= -20000) { num += 20000; digit += 2; zeroes = 0; }
  if (num <= -10000) { num += 10000; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  digit = 0;
  if (num <= -8000) { num += 8000; digit += 8; zeroes = 0; } else if (num <= -4000) { num += 4000; digit += 4; zeroes = 0; }
  if (num <= -2000) { num += 2000; digit += 2; zeroes = 0; }
  if (num <= -1000) { num += 1000; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  digit = 0;
  if (num <= -800) { num += 800; digit += 8; zeroes = 0; } else if (num <= -400) { num += 400; digit += 4; zeroes = 0; }
  if (num <= -200) { num += 200; digit += 2; zeroes = 0; }
  if (num <= -100) { num += 100; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  digit = 0;
  if (num <= -80) { num += 80; digit += 8; zeroes = 0; } else if (num <= -40) { num += 40; digit += 4; zeroes = 0; }
  if (num <= -20) { num += 20; digit += 2; zeroes = 0; }
  if (num <= -10) { num += 10; digit += 1; zeroes = 0; }
  if (!zeroes) show_digit(digit);
  show_digit((int8_t)-num);
  *dest = 0x80;
}

void assertx(int8_t condition, char *condstr, long line) {
  if (!condition) {
    for (;;) {
     int8_t strlen = 0;
      for (;;) {
        if (condstr[strlen] == '\0') break;
        strlen += 1;
      }
      if (strlen < 5) strlen=5; 
      char buffer[strlen+2];
      strlen=0;
      for (;;) {
        buffer[strlen] = condstr[strlen];
        if ('a' <= buffer[strlen] && buffer[strlen] <= 'z') buffer[strlen] += (char)('A' - 'a');
        if (condstr[strlen] == '\0') break;
        strlen += 1;
      }
      buffer[strlen++] = ' ';buffer[strlen++] = ' ';
      buffer[strlen] = 0x80;
      Wait_Recal (); Flash++;
      Reset0Ref ();
      Intensity_7F ();
      set_scale (BIG_SCALE);
      Print_Str_d ( 40, -120, "ASSERTION\x80");
      Print_Str_d ( 20, -120, buffer);
      Print_Str_d (  0, -120, "FAILS AT LINE\x80");
      SHOW_NUM(buffer, line); Print_Str_d (-20, -120, buffer);
    }
  }
}
#define assert(test) assertx(test, #test, __LINE__)

long CHECK (long index, char *name, int8_t low, int8_t high, long line) {
  if ((index < low) || (index > high)) {
    //fprintf (stderr, "%s[%d] out of bounds at line %ld.  Declared as %s[%d:%d]\n", name, index, line, name, low, high);
    //exit (1);
    for (;;) {
      int8_t strlen = 0;
      for (;;) {
        if (name[strlen] == '\0') break;
        strlen += 1;
      }
      if (strlen < 5) strlen=5; 
      char buffer[strlen+2];
      strlen=0;
      for (;;) {
        buffer[strlen] = name[strlen];
        if ('a' <= buffer[strlen] && buffer[strlen] <= 'z') buffer[strlen] += (char)('A' - 'a');
        if (name[strlen] == '\0') break;
        strlen += 1;
      }
      buffer[strlen++] = ' ';buffer[strlen++] = ' ';
      buffer[strlen] = 0x80;
      Wait_Recal (); Flash++;
      Reset0Ref ();
      Intensity_7F ();
      set_scale (BIG_SCALE);
      Print_Str_d ( 40, -120, buffer);
      SHOW_NUM(buffer, (long)index); Print_Str_d ( 20, -120, buffer);
      Print_Str_d (  0, -120, "OUT OF BOUNDS AT LINE\x80");
      SHOW_NUM(buffer, line); Print_Str_d (-20, -120, buffer);
      Print_Str_d (-40, -120, "DECLARED AS\x80");
      SHOW_NUM(buffer, (long)low); Print_Str_d (-60, -120, buffer);
      Print_Str_d (-80, -120, "TO \x80");
      SHOW_NUM(buffer, (long)high); Print_Str_d (-100, -120, buffer);
    }                             // for (main polling loop)

  }
  return index;
}
int16_t CKTYPEx(int16_t val, char *s, int line) {
  if (val != CROWN && val != 1000 && val != 0) {
    if (logfile) fprintf(logfile, "Bad TYPE assignment at line %d - value of %s is %d\n", line, s, (int)val);
    exit(0);
  }
  return val;
}
int16_t CKTYPE2x(int16_t val, char *s, int line, INTEGER num) {
  if (val != CROWN && val != 1000 && val != 0) {
    if (logfile) fprintf(logfile, "Bad TYPE assignment at line %d - value of %s is %d  COMP_TYPE(%d)\n", line, s, (int)val, (int)num);
    exit(0);
  }
  return val;
}
#define CKTYPE(val) CKTYPEx(val, #val, __LINE__)
#define CKTYPE2(val,num) CKTYPE2x(val, #val, __LINE__, num)
#else
#define assert(x) do { } while (0)
#define CHECK(index,name,low,high,line) ((long)(index))
// no arrays have > 127 elements so we might be tempted to use
// and int8_t here, HOWEVER we need 'long' here if we have *any* 
// arrays indexed by '-1'.  Made that mistake once and it created
// a huge number of hard-to-find bugs!
#define CKTYPE(val) (val)
#endif