/* Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include "namespace.h" #include using namespace std; /* generic utilities */ static list symbolToList(string symbol) { list result; string current; string::iterator si; for(si = symbol.begin(); si != symbol.end(); si++) { if(*si != ':') { current += *si; } else { if(!current.empty()) result.push_back(current); current = ""; } } result.push_back(current); return result; } static string listToSymbol(list& symlist) { string s; list::iterator si; for(si = symlist.begin(); si != symlist.end(); si++) { if(!s.empty()) s += "::"; s += *si; } return s; } /* ModuleHelper */ static list modulePath; static map moduleDefinitions; void ModuleHelper::enter(const char *name) { modulePath.push_back(name); } void ModuleHelper::leave() { assert(!modulePath.empty()); modulePath.pop_back(); } string prependModulePath(string s) { if(modulePath.empty()) return s; else return listToSymbol(modulePath)+"::"+s; } void ModuleHelper::define(const char *name) { moduleDefinitions[prependModulePath(name)] = true; } char *ModuleHelper::qualify(const char *name) { char *result = 0; // TODO: nested namespaces string inCurrentModule = prependModulePath(name); if(moduleDefinitions[inCurrentModule]) { result = strdup(inCurrentModule.c_str()); } else if(moduleDefinitions[name]) { result = strdup(name); } else { fprintf(stderr,"warning: qualifyName failed for %s\n",name); result = strdup(name); } return result; } /* NamespaceHelper */ NamespaceHelper::NamespaceHelper(FILE *outputfile) : out(outputfile) { } NamespaceHelper::~NamespaceHelper() { leaveAll(); } void NamespaceHelper::setFromSymbol(string symbol) { list symlist = symbolToList(symbol); symlist.pop_back(); /* check that the current namespace doesn't contain wrong parts at end */ list::iterator ni,si; ni = currentNamespace.begin(); si = symlist.begin(); long wrong = currentNamespace.size(); while(ni != currentNamespace.end() && si != symlist.end() && *ni == *si) { ni++; si++; wrong--; } while(wrong--) { fprintf(out,"}\n"); } /* enter new components at the end */ while(si != symlist.end()) { fprintf(out,"namespace %s {\n",(*si++).c_str()); } currentNamespace = symlist; } void NamespaceHelper::leaveAll() { setFromSymbol("unqualified"); } string NamespaceHelper::printableForm(string symbol) { list symlist = symbolToList(symbol); list current = currentNamespace; while(!current.empty()) { // namespace longer than symbol? assert(!symlist.empty()); if(*current.begin() == *symlist.begin()) { current.pop_front(); symlist.pop_front(); } else { return "::"+symbol; } } return listToSymbol(symlist); } string NamespaceHelper::nameOf(string symbol) { if(symbol.empty()) return ""; list symlist = symbolToList(symbol); return symlist.back(); } string NamespaceHelper::namespaceOf(string symbol) { list symlist = symbolToList(symbol); if(symlist.size() < 2) return ""; symlist.pop_back(); return listToSymbol(symlist); }