Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Parser/C++/occ/buffer.cc
1| /*
2| Copyright (C) 1997-2000 Shigeru Chiba, University of Tsukuba.
3|
4| Permission to use, copy, distribute and modify this software and
5| its documentation for any purpose is hereby granted without fee,
6| provided that the above copyright notice appear in all copies and that
7| both that copyright notice and this permission notice appear in
8| supporting documentation.
9|
10| Shigeru Chiba makes no representations about the suitability of this
11| software for any purpose. It is provided "as is" without express or
12| implied warranty.
13| */
14| /*
15| Copyright (c) 1995, 1996 Xerox Corporation.
16| All Rights Reserved.
17|
18| Use and copying of this software and preparation of derivative works
19| based upon this software are permitted. Any copy of this software or
20| of any derivative work must include the above copyright notice of
21| Xerox Corporation, this paragraph and the one after it. Any
22| distribution of this software or derivative works must comply with all
23| applicable United States export control laws.
24|
25| This software is made available AS IS, and XEROX CORPORATION DISCLAIMS
26| ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
27| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28| PURPOSE, AND NOTWITHSTANDING ANY OTHER PROVISION CONTAINED HEREIN, ANY
29| LIABILITY FOR DAMAGES RESULTING FROM THE SOFTWARE OR ITS USE IS
30| EXPRESSLY DISCLAIMED, WHETHER ARISING IN CONTRACT, TORT (INCLUDING
31| NEGLIGENCE) OR STRICT LIABILITY, EVEN IF XEROX CORPORATION IS ADVISED
32| OF THE POSSIBILITY OF SUCH DAMAGES.
33| */
34|
35| #include <iostream>
36| #include <string>
37| #include <cstring>
38| #include <cstdlib>
39| #include "buffer.h"
40| #include "token.h"
41| #include "ptree-core.h"
42| #include "mop.h"
43|
44| #if defined(_PARSE_VCC)
45| #define _MSC_VER
46| #endif
47|
48|
49| struct LineMapNode {
50|
51| uint pos;
52|
53| int line;
54|
55| char* filename;
56|
57| int filename_len;
58| };
59|
60| struct Program::Private {
61|
62| LineMapNode first, last;
63|
64|
65| uint lastPos() {
66| return last.pos;
67| }
68| void start(LineMapNode& node) {
69| first = last = node;
70| }
71| void insert(LineMapNode& node) {
72| //cout << "### Inserting node at " << node.pos << " line " << node.line;
73| //cout << " in " << std::string(node.filename, node.filename_len) << endl;
74| last = node;
75| }
76| };
77|
78| Program::Program(char* name)
79| {
80| replacement = nil;
81| defaultname = name;
82| m = new Private;
83|
84| LineMapNode node;
85| node.pos = 0; node.line = 0;
86| node.filename = name;
87| node.filename_len = strlen(name);
88| m->start(node);
89| }
90|
91| Program::~Program()
92| {
93| delete m;
94| }
95|
96| char Program::Get()
97| {
98| if(buf[index] == '\0')
99| return buf[index];
100| else
101| return buf[index++];
102| }
103|
104| void Program::Subst(Ptree* newtext, Ptree* oldtext)
105| {
106| Replace(oldtext->LeftMost(), oldtext->RightMost(), newtext);
107| }
108|
109| void Program::Insert(Ptree* pos, Ptree* before_text, Ptree* after_text)
110| {
111| char* p;
112|
113| if(before_text != nil){
114| p = pos->LeftMost();
115| Replace(p, p, before_text);
116| }
117|
118| if(after_text != nil){
119| p = pos->RightMost();
120| Replace(p, p, after_text);
121| }
122| }
123|
124| void Program::MinimumSubst(Ptree* newtext, Ptree* oldtext)
125| {
126| if(MinimumSubst2(newtext, oldtext))
127| Subst(newtext, oldtext);
128| }
129|
130| bool Program::MinimumSubst2(Ptree* newtext, Ptree* oldtext)
131| {
132| int what;
133| if(oldtext == newtext)
134| return FALSE;
135| else if(oldtext == nil || newtext == nil)
136| return TRUE;
137| else if(what = newtext->What(),
138| (what == ntExprStatement || what == ntTypedef))
139| return TRUE;
140| else if(oldtext->IsLeaf() || newtext->IsLeaf())
141| return TRUE;
142| else if(oldtext->Car() == nil && oldtext->Cdr() == nil)
143| return TRUE;
144| else if(oldtext == newtext->Cdr()){
145| Insert(oldtext, newtext->Car(), nil);
146| return FALSE;
147| }
148| else if(oldtext->Car() != nil && oldtext->Car() == newtext->Second()){
149| Insert(oldtext->Car(), newtext->Car(), nil);
150| newtext = newtext->ListTail(2);
151| if(MinimumSubst2(newtext, oldtext->Cdr()))
152| if(oldtext->Cdr() == nil)
153| Insert(oldtext->Car(), nil, newtext);
154| else
155| Subst(newtext, oldtext->Cdr());
156|
157| return FALSE;
158| }
159| else{
160| bool dirty1 = MinimumSubst2(newtext->Car(), oldtext->Car());
161| bool dirty2 = MinimumSubst2(newtext->Cdr(), oldtext->Cdr());
162| if(dirty1 == dirty2)
163| return dirty1;
164| else if(dirty1)
165| if(oldtext->Cdr() == nil && newtext->Cdr() == nil)
166| return TRUE;
167| else if(oldtext->Car() == nil)
168| Insert(oldtext->Cdr(), newtext->Car(), nil);
169| else
170| Subst(newtext->Car(), oldtext->Car());
171| else
172| if(oldtext->Car() == nil && newtext->Car() == nil)
173| return TRUE;
174| else if(oldtext->Cdr() == nil)
175| Insert(oldtext->Car(), nil, newtext->Cdr());
176| else
177| Subst(newtext->Cdr(), oldtext->Cdr());
178|
179| return FALSE;
180| }
181| }
182|
183| void Program::Replace(char* startpos, char* endpos, Ptree* text)
184| {
185| if(startpos == nil || endpos == nil)
186| return;
187|
188| uint start = uint(startpos - buf);
189| uint end = uint(endpos - buf);
190| Replacement* p = replacement;
191| if(p == nil)
192| replacement = new Replacement(nil, start, end, text);
193| else if(p->next == nil)
194| if(start < p->startpos)
195| replacement = new Replacement(p, start, end, text);
196| else
197| p->next = new Replacement(nil, start, end, text);
198| else{
199| for(; p->next != nil; p = p->next)
200| if(start < p->next->startpos)
201| break;
202|
203| p->next = new Replacement(p->next, start, end, text);
204| }
205| }
206|
207| /*
208| LineNumber() returns the line number of the line pointed to by PTR.
209| */
210| uint Program::LineNumber(char* ptr, char*& filename, int& filename_length)
211| {
212| sint n;
213| int len;
214| uint name;
215| int nline = 0;
216|
217|
218| uint pos = uint(ptr - buf), startpos = pos;
219| if(pos > size){
220| // error?
221| filename = defaultname;
222| filename_length = strlen(defaultname);
223| return 0;
224| }
225|
226|
227| uint lastpos = m->lastPos();
228|
229| sint line_number = -1;
230| filename_length = 0;
231|
232| while(pos != lastpos){
233| switch(Ref(--pos)){
234| case '\n' :
235| ++nline;
236| break;
237| case '#' :
238| len = 0;
239| n = ReadLineDirective(pos, -1, name, len);
240| if(n >= 0){
241| if(line_number < 0)
242| line_number = n + nline;
243|
244| if(len > 0 && filename_length == 0){
245| filename = (char*)Read(name);
246| filename_length = len;
247| }
248| }
249| break;
250| }
251|
252| if(line_number >= 0 && filename_length > 0) {
253|
254|
255| LineMapNode node;
256| node.pos = startpos; node.line = line_number;
257| node.filename = filename; node.filename_len = filename_length;
258| m->insert(node);
259| return line_number;
260| }
261| }
262|
263|
264|
265|
266| LineMapNode& node = m->last;
267|
268| if(filename_length == 0){
269| filename = node.filename;
270| filename_length = node.filename_len;
271| }
272|
273| if(line_number < 0)
274| line_number = nline + node.line;
275|
276|
277| LineMapNode newnode;
278| newnode.pos = startpos; newnode.line = line_number;
279| newnode.filename = filename; newnode.filename_len = filename_length;
280| m->insert(newnode);
281|
282| return line_number;
283| }
284|
285| /*
286| Write() saves the program as a file named FILE_NAME.
287| This assumes that the first line of the program is
288| a # line directive.
289| */
290| void Program::Write(std::ostream& out, const char* file_name)
291| {
292| Replacement* rep = replacement;
293| uint pos;
294| uint nlines = 1;
295| uint line_number = 1;
296| uint i = 0;
297| char c;
298|
299| uint filename = 0;
300| int filename_length = 0;
301|
302| if(Ref(i) == '#')
303| line_number = ReadLineDirective(i, (sint)line_number,
304| filename, filename_length);
305|
306| for(; rep != nil; rep = rep->next){
307| pos = rep->startpos;
308| while(i < pos){
309| c = Ref(i++);
310| if(c == '\0'){
311| --i;
312| break;
313| }
314|
315| out << c;
316| if(c == '\n'){
317| ++nlines;
318| ++line_number;
319| if(Ref(i) == '#')
320| line_number = ReadLineDirective(i, (sint)line_number,
321| filename, filename_length);
322| }
323| }
324|
325| if(i > 0 && Ref(i - 1) != '\n'){
326| out << '\n';
327| ++nlines;
328| }
329|
330| #if defined(_MSC_VER) || defined(IRIX_CC)
331| out << "#line " << nlines + 1 << " \"" << file_name << "\"\n";
332| #else
333| out << "# " << nlines + 1 << " \"" << file_name << "\"\n";
334| #endif
335| ++nlines;
336| nlines += rep->text->Write(out);
337| pos = rep->endpos;
338| if(rep->next != nil && rep->next->startpos <= pos){
339| rep = rep->next;
340| out << '\n';
341| ++nlines;
342| nlines += rep->text->Write(out);
343| if(rep->endpos > pos)
344| pos = rep->endpos;
345| }
346|
347| while(i < pos){
348| c = Ref(i++);
349| if(c == '\0'){
350| --i;
351| break;
352| }
353| else if(c == '\n'){
354| ++line_number;
355| if(Ref(i) == '#')
356| line_number = ReadLineDirective(i, (sint)line_number,
357| filename, filename_length);
358| }
359| }
360|
361| #if defined(_MSC_VER) || defined(IRIX_CC)
362| out << "\n#line " << line_number << ' ';
363| #else
364| out << "\n# " << line_number << ' ';
365| #endif
366| ++nlines;
367| if(filename_length > 0)
368| for(int j = 0; j < filename_length; ++j)
369| out << (char)Ref(filename + j);
370| else
371| out << '"' << defaultname << '"';
372|
373| out << '\n';
374| ++nlines;
375| }
376|
377| while((c = Ref(i++)) != '\0'){
378| out << c;
379| if(c == '\n')
380| ++nlines;
381| }
382|
383| #if defined(_MSC_VER) || defined(IRIX_CC)
384| out << "\n#line " << nlines + 2 << " \"" << file_name << "\"\n";
385| #else
386| out << "\n# " << nlines + 2 << " \"" << file_name << "\"\n";
387| #endif
388| Class::FinalizeAll(out);
389| opcxx_ListOfMetaclass::FinalizeAll(out);
390| }
391|
392| sint Program::ReadLineDirective(uint i, sint line_number,
393| uint& filename, int& filename_length)
394| {
395| char c;
396|
397| do{
398| c = Ref(++i);
399| }while(is_blank(c));
400|
401| #if defined(_MSC_VER) || defined(IRIX_CC)
402| if(i + 4 <= GetSize() && strncmp(Read(i), "line", 4) == 0){
403| i += 3;
404| do{
405| c = Ref(++i);
406| }while(is_blank(c));
407| }
408| #endif
409|
410| if(is_digit(c)){
411| uint num = c - '0';
412| for(;;){
413| c = Ref(++i);
414| if(is_digit(c))
415| num = num * 10 + c - '0';
416| else
417| break;
418| }
419|
420| line_number = num - 1; /* line_number'll be incremented soon *
421|
422| if(is_blank(c)){
423| do{
424| c = Ref(++i);
425| }while(is_blank(c));
426| if(c == '"'){
427| uint fname_start = i;
428| do{
429| c = Ref(++i);
430| } while(c != '"');
431| if(i > fname_start + 2){
432| filename = fname_start;
433| filename_length = int(i - fname_start + 1);
434| }
435| }
436| }
437| }
438|
439| return line_number;
440| }
441|
442| // class Program::Replacement
443|
444| Program::Replacement::Replacement(Replacement* n, uint st,
445| uint ed, Ptree* t)
446| {
447| next = n;
448| startpos = st;
449| endpos = ed;
450| text = t;
451| }
452|
453| // subclasses
454|
455| ProgramFile::ProgramFile(std::ifstream& f, char *filename)
456| : Program(filename)
457| {
458| f.seekg(0, std::ios::end);
459| size = f.tellg();
460| f.seekg(0);
461|
462| buf = new char[size + 1];
463| f.read(buf, int(size));
464| #if defined(_WIN32)
465| // Under win31/95/NT, the pair CR-LF is replaced by LF,
466| // implying a smallest size
467| size = f.gcount();
468| #endif
469| buf[size] = '\0';
470| index = 0;
471| }
472|
473| ProgramFile::~ProgramFile()
474| {
475| delete [] buf;
476| buf = nil;
477| }
478|
479| ProgramFromStdin::ProgramFromStdin()
480| : Program("stdin")
481| {
482| const int Size = 512 * 1024;
483| buf = new char[Size];
484| buf_size = Size;
485| index = size = 0;
486| }
487|
488| ProgramFromStdin::~ProgramFromStdin()
489| {
490| delete [] buf;
491| buf = nil;
492| }
493|
494| char ProgramFromStdin::Get()
495| {
496| if(size >= buf_size){
497| std::cerr << "ProgramFromStdin: sorry, out of memory\n";
498| exit(1);
499| }
500|
501| if(index >= size){
502| int c = std::cin.get();
503| if(c == EOF)
504| c = '\0';
505|
506| buf[size++] = c;
507| }
508|
509| if(buf[index] == '\0')
510| return buf[index];
511| else
512| return buf[index++];
513| }
514|
515|
516|
517| const int Quantum = 4;
518| const int BufSize = 1 << Quantum;
519|
520| ProgramString::ProgramString()
521| : Program("unknown")
522| {
523| buf = new (GC) char[BufSize];
524| buf[0] = '\0';
525| size = BufSize;
526| index = str_length = 0;
527| }
528|
529| ProgramString::~ProgramString()
530| {
531| // delete [] buf;
532| buf = nil;
533| }
534|
535| ProgramString& ProgramString::operator << (const char* str)
536| {
537| int len = strlen(str) + 1;
538|
539| if(str_length + len < size){
540| memmove(&buf[str_length], str, len);
541| str_length += len - 1;
542| }
543| else{
544| size = (str_length + len + BufSize) & ~(BufSize - 1);
545| char* newbuf = new (GC) char[size];
546| memmove(newbuf, buf, size_t(str_length));
547| memmove(&newbuf[str_length], str, len);
548| // delete [
549| buf = newbuf;
550| str_length += len - 1;
551| }
552|
553| return *this;
554| }
555|
556| ProgramString& ProgramString::operator << (const char c)
557| {
558| if(str_length + 2 < size){
559| buf[str_length] = c;
560| buf[++str_length] = '\0';
561| }
562| else{
563| size = (str_length + 2 + BufSize) & ~(BufSize - 1);
564| char* newbuf = new (GC) char[size];
565| memmove(newbuf, buf, size_t(str_length));
566| newbuf[str_length] = c;
567| newbuf[++str_length] = '\0';
568| // delete [
569| buf = newbuf;
570| }
571|
572| return *this;
573| }