view anagram/agcore/tsd.cpp @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 *
 * tsd.cpp - tuple set dictionary
 */

#include <stdarg.h>
#include <string.h>
#include "port.h"

#include "assert.h"
#include "myalloc.h"
#include "tsd.h"

//#define INCLUDE_LOGGING
#include "log.h"


/*
 invalid_tsd() checks the internal consistency of a tuple set and
 returns true if the tuple set is invalid
*/

int invalid_tsd(tsd *t) {
  if (!ptr_ok(t)) return 1;
  if (t->nt > t->na) return 1;
  if (t->sb == NULL) return 0;
  return !ptr_ok(t->sb);
}

void purge_tsd(tsd *r, tsd *k) {
  LOGSECTION("purge_tsd");
  int *rp = r->sb;
  int *wp = rp;
  int  wn = 0;
  int  rn = r->nt;
  int  rw = r->tw;
  int *kp = k->sb;
  int  kn = k->nt;
  int  kw = k->tw;

  LOGV(r->nt) LCV(k->nt);
  check_tsd(r);
  check_tsd(k);
  assert (kw == rw);
  while (rn--) {
    int *sp = kp;
    int  sn = kn;

#ifdef INCLUDE_LOGGING
    LOGS("Contains   ");
    for (int k = 0; k < kw; k++) LOGX() LS(rp[k]);
#endif

    while (sn--) {
      int k = rw;
      while (k--) {
	if (rp[k] != sp[k]) break;
      }
      if (k < 0) break;
      sp += kw;
    }
    if (sn < 0) {
      if (wp != rp) {
        int k = rw;
        while (k--) {
	  wp[k] = rp[k];
	}
      }
      wp += rw;
      wn++;
    }
#ifdef INCLUDE_LOGGING
    else {
      LOGS("Eliminating");
      for (int k = 0; k < kw; k++) (*Log::theLog) LS(rp[k]);
    }
#endif
    rp += rw;
  }
  r->nt = wn;
}

void p1_tsd(tsd *r, int rc, tsd *k, int kc) {
  int *rp = r->sb;
  int *wp = rp;
  int  wn = 0;
  int  rn = r->nt;
  int  rw = r->tw;
  int *kp = k->sb;
  int  kn = k->nt;
  int  kw = k->tw;

  check_tsd(k);
  while (rn--) {
    int *sp = kp;
    int  sn = kn;
    int  tv = rp[rc];

    while (sn--) {
      if (tv == sp[kc]) break;
      sp += kw;
    }
    if (sn < 0) {
      if (wp != rp) {
        int k = rw;
        while (k--) {
	  wp[k] = rp[k];
	}
      }
      wp += rw;
      wn++;
    }
    rp += rw;
  }
  r->nt = wn;
}

/*
 copy_tuple_set makes a copy of a tuple set, including a copy
 of the contents
*/

tsd *copy_tuple_set(tsd *t) {
  tsd *c;
  unsigned n;

  check_tsd(t);
  c = ZALLOCATE(1,tsd);
  n = t->na * t->tw;
  c->sb = ALLOCATE(n, int);
  if (n) {
    memmove(c->sb,t->sb, n*sizeof(*t->sb));
  }
  c->nt = t->nt;
  c->tw = t->tw;
  c->na = t->na;
  return c;
}

tsd *delete_tsd(tsd *ts) {
  if (ts == NULL) {
    return NULL;
  }
  assert(ts->nt <= ts->na);
  if (ts->sb != NULL) {
    DEALLOCATE(ts->sb);
  }
  DEALLOCATE(ts);
  return NULL;
}

void reset_tsd(tsd *ts) {
  unsigned na,tw;
  unsigned k;

  check_tsd(ts);
  assert(ts->nt <= ts->na);
  if (ts->nt == 0) {
    if (ts->sb == NULL) {
      return;
    }
  }
  tw = ts->tw;
  na = ts->na;
  ts->nt = 0;
  ok_ptr(ts->sb);
  k = tw*na*sizeof(*ts->sb);
  size_ok(ts->sb, k, __FILE__, __LINE__);
  memset(ts->sb, 0, k);
}

tsd *spec_tsd(unsigned size, unsigned n) {
  tsd *ts;

  ts = ZALLOCATE(1, tsd);
  ok_ptr(ts);
  ts->tw = n;
  if (size == 0) {
    return ts;
  }
  ts->na = size;
  ts->sb = ZALLOCATE(size*ts->tw, int);
  return ts;
}

