/* $Header$ */
/*
* Copyright © 1988-2004 Keith Packard and Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
#include "nickle.h"
#include "ref.h"
static void
NamespaceMark (void *object)
{
NamespacePtr namespace = object;
MemReference (namespace->previous);
MemReference (namespace->names);
}
DataType namespaceType = { NamespaceMark, 0, "namespaceType" };
NamespacePtr
NewNamespace (NamespacePtr previous)
{
ENTER ();
NamespacePtr namespace;
namespace = ALLOCATE (&namespaceType, sizeof (Namespace));
namespace->previous = previous;
namespace->names = 0;
namespace->publish = publish_public;
RETURN (namespace);
}
static void
NamelistMark (void *object)
{
NamelistPtr namelist = object;
MemReference (namelist->next);
MemReference (namelist->symbol);
}
DataType namelistType = { NamelistMark, 0, "namelistType" };
static NamelistPtr
NewNamelist (NamelistPtr next, SymbolPtr symbol, Publish publish)
{
ENTER ();
NamelistPtr namelist;
namelist = ALLOCATE (&namelistType, sizeof (Namelist));
namelist->next = next;
namelist->symbol = symbol;
namelist->publish = publish;
RETURN (namelist);
}
NamespacePtr GlobalNamespace, TopNamespace, CurrentNamespace;
ReferencePtr TopNamespaceReference;
ReferencePtr CurrentNamespaceReference;
CommandPtr CurrentCommands;
ReferencePtr CurrentCommandsReference;
void
NamespaceInit (void)
{
ENTER ();
GlobalNamespace = NewNamespace (0);
MemAddRoot (GlobalNamespace);
TopNamespace = GlobalNamespace;
TopNamespaceReference = NewReference ((void **) &TopNamespace);
MemAddRoot (TopNamespaceReference);
CurrentNamespace = GlobalNamespace;
CurrentNamespaceReference = NewReference ((void **) &CurrentNamespace);
MemAddRoot (CurrentNamespaceReference);
CurrentCommands = 0;
CurrentCommandsReference = NewReference ((void **) &CurrentCommands);
MemAddRoot (CurrentCommandsReference);
EXIT ();
}
static NamelistPtr
NamespaceFindNamelist (NamespacePtr namespace, Atom atom, Bool search, Bool allow_private)
{
NamelistPtr namelist;
do
{
for (namelist = namespace->names; namelist; namelist = namelist->next)
if (namelist->symbol->symbol.name == atom &&
(allow_private ||
namespace->publish != publish_private ||
namelist->publish != publish_private))
return namelist;
namespace = namespace->previous;
} while (search && namespace);
return 0;
}
SymbolPtr
NamespaceFindName (NamespacePtr namespace, Atom atom, Bool search)
{
NamelistPtr namelist;
namelist = NamespaceFindNamelist (namespace, atom, search, False);
if (namelist)
return namelist->symbol;
return 0;
}
Bool
NamespaceIsNamePrivate (NamespacePtr namespace, Atom atom, Bool search)
{
return NamespaceFindNamelist (namespace, atom, search, True) != 0;
}
SymbolPtr
NamespaceAddName (NamespacePtr namespace, SymbolPtr symbol, Publish publish)
{
NamelistPtr namelist;
NamelistPtr *prev;
/*
* Remove old symbol
*/
for (prev = &namespace->names; (namelist = *prev); prev = &namelist->next)
if (namelist->symbol->symbol.name == symbol->symbol.name)
{
*prev = namelist->next;
break;
}
namelist = NewNamelist (namespace->names, symbol, publish);
namespace->names = namelist;
return symbol;
}
Bool
NamespaceRemoveName (NamespacePtr namespace, Atom atom)
{
NamelistPtr namelist, *prev;
for (prev = &namespace->names; (namelist = *prev); prev = &namelist->next)
if (namelist->symbol->symbol.name == atom)
{
*prev = namelist->next;
return True;
break;
}
return False;
}
void
NamespaceImport (NamespacePtr namespace, NamespacePtr import, Publish publish)
{
NamelistPtr namelist;
for (namelist = import->names; namelist; namelist = namelist->next)
if (namelist->publish == publish_public)
NamespaceAddName (namespace, namelist->symbol, publish);
}
static void
CommandMark (void *object)
{
CommandPtr command = object;
MemReference (command->previous);
MemReference (command->func);
}
DataType commandType = { CommandMark, 0, "commandType" };
CommandPtr
NewCommand (CommandPtr previous, Atom name, Value func, Bool names)
{
ENTER ();
CommandPtr command;
command = ALLOCATE (&commandType, sizeof (*command));
command->previous = previous;
command->name = name;
command->func = func;
command->names = names;
RETURN (command);
}
CommandPtr
CommandFind (CommandPtr command, Atom name)
{
for(; command; command = command->previous)
if (command->name == name)
return command;
return 0;
}
CommandPtr
CommandRemove (CommandPtr command, Atom name)
{
ENTER ();
CommandPtr *prev;
for (prev = &command; *prev; prev = &(*prev)->previous)
if ((*prev)->name == name)
{
*prev = (*prev)->previous;
break;
}
RETURN (command);
}
Bool
NamespaceLocate (Value names,
NamespacePtr *namespacep,
SymbolPtr *symbolp,
Publish *publishp,
Bool complain)
{
int i;
NamespacePtr namespace;
FramePtr f;
CodePtr c;
Value string;
NamelistPtr namelist = 0;
SymbolPtr symbol;
Bool search = True;
if (!ValueIsArray(names) || names->array.ndim != 1 ||
ArrayLimits(&names->array)[0] == 0)
{
RaiseStandardException (exception_invalid_argument,
"not non-empty array of strings",
2,
NewInt (0), names);
return False;
}
GetNamespace (&namespace, &f, &c);
for (i = 0; i < ArrayLimits(&names->array)[0]; i++)
{
string = ArrayValue (&names->array, i);
if (aborting)
return False;
if (!ValueIsString(string))
{
RaiseStandardException (exception_invalid_argument,
"not string",
2,
NewInt (0), string);
return False;
}
namelist = NamespaceFindNamelist (namespace,
AtomId (StringChars (&string->string)),
search, False);
search = False;
if (!namelist)
{
if (complain)
FilePrintf (FileStdout, "No symbol %v in namespace\n",
string);
return False;
}
symbol = namelist->symbol;
if (i != ArrayLimits(&names->array)[0] - 1)
{
if (symbol->symbol.class != class_namespace)
{
RaiseStandardException (exception_invalid_argument,
"not namespace",
2,
NewInt(i), string);
return False;
}
namespace = symbol->namespace.namespace;
}
}
*namespacep = namespace;
*symbolp = namelist->symbol;
*publishp = namelist->publish;;
return True;
}
syntax highlighted by Code2HTML, v. 0.9.1