|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 10399 (0x289f) Types: TextFile Names: »classbuffer.c«
└─⟦8648bda34⟧ Bits:30007244 EUUGD5_II: X11R5 └─⟦87c3ac0e0⟧ »./contrib-3/contrib-3.00« └─⟦de8ce1454⟧ └─⟦this⟧ »contrib/lib/iv/src/bin/iclass/classbuffer.c«
/* * Copyright (c) 1989 Stanford University * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Stanford not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Stanford makes no representations about * the suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * ClassBuffer implementation. */ #include "classbuffer.h" #include "classinfo.h" #include "direct.h" #include "globals.h" #include <InterViews/regexp.h> #include <InterViews/textbuffer.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> /*****************************************************************************/ static const int MINTEXTSIZE = 10000; /*****************************************************************************/ class Classes { public: Classes(); ~Classes(); void Include(ClassInfo*); ClassInfo* Class(int index); ClassInfo* Find(const char* className); void Clear(); private: void Insert(ClassInfo*, int index); void Remove(int index); int Index(ClassInfo*); int Position(ClassInfo*); private: ClassInfo** _buf; int _bufsize; int _count; }; Classes::Classes () { const int defaultSize = 64; _bufsize = defaultSize; _buf = new ClassInfo*[_bufsize]; _count = 0; } Classes::~Classes () { Clear(); delete _buf; } void Classes::Include (ClassInfo* info) { Insert(info, Position(info)); } ClassInfo* Classes::Class (int index) { return (0 <= index && index < _count) ? _buf[index] : nil; } ClassInfo* Classes::Find (const char* className) { for (int i = 0; i < _count; ++i) { if (strcmp(className, _buf[i]->Name()) == 0) { return _buf[i]; } } return nil; } void Classes::Insert (ClassInfo* info, int index) { BufInsert(info, index, (void**&) _buf, _bufsize, _count); } void Classes::Remove (int index) { if (0 <= index && index < _count) { BufRemove(index, (void**) _buf, _count); } } int Classes::Index (ClassInfo* info) { for (int i = 0; i < _count; ++i) { if (info == _buf[i]) { return i; } } return -1; } int Classes::Position (ClassInfo* info) { for (int i = 0; i < _count; ++i) { if (strcmp(info->Name(), _buf[i]->Name()) < 0) { return i; } } return _count; } void Classes::Clear () { for (int i = 0; i < _count; ++i) { delete _buf[i]; } _count = 0; } /*****************************************************************************/ ClassBuffer::ClassBuffer ( boolean recursive, boolean verbose, boolean CPlusPlusFiles ) { _classes = new Classes; _recursive = recursive; _verbose = verbose; _CPlusPlusFiles = CPlusPlusFiles; } ClassBuffer::~ClassBuffer () { delete _classes; } const char* ClassBuffer::Class (int index) { ClassInfo* info = _classes->Class(index); return (info == nil) ? nil : info->Name(); } const char* ClassBuffer::Parent (const char* className, int index) { ClassInfo* info = _classes->Find(className); ClassInfo* parentInfo = (info == nil) ? nil : info->Parent(index); return (parentInfo == nil) ? nil : parentInfo->Name(); } const char* ClassBuffer::Child (const char* className, int index) { ClassInfo* info = _classes->Find(className); ClassInfo* childInfo = (info == nil) ? nil : info->Child(index); return (childInfo == nil) ? nil : childInfo->Name(); } const char* ClassBuffer::Path (const char* className) { ClassInfo* info = _classes->Find(className); return (info == nil) ? nil : info->Path(); } int ClassBuffer::LineNumber (const char* className) { ClassInfo* info = _classes->Find(className); return (info == nil) ? nil : info->LineNumber(); } ClassInfo* ClassBuffer::Info (const char* className) { return _classes->Find(className); } inline boolean DotOrDotDot (const char* dir) { return strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0; } inline boolean HeaderFile (const char* file) { int length = strlen(file); return file[length-1] == 'h' && file[length-2] == '.'; } inline boolean CPlusPlusFile (const char* file) { int length = strlen(file); return file[length-1] == 'C' && file[length-2] == '.'; } static boolean IsADirectory (const char* path, struct stat& filestats) { stat(path, &filestats); return S_ISDIR(filestats.st_mode); } void ClassBuffer::Search (const char* path) { struct stat filestats; if (IsADirectory(path, filestats)) { if (_recursive) { SearchDirs(path); } else { SearchDir(path); } } else if (HeaderFile(path) || (_CPlusPlusFiles && CPlusPlusFile(path))) { SearchFile(path, filestats); } } void ClassBuffer::SearchDir (const char* path) { Directory dir(path); if (_verbose) { printf("searching directory %s\n", path); } for (int i = 0; i < dir.Count(); ++i) { const char* file = dir.File(i); if (HeaderFile(file) || (_CPlusPlusFiles && CPlusPlusFile(path))) { struct stat filestats; char filePath[MAXPATHLEN+1]; strcpy(filePath, dir.Normalize(path)); strcat(filePath, file); if (!IsADirectory(filePath, filestats)) { SearchFile(filePath, filestats); } } } } void ClassBuffer::SearchDirs (const char* path) { Directory dir(path); if (_verbose) { printf("recursively searching directory %s\n", path); } for (int i = 0; i < dir.Count(); ++i) { const char* file = dir.File(i); if (!DotOrDotDot(file)) { char filePath[MAXPATHLEN+1]; strcpy(filePath, dir.Normalize(path)); strcat(filePath, file); Search(filePath); } } } #include <OS/file.h> #include <OS/memory.h> void ClassBuffer::SearchFile (const char* path, struct stat&) { InputFile* f = InputFile::open(path); if (f == nil) { return; } const char* buf; int len = f->read(buf); if (len <= 0) { return; } if (_verbose) { printf("searching file %s\n", path, len); } /* * stupid regular expression requires writable strings to guarantee * null-termination */ char* tbuf = new char[len + 1]; Memory::copy(buf, tbuf, len); tbuf[len] = '\0'; TextBuffer textbuf(tbuf, len, len); SearchTextBuffer(&textbuf, path); delete tbuf; f->close(); delete f; } #include <OS/leave-scope.h> void ClassBuffer::SearchTextBuffer (TextBuffer* tb, const char* path) { int beg = 0; for (;;) { char* className = FindClassDecl(tb, beg); if (className == nil) { break; } ClassInfo* info = _classes->Find(className); if (info == nil) { info = new ClassInfo(className, path, tb->LineNumber(beg)); _classes->Include(info); } else { info->Path(path); info->LineNumber(tb->LineNumber(beg)); } for (;;) { char* parentName = ParentName(tb, beg); if (parentName == nil) { break; } ClassInfo* parentInfo = _classes->Find(parentName); if (parentInfo == nil) { parentInfo = new ClassInfo(parentName); _classes->Include(parentInfo); } info->IncludeParent(parentInfo); parentInfo->IncludeChild(info); delete parentName; } delete className; } } inline boolean KeyWord (const char* string) { return strcmp(string, "public") == 0 || strcmp(string, "protected") == 0 || strcmp(string, "private") == 0 || strcmp(string, "virtual") == 0; } char* ClassBuffer::ParentName (TextBuffer* tb, int& beg) { Regexp delimiter("{"); int delim = tb->ForwardSearch(&delimiter, beg); if (delim < 0) { return nil; } for (;;) { char* string = Identifier(tb, beg); if (string == nil || beg >= delim) { delete string; beg = delim; return nil; } else if (KeyWord(string)) { delete string; string = nil; } else { return string; } } } char* ClassBuffer::FindClassDecl (TextBuffer* tb, int& beg) { Regexp classKeyWord("^class[ $]"); Regexp delimiter("[:{;]"); char* className = nil; for (;;) { beg = tb->ForwardSearch(&classKeyWord, beg); if (beg < 0) { break; } int tmp = beg; int delim = tb->ForwardSearch(&delimiter, tmp); if (delim >= 0 && *tb->Text(delim-1) != ';') { className = Identifier(tb, beg); break; } } return className; } inline boolean IsValidChar (char c) { return isalpha(c) || c == '_' || c == '$'; } char* ClassBuffer::Identifier (TextBuffer* tb, int& beg) { int i, j; const char* text = tb->Text(); char* string = nil; for (i = beg; i < tb->Length(); ++i) { if (IsValidChar(text[i])) { break; } } for (j = i+1; j < tb->Length(); ++j) { char c = text[j]; if (!IsValidChar(c) && !isdigit(c)) { break; } } if (j < tb->Length()) { string = strnnew(&text[i], j-i); beg = j; } return string; }