tsd *resize_tsd(tsd *ts, unsigned size) {
  LOGSECTION("resize_tsd");
  unsigned lim;

  ok_ptr(ts);
  if (size == ts->na) {
    return ts;
  }

  lim = (unsigned) MAX_BYTES/(ts->tw * sizeof(*ts->sb));
  if (size > lim) {
    size = lim;
  }
  LOGV(ts->nt) LCV(size);

  assert(ts->nt <= size);
  ts->sb = reallocate(ts->sb,ts->tw*size, int);
  ts->na = size;
  return ts;
}

tsd *init_tsd(unsigned n) {
  tsd *ts;

  ts = spec_tsd(32,n);
  return ts;
}

int sit(tsd *t,...) {
  va_list ap;
  int *sp,*p;
  unsigned i,j;
  unsigned long size;
  unsigned long lim;
  unsigned nt,tw,nb;
  int flag;

  check_stack;
  check_tsd(t);
  if (t->nt >= t->na) {
    if (t->na == 0) {
      size = 32;
    }
    else if (t->na > ((MAX_BYTES/2)/3)) {
      size = MAX_BYTES;
    }
    else {
      size = 1 + t->na + t->na/2;
    }

    lim = MAX_BYTES/(t->tw * sizeof(*t->sb));
    if (size > lim) size = lim;
    LOGSECTION("sit::resize");
    LOGV(t->nt) LCV(size);
    assert(t->nt < size);

    t->sb = reallocate(t->sb,t->tw*(unsigned)size, int);
    t->na = (unsigned) size;
  }

  va_start(ap,t);
  sp = t->sb + t->tw * t->nt;
  for (i = 0; i < t->tw; i++) {
    sp[i] = va_arg(ap, int);
  }
  va_end(ap);
  p = t->sb;
  tw = t->tw;
  nb = sizeof(*t->sb)*tw;
  nt = t->nt;
  for (i = 0; i < nt; i++, p += tw) {
    for (j = 0; j < tw; j++) {
      if ((flag = sp[j] - p[j]) < 0) {
	goto b;
      }
      if (flag > 0) {
	goto c;
      }
    }
    return 1;
  c:
    continue;
  b:
    break;
  }
  memmove(p+tw,p,nb*(nt - i));
  va_start(ap, t);
  for (i = 0; i < t->tw; i++) {
    p[i] = va_arg(ap, int);
  }
  t->nt++;
  va_end(ap);
  return 0;
}

void at(tsd *t,...) {
  va_list ap;
  int *sp;
  int i;
  unsigned long size;
  unsigned long lim;

  check_stack;
  check_tsd(t);
  if (t->nt >= t->na) {
    if (t->na == 0) {
      size = 32;
    }
    else if (t->na > ((MAX_BYTES/2)/3)) {
      size = MAX_BYTES;
    }
    else {
      size = 1 + t->na + t->na/2;
    }

    lim = MAX_BYTES/(t->tw * sizeof(*t->sb));
    if (size > lim) {
      size = lim;
    }
    LOGSECTION("at::resize");
    LOGV(t->nt) LCV(size);
    assert(t->nt < size);

    t->sb = reallocate(t->sb, t->tw*(int)size, int);
    t->na = (unsigned) size;
  }

  va_start(ap,t);
  sp = t->sb + t->tw * t->nt;
  for (i = t->tw; i--; ) {
    *sp++ = va_arg(ap, int);
  }
  t->nt++;
  va_end(ap);
}

void xtx(tsd *t, unsigned x, ...) {
  va_list ap;
  int *sp;
  unsigned i;

  check_stack;
  check_tsd(t);
  assert(x < t->nt);
  va_start(ap, x);
  sp = t->sb + t->tw*x;
  for (i = 0; i<t->tw; i++) {
    *(va_arg(ap, int*)) = sp[i];
  }
  va_end(ap);
}

void xtxf(tsd *t, unsigned x, ...) {
  va_list ap;
  int *sp;
  unsigned i;

  va_start(ap, x);
  sp = t->sb+t->tw*x;
  for (i = t->tw; i--; ) {
    *(va_arg(ap, int*)) = *sp++;
  }
  va_end(ap);
}