modules/up/src/rpsl/rpsl/rptype.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. Attribute
  2. newRPType
  3. newRPType
  4. newRPType
  5. newRPType
  6. validate
  7. typeCast
  8. validate
  9. validate
  10. validate
  11. typeCast
  12. validate
  13. validate
  14. validate
  15. typeCast
  16. validate
  17. validate
  18. typeCast
  19. validate
  20. validate
  21. validate
  22. validate
  23. validate
  24. validate
  25. validate
  26. validate
  27. typeCast
  28. validate
  29. validate
  30. validate
  31. validate
  32. validate
  33. validate
  34. typeCast
  35. validate
  36. validate
  37. validate
  38. typeCast
  39. validate
  40. typeCast
  41. name
  42. validate
  43. typeCast
  44. validate
  45. validate

//  $Id: rptype.cc,v 1.1.1.1 2000/03/10 16:32:23 engin Exp $
//
//  Copyright (c) 1994 by the University of Southern California
//  All rights reserved.
//
//  Permission to use, copy, modify, and distribute this software and its
//  documentation in source and binary forms for lawful non-commercial
//  purposes and without fee is hereby granted, provided that the above
//  copyright notice appear in all copies and that both the copyright
//  notice and this permission notice appear in supporting documentation,
//  and that any documentation, advertising materials, and other materials
//  related to such distribution and use acknowledge that the software was
//  developed by the University of Southern California, Information
//  Sciences Institute. The name of the USC may not be used to endorse or
//  promote products derived from this software without specific prior
//  written permission.
//
//  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
//  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
//  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
//  TITLE, AND NON-INFRINGEMENT.
//
//  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
//  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
//  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
//  OR PERFORMANCE OF THIS SOFTWARE.
//
//  Questions concerning this software should be directed to 
//  ratoolset@isi.edu.
//
//  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>

#include "config.h"
#include <cstring>
#include <cstdarg>
#include <cstdio>
#include <typeinfo>
#include "util/List.hh"

class Attribute;
/* [<][>][^][v][top][bottom][index][help] */
#include "rptype.hh"
#include "schema.hh"

extern "C" {
int strcasecmp(...);
}

////////////////////////////// RPType ////////////////////

RPType *RPType::newRPType(char *name) {
   if (!strcasecmp(name, "integer"))
      return new RPTypeInt;
   if (!strcasecmp(name, "real"))
      return new RPTypeReal;
   if (!strcasecmp(name, "rpsl_word"))
      return new RPTypeWord;
   //   if (!strcasecmp(name, "blob"))
   //      return new RPTypeBlob;
   if (!strcasecmp(name, "as_number"))
      return new RPTypeASNumber;
   if (!strcasecmp(name, "ipv4_address"))
      return new RPTypeIPv4Address;
   if (!strcasecmp(name, "address_prefix"))
      return new RPTypeIPv4Prefix;
   if (!strcasecmp(name, "ipv6_prefix"))
      return new RPTypeIPv6Prefix;
   if (!strcasecmp(name, "address_prefix_range"))
      return new RPTypeIPv4PrefixRange;
   if (!strcasecmp(name, "connection"))
      return new RPTypeConnection;
   if (!strcasecmp(name, "dns_name"))
      return new RPTypeDNSName;
   if (!strcasecmp(name, "filter"))
      return new RPTypeFilter;
   if (!strcasecmp(name, "as_set_name"))
      return new RPTypeASName;
   if (!strcasecmp(name, "route_set_name"))
      return new RPTypeRSName;
   if (!strcasecmp(name, "rtr_set_name"))
      return new RPTypeRtrsName;
   if (!strcasecmp(name, "peering_set_name"))
      return new RPTypePrngName;
   if (!strcasecmp(name, "filter_set_name"))
      return new RPTypeFltrName;
   if (!strcasecmp(name, "string"))
      return new RPTypeString;
   if (!strcasecmp(name, "time_stamp"))
      return new RPTypeTimeStamp;
   if (!strcasecmp(name, "boolean"))
      return new RPTypeBoolean;
   if (!strcasecmp(name, "free_text"))
      return new RPTypeFreeText;
   if (!strcasecmp(name, "email"))
      return new RPTypeEMail;
//   if(!strcasecmp(name, "nichdl"))
//      return new RPTypeNICHdl;
   if(!strcasecmp(name, "keycrtname"))
      return new RPTypeKeyCrtName;

   return schema.searchTypedef(name);
}

