Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

buffer.cc

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 1997-2001 Shigeru Chiba, Tokyo Institute of Technology.
00003 
00004   Permission to use, copy, distribute and modify this software and   
00005   its documentation for any purpose is hereby granted without fee,        
00006   provided that the above copyright notice appear in all copies and that 
00007   both that copyright notice and this permission notice appear in 
00008   supporting documentation.
00009 
00010   Shigeru Chiba makes no representations about the suitability of this 
00011   software for any purpose.  It is provided "as is" without express or
00012   implied warranty.
00013 */
00014 
00015 /*
00016   Copyright (c) 1995, 1996 Xerox Corporation.
00017   All Rights Reserved.
00018 
00019   Use and copying of this software and preparation of derivative works
00020   based upon this software are permitted. Any copy of this software or
00021   of any derivative work must include the above copyright notice of
00022   Xerox Corporation, this paragraph and the one after it.  Any
00023   distribution of this software or derivative works must comply with all
00024   applicable United States export control laws.
00025 
00026   This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
00027   ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029   PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
00030   LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
00031   EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
00032   NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
00033   OF THE POSSIBILITY OF SUCH DAMAGES.
00034 */
00035 
00036 #include <string.h>
00037 #include <stdlib.h>
00038 #include "buffer.h"
00039 #include "token.h"
00040 #include "ptree-core.h"
00041 #include "mop.h"
00042 
00043 #if defined(_PARSE_VCC)
00044 #define _MSC_VER        1100
00045 #endif
00046 
00047 char Program::Get()
00048 {
00049     if(buf[index] == '\0')
00050         return buf[index];
00051     else
00052         return buf[index++];
00053 }
00054 
00055 void Program::Subst(Ptree* newtext, Ptree* oldtext)
00056 {
00057     Replace(oldtext->LeftMost(), oldtext->RightMost(), newtext);
00058 }
00059 
00060 void Program::Insert(Ptree* pos, Ptree* before_text, Ptree* after_text)
00061 {
00062     char* p;
00063 
00064     if(before_text != nil){
00065         p = pos->LeftMost();
00066         Replace(p, p, before_text);
00067     }
00068 
00069     if(after_text != nil){
00070         p = pos->RightMost();
00071         Replace(p, p, after_text);
00072     }
00073 }
00074 
00075 void Program::MinimumSubst(Ptree* newtext, Ptree* oldtext)
00076 {
00077     if(MinimumSubst2(newtext, oldtext))
00078         Subst(newtext, oldtext);
00079 }
00080 
00081 bool Program::MinimumSubst2(Ptree* newtext, Ptree* oldtext)
00082 {
00083     int what;
00084     if(oldtext == newtext)
00085         return FALSE;
00086     else if(oldtext == nil || newtext == nil)
00087         return TRUE;
00088     else if(what = newtext->What(),
00089             (what == ntExprStatement || what == ntTypedef))
00090         return TRUE;
00091     else if(oldtext->IsLeaf() || newtext->IsLeaf())
00092         return TRUE;
00093     else if(oldtext->Car() == nil && oldtext->Cdr() == nil)
00094         return TRUE;
00095     else if(oldtext == newtext->Cdr()){
00096         Insert(oldtext, newtext->Car(), nil);
00097         return FALSE;
00098     }
00099     else if(oldtext->Car() != nil && oldtext->Car() == newtext->Second()){
00100         Insert(oldtext->Car(), newtext->Car(), nil);
00101         newtext = newtext->ListTail(2);
00102         if(MinimumSubst2(newtext, oldtext->Cdr()))
00103             if(oldtext->Cdr() == nil)
00104                 Insert(oldtext->Car(), nil, newtext);
00105             else
00106                 Subst(newtext, oldtext->Cdr());
00107 
00108         return FALSE;
00109     }
00110     else{
00111         bool dirty1 = MinimumSubst2(newtext->Car(), oldtext->Car());
00112         bool dirty2 = MinimumSubst2(newtext->Cdr(), oldtext->Cdr());
00113         if(dirty1 == dirty2)
00114             return dirty1;
00115         else if(dirty1)
00116             if(oldtext->Cdr() == nil && newtext->Cdr() == nil)
00117                 return TRUE;
00118             else if(oldtext->Car() == nil)
00119                 Insert(oldtext->Cdr(), newtext->Car(), nil);
00120             else
00121                 Subst(newtext->Car(), oldtext->Car());
00122         else
00123             if(oldtext->Car() == nil && newtext->Car() == nil)
00124                 return TRUE;
00125             else if(oldtext->Cdr() == nil)
00126                 Insert(oldtext->Car(), nil, newtext->Cdr());
00127             else
00128                 Subst(newtext->Cdr(), oldtext->Cdr());
00129 
00130         return FALSE;
00131     }
00132 }
00133 
00134 void Program::Replace(char* startpos, char* endpos, Ptree* text)
00135 {
00136     if(startpos == nil || endpos == nil)
00137         return;
00138 
00139     uint start = uint(startpos - buf);
00140     uint end = uint(endpos - buf);
00141     Replacement* p = replacement;
00142     if(p == nil)
00143         replacement = new Replacement(nil, start, end, text);
00144     else if (start < p->startpos)
00145         replacement = new Replacement(p, start, end, text);
00146     else if(p->next == nil)
00147         p->next = new Replacement(nil, start, end, text);
00148     else{
00149         for(; p->next != nil; p = p->next)
00150             if(start < p->next->startpos)
00151                 break;
00152 
00153         p->next = new Replacement(p->next, start, end, text);
00154     }
00155 }
00156 
00157 /*
00158   LineNumber() returns the line number of the line pointed to by PTR.
00159 */
00160 uint Program::LineNumber(char* ptr, char*& filename, int& filename_length)
00161 {
00162     sint n;
00163     int  len;
00164     uint name;
00165 
00166     int nline = 0;
00167     uint pos = uint(ptr - buf);
00168     if(pos > size){
00169         // error?
00170         filename = defaultname;
00171         filename_length = strlen(defaultname);
00172         return 0;
00173     }
00174 
00175     sint line_number = -1;
00176     filename_length = 0;
00177 
00178     while(pos > 0){
00179         switch(Ref(--pos)){
00180         case '\n' :
00181             ++nline;
00182             break;
00183         case '#' :
00184             len = 0;
00185             n = ReadLineDirective(pos, -1, name, len);
00186             if(n >= 0){                 // unless #pragma
00187                 if(line_number < 0)
00188                     line_number = n + nline;
00189 
00190                 if(len > 0 && filename_length == 0){
00191                     filename = (char*)Read(name);
00192                     filename_length = len;
00193                 }
00194             }
00195             break;
00196         }
00197 
00198         if(line_number >= 0 && filename_length > 0)
00199             return line_number;
00200     }
00201 
00202     if(filename_length == 0){
00203         filename = defaultname;
00204         filename_length = strlen(defaultname);
00205     }
00206 
00207     if(line_number < 0)
00208         line_number = nline + 1;
00209 
00210     return line_number;
00211 }
00212 
00213 /*
00214   Write() saves the program as a file named FILE_NAME.
00215   This assumes that the first line of the program is
00216   a # line directive.
00217 */
00218 void Program::Write(ostream& out, const char* file_name)
00219 {
00220     Replacement* rep = replacement;
00221     uint pos;
00222     uint nlines = 1;
00223     uint line_number = 1;
00224     uint i = 0;
00225     char c;
00226 
00227     uint filename = 0;
00228     int filename_length = 0;
00229 
00230     if(Ref(i) == '#')
00231         line_number = ReadLineDirective(i, (sint)line_number,
00232                                         filename, filename_length);
00233 
00234     for(; rep != nil; rep = rep->next){
00235         pos = rep->startpos;
00236         while(i < pos){
00237             c = Ref(i++);
00238             if(c == '\0'){
00239                 --i;
00240                 break;
00241             }
00242 
00243             out << c;
00244             if(c == '\n'){
00245                 ++nlines;
00246                 ++line_number;
00247                 if(Ref(i) == '#')
00248                     line_number = ReadLineDirective(i, (sint)line_number,
00249                                                     filename, filename_length);
00250             }
00251         }
00252 
00253         if(i > 0 && Ref(i - 1) != '\n'){
00254             out << '\n';
00255             ++nlines;
00256         }
00257 
00258 #if defined(_MSC_VER) || defined(IRIX_CC)
00259         out << "#line " << nlines + 1 << " \"" << file_name << "\"\n";
00260 #else
00261         out << "# " << nlines + 1 << " \"" << file_name << "\"\n";
00262 #endif
00263         ++nlines;
00264         nlines += rep->text->Write(out);
00265         pos = rep->endpos;
00266         if(rep->next != nil && rep->next->startpos <= pos){
00267             rep = rep->next;
00268             out << '\n';
00269             ++nlines;
00270             nlines += rep->text->Write(out);
00271             if(rep->endpos > pos)
00272                 pos = rep->endpos;
00273         }
00274 
00275         while(i < pos){
00276             c = Ref(i++);
00277             if(c == '\0'){
00278                 --i;
00279                 break;
00280             }
00281             else if(c == '\n'){
00282                 ++line_number;
00283                 if(Ref(i) == '#')
00284                     line_number = ReadLineDirective(i, (sint)line_number,
00285                                                     filename, filename_length);
00286             }
00287         }
00288 
00289 #if defined(_MSC_VER) || defined(IRIX_CC)
00290         out << "\n#line " << line_number << ' ';
00291 #else
00292         out << "\n# " << line_number << ' ';
00293 #endif
00294         ++nlines;
00295         if(filename_length > 0)
00296             for(int j = 0; j < filename_length; ++j)
00297                 out << (char)Ref(filename + j);
00298         else
00299             out << '"' << defaultname << '"';
00300 
00301         out << '\n';
00302         ++nlines;
00303     }
00304 
00305     while((c = Ref(i++)) != '\0'){
00306         out << c;
00307         if(c == '\n')
00308             ++nlines;
00309     }
00310 
00311 #if defined(_MSC_VER) || defined(IRIX_CC)
00312     out << "\n#line " << nlines + 2 << " \"" << file_name << "\"\n";
00313 #else
00314     out << "\n# " << nlines + 2 << " \"" << file_name << "\"\n";
00315 #endif
00316     Class::FinalizeAll(out);
00317     opcxx_ListOfMetaclass::FinalizeAll(out);
00318 }
00319 
00320 sint Program::ReadLineDirective(uint i, sint line_number,
00321                                 uint& filename, int& filename_length)
00322 {
00323     char c;
00324 
00325     do{
00326         c = Ref(++i);
00327     }while(is_blank(c));
00328 
00329 #if defined(_MSC_VER) || defined(IRIX_CC)
00330     if(i + 4 <= GetSize() && strncmp(Read(i), "line", 4) == 0){
00331         i += 3;
00332         do{
00333             c = Ref(++i);
00334         }while(is_blank(c));
00335     }
00336 #endif
00337 
00338     if(is_digit(c)){            /* # <line> <file> */
00339         uint num = c - '0';
00340         for(;;){
00341             c = Ref(++i);
00342             if(is_digit(c))
00343                 num = num * 10 + c - '0';
00344             else
00345                 break;
00346         }
00347 
00348         line_number = num - 1;  /* line_number'll be incremented soon */
00349 
00350         if(is_blank(c)){
00351             do{
00352                 c = Ref(++i);
00353             }while(is_blank(c));
00354             if(c == '"'){
00355                 uint fname_start = i;
00356                 do{
00357                     c = Ref(++i);
00358                 } while(c != '"');
00359                 if(i > fname_start + 2){
00360                     filename = fname_start;
00361                     filename_length = int(i - fname_start + 1);
00362                 }
00363             }
00364         }
00365     }
00366 
00367     return line_number;
00368 }
00369 
00370 // class Program::Replacement
00371 
00372 Program::Replacement::Replacement(Replacement* n, uint st,
00373                                   uint ed, Ptree* t)
00374 {
00375     next = n;
00376     startpos = st;
00377     endpos = ed;
00378     text = t;
00379 }
00380 
00381 // subclasses
00382 
00383 ProgramFile::ProgramFile(ifstream& f, char *filename)
00384 : Program(filename)
00385 {
00386     f.seekg(0, ios::end);
00387     size = f.tellg();
00388     f.seekg(0);
00389 
00390     buf = new char[size + 1];
00391     f.read(buf, int(size));
00392 #if defined(_WIN32)
00393     // Under win31/95/NT, the pair CR-LF is replaced by LF,
00394     // implying a smallest size
00395     size = f.gcount();
00396 #endif
00397     buf[size] = '\0';
00398     index = 0;
00399 }
00400 
00401 ProgramFile::~ProgramFile()
00402 {
00403     delete [] buf;
00404     buf = nil;
00405 }
00406 
00407 ProgramFromStdin::ProgramFromStdin()
00408 : Program("stdin")
00409 {
00410     const int Size = 512 * 1024;
00411     buf = new char[Size];
00412     buf_size = Size;
00413     index = size = 0;
00414 }
00415 
00416 ProgramFromStdin::~ProgramFromStdin()
00417 {
00418     delete [] buf;
00419     buf = nil;
00420 }
00421 
00422 char ProgramFromStdin::Get()
00423 {
00424     if(size >= buf_size){
00425         cerr << "ProgramFromStdin: sorry, out of memory\n";
00426         exit(1);
00427     }
00428 
00429     if(index >= size){
00430         int c = cin.get();
00431         if(c == EOF)
00432             c = '\0';
00433 
00434         buf[size++] = c;
00435     }
00436 
00437     if(buf[index] == '\0')
00438         return buf[index];
00439     else
00440         return buf[index++];
00441 }
00442 
00443 // class ProgramString
00444 
00445 const int Quantum = 4;
00446 const int BufSize = 1 << Quantum;
00447 
00448 ProgramString::ProgramString()
00449 : Program("unknown")
00450 {
00451     buf = new (GC) char[BufSize];
00452     buf[0] = '\0';
00453     size = BufSize;
00454     index = str_length = 0;
00455 }
00456 
00457 ProgramString::~ProgramString()
00458 {
00459 //  delete [] buf;
00460     buf = nil;
00461 }
00462 
00463 ProgramString& ProgramString::operator << (const char* str)
00464 {
00465     int len = strlen(str) + 1;
00466 
00467     if(str_length + len < size){
00468         memmove(&buf[str_length], str, len);
00469         str_length += len - 1;
00470     }
00471     else{
00472         size = (str_length + len + BufSize) & ~(BufSize - 1);
00473         char* newbuf = new (GC) char[size];
00474         memmove(newbuf, buf, size_t(str_length));
00475         memmove(&newbuf[str_length], str, len);
00476 //      delete [] buf;
00477         buf = newbuf;
00478         str_length += len - 1;
00479     }
00480 
00481     return *this;
00482 }
00483 
00484 ProgramString& ProgramString::operator << (const char c)
00485 {
00486     if(str_length + 2 < size){
00487         buf[str_length] = c;
00488         buf[++str_length] = '\0';
00489     }
00490     else{
00491         size = (str_length + 2 + BufSize) & ~(BufSize - 1);
00492         char* newbuf = new (GC) char[size];
00493         memmove(newbuf, buf, size_t(str_length));
00494         newbuf[str_length] = c;
00495         newbuf[++str_length] = '\0';
00496 //      delete [] buf;
00497         buf = newbuf;
00498     }
00499 
00500     return *this;
00501 }

Generated on Mon Feb 10 17:32:44 2003 for VFiasco Semantics Compiler by doxygen1.2.15