## 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
7. reportErrors
8. PRINT1
9. PRINT2
10. printPTree
11. setClass
12. addAttr
13. setAttr
14. setAttr

       1 //  $Id: object.cc,v 1.1.1.1 2000/03/10 16:32:24 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 bool Object::scan(const char *_text, const int sz, ostream &err) {
         /* [<][>][^][v][top][bottom][index][help] */
     152    contents = (char *) _text;
     153    size     = sz;
     154
     155    scan(err);
     156
     157    contents = NULL;
     158    size     = 0;
     159    return ! has_error;
     160 }
     161
     162 void Object::reportErrors(ostream &ostrm) {
         /* [<][>][^][v][top][bottom][index][help] */
     163    Attr *n_attr;
     164
     165    for (Attr *attr = attrs.head(); attr; attr = n_attr) {
     166       n_attr = attrs.next(attr);
     167       if (attr->errors.empty() || attr->errorLeng == 0) {
     168          ostrm.write(&contents[attr->offset], attr->len);
     169          ostrm << attr->errors;
     170       } else {
     171          char *begin = &contents[attr->offset];
     172          char *end = begin;
     173          for (int i = 0; i <= attr->errorLine; ++i)
     174             end = strchr(end, '\n') + 1;
     175          ostrm.write(begin, end - begin);
     176          for (int i = 0; i < attr->errorColon; ++i)
     177             ostrm << " ";
     178          for (int i = 0; i < attr->errorLeng; ++i)
     179             ostrm << "^";
     180          ostrm << "\n";
     181          ostrm << attr->errors;
     182          ostrm.write(end, attr->len - (end - begin));
     183       }
     184    }
     185    if (! attrs.head() && contents)
     186       ostrm << contents;
     187
     188    ostrm << errors;
     189    ostrm << "\n";
     190 }
     191
     192 // Added by wlee@isi.edu
     193 #ifdef DEBUG
     194
     195 #define PRINT1(x) os << "  " #x " = " << x << endl
         /* [<][>][^][v][top][bottom][index][help] */
     196 #define PRINT2(x, y) os << "  " #x " = " << y << endl
         /* [<][>][^][v][top][bottom][index][help] */
     197
     198 void Object::printPTree(ostream &os) const
         /* [<][>][^][v][top][bottom][index][help] */
     199 {
     200   os << "Object" << endl;
     201   PRINT2(contents, "\"...\"");
     202   PRINT1(size);
     203   os << "  type" << endl;
     204   os << "  "; PRINT2(name, type->name);
     205   os << "  attrs (List <Attr>)" << endl;
     206   os << "  "; PRINT2(length, attrs.size());
     207   for (Attr *attr = attrs.head(); attr; attr = attrs.next(attr)) {
     208     os << "    ListNode" << endl;
     209     //    os << "      forw" << endl;
     210     //    os << "      back" << endl;
     211     os << "      data (Attr *)" << endl;
     212     os << "      "; PRINT2(offset, attr->offset);
     213     os << "      "; PRINT2(len, attr->len);
     214     os << "      " << attr->className() << endl;
     215     attr->printClass(os, 10);
     216   }
     217 }
     218
     219 #endif // #ifdef DEBUG
     220
     221 ostream& operator<<(ostream &os, const Object &o) {
     222    Attr *attr;
     223
     224    for (attr = o.attrs.head(); attr; attr = o.attrs.next(attr))
     225       if (attr->type && !attr->type->isObsolete())
     226          os << *attr << "\n";
     227
     228    os << "\n";
     229    return os;
     230 }
     231
     232 bool Object::setClass(char *cls) {
         /* [<][>][^][v][top][bottom][index][help] */
     233    type = schema.searchClass(cls);
     234    // make sure there is an extra \n at the end
     235    append("\n", 1);
     236    return type;
     237 }
     238
     239 bool Object::addAttr(char *attr, Item *item) {
         /* [<][>][^][v][top][bottom][index][help] */
     240    if (!type)
     241       return false;
     242
     243    const AttrAttr *attrType = type->searchAttr(attr);
     244    if (!attrType)
     245       return false;
     246
     247    ItemList *items = new ItemList;
     248    items->append(item);
     249    Attr *attrib = new AttrGeneric(attrType, items);
     250
     251    ostrstream s;
     252    s << *attrib << ends;
     253    attrib->offset = size;
     254    attrib->len    = strlen(s.str());
     255
     256    // delete the extra \n at the end, and reinsert after this attribute
     257    size--;
     258    append(s.str(), attrib->len);
     259    append("\n", 1);
     260    s.freeze(0);
     261
     262    (*this) += attrib;
     263    return true;
     264 }
     265
     266 bool Object::setAttr(char *attrName, Item *item) {
         /* [<][>][^][v][top][bottom][index][help] */
     267    if (!type)
     268       return false;
     269
     270    const AttrAttr *attrType = type->searchAttr(attrName);
     271    if (!attrType)
     272       return false;
     273
     274    ItemList *items = new ItemList;
     275    items->append(item);
     276    AttrGeneric *attr = new AttrGeneric(attrType, items);
     277
     278    return setAttr(attrName, attr);
     279 }
     280
     281 bool Object::setAttr(char *attrName, Attr *attr) {
         /* [<][>][^][v][top][bottom][index][help] */
     282    if (!type)
     283       return false;
     284
     285    const AttrAttr *attrType = type->searchAttr(attrName);
     286    if (!attrType)
     287       return false;
     288
     289    Attr *atr2;
     290    for (Attr *atr = attrs.head(); atr; atr = atr2) {
     291       atr2 = attrs.next(atr);
     292       if (atr->type == attrType) {
     293          attrs.remove(atr);
     294          flush(atr->len, atr->offset);
     295          delete atr;
     296       }
     297    }
     298
     299    (*this) += attr;
     300
     301    ostrstream s;
     302    s << *attr << "\n" << ends;
     303    attr->offset = size;
     304    attr->len    = strlen(s.str());
     305
     306    // delete the extra \n at the end, and reinsert after this attribute
     307    size--;
     308    append(s.str(), attr->len);
     309    append("\n", 1);
     310    s.freeze(0);
     311
     312    return true;
     313 }
     314

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