Generic_Window_Manager/wl_name.c

414 lines
10 KiB
C

/* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
* Copyright 1989 Massachusetts Institute of Technology
*/
/**************************\
* *
* WOOL_OBJECT: Namespace *
* BODY *
* *
\**************************/
#include "EXTERN.h"
#include <stdlib.h>
#include <stdio.h>
#include "wool.h"
#include "wl_atom.h"
#include "wl_list.h"
#include "wl_number.h"
#include "wl_string.h"
#include "INTERN.h"
#include "wl_name.h"
#define WLNAMESPACE_INITIAL_SIZE 3 /* initial size (in longs) */
#define DELETED (WOOL_OBJECT *) -1 /* slot is vacant */
#define NONE_DELETED -1 /* no slot is vacant */
int WLNamespace_search_deleted();
/* High level function callable from wool. Makes a new namespace.
*/
WOOL_Namespace
WLNamespace_make()
{
WOOL_Namespace object = (WOOL_Namespace)
Malloc(sizeof(struct _WOOL_Namespace));
bzero(object, sizeof(struct _WOOL_Namespace));
object -> type = WLNamespace;
zrt_put(object);
object -> first_deleted = NONE_DELETED;
return object;
}
/* adding a namespace domain to a namespace. returns int of created namespace
*/
WOOL_OBJECT
WLNamespace_add(namespace)
WOOL_Namespace namespace;
{
int new_index;
must_be_namespace(namespace, 0);
if (!namespace -> number) /* non-empty namespaces */
increase_reference(namespace); /* must never disapear */
if (namespace -> first_deleted == NONE_DELETED) {
new_index = namespace -> number++;
namespace -> namespaces = (WOOL_OBJECT **)
Realloc(namespace -> namespaces,
namespace -> number * sizeof(WOOL_OBJECT *));
} else {
new_index = namespace -> first_deleted;
namespace -> first_deleted =
WLNamespace_search_deleted(namespace, new_index);
}
if (namespace -> limit)
namespace -> namespaces[new_index] = (WOOL_OBJECT *)
Malloc(sizeof(WOOL_OBJECT) * namespace -> limit);
else
namespace -> namespaces[new_index] = 0;
return (WOOL_OBJECT) WLNumber_make(new_index);
}
/* removing a namespace.
* just puts a DELETED in the entry
*/
WOOL_OBJECT
WLNamespace_remove(namespace, number)
WOOL_Namespace namespace;
WOOL_Number number;
{
int index;
WOOL_OBJECT *p;
must_be_namespace(namespace, 0);
must_be_number(number, 1);
index = number -> number;
if (index < 0 || index >= namespace -> number)
return NIL;
for (p = namespace -> namespaces[index];
p < (namespace -> namespaces[index]) + namespace -> limit;
p++)
decrease_reference(*p);
Free(namespace -> namespaces[index]);
namespace -> namespaces[index] = DELETED;
if (namespace -> first_deleted == NONE_DELETED
|| namespace -> first_deleted > index)
namespace -> first_deleted = index;
return NIL;
}
/* searches for first vacant spot
*/
int
WLNamespace_search_deleted(namespace, index)
WOOL_Namespace namespace;
int index;
{
WOOL_OBJECT **p;
for (p = namespace -> namespaces + index;
p < namespace -> namespaces + namespace -> number;
p++) {
if (*p == DELETED)
return p - namespace -> namespaces;
}
return NONE_DELETED;
}
/* adding a new name entry in a namespace
* returns new index
*/
Num
WLNamespace_add_name(namespace)
WOOL_Namespace namespace;
{
int i;
WOOL_OBJECT *p;
if (namespace -> size >= namespace -> limit) { /* must realloc */
if (namespace -> limit)
namespace -> limit = namespace -> limit * 2 + 1;
else
namespace -> limit = WLNAMESPACE_INITIAL_SIZE;
for (i = 0; i < namespace -> number; i++) {
namespace -> namespaces[i] = (WOOL_OBJECT *) Realloc(
namespace -> namespaces[i],
namespace -> limit * sizeof(WOOL_OBJECT));
for (p = (namespace -> namespaces[i]) + namespace -> size;
p < (namespace -> namespaces[i]) + namespace -> limit;
p++)
increase_reference(*p = UNDEFINED_WOOL_VALUE);
}
}
return (Num) namespace -> size++;
}
/* adding a name in a namespace
* (defname 'name namespace [value]) ==> sets value in each namespace state
* if no value given, and atom had a previous value, sets all name values
* this value
*/
WOOL_OBJECT
WLName_add(argc, argv)
int argc;
WOOL_OBJECT argv[];
{
WOOL_OBJECT value;
switch (argc) {
case 2:
value = 0;
break;
case 3:
value = argv[2];
break;
default:
return wool_error(BAD_NUMBER_OF_ARGS, argc);
}
must_be_namespace(argv[1], 1);
if (argv[0] -> type == WLAtom) {
if (!value && ((WOOL_Atom) argv[0]) -> c_val)
value = (WOOL_OBJECT)
WLQuotedExpr_make(((WOOL_Atom) argv[0]) -> c_val);
decrease_reference(((WOOL_Atom) argv[0]) -> c_val);
argv[0] -> type = WLName;
NameNamespace(((WOOL_Name) argv[0])) = ((WOOL_Namespace) argv[1]);
((WOOL_Name) argv[0]) -> index =
WLNamespace_add_name((WOOL_Namespace) argv[1]);
} else if (argv[0] -> type == WLName) {
if (NameNamespace(((WOOL_Name) argv[0])) !=
((WOOL_Namespace) argv[1])) {
WLName_release_values(argv[0]);
NameNamespace(((WOOL_Name) argv[0])) = ((WOOL_Namespace) argv[1]);
((WOOL_Name) argv[0]) -> index =
WLNamespace_add_name((WOOL_Namespace) argv[1]);
} else {
return argv[0];
}
} else
bad_argument(argv[0], 0, "symbol");
if (value) { /* set to arg */
WLName_set_all(argv[1], argv[0], value);
}
return argv[0];
}
/* manage active namespace
* (set-current-namespace namespace current)
* with current out-of-bounds (e.g -1) returning current one
*/
WOOL_OBJECT
WLNamespace_set_current(namespace, index)
WOOL_Namespace namespace;
WOOL_Number index;
{
must_be_namespace(namespace, 0);
must_be_number(index, 1);
if (index -> number >= 0 && index -> number < namespace -> number) {
namespace -> current = index -> number;
if (namespace -> trigger)
(*(namespace -> trigger))(index -> number);
return (WOOL_OBJECT) index;
} else {
return (WOOL_OBJECT) WLNumber_make(namespace -> current);
}
}
/* size of states in the namespace
*/
WOOL_OBJECT
WLNamespace_size(namespace)
WOOL_Namespace namespace;
{
must_be_namespace(namespace, 0);
return (WOOL_OBJECT) WLNumber_make(namespace -> number);
}
/* namespace-of:
* on a name returns namespace or NIL if global
*/
WOOL_OBJECT
WLName_namespace(name)
WOOL_Name name;
{
if (name -> type == WLAtom)
return NIL;
else if (name -> type == WLName)
return (WOOL_OBJECT) NameNamespace(name);
else
return bad_argument(name, 0, "symbol");
}
/* free all c_val values */
WLName_release_values(name)
WOOL_Name name;
{
WOOL_Namespace namespace = NameNamespace(name);
int i;
for (i = 0; i < namespace -> number; i++)
decrease_reference((namespace -> namespaces[i])[name -> index]);
}
WOOL_OBJECT
WLName_unbind(name)
WOOL_Name name;
{
WOOL_Namespace namespace = NameNamespace(name);
decrease_reference((namespace -> namespaces[namespace -> current])
[name -> index]);
(namespace -> namespaces[namespace -> current])
[name -> index] = UNDEFINED_WOOL_VALUE;
return NIL;
}
/* namespace methods */
WOOL_OBJECT
WLNamespace_print(obj)
WOOL_Namespace obj;
{
wool_printf("{NAMESPACE 0x%x ", obj);
wool_printf("(%d spaces", obj -> number);
wool_printf(" of %d names)}", obj -> size);
return (WOOL_OBJECT) obj;
}
WOOL_OBJECT
WLNamespace_free(namespace)
WOOL_Namespace namespace;
{
free(namespace);
return NULL;
}
/* name methods */
/*
* Evaluating an name returns the pointed slot
*/
WOOL_OBJECT
WLName_eval(name)
WOOL_Name name;
{
WOOL_Namespace namespace = NameNamespace(name);
WOOL_OBJECT value;
if ((value = ((namespace -> namespaces)[namespace -> current])
[name -> index]) != UNDEFINED_WOOL_VALUE)
return value;
else
return wool_error(UNDEFINED_VARIABLE, name -> p_name);
}
WOOL_OBJECT *
WLName_slot(name)
WOOL_Name name;
{
WOOL_Namespace namespace = NameNamespace(name);
return &(((namespace -> namespaces)[namespace -> current])[name -> index]);
}
WOOL_OBJECT
WLName_silent_eval(name)
WOOL_Name name;
{
WOOL_Namespace namespace = NameNamespace(name);
return ((namespace -> namespaces)[namespace -> current]) [name -> index];
}
WOOL_OBJECT
WLName_set(name, value)
WOOL_Name name;
WOOL_OBJECT value;
{
WOOL_OBJECT new = WOOL_send(WOOL_eval, value, (value));
WOOL_Namespace namespace = NameNamespace(name);
WOOL_OBJECT *value_ptr = &(((namespace -> namespaces)
[namespace -> current])[name -> index]);
decrease_reference(*value_ptr);
increase_reference(*value_ptr = new);
return new;
}
WOOL_OBJECT
WLName_setq(name, value)
WOOL_Name name;
WOOL_OBJECT value;
{
WOOL_Namespace namespace = NameNamespace(name);
WOOL_OBJECT *value_ptr = &(((namespace -> namespaces)
[namespace -> current])[name -> index]);
decrease_reference(*value_ptr);
increase_reference(*value_ptr = value);
return value;
}
/* like set but on all spaces */
WLName_set_all(namespace, name, value)
WOOL_Namespace namespace;
WOOL_Name name;
WOOL_OBJECT value;
{
WOOL_OBJECT *value_ptr;
int i, old_current = namespace -> current;
if (namespace -> save_state)
(*(namespace -> save_state)) ();
for (i = 0; i < namespace -> number; i++) {
value_ptr = &(((namespace -> namespaces)[i])[name -> index]);
decrease_reference(*value_ptr);
namespace -> current = i;
if (namespace -> trigger)
(*(namespace -> trigger)) (i);
increase_reference(*value_ptr = WOOL_send(WOOL_eval, value, (value)));
}
namespace -> current = old_current;
if (namespace -> trigger)
(*(namespace -> trigger)) (old_current);
if (namespace -> restore_state)
(*(namespace -> restore_state)) ();
}
/*
* WLName_execute:
* executes the object in the C_val
*/
WOOL_OBJECT
WLName_execute(name, list)
WOOL_Name name;
WOOL_List list;
{
WOOL_Namespace namespace = NameNamespace(name);
WOOL_OBJECT value = ((namespace -> namespaces)
[namespace -> current])[name -> index];
if (value != UNDEFINED_WOOL_VALUE && (value -> type != WLAtom)) {
return WOOL_send(WOOL_execute, value, (value, list));
} else if (value && (value == NIL)) {
return NIL;
} else {
return (wool_error(UNDEFINED_FUNCTION, name));
}
}