00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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){
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
00215
00216
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)){
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;
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
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
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
00394
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
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
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
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
00497 buf = newbuf;
00498 }
00499
00500 return *this;
00501 }