RPType *RPType::newRPType(char *name, long long int min, long long int max) {
/* [<][>][^][v][top][bottom][index][help] */
   if (!strcasecmp(name, "integer"))
      return new RPTypeInt(min, max);
   if (!strcasecmp(name, "real"))
      return new RPTypeReal(min, max);

   return NULL;
}

RPType *RPType::newRPType(char *name, double min, double max) {
/* [<][>][^][v][top][bottom][index][help] */
   if (!strcasecmp(name, "real"))
      return new RPTypeReal(min, max);

   return NULL;
}

RPType *RPType::newRPType(char *name, List<WordNode> *words) {
/* [<][>][^][v][top][bottom][index][help] */
   if (!strcasecmp(name, "enum"))
      return new RPTypeEnum(words);

   return NULL;
}

RPType *RPType::newRPType(char *name, List<RPTypeNode> *types) {
/* [<][>][^][v][top][bottom][index][help] */
   if (types && !types->isEmpty())
      if (!strcasecmp(name, "union"))
         return new RPTypeUnion(types);

   return NULL;
}

bool RPType::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return false;
}
Item *RPType::typeCast(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return NULL;
}
bool RPType::validate(ItemList *list) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (! list->isSingleton())
      return false;
   if (validate(list->head()))
      return true;
   
   Item *w = typeCast(list->head());
   if (!w)
      return false;
   
   list->clear();
   list->append(w);

   return true;
}

////////////////////////////// RPTypeInt ////////////////////

bool RPTypeInt::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemINT) 
           && min <= ((ItemINT *) item)->i
           && max >= ((ItemINT *) item)->i);
}

////////////////////////////// RPTypeReal ////////////////////

bool RPTypeReal::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemREAL) 
           && min <= ((ItemREAL *) item)->real
           && max >= ((ItemREAL *) item)->real);
}

Item *RPTypeReal::typeCast(const Item  *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemINT)  
       && min <= ((ItemINT *) item)->i
       && max >= ((ItemINT *) item)->i)
      return new ItemREAL(((ItemINT *) item)->i);

   return NULL;
}

////////////////////////////// RPTypeString ////////////////////

bool RPTypeString::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemSTRING));
}

////////////////////////////// RPTypeTimeStamp ////////////////////

bool RPTypeTimeStamp::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemTimeStamp));
}

////////////////////////////// RPTypeWORD ////////////////////

