You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/mcopidl/namespace.cc

209 lines
4.0 KiB

/*
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 <string.h>
#include <stdio.h>
#include <list>
#include <string>
#include <map>
#include "namespace.h"
#include <assert.h>
using namespace std;
/* generic utilities */
static list<string> symbolToList(string symbol)
{
list<string> 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<string>& symlist)
{
string s;
list<string>::iterator si;
for(si = symlist.begin(); si != symlist.end(); si++)
{
if(!s.empty()) s += "::";
s += *si;
}
return s;
}
/* ModuleHelper */
static list<string> modulePath;
static map<string,bool> 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<string> symlist = symbolToList(symbol);
symlist.pop_back();
/* check that the current namespace doesn't contain wrong parts at end */
list<string>::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<string> symlist = symbolToList(symbol);
list<string> 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<string> symlist = symbolToList(symbol);
return symlist.back();
}
string NamespaceHelper::namespaceOf(string symbol)
{
list<string> symlist = symbolToList(symbol);
if(symlist.size() < 2) return "";
symlist.pop_back();
return listToSymbol(symlist);
}