Logo Search packages:      
Sourcecode: maria version File versions

StructType.C

Go to the documentation of this file.
// Struct type class -*- c++ -*-

#include "snprintf.h"

#ifdef __GNUC__
# pragma implementation
#endif // __GNUC__
#include "StructType.h"
#include "StructValue.h"
#include "Constraint.h"
#include "Printer.h"

/** @file StructType.C
 * Struct data type
 */

/* Copyright © 1998-2002 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA 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 2, or (at your option)
   any later version.

   MARIA 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.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

class Value&
00038 StructType::getFirstValue () const
{
  if (myConstraint)
    return *myConstraint->getFirstValue ().copy ();
  else {
    class StructValue* v = new class StructValue (*this);
    for (card_t i = 0; i < getSize (); i++)
      (*v)[i] = &(*this)[i].getFirstValue ();
    return *v;
  }
}

class Value&
00051 StructType::getLastValue () const
{
  if (myConstraint)
    return *myConstraint->getLastValue ().copy ();
  else {
    class StructValue* v = new class StructValue (*this);
    for (card_t i = 0; i < getSize (); i++)
      (*v)[i] = &(*this)[i].getLastValue ();
    return *v;
  }
}

bool
00064 StructType::isAssignable (const class Type& type) const
{
  if (&type == this)
    return true;

  if (type.getKind () != getKind ())
    return Type::isAssignable (type);

  return myComponents.isAssignable
    (static_cast<const class StructType&>(type).myComponents);
}

bool
00077 StructType::isAlwaysAssignable (const class Type& type) const
{
  if (&type == this)
    return true;

  if (type.getKind () != getKind ())
    return false;

  return myComponents.isAlwaysAssignable
    (static_cast<const class StructType&>(type).myComponents);
}

bool
00090 StructType::isConstrained (const class Value& value) const
{
  assert (value.getType ().isAssignable (*this));
  const class StructValue& v = static_cast<const class StructValue&>(value);
  assert (v.getSize () == getSize ());

  for (card_t i = getSize (); i--; )
    if (!(*this)[i].isConstrained (v[i]))
      return false;

  return Type::isConstrained (value);
}

card_t
00104 StructType::do_getNumValues () const
{
  assert (!myConstraint);
  card_t numValues = 1;
  for (card_t i = 0; i < myComponents.getSize (); i++) {
    card_t num = myComponents[i].getNumValues ();
    if (num != CARD_T_MAX && num < CARD_T_MAX / numValues)
      numValues *= num;
    else
      return CARD_T_MAX;
  }

  return numValues;
}

card_t
00120 StructType::convert (const class Value& value) const
{
  assert (value.getKind () == Value::vStruct);
  assert (isConstrained (value));
  assert (getNumValues () < CARD_T_MAX);

  if (myConstraint)
    return Type::convert (value);

  if (!myComponents.getSize ())
    return 0;

  card_t number = 0;
  const class StructValue& v = static_cast<const class StructValue&>(value);
  for (card_t i = myComponents.getSize (); --i; ) {
    number += myComponents[i].convert (v[i]);
    number *= myComponents[i - 1].getNumValues ();
  }
  number += myComponents[0u].convert (v[0]);

  assert (number < getNumValues ());
  return number;
}

class Value*
00145 StructType::convert (card_t number) const
{
  assert (number < getNumValues ());
  assert (getNumValues () < CARD_T_MAX);

  if (myConstraint)
    return Type::convert (number);

  class StructValue* value = new class StructValue (*this);
  if (myComponents.getSize ()) {
    const card_t size = myComponents.getSize ();
    for (card_t i = 0; i < size; i++) {
      const card_t card = myComponents[i].getNumValues ();
      card_t num = number % card;
      number /= card;
      (*value)[i] = myComponents[i].convert (num);
    }
  }

  assert (isConstrained (*value));
  return value;
}

#ifdef EXPR_COMPILE
# include "CExpression.h"
# include <stdio.h>

void
StructType::compile (class StringBuffer& out)
{
  for (card_t i = 0; i < myComponents.getSize (); i++)
    const_cast<class Type&>(myComponents[i]).compile (out);
  Type::compile (out);
}

void
StructType::compileDefinition (class StringBuffer& out,
                         unsigned indent) const
{
  out.indent (indent), out.append ("struct {\n");
  for (card_t i = 0; i < myComponents.getSize (); i++) {
    out.indent (indent + 2), myComponents[i].appendName (out);
    out.append (" s"), out.append (i), out.append (";\n");
  }
  out.indent (indent), out.append ("}");
}

bool
StructType::compileEqual (class StringBuffer& out,
                    unsigned indent,
                    const char* left,
                    const char* right,
                    bool equal,
                    bool first,
                    bool last,
                    bool backslash) const
{
  if (!myComponents.getSize ())
    return false;

  size_t llen = strlen (left), rlen = strlen (right);
  char* l = new char[llen + 23];
  char* r = new char[rlen + 23];
  memcpy (l, left, llen);
  memcpy (r, right, rlen);

  bool gen = false, genAny = false;

  for (card_t i = myComponents.getSize (); i--; ) {
    snprintf (l + llen, 23, ".s%u", i);
    snprintf (r + rlen, 23, ".s%u", i);
    gen = myComponents[i].compileEqual (out, indent, l, r,
                              equal, first, !i, backslash);
    if (gen)
      genAny = true, first = false;
  }

  delete[] l; delete[] r;

  if (gen) {
    if (!last)
      out.append (backslash
              ? (equal ? "&&\\\n" : "||\\\n")
              : (equal ? "&&\n" : "||\n"));
  }
  else if (genAny && last)
    out.indent (indent);

  return gen || !last;
}

void
StructType::compileCompare3 (class StringBuffer& out,
                       const char* condition,
                       const char* component) const
{
  const size_t len = strlen (component);
  char* const newcomp = new char[len + 23];
  char* const offset = newcomp + len;
  memcpy (newcomp, component, len);

  for (card_t i = myComponents.getSize (); i--; ) {
    snprintf (offset, 23, ".s%u", i);
    myComponents[i].compileCompare3 (out, condition, newcomp);
  }
  delete[] newcomp;
}

void
StructType::do_compileSuccessor (class StringBuffer& out,
                         unsigned indent,
                         const char* lvalue,
                         const char* rvalue,
                         const char* wrap) const
{
  if (!myComponents.getSize ())
    return;

  size_t llen = strlen (lvalue), rlen = strlen (rvalue);
  char* lval = new char[llen + 23];
  char* rval = new char[rlen + 23];
  memcpy (lval, lvalue, llen);
  memcpy (rval, rvalue, rlen);

  out.indent (indent);
  out.append ("do {\n");
  if (!wrap) {
    wrap = "wrap";
    out.indent (indent + 2);
    out.append ("bool_t ");
    out.append (wrap);
    out.append ("=0;\n");
  }

  for (card_t i = 0;; ) {
    snprintf (lval + llen, 23, ".s%u", i);
    snprintf (rval + rlen, 23, ".s%u", i);
    myComponents[i].compileSuccessor (out, indent + 2, lval, rval, wrap);
    if (++i < myComponents.getSize ()) {
      out.indent (indent + 2);
      out.append ("if (!");
      out.append (wrap);
      out.append (") {\n");
      if (lvalue != rvalue && strcmp (lvalue, rvalue)) {
      for (card_t j = i; j < myComponents.getSize (); j++) {
        out.indent (indent + 4);
        out.append (lvalue);
        out.append (".s");
        out.append (j);
        out.append ("=");
        out.append (rvalue);
        out.append (".s");
        out.append (j);
        out.append (";\n");
      }
      }
      out.indent (indent + 4);
      out.append ("continue;\n");
      out.indent (indent + 2);
      out.append ("}\n");
      out.indent (indent + 2);
      out.append (wrap);
      out.append ("=0;\n");
    }
    else
      break;
  }

  out.indent (indent);
  out.append ("} while (0);\n");

  delete[] lval;
  delete[] rval;
}

void
StructType::do_compilePredecessor (class StringBuffer& out,
                           unsigned indent,
                           const char* lvalue,
                           const char* rvalue,
                           const char* wrap) const
{
  if (!myComponents.getSize ())
    return;

  size_t llen = strlen (lvalue), rlen = strlen (rvalue);
  char* lval = new char[llen + 23];
  char* rval = new char[rlen + 23];
  memcpy (lval, lvalue, llen);
  memcpy (rval, rvalue, rlen);

  out.indent (indent);
  out.append ("do {\n");
  if (!wrap) {
    wrap = "wrap";
    out.indent (indent + 2);
    out.append ("bool_t ");
    out.append (wrap);
    out.append ("=0;\n");
  }

  for (card_t i = 0;; ) {
    snprintf (lval + llen, 23, ".s%u", i);
    snprintf (rval + rlen, 23, ".s%u", i);
    myComponents[i].compilePredecessor (out, indent + 2, lval, rval, wrap);
    if (++i < myComponents.getSize ()) {
      out.indent (indent + 2);
      out.append ("if (!");
      out.append (wrap);
      out.append (") {\n");
      if (lvalue != rvalue && strcmp (lvalue, rvalue)) {
      for (card_t j = i; j < myComponents.getSize (); j++) {
        out.indent (indent + 4);
        out.append (lvalue);
        out.append (".s");
        out.append (j);
        out.append ("=");
        out.append (rvalue);
        out.append (".s");
        out.append (j);
        out.append (";\n");
      }
      }
      out.indent (indent + 4);
      out.append ("continue;\n");
      out.indent (indent + 2);
      out.append ("}\n");
      out.indent (indent + 2);
      out.append (wrap);
      out.append ("=0;\n");
    }
    else
      break;
  }

  out.indent (indent);
  out.append ("} while (0);\n");

  delete[] lval;
  delete[] rval;
}

void
StructType::compileCast (class CExpression& cexpr,
                   unsigned indent,
                   const class Type& target,
                   const char* lvalue,
                   const char* rvalue) const
{
  assert (isAssignable (target));
  if (target.getKind () != Type::tStruct)
    Type::compileCast (cexpr, indent, target, lvalue, rvalue);
  else {
    const class StructType& st = static_cast<const class StructType&>(target);
    assert (getSize () == st.getSize ());
    size_t llen = strlen (lvalue);
    size_t rlen = strlen (rvalue);
    char* lval = new char[llen + 23];
    char* rval = new char[llen + 23];
    memcpy (lval, lvalue, llen);
    memcpy (rval, rvalue, rlen);
    for (card_t i = getSize (); i--; ) {
      snprintf (lval + llen, 23, ".s%u", i);
      snprintf (rval + rlen, 23, ".s%u", i);
      myComponents[i].compileCast (cexpr, indent, st[i], lval, rval);
    }
    delete[] lval;
    delete[] rval;
    if (const class Constraint* c = target.getConstraint ())
      c->compileCheck (cexpr, indent, lvalue);
  }
}

void
StructType::do_compileConversion (class StringBuffer& out,
                          unsigned indent,
                          const char* value,
                          const char* number,
                          bool add) const
{
  card_t i = myComponents.getSize ();
  assert (getNumValues () < CARD_T_MAX && i);
  size_t length = strlen (value);
  char* val = new char[length + 23];
  char* offset = val + length;
  memcpy (val, value, length);
  memcpy (offset, ".s0", 4);

  if (myComponents[0u].getNumValues () == getNumValues ())
    myComponents[0u].compileConversion (out, indent, val, number, add);
  else if (--i) {
    const char* num = number;
    if (add) {
      out.indent (indent), out.append ("{\n");
      out.indent (indent += 2), out.append ("card_t ");
      length = strlen (number);
      char* nbr = new char[length + 2];
      memcpy (nbr, number, length);
      memcpy (nbr + length, "_", 2);
      num = nbr;
      out.append (num), out.append (";\n");
    }

    for (bool next = false; i; next = true) {
      snprintf (offset, 23, ".s%u", i);
      myComponents[i].compileConversion (out, indent, val, num, next);
      const card_t numValues = myComponents[--i].getNumValues ();
      if (numValues != 1) {
      out.indent (indent), out.append (num), out.append ("*=");
      out.append (numValues), out.append (";\n");
      }
    }

    memcpy (offset, ".s0", 4);
    myComponents[0u].compileConversion (out, indent, val, num, true);

    if (add) {
      out.indent (indent), out.append (number), out.append ("+=");
      out.append (num), out.append (";\n");
      out.indent (indent -= 2), out.append ("}\n");
      delete[] num;
    }
  }
  else
    myComponents[0u].compileConversion (out, indent, val, number, add);

  delete[] val;
}

void
StructType::compileReverseConversion (class StringBuffer& out,
                              unsigned indent,
                              const char* number,
                              const char* value) const
{
  if (myConstraint)
    Type::compileReverseConversion (out, indent, number, value);
  else if (getNumValues () == 1)
    compileBottom (out, indent, value);
  else {
    size_t length = strlen (value);
    char* val = new char[length + 23];
    char* offset = val + length;
    memcpy (val, value, length);

    switch (myComponents.getSize ()) {
    case 0:
      assert (false);
      break;
    default:
      if (myComponents[0u].getNumValues () != getNumValues ()) {
      length = strlen (number);
      char* num = new char[length + 2];
      memcpy (num, number, length);
      memcpy (num + length, "_", 2);

      out.indent (indent), out.append ("{\n");
      out.indent (indent + 2);
      out.append ("card_t "), out.append (num), out.append (";\n");

      for (card_t i = 0; i < myComponents.getSize (); i++) {
        snprintf (offset, 23, ".s%u", i);
        card_t numValues = myComponents[i].getNumValues ();
        if (numValues != 1) {
          out.indent (indent + 2);
          out.append (num), out.append ("="), out.append (number);
          out.append ("%"), out.append (numValues);
          out.append (", ");
          out.append (number), out.append ("/=");
          out.append (numValues);
          out.append (";\n");
          myComponents[i].compileReverseConversion (out, indent + 2,
                                          num, val);
        }
        else
          myComponents[i].compileBottom (out, indent + 2, val);
      }

      out.indent (indent), out.append ("}\n");

      delete[] num;
      break;
      }
      else {
      for (card_t i = myComponents.getSize (); --i; ) {
        snprintf (offset, 23, ".s%u", i);
        myComponents[i].compileBottom (out, indent, val);
      }
      }
      // fall through
    case 1:
      memcpy (offset, ".s0", 4);
      myComponents[0u].compileReverseConversion (out, indent, number, val);
    }
    delete[] val;
  }
}

void
StructType::compileEncoder (class CExpression& cexpr,
                      unsigned indent,
                      const char* func,
                      const char* value) const
{
  if (getNumValues () < CARD_T_MAX)
    Type::compileEncoder (cexpr, indent, func, value);
  else {
    size_t length = strlen (value);
    char* val = new char[length + 23];
    char* offset = val + length;
    memcpy (val, value, length);
    for (card_t i = 0; i < myComponents.getSize (); i++) {
      snprintf (offset, 23, ".s%u", i);
      myComponents[i].compileEncoder (cexpr, indent, func, val);
    }
    delete[] val;
  }
}

void
StructType::compileDecoder (class CExpression& cexpr,
                      unsigned indent,
                      const char* func,
                      const char* value) const
{
  if (getNumValues () < CARD_T_MAX)
    Type::compileDecoder (cexpr, indent, func, value);
  else {
    size_t length = strlen (value);
    char* val = new char[length + 23];
    char* offset = val + length;
    memcpy (val, value, length);
    for (card_t i = 0; i < myComponents.getSize (); i++) {
      snprintf (offset, 23, ".s%u", i);
      myComponents[i].compileDecoder (cexpr, indent, func, val);
    }
    delete[] val;
  }
}

#endif // EXPR_COMPILE

void
00588 StructType::display (const class Printer& printer) const
{
  printer.printRaw ("struct ");
  printer.delimiter ('{')++;
  myComponents.display (printer);
  --printer.delimiter ('}');

  if (myConstraint)
    myConstraint->display (printer);
}

Generated by  Doxygen 1.6.0   Back to index