bool RPTypeWord::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemWORD));
}
Item *RPTypeWord::typeCast(const Item  *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemASNAME)){
      return new ItemWORD(strdup(((ItemASNAME *) item)->name));
   }
   if (typeid(*item) == typeid(ItemRSNAME))
      return new ItemWORD(strdup(((ItemRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRTRSNAME))
      return new ItemWORD(strdup(((ItemRTRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemPRNGNAME))
      return new ItemWORD(strdup(((ItemPRNGNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemNICHDL)){
//      cout << "typecasting: ItemNICHDL->ItemWORD" << endl;
//      return new ItemWORD(strdup(((ItemNICHDL *) item)->nichdl));
//   }
   if (typeid(*item) == typeid(ItemFLTRNAME))
      return new ItemWORD(strdup(((ItemFLTRNAME *) item)->name));
   if (typeid(*item) == typeid(ItemKEYCRTNAME))
      return new ItemWORD(strdup(((ItemKEYCRTNAME *) item)->name));
   if (typeid(*item) == typeid(ItemBOOLEAN))
      if (((ItemBOOLEAN *) item)->i)
         return new ItemWORD(strdup("true"));
      else
         return new ItemWORD(strdup("false"));
   if (typeid(*item) == typeid(ItemASNO)) {
      char buffer[64];
      sprintf(buffer, "AS%d", ((ItemASNO *) item)->asno);
      return new ItemWORD(strdup(buffer));
   }

   return NULL;
}

////////////////////////////// RPTypeNICHdl ////////////////////
/*
bool RPTypeNICHdl::validate(const Item *item) const {
   if(typeid(*item) == typeid(ItemNICHDL)){
      cout << "Debug: RPTypeNICHdl::validate (nichdl = "<< ((ItemNICHDL *) item)->nichdl << ")" << endl;
   }else{
      cout << "Debug: RPTypeNICHdl::validate" << endl;
   }
   cout << "Debug: RPTypeNICHdl::validate " << typeid(*item).name() << " " << typeid(ItemNICHDL).name() << endl;
//   return false;
   return (typeid(*item) == typeid(ItemNICHDL)
            && ((strchr(((ItemNICHDL *) item)->nichdl,'q') != NULL) 
               || (strchr(((ItemNICHDL *) item)->nichdl,'Q') != NULL)));
}
*/
/*Item *RPTypeNICHdl::typeCast(const Item  *item) const {
   if (typeid(*item) == typeid(ItemWORD)){
      cout << "typecasting: ItemWORD -> ItemNICHDL" << endl;
      return new ItemNICHDL(strdup(((ItemWORD *) item)->word));
   }
   if (typeid(*item) == typeid(ItemASNAME))
      return new ItemNICHDL(strdup(((ItemASNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRSNAME))
      return new ItemNICHDL(strdup(((ItemRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRTRSNAME))
      return new ItemNICHDL(strdup(((ItemRTRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemPRNGNAME))
      return new ItemNICHDL(strdup(((ItemPRNGNAME *) item)->name));
   if (typeid(*item) == typeid(ItemFLTRNAME))
      return new ItemNICHDL(strdup(((ItemFLTRNAME *) item)->name));
   if (typeid(*item) == typeid(ItemKEYCRTNAME))
      return new ItemWORD(strdup(((ItemKEYCRTNAME *) item)->name));
   if (typeid(*item) == typeid(ItemBOOLEAN))
      if (((ItemBOOLEAN *) item)->i)
         return new ItemNICHDL(strdup("true"));
      else
         return new ItemNICHDL(strdup("false"));
   if (typeid(*item) == typeid(ItemASNO)) {
      char buffer[64];
      sprintf(buffer, "AS%d", ((ItemASNO *) item)->asno);
      return new ItemNICHDL(strdup(buffer));
   }

   return NULL;
}*/

////////////////////////////// RPTypeKeyCrtName ////////////////////

bool RPTypeKeyCrtName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemKEYCRTNAME));
}
//Item *RPTypeKeyCrtName::typeCast(const Item  *item) const {
//   if (typeid(*item) == typeid(ItemWORD))
//      return new ItemKEYCRTNAME(strdup(((ItemWORD *) item)->word));
//   if (typeid(*item) == typeid(ItemASNAME))
//      return new ItemKEYCRTNAME(strdup(((ItemASNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemRSNAME))
//      return new ItemKEYCRTNAME(strdup(((ItemRSNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemRTRSNAME))
//      return new ItemKEYCRTNAME(strdup(((ItemRTRSNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemPRNGNAME))
//      return new ItemKEYCRTNAME(strdup(((ItemPRNGNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemFLTRNAME))
//      return new ItemKEYCRTNAME(strdup(((ItemFLTRNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemNICHDL))
//      return new ItemKEYCRTNAME(strdup(((ItemNICHDL *) item)->nichdl));
//   if (typeid(*item) == typeid(ItemBOOLEAN))
//      if (((ItemBOOLEAN *) item)->i)
//       return new ItemNICHDL(strdup("true"));
//      else
//       return new ItemNICHDL(strdup("false"));
//   if (typeid(*item) == typeid(ItemASNO)) {
//      char buffer[64];
//      sprintf(buffer, "AS%d", ((ItemASNO *) item)->asno);
//      return new ItemNICHDL(strdup(buffer));
//   }
//
//   return NULL;
//}

////////////////////////////// RPTypeBlob ////////////////////

bool RPTypeBlob::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemBLOB));
}

