## modules/up/src/rpsl/rpsl/object.cc

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

## FUNCTIONS

This source file includes following functions.

1. Object
2. read
3. read
4. parse
5. scan
6. scan_silent
7. scan
8. scan_silent
9. reportErrors
10. PRINT1
11. PRINT2
12. printPTree
13. setClass
14. addAttr
15. setAttr
16. setAttr

       1 //  $Id: object.cc,v 1.1 2001/03/19 17:15:32 engin Exp $
       2 //
       3 //  Copyright (c) 1994 by the University of Southern California
       4 //  All rights reserved.
       5 //
       6 //  Permission to use, copy, modify, and distribute this software and its
       7 //  documentation in source and binary forms for lawful non-commercial
       8 //  purposes and without fee is hereby granted, provided that the above
       9 //  copyright notice appear in all copies and that both the copyright
      10 //  notice and this permission notice appear in supporting documentation,
      11 //  and that any documentation, advertising materials, and other materials
      12 //  related to such distribution and use acknowledge that the software was
      13 //  developed by the University of Southern California, Information
      14 //  Sciences Institute. The name of the USC may not be used to endorse or
      15 //  promote products derived from this software without specific prior
      16 //  written permission.
      17 //
      18 //  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
      19 //  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
      20 //  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
      21 //  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
      22 //  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
      23 //  TITLE, AND NON-INFRINGEMENT.
      24 //
      25 //  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
      26 //  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
      27 //  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
      28 //  OR PERFORMANCE OF THIS SOFTWARE.
      29 //
      30 //  Questions concerning this software should be directed to
      31 //  ratoolset@isi.edu.
      32 //
      33 //  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
      34
      35 #include "config.h"
      36 #include <istream.h>
      37 #include <cstdio>
      38 #include <strstream.h>
      39 #include <fstream.h>
      40 #include <iomanip.h>
      41
      42 #include "object.hh"
      43 #include "schema.hh"
      44
      45 extern int rpslparse(void *);
      46 extern void rpsl_scan_object(Object *);
      47
      48 Object::~Object() {
         /* [<][>][^][v][top][bottom][index][help] */
      49    attrs.clear();
      50 }
      51
      52 const int MAX_KEY_LENGTH       = 1024;
      53 const int INITIAL_CHUNK_SIZE   = 1024;
      54 const int TOO_SMALL_CHUNK_SIZE = 64;
      55
      56
      57 bool Object::read(istream &in) {
         /* [<][>][^][v][top][bottom][index][help] */
      58    return read(*this, in);
      59 }
      60
      61 bool Object::read(Buffer &buf, istream &in) {
         /* [<][>][^][v][top][bottom][index][help] */
      62    if (in.eof())
      63       return false;
      64
      65    int size = INITIAL_CHUNK_SIZE;
      66    int remaining = size;
      67
      68    char *text = (char *) malloc(size);
      69    char *start = text;
      70    char *p;
      71
      72    int linelen;
      73    int len = 0;
      74
      75    while (1) {
      76       in.getline(start, remaining);
      77
      78       linelen = strlen(start);
      79       remaining -= linelen;
      80       len       += linelen;
      81       start     += linelen;
      82
      83       if (!linelen || in.eof()) // empty line or eof => end of object
      84          break;
      85       // blank line => end of object?
      86       for (p = start - linelen;
      87            *p && (*p == ' ' || *p == '\t' || *p == '\r'); ++p)
      88          ;
      89       if (! *p)
      90          break;
      91
      92       if (remaining < TOO_SMALL_CHUNK_SIZE) {
      93          remaining += size;
      94          size *= 2;
      95          text = (char *) realloc(text, size);
      96          start = text + len;
      97       }
      98
      99       if (in) { // append \n if we successfully read a line
     100          *start = '\n';
     101          start++;
     102          len++;
     103          remaining--;
     104       } else
     105          in.clear();
     106    }
     107
     108    buf.size=len;
     109    buf.contents = (char *) realloc(text, len+2);
     110
     111    return len;
     112 }
     113
     114 void Object::parse() {
         /* [<][>][^][v][top][bottom][index][help] */
     115    rpsl_scan_object(this);
     116    rpslparse(this);
     117
     118    if (type) {
     119       bool forgiving = schema.isForgiving();
     120       if (isDeleted || schema.isVeryForgiving()) {
     121          if (has_error) {
     122             has_error = false;
     123             Attr *n_attr;
     124
     125             for (Attr *attr = attrs.head(); attr; attr = attrs.next(attr))
     126                if (! attr->errors.empty()
     127                    && attr->type && attr->type->isKey()) {
     128                   has_error = true;
     129                   break;
     130                }
     131          }
     132          schema.beForgiving();
     133       }
     134       has_error |= ! type->validate(errors);
     135       schema.beForgiving(forgiving);
     136    } else {
     137       errors = "***Error: Unknown class encountered.";
     138       has_error = true;
     139    }
     140 }
     141
     142 bool Object::scan(ostream &err) {
         /* [<][>][^][v][top][bottom][index][help] */
     143    parse();
     144
     145    if (has_error)
     146       reportErrors(err);
     147
     148    return ! has_error;
     149 }
     150
     151 /* added by Engin, 19/03/2001 */
     152 /* a silent version of "Object::scan" */
     153 bool Object::scan_silent() {
         /* [<][>][^][v][top][bottom][index][help] */
     154    parse();
     155
     156    return ! has_error;
     157 }
     158
     159
     160 bool Object::scan(const char *_text, const int sz, ostream &err) {
         /* [<][>][^][v][top][bottom][index][help] */
     161    contents = (char *) _text;
     162    size     = sz;
     163
     164    scan(err);
     165
     166    contents = NULL;
     167    size     = 0;
     168    return ! has_error;
     169 }
     170
     171 /* added by Engin, 19/03/2001 */
     172 /* a silent version of "Object::scan" */
     173 bool Object::scan_silent(const char *_text, const int sz) {
         /* [<][>][^][v][top][bottom][index][help] */
     174    contents = (char *) _text;
     175    size     = sz;
     176
     177    scan_silent();
     178
     179    contents = NULL;
     180    size     = 0;
     181    return ! has_error;
     182 }
     183
     184 void Object::reportErrors(ostream &ostrm) {
         /* [<][>][^][v][top][bottom][index][help] */
     185    Attr *n_attr;
     186
     187    for (Attr *attr = attrs.head(); attr; attr = n_attr) {
     188       n_attr = attrs.next(attr);
     189       if (attr->errors.empty() || attr->errorLeng == 0) {
     190          ostrm.write(&contents[attr->offset], attr->len);
     191          ostrm << attr->errors;
     192       } else {
     193          char *begin = &contents[attr->offset];
     194          char *end = begin;
     195          for (int i = 0; i <= attr->errorLine; ++i)
     196             end = strchr(end, '\n') + 1;
     197          ostrm.write(begin, end - begin);
     198          for (int i = 0; i < attr->errorColon; ++i)
     199             ostrm << " ";
     200          for (int i = 0; i < attr->errorLeng; ++i)
     201             ostrm << "^";
     202          ostrm << "\n";
     203          ostrm << attr->errors;
     204          ostrm.write(end, attr->len - (end - begin));
     205       }
     206    }
     207    if (! attrs.head() && contents)
     208       ostrm << contents;
     209
     210    ostrm << errors;
     211    ostrm << "\n";
     212 }
     213
     214 // Added by wlee@isi.edu
     215 #ifdef DEBUG
     216
     217 #define PRINT1(x) os << "  " #x " = " << x << endl
         /* [<][>][^][v][top][bottom][index][help] */
     218 #define PRINT2(x, y) os << "  " #x " = " << y << endl
         /* [<][>][^][v][top][bottom][index][help] */
     219
     220 void Object::printPTree(ostream &os) const
         /* [<][>][^][v][top][bottom][index][help] */
     221 {
     222   os << "Object" << endl;
     223   PRINT2(contents, "\"...\"");
     224   PRINT1(size);
     225   os << "  type" << endl;
     226   os << "  "; PRINT2(name, type->name);
     227   os << "  attrs (List <Attr>)" << endl;
     228   os << "  "; PRINT2(length, attrs.size());
     229   for (Attr *attr = attrs.head(); attr; attr = attrs.next(attr)) {
     230     os << "    ListNode" << endl;
     231     //    os << "      forw" << endl;
     232     //    os << "      back" << endl;
     233     os << "      data (Attr *)" << endl;
     234     os << "      "; PRINT2(offset, attr->offset);
     235     os << "      "; PRINT2(len, attr->len);
     236     os << "      " << attr->className() << endl;
     237     attr->printClass(os, 10);
     238   }
     239 }
     240
     241 #endif // #ifdef DEBUG
     242
     243 ostream& operator<<(ostream &os, const Object &o) {
     244    Attr *attr;
     245
     246    for (attr = o.attrs.head(); attr; attr = o.attrs.next(attr))
     247       if (attr->type && !attr->type->isObsolete())
     248          os << *attr << "\n";
     249
     250    os << "\n";
     251    return os;
     252 }
     253
     254 bool Object::setClass(char *cls) {
         /* [<][>][^][v][top][bottom][index][help] */
     255    type = schema.searchClass(cls);
     256    // make sure there is an extra \n at the end
     257    append("\n", 1);
     258    return type;
     259 }
     260
     261 bool Object::addAttr(char *attr, Item *item) {
         /* [<][>][^][v][top][bottom][index][help] */
     262    if (!type)
     263       return false;
     264
     265    const AttrAttr *attrType = type->searchAttr(attr);
     266    if (!attrType)
     267       return false;
     268
     269    ItemList *items = new ItemList;
     270    items->append(item);
     271    Attr *attrib = new AttrGeneric(attrType, items);
     272
     273    ostrstream s;
     274    s << *attrib << ends;
     275    attrib->offset = size;
     276    attrib->len    = strlen(s.str());
     277
     278    // delete the extra \n at the end, and reinsert after this attribute
     279    size--;
     280    append(s.str(), attrib->len);
     281    append("\n", 1);
     282    s.freeze(0);
     283
     284    (*this) += attrib;
     285    return true;
     286 }
     287
     288 bool Object::setAttr(char *attrName, Item *item) {
         /* [<][>][^][v][top][bottom][index][help] */
     289    if (!type)
     290       return false;
     291
     292    const AttrAttr *attrType = type->searchAttr(attrName);
     293    if (!attrType)
     294       return false;
     295
     296    ItemList *items = new ItemList;
     297    items->append(item);
     298    AttrGeneric *attr = new AttrGeneric(attrType, items);
     299
     300    return setAttr(attrName, attr);
     301 }
     302
     303 bool Object::setAttr(char *attrName, Attr *attr) {
         /* [<][>][^][v][top][bottom][index][help] */
     304    if (!type)
     305       return false;
     306
     307    const AttrAttr *attrType = type->searchAttr(attrName);
     308    if (!attrType)
     309       return false;
     310
     311    Attr *atr2;
     312    for (Attr *atr = attrs.head(); atr; atr = atr2) {
     313       atr2 = attrs.next(atr);
     314       if (atr->type == attrType) {
     315          attrs.remove(atr);
     316          flush(atr->len, atr->offset);
     317          delete atr;
     318       }
     319    }
     320
     321    (*this) += attr;
     322
     323    ostrstream s;
     324    s << *attr << "\n" << ends;
     325    attr->offset = size;
     326    attr->len    = strlen(s.str());
     327
     328    // delete the extra \n at the end, and reinsert after this attribute
     329    size--;
     330    append(s.str(), attr->len);
     331    append("\n", 1);
     332    s.freeze(0);
     333
     334    return true;
     335 }
     336

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