/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include # #include #include #define NAME in[0] #define DEFAULT in[1] #define RESULT out[0] #define NOTIFY_READYTORUN 1 #define NOTIFY_READYTORUN_NOEXECUTE 2 struct _string { struct _string *next; struct _string *link; int executeFlag; char string[1]; }; struct _table { struct _string *strings; HashTable hash; Private owner; }; typedef struct _entry { char *name; struct _string *modids; } *Entry; static struct _string * newString(struct _table *table, char *str) { struct _string *_str; if (! table) { DXSetError(ERROR_INTERNAL, "newString: no table"); return NULL; } _str = (struct _string *)DXAllocate(strlen(str) + sizeof(struct _string) + 3); if (! str) return ERROR; strcpy(_str->string, str); _str->next = table->strings; table->strings = _str; _str->link = NULL; return _str; } static Error delete_table(Pointer p) { struct _string *s, *n; struct _table *table = (struct _table *)p; HashTable hash = table->hash; DXDestroyHash(hash); for (s = table->strings; s; s = n) { n = s->next; DXFree((Pointer)s); } return OK; } static PseudoKey hash(Entry key) { char *name = ((struct _entry *) key)->name; long l, i; for (l = i = 0; i < strlen(name); i++, l ^= name[i]); return l; } static int cmp(Entry k0, Entry k1) { char *n0 = ((struct _entry *) k0)->name; char *n1 = ((struct _entry *) k1)->name; return strcmp(n0, n1); } static void freeTable(struct _table *tab) { if (tab) DXDelete((Object)tab->owner); } static struct _table * getTable() { struct _table *table; Private pht = (Private)DXGetCacheEntry("__HASH_DXLInputNAMED", 0, 0); if (! pht) { table = (struct _table *)DXAllocate(sizeof(struct _table)); if (! table) goto error; table->hash = DXCreateHash(sizeof(struct _entry), hash, cmp); if (! table->hash) { DXFree((Pointer)table); goto error; } table->strings = NULL; table->owner = DXNewPrivate((Pointer)table, delete_table); if (! table->owner) { DXDestroyHash(table->hash); DXFree((Pointer)table); goto error; } if (! DXSetCacheEntry((Object)table->owner, CACHE_PERMANENT, "__HASH_DXLInputNAMED", 0, 0)) { DXDelete((Object)table->owner); goto error; } pht = (Private)DXReference((Object)table->owner); } return (struct _table *)DXGetPrivateData(pht); error: return NULL; } static struct _entry * getEntry(struct _table *table, char *name) { struct _entry key, *entry; key.name = name; entry = (struct _entry *)DXQueryHashElement(table->hash, (Key)&key); if (! entry) { struct _string *str = newString(table, name); if (! str) return NULL; key.name = str->string; key.modids = NULL; if (! DXInsertHashElement(table->hash, (void *)&key)) return NULL; entry = (struct _entry *)DXQueryHashElement(table->hash, (Key)&key); } return entry; } static int isModidRegistered(struct _entry *entry, Pointer modid) { struct _string *str; for (str = entry->modids; str; str = str->link) if (! strcmp((char *)modid, str->string)) return 1; return 0; } static Error registerModid(struct _table *table, struct _entry *entry, Pointer modid, int flag) { struct _string *str = newString(table, (char *)modid); if (! str) return ERROR; str->link = entry->modids; entry->modids = str; str->executeFlag = flag; return OK; } Error DXRegisterForNotification(char *name, Pointer modid) { struct _entry *entry; struct _table *table = getTable(); if (! table) return ERROR; entry = getEntry(table, name); if (! entry) goto error; if (! isModidRegistered(entry, modid)) if (! registerModid(table, entry, modid, NOTIFY_READYTORUN)) goto error; done: freeTable(table); return OK; error: freeTable(table); return ERROR; } Error DXRegisterForNotificationNoExecute(char *name, Pointer modid) { struct _entry *entry; struct _table *table = getTable(); if (! table) return ERROR; entry = getEntry(table, name); if (! entry) goto error; if (! isModidRegistered(entry, modid)) if (! registerModid(table, entry, modid, NOTIFY_READYTORUN_NOEXECUTE)) goto error; done: freeTable(table); return OK; error: freeTable(table); return ERROR; } Error DXNotifyRegistered(char *name) { struct _entry *entry; struct _string *str; struct _table *table = getTable(); if (! table) return ERROR; entry = getEntry(table, name); if (! entry) goto error; for (str = entry->modids; str; str = str->link) if (str->executeFlag == NOTIFY_READYTORUN) DXReadyToRun((Pointer)str->string); else DXReadyToRunNoExecute((Pointer)str->string); done: freeTable(table); return OK; error: freeTable(table); return ERROR; } Error DXNotifyRegisteredNoExecute(char *name) { struct _entry *entry; struct _string *str; struct _table *table = getTable(); if (! table) return ERROR; entry = getEntry(table, name); if (! entry) goto error; for (str = entry->modids; str; str = str->link) DXReadyToRunNoExecute((Pointer)str->string); done: freeTable(table); return OK; error: freeTable(table); return ERROR; }