Item *RPTypeBlob::typeCast(const Item  *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemASNAME))
      return new ItemBLOB(strdup(((ItemASNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRSNAME))
      return new ItemBLOB(strdup(((ItemRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRTRSNAME))
      return new ItemBLOB(strdup(((ItemRTRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemPRNGNAME))
      return new ItemBLOB(strdup(((ItemPRNGNAME *) item)->name));
   if (typeid(*item) == typeid(ItemFLTRNAME))
      return new ItemBLOB(strdup(((ItemFLTRNAME *) item)->name));
  // if (typeid(*item) == typeid(ItemNICHDL))
  //    return new ItemBLOB(strdup(((ItemNICHDL *) item)->nichdl));
   if (typeid(*item) == typeid(ItemKEYCRTNAME))
      return new ItemBLOB(strdup(((ItemKEYCRTNAME *) item)->name));
   if (typeid(*item) == typeid(ItemBOOLEAN))
      if (((ItemBOOLEAN *) item)->i)
         return new ItemBLOB(strdup("true"));
      else
         return new ItemBLOB(strdup("false"));
   if (typeid(*item) == typeid(ItemASNO)) {
      char buffer[64];
      sprintf(buffer, "AS%d", ((ItemASNO *) item)->asno);
      return new ItemWORD(strdup(buffer));
   }

   return NULL;
}

////////////////////////////// RPTypeASName ////////////////////

bool RPTypeASName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemASNAME));
}

////////////////////////////// RPTypeRSName ////////////////////

bool RPTypeRSName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemRSNAME));
}

////////////////////////////// RPTypeRTRSName ////////////////////

bool RPTypeRtrsName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemRTRSNAME));
}

////////////////////////////// RPTypePrngName ////////////////////

bool RPTypePrngName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemPRNGNAME));
}

////////////////////////////// RPTypeFltrName ////////////////////

bool RPTypeFltrName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemFLTRNAME));
}

////////////////////////////// RPTypeEMail ////////////////////

bool RPTypeEMail::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemEMAIL));
}

////////////////////////////// RPTypeFreeText ////////////////////

bool RPTypeFreeText::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemFREETEXT));
}

////////////////////////////// RPTypeEnum ////////////////////

bool RPTypeEnum::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) != typeid(ItemWORD))
         return false;
   
   for (WordNode* p = words->head(); p; p = words->next(p))
         if (!strcasecmp(((ItemWORD *) item)->word, p->word))
            return true;

   return false;
}

Item *RPTypeEnum::typeCast(const Item  *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   ItemWORD *w = NULL;

   if (typeid(*item) == typeid(ItemASNAME))
      w = new ItemWORD(strdup(((ItemASNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRSNAME))
      w = new ItemWORD(strdup(((ItemRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRTRSNAME))
      w = new ItemWORD(strdup(((ItemRTRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemPRNGNAME))
      w = new ItemWORD(strdup(((ItemPRNGNAME *) item)->name));
   if (typeid(*item) == typeid(ItemFLTRNAME))
      w = new ItemWORD(strdup(((ItemFLTRNAME *) item)->name));
//   if (typeid(*item) == typeid(ItemNICHDL))
//      w = new ItemWORD(strdup(((ItemNICHDL *) item)->nichdl));
   if (typeid(*item) == typeid(ItemKEYCRTNAME))
      w = new ItemWORD(strdup(((ItemKEYCRTNAME *) item)->name));
   if (typeid(*item) == typeid(ItemBOOLEAN))
      if (((ItemBOOLEAN *) item)->i)
         w = new ItemWORD(strdup("true"));
      else
         w = new ItemWORD(strdup("false"));
   if (typeid(*item) == typeid(ItemASNO)) {
      char buffer[64];
      sprintf(buffer, "AS%d", ((ItemASNO *) item)->asno);
      w = new ItemWORD(strdup(buffer));
   }

   if (w && validate(w))
      return w;
   if (w)
      delete w;

   return NULL;
}

////////////////////////////// RPTypeBoolean ////////////////////

bool RPTypeBoolean::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemBOOLEAN));
}

////////////////////////////// RPTypeASNumber ////////////////////

bool RPTypeASNumber::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return ((typeid(*item) == typeid(ItemASNO))
           && ((ItemASNO *) item)->asno <= 65535);
}

////////////////////////////// RPTypeIPv4Address ////////////////////

bool RPTypeIPv4Address::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemIPV4));
}

////////////////////////////// RPTypeIPv4Prefix ////////////////////

bool RPTypeIPv4Prefix::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemPRFXV4));
}

////////////////////////////// RPTypeIPv6Prefix ////////////////////

bool RPTypeIPv6Prefix::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
      return (typeid(*item) == typeid(ItemPRFXV6));
}

////////////////////////////// RPTypeIPv4PrefixRange ////////////////////

bool RPTypeIPv4PrefixRange::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemPRFXV4Range));
}

Item *RPTypeIPv4PrefixRange::typeCast(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemPRFXV4))
      return new ItemPRFXV4Range
         (new PrefixRange(*((ItemPRFXV4 *) item)->prfxv4));
   return NULL;
}

////////////////////////////// RPTypeConnection ////////////////////

bool RPTypeConnection::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemConnection));
}

////////////////////////////// RPTypeDNSName ////////////////////

bool RPTypeDNSName::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemDNS));
}

////////////////////////////// RPTypeFilter ////////////////////

bool RPTypeFilter::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   return (typeid(*item) == typeid(ItemFilter));
}

Item *RPTypeFilter::typeCast(const Item  *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemASNAME))
      return new ItemFilter(new FilterASNAME(((ItemASNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRSNAME))
      return new ItemFilter(new FilterRSNAME(((ItemRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemRTRSNAME))
      return new ItemFilter(new FilterRTRSNAME(((ItemRTRSNAME *) item)->name));
   if (typeid(*item) == typeid(ItemFLTRNAME))
      return new ItemFilter(new FilterFLTRNAME(((ItemFLTRNAME *) item)->name));
   if (typeid(*item) == typeid(ItemASNO))
      return new ItemFilter(new FilterASNO(((ItemASNO *) item)->asno));

   return NULL;
}

////////////////////////////// RPTypeUnion ////////////////////

bool RPTypeUnion::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   for (RPTypeNode* p = types->head(); p; p = types->next(p))
      if (p->type->validate(item))
         return true;
   
   return false;
}

Item *RPTypeUnion::typeCast(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   Item *w;
   for (RPTypeNode* p = types->head(); p; p = types->next(p)) {
      w = p->type->typeCast(item);
      if (w)
         return w;
   }
   
   return NULL;
}

const char *RPTypeUnion::name() {
/* [<][>][^][v][top][bottom][index][help] */
   if (!_name) {
      char buffer[1024];
      strcpy(buffer, "union ");
      for (RPTypeNode *n = types->head(); n; ) {
         strcat(buffer, n->type->name());
         n = types->next(n);
         if (n)
            strcat(buffer, ", ");
      }
      _name = strdup(buffer);
   }   
   return _name;
}

////////////////////////////// RPTypeRange ////////////////////

bool RPTypeRange::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemRange))
      return type->validate(((ItemRange*) item)->begin)
         && type->validate(((ItemRange*) item)->end)
         && (*((ItemRange*) item)->begin) <= (*((ItemRange*) item)->end);
   return false;
}

Item *RPTypeRange::typeCast(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   Item *w = NULL;

   if (type->validate(item))
      w = item->dup();
   else
      w = type->typeCast(item);

   if (w)
      return new ItemRange(w, w->dup());
   
   return NULL;
}

////////////////////////////// RPTypeList ////////////////////

bool RPTypeList::validate(const Item *item) const {
/* [<][>][^][v][top][bottom][index][help] */
   if (typeid(*item) == typeid(ItemList))
      return validate((ItemList*) item);
   return false;
}
bool RPTypeList::validate(ItemList *l) const {
/* [<][>][^][v][top][bottom][index][help] */
   Item *w;

   if (! (min_elms <= l->size() && l->size() <= max_elms))
      return false;

   for (Item *item = l->head(); item; item = l->next(item))
      if (! type->validate(item)) {
         w = type->typeCast(item);
         if (w) {
            l->insertAfter(item, w);
            l->remove(item);
            delete item;
            item = w;
         } else
            return false;
      }

   return true;
}


/* [<][>][^][v][top][bottom][index][help] */