Files
modules/cmdVersion.c
2009-09-01 19:16:28 +00:00

1192 lines
35 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*****
** ** Module Header ******************************************************* **
** **
** Modules Revision 3.0 **
** Providing a flexible user environment **
** **
** File: cmdVersion.c **
** First Edition: 1995/12/28 **
** **
** Authors: Jens Hamisch, jens@Strawberry.COM **
** R.K. Owen, <rk@owen.sj.ca.us> or <rkowen@nersc.gov> **
** **
** Description: The Tcl module-version routine which provides the **
** definition of symbolic version names and the module- **
** alias command providing the definition of module and **
** version aliases **
** **
** Exports: cmdModuleVersion **
** cmdModuleAlias **
** CleanupVersion **
** AliasLookup **
** ExpandVersions **
** **
** Notes: This module defines the callback functions for the defi- **
** nition of symbolic module names and module aliases. The **
** syntax of the according commands is defined as: **
** **
** Module-Versions: **
** module-version <module>/<version> <name> [ <name> ... ] **
** module-version /<version> <name> [ <name> ... ] **
** module-version <module> <name> [ <name> ... ] **
** module-version <alias> <name> [ <name> ... ] **
** **
** Module-Alias: **
** module-alias <alias> <module>/<version> **
** module-alias <alias> /<version> **
** module-alias <alias> <module> **
** module-alias <alias> <alias> **
** **
** **
** ************************************************************************ **
****/
/** ** Copyright *********************************************************** **
** **
** Copyright 1991-1994 by John L. Furlan. **
** see LICENSE.GPL, which must be provided, for details **
** **
** ************************************************************************ **/
static char Id[] = "@(#)$Id: cmdVersion.c,v 1.19 2009/09/02 20:37:39 rkowen Exp $";
static void *UseId[] = { &UseId, Id };
/** ************************************************************************ **/
/** HEADERS **/
/** ************************************************************************ **/
#include "modules_def.h"
/** ************************************************************************ **/
/** LOCAL DATATYPES **/
/** ************************************************************************ **/
/** ************************************************************************ **/
/** **/
/** The whole thing is handled in memory. The structure is build of module **/
/** and name records. There are 3 types of name records: version, name **/
/** and alias. **/
/** **/
/** | | **/
/** +---+---+<-------------------------------+ +---+---+ **/
/** | module| ------------------------+ | | alias | **/
/** +---+---+ --------+ | | +-------+ **/
/** | ^ +----+----+ | | | **/
/** | +--- | version | +--+--+ | +---+---+ **/
/** | | +----+----+ | name|---+ <-----| alias | **/
/** | | | +--+--+ | +---+---+ **/
/** | | +----+----+ | | | **/
/** | +--- | version |------>+--+--+ | +---+---+ **/
/** | | +----+----+<-+--- | name|---+ | alias | **/
/** | | | | +- +--+--+ | +---+---+ **/
/** | | +----+----+ | | | | | **/
/** | +--- | version | | | +--+--+ | +---+---+ **/
/** | | +----+----+ | | | name|---+ <-----| alias | **/
/** | | | | | +--+--+ | +---+---+ **/
/** | | | | | | **/
/** | | +->+--+--+ | +---+---+ **/
/** +---+---+ +--- | name|---+ | alias | **/
/** | module| +--+--+ | +---+---+ **/
/** +---+---+ | | | **/
/** | **/
/** alphabetic ordered alphabtic ordered **/
/** list of names depending list of aliases **/
/** on a single module file **/
/** **/
/** Each module name points to a list of symbolic names and versions. **/
/** The versions themselves can be symbolic names and therefore are of the **/
/** same record type as the names. **/
/** The name and the version list are alphabetically sorted (even the **/
/** module list is). A version record points to a related name record **/
/** containing a symbolic name for the version. Starting at this record, **/
/** the name records build a queue of symbolic names for the version. **/
/** Both, the version and the name record, do have a backward pointer to **/
/** the module record. **/
/** **/
/** The alias list builds a alphabetic ordered list of defined aliases. **/
/** Each alias record points to the related name record. **/
/** **/
/** ************************************************************************ **/
typedef struct _mod_module {
struct _mod_module *next; /** alphabetic queue **/
struct _mod_name *version; /** version queue **/
struct _mod_name *name; /** name queue **/
char *module; /** the name itself **/
} ModModule;
typedef struct _mod_name {
struct _mod_name *next; /** alphabetic queue **/
struct _mod_name *ptr; /** logical next **/
struct _mod_name *version; /** backwards version pointer **/
struct _mod_module *module; /** related module **/
char *name; /** the name itself **/
} ModName;
/** ************************************************************************ **/
/** CONSTANTS **/
/** ************************************************************************ **/
#define HISTTAB 100
/** ************************************************************************ **/
/** MACROS **/
/** ************************************************************************ **/
/** not applicable **/
/** ************************************************************************ **/
/** LOCAL DATA **/
/** ************************************************************************ **/
static char module_name[] = __FILE__;
/**
** The module and aliases list
**/
static ModModule *modlist = (ModModule *) NULL;
static ModName *aliaslist = (ModName *) NULL;
/** ************************************************************************ **/
/** PROTOTYPES **/
/** ************************************************************************ **/
static void CleanupVersionSub( ModModule *ptr);
static void CleanupName( ModName *ptr);
static ModModule *AddModule( char *name);
static ModModule *FindModule( char *name,
ModModule **prev);
static ModName *AddName( char *name,
ModName **start,
ModModule *module);
static ModName *FindName( char *name,
ModName *start,
ModName **prev);
static char *CheckModuleVersion( char *name);
static char *scan_versions( char *buffer,
char *base,
ModName *ptr,
ModModule *modptr);
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: cmdModuleVersion **
** **
** Description: Callback function for 'version' **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: ClientData client_data **
** Tcl_Interp *interp According Tcl interp.**
** int objc Number of arguments **
** Tcl_Obj *objv[] Argument array **
** **
** Result: int TCL_OK Successful completion **
** TCL_ERROR Any error **
** **
** Attached Globals: modlist List containing all version names **
** g_flags These are set up accordingly before **
** this function is called in order to **
** control everything **
** **
** ************************************************************************ **
++++*/
int cmdModuleVersion(
ClientData client_data,
Tcl_Interp * interp,
int objc,
Tcl_Obj * CONST84 objv[]
) {
char *version, *module;
ModModule *modptr;
ModName *versptr, *nameptr, *tmp, *ptr;
int i;
/**
** Whatis mode?
**/
if (g_flags & M_WHATIS)
return (TCL_OK); /** ------- EXIT PROCEDURE -------> **/
/**
** Parameter check
**/
if (objc < 3) {
if (OK != ErrorLogger(ERR_USAGE, LOC, Tcl_GetString(objv[0]),
" modulename ",
" symbolic-version [symbolic-version ...] ",
NULL))
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
if ((char *)NULL ==
(module = CheckModuleVersion((char *)Tcl_GetString(objv[1])))) {
ErrorLogger(ERR_BADMODNAM, LOC, Tcl_GetString(objv[1]), NULL);
return (TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
/**
** Display mode?
**/
if (g_flags & M_DISPLAY) {
fprintf(stderr, "%s\t ", Tcl_GetString(objv[0]));
for (i = 1; i < objc; i++)
fprintf(stderr, "%s ", Tcl_GetString(objv[i]));
fprintf(stderr, "\n");
}
/**
** get the version from the argument
**/
if ((char *)NULL == (version = strrchr(module, '/'))) {
if (OK != ErrorLogger(ERR_INTERAL, LOC, NULL))
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
*version++ = '\0';
/**
** Now we have a module and a version.
** Check whether it exists (cond. create them). Check both, the version
** and the name queue in order to locate the desired version ...
**/
if ((ModModule *) NULL == (modptr = AddModule(module))) {
ErrorLogger(ERR_BADMODNAM, LOC,Tcl_GetString(objv[1]), NULL);
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
if ((ModName *) NULL ==
(ptr = FindName(version, modptr->version, &tmp))) {
if ((ModName *) NULL ==
(ptr = FindName(version, modptr->name, &tmp)))
versptr = AddName(version, &modptr->version, modptr);
else
versptr = ptr->version;
} else
versptr = ptr;
/**
** Check all symbolic names now and allocate a name record for them
**/
for (i = 2; i < objc; i++) {
if (FindName(Tcl_GetString(objv[i]), modptr->name, &tmp)) {
if (OK != ErrorLogger(ERR_DUP_SYMVERS, LOC,
Tcl_GetString(objv[i]), NULL))
break;
else
continue;
}
if ((ModName *) NULL == (nameptr =
AddName((char *)Tcl_GetString(objv[i]),
&modptr->name, modptr))) {
if (OK != ErrorLogger(ERR_INTERAL, LOC, NULL))
break;
else
continue;
}
/**
** Concat the new element at the beginning of the name queue ...
**/
nameptr->ptr = versptr->ptr;
versptr->ptr = nameptr;
nameptr->version = versptr;
}
return (TCL_OK);
} /** End of 'cmdModuleVersion' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: ExpandVersions **
** **
** Description: Callback function for 'version' **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *name Name to be expanded **
** **
** Result: char* NULL No symbols found **
** Otherwise Pointer to the list string **
** **
** ************************************************************************ **
++++*/
char *ExpandVersions( char *name)
{
char *version, *module, *s;
static char buffer[ BUFSIZ];
ModModule *modptr, *tmp1;
ModName *ptr, *tmp2;
/**
** Parameter check
**/
if((char *) NULL == (module = CheckModuleVersion( name)))
return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
if((char *) NULL == (version = strrchr( module, '/'))) {
if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
}
*version++ = '\0';
/**
** Now we have a module and a version.
** Check wheter it exists
**/
if((ModModule *) NULL == (modptr = FindModule( module, &tmp1)))
return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
if((ModName *) NULL == (ptr = FindName( version, modptr->version, &tmp2))) {
if((ModName *) NULL == (ptr = FindName( version, modptr->name, &tmp2)))
return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
ptr = ptr->version;
}
if( !ptr->ptr)
return((char *) NULL ); /** -------- EXIT (FAILURE) -------> **/
/**
** Now scan in all the symbolic version names
**/
*buffer = '\0';
if( (s = scan_versions( buffer, buffer, ptr->ptr, modptr)) )
*--s = '\0'; /** remove trailing ':' **/
return( buffer);
} /** End of 'ExpandVersions' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: scan_versions **
** **
** Description: Scan all symbolic versions pointed to be the passed **
** ModName pointer and print them as a list into the **
** passed buffer. **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *buffer Buffer for printing in **
** ModName *ptr Name structure pointer **
** ModModule *modptr Assigned module name **
** **
** Result: char* NULL Nothing printed into the **
** buffer **
** Otherwise Pointer to the end of the **
** string in the buffer **
** **
** ************************************************************************ **
++++*/
static char *scan_versions( char *buffer,
char *base,
ModName *ptr,
ModModule *modptr)
{
ModName *tmp, *vers;
char *s;
char *mayloop;
/**
** Recursively print the queue of names
**/
if( !ptr)
return((char *) NULL); /** ------ EXIT (END) -----> **/
if( !ptr->name) {
if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
return((char *) NULL); /** ---- EXIT (FAILURE) ---> **/
} else {
/**
** Prevent endless loops
** To allow for version names that are substrings of other
** version names, match against "(^|:)name:" not just "name"...
**/
mayloop = strstr( base, ptr->name);
if( mayloop != NULL ) {
if( mayloop == base || *(mayloop-1) == ':' ) {
if( *(mayloop + strlen(ptr->name)) == ':' ) {
ErrorLogger( ERR_SYMLOOP, LOC, ptr->name, NULL);
return((char *) NULL); /** ---- EXIT (FAILURE) ---> **/
}
}
}
/**
** Now print ...
**/
/* sprintf( buffer, "%s:", ptr->name); */
strcpy( buffer, ptr->name);
/* if you change this, may affect the loop checker above */
strcat( buffer, ":");
buffer += strlen( buffer);
/**
** Check wheter this is a version name again ...
** This is a recursion, too
**/
if((ModName *) NULL != (vers = FindName( ptr->name, modptr->version,
&tmp))) {
if( (s = scan_versions( buffer, base, vers->ptr, modptr)) )
buffer = s;
}
}
/**
** This is the recursion. Preserve the buffer end pointer
**/
if( (s = scan_versions( buffer, base, ptr->ptr, modptr)) )
buffer = s;
return( buffer);
} /** End of 'scan_versions' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: CheckModuleVersion **
** **
** Description: Reduce the passed module name into a <mod>/<vers> **
** string **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *name name to be checked **
** **
** Result: char* NULL any error **
** Otherwise Pointer to a <mod>/<vers> **
** string **
** **
** Attached Globals: modlist List containing all version names **
** aliaslist List containing all alises **
** g_current_module The module which is handled **
** by the current command **
** **
** ************************************************************************ **
++++*/
static char *CheckModuleVersion( char *name)
{
static char buffer[ BUFSIZ];
char *s, *t;
/**
** Check the first parameter and extract modulename and version
**/
if( '/' == *name) { /** only the version specified **/
/**
** get the module name from the current module ...
**/
if( !g_current_module)
return((char *) NULL);
strcpy( buffer, g_current_module);
if((char *) NULL == (t = strrchr( buffer, '/')))
t = buffer + strlen( buffer);
*t++ = '/';
*t = '\0';
/**
** The version has been specified as a parameter
**/
if( (s = strrchr( name, '/')) ) {
s++;
} else {
ErrorLogger( ERR_INTERAL, LOC, NULL);
return((char *) NULL);
}
strcpy( t, s);
} else { /** Maybe an alias or a module **/
strcpy( buffer, name);
if( !strrchr( buffer, '/')) {
/**
** Check wheter this is an alias ...
**/
if( AliasLookup( buffer, &s, &t)) {
/* sprintf( buffer, "%s/%s", s, t); */
strcpy( buffer, s);
strcat( buffer, "/");
strcat( buffer, t);
} else {
/**
** The default version is being selected
**/
t = buffer + strlen( buffer);
if( '/' != *t)
*t++ = '/';
strcpy( t, _(em_default));
}
}
}
/**
** Pass the buffer reference to the caller
**/
return( buffer);
} /** End of 'CheckModuleVersion' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: cmdModuleAlias **
** **
** Description: Callback function for 'alias' **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: ClientData client_data **
** Tcl_Interp *interp According Tcl interp.**
** int objc Number of arguments **
** Tcl_Obj *objv[] Argument array **
** **
** Result: int TCL_OK Successful completion **
** TCL_ERROR Any error **
** **
** Attached Globals: aliaslist List containing all alises **
** g_flags These are set up accordingly before **
** this function is called in order to **
** control everything **
** **
** ************************************************************************ **
++++*/
int cmdModuleAlias(
ClientData client_data,
Tcl_Interp * interp,
int objc,
Tcl_Obj * CONST84 objv[]
) {
ModName *tmp, *ptr;
char *version, *module;
ModName *trg_alias;
ModModule *modptr;
/**
** Parameter check
**/
if (objc != 3) {
if (OK !=
ErrorLogger(ERR_USAGE, LOC, Tcl_GetString(objv[0]),
" aliasname ", "modulename", NULL))
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
/**
** Whatis mode?
**/
if (g_flags & M_WHATIS)
return (TCL_OK); /** -------- EXIT PROCEDURE -------> **/
if (g_flags & M_DISPLAY) {
fprintf(stderr, "%s\t %s %s\n", Tcl_GetString(objv[0]),
Tcl_GetString(objv[1]), Tcl_GetString(objv[2]));
}
/**
** Check if the target is an alias ...
** Conditionally split up the passed <module>/<version> pair.
**/
trg_alias = FindName((char *)Tcl_GetString(objv[2]), aliaslist, &tmp);
if (!trg_alias) {
if ((char *)NULL ==
(module = CheckModuleVersion(Tcl_GetString(objv[2]))))
module = (char *)Tcl_GetString(objv[2]);
if ((char *)NULL != (version = strrchr(module, '/')))
*version++ = '\0';
}
/**
** Any alias record existing with this name?
** If it does, we're finished ...
**/
if ((ptr = FindName((char *)Tcl_GetString(objv[1]), aliaslist, &tmp))) {
if (!ptr->ptr || !ptr->ptr->name ||
(!trg_alias
&& (!ptr->ptr->module || !ptr->ptr->module->module))) {
ErrorLogger(ERR_INTERAL, LOC, NULL);
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
if((trg_alias && !strcmp(ptr->ptr->name,Tcl_GetString(objv[2])))
|| (!trg_alias && !strcmp(ptr->ptr->name, version)
&& !strcmp(ptr->ptr->module->module, module)))
return (TCL_OK);/** -------- EXIT (SUCCESS) -------> **/
if (OK != ErrorLogger(ERR_DUP_ALIAS,LOC,Tcl_GetString(objv[1]),
NULL))
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
} else {
/**
** We have to allocate a new alias entry
**/
if ((ModName *) NULL ==
(ptr = AddName((char *)Tcl_GetString(objv[1]), &aliaslist,
NULL))) {
ErrorLogger(ERR_INTERAL, LOC, NULL);
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
}
/**
** Now ptr points to the affected module alias record ...
** Conditionally we have to create the module and the version record now.
**/
if (trg_alias) {
ptr->ptr = trg_alias;
} else {
if ((ModModule *) NULL == (modptr = AddModule(module))) {
ErrorLogger(ERR_BADMODNAM, LOC, Tcl_GetString(objv[2]),
NULL);
ptr->ptr = (ModName *) NULL;
return (TCL_ERROR); /** ------ EXIT (FAILURE) -----> **/
}
ptr->ptr = AddName((version ? version : _(em_default)),
&modptr->version, modptr);
}
return (TCL_OK);
} /** End of 'cmdModuleAlias' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: AliasLookup **
** **
** Description: Resolves a given alias to a module/version string **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *alias Name of the alias to be re- **
** solved **
** char **module Buffer for the module name **
** char **version Buffer for the module version**
** **
** Result: int 1 Success, value in the buffer **
** is valid **
** 0 Any error, or not found **
** **
** Attached Globals: aliaslist List containing all alises **
** **
** ************************************************************************ **
++++*/
int AliasLookup( char *alias,
char **module,
char **version)
{
ModName *ptr, *tmp, *oldptr = NULL;
while( 1) {
/**
** Lokate the alias entry and check intergrity
**/
if((ModName *) NULL == (ptr = FindName( alias, aliaslist, &tmp)))
return( 0); /** ------- EXIT (not found) ------> **/
if( ptr == oldptr || !ptr->ptr || !ptr->ptr->name ) {
ErrorLogger( ERR_INTERAL, LOC, NULL);
return( 0); /** -------- EXIT (FAILURE) -------> **/
}
/**
** Do we have to loop? Another alias has no module reference ...
**/
if( !ptr->ptr->module) {
alias = ptr->ptr->name;
oldptr = ptr;
continue;
}
/**
** Got it. Get the module name and the version from the found
** entry.
** Dereference symbolic module versions
**/
*module = ptr->ptr->module->module;
*version = ptr->ptr->name;
if((ModName *) NULL != (ptr = FindName( *version,
ptr->ptr->module->name, &tmp))) {
if( !ptr->version || !ptr->version->name) {
if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
return( 0);
} else
*version = ptr->version->name;
}
break;
} /** while **/
return( 1);
} /** End of 'AliasLookup' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: VersionLookup **
** **
** Description: Resolves a given alias to a module/version string **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *alias Name of the alias to be re- **
** solved **
** char **module Buffer for the module name **
** char **version Buffer for the module version**
** **
** Result: int 1 Success, value in the buffer **
** is valid **
** 0 Any error, or not found **
** Attached Globals: g_current_module The module which is handled **
** by the current command **
** **
** ************************************************************************ **
++++*/
int VersionLookup( char *name, char **module, char **version)
{
static char buffer[ BUFSIZ];
ModModule *mptr, *mtmp;
ModName *vptr, *vtmp;
ModName **history;
char *s, *t;
int histsize = 0, histndx = 0, i;
/**
** Check whether this is an alias ...
** BTW: Alias lookups return the FQMN (full qualifed module name ;-)
**/
if( '/' == *name) {
strcpy( buffer, g_current_module);
if( (s = strrchr( buffer, '/')) )
*s = '\0';
*module = buffer;
*version = name + 1;
} else {
strcpy( buffer, name);
*module = buffer;
if((char *) NULL == (*version = strrchr( buffer, '/'))) {
if( AliasLookup( buffer, &s, &t)) {
*module = s; *version = t;
} else
*version = _(em_default);
} else
*(*version)++ = '\0';
}
/**
** Look up modulename ...
** We call it success, if we do not find a registered name.
** In this case <module>/<version> will be returned as passed.
**/
if((ModModule *) NULL == (mptr = FindModule( *module, &mtmp))) {
return( 1); /** -------- EXIT (SUCCESS) -------> **/
}
/**
** This is for preventing from endless loops
**/
histsize = HISTTAB;
histndx = 0;
if((ModName **) NULL == (history = (ModName **) module_malloc( histsize *
sizeof( ModName *)))) {
ErrorLogger( ERR_ALLOC, LOC, NULL);
return( 0); /** -------- EXIT (FAILURE) -------> **/
}
/**
** Now look up the version name. Check symbolic names first. If some-
** thing is found, check if the related version record itself relates
** to a name record ...
**/
while( 1) {
/**
** Check the symbolic names ...
**/
if((ModName *) NULL != (vptr = FindName( *version, mptr->name, &vtmp))){
if( !vptr->version || !vptr->version->name) {
if( OK != ErrorLogger( ERR_INTERAL, LOC, NULL))
*version = (char *) NULL;
break;
}
*version = vptr->version->name;
/**
** Prevent from looping ...
**/
for( i=0; i<histndx; i++) {
if( history[ i] == vptr) { /** That's the loop **/
ErrorLogger( ERR_SYMLOOP, LOC, *version, NULL);
*version = (char *) NULL;
break;
}
}
if( !*version)
break;
if( histndx >= histsize) {
histsize += HISTTAB;
if((ModName **) NULL == (history = (ModName **) module_realloc(
history, histsize * sizeof( ModName *)))) {
ErrorLogger( ERR_ALLOC, LOC, NULL);
return( 0); /** -------- EXIT (FAILURE) -------> **/
}
}
history[ histndx++] = vptr;
} else {
break;
} /** if( FindName) **/
} /** while( 1) **/
/**
** Free the loop preventing list
** If version is NULL now, something went wrong in the lookup loop above
**/
null_free((void *) &history);
return((char *) NULL != *version);
} /** End of 'VersionLookup' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: CleanupVersion **
** **
** Description: Cleanup the version structure **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: - **
** **
** Result: - **
** **
** Attached Globals: modlist List containing all version names **
** aliaslist List containing all alises **
** **
** ************************************************************************ **
++++*/
void CleanupVersion(ModModule *ptr)
{
CleanupVersionSub( modlist);
modlist = (ModModule *) NULL;
CleanupName( aliaslist);
aliaslist = (ModName *) NULL;
} /** End of 'CleanupVersion' **/
static void CleanupVersionSub( ModModule *ptr)
{
/**
** Recursion
**/
if( !ptr)
return;
CleanupVersion( ptr->next);
/**
** Cleanup everything that relates to this record
**/
CleanupName( ptr->version);
CleanupName( ptr->name);
null_free((void *) &(ptr->module));
} /** End of 'CleanupVersionSub' **/
static void CleanupName( ModName *ptr)
{
/**
** Recursion
**/
if( !ptr)
return;
CleanupName( ptr->next);
/**
** Cleanup everything that relates to this record
**/
null_free((void *) &(ptr->name));
} /** End of 'CleanupName' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: AddModule **
** **
** Description: Add a new entry to the modules queue **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *name Name of the new module **
** **
** Result: ModModule* NULL Any error **
** Else Pointer to the new record **
** **
** Attached Globals: modlist List containing all version names **
** **
** ************************************************************************ **
++++*/
static ModModule *AddModule( char *name)
{
ModModule *app_ptr, *ptr;
/**
** We do not trust in NULL module names
**/
if( !name || !*name)
return((ModModule *) NULL);
/**
** Check if the module name already exists and save the 'prev' pointer
** for appending the new one.
**/
if( (ptr = FindModule( name, &app_ptr)) )
return( ptr);
/**
** Allocate a new guy
**/
if((ModModule *) NULL ==
(ptr = (ModModule *) module_malloc( sizeof(ModModule)))) {
ErrorLogger( ERR_ALLOC, LOC, NULL);
return((ModModule *) NULL);
}
/**
** Fill the name in and put it in the queue
**/
if((char *) NULL == (ptr->module = stringer(NULL,0, name, NULL))) {
ErrorLogger( ERR_ALLOC, LOC, NULL);
null_free((void *) &ptr);
return((ModModule *) NULL);
}
if( app_ptr) {
ptr->next = app_ptr->next;
app_ptr->next = ptr;
} else {
ptr->next = modlist;
modlist = ptr;
}
ptr->version = (ModName *) NULL;
ptr->name = (ModName *) NULL;
/**
** Pass back the pointer to the new entry
**/
return( ptr);
} /** End of 'AddModule' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: FindModule **
** **
** Description: Find a new entry in the modules queue **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *name Name of be found **
** ModModule **prev Buffer for the 'previous' **
** pointer **
** **
** Result: ModModule* NULL Any error or not found **
** Else Pointer to the record **
** **
** Attached Globals: modlist List containing all version names **
** **
** ************************************************************************ **
++++*/
static ModModule *FindModule( char *name,
ModModule **prev)
{
ModModule *ptr = modlist;
int cmp = 1;
*prev = (ModModule *) NULL;
while( ptr && 0 < (cmp = strcmp( name, ptr->module))) {
*prev = ptr;
ptr = ptr->next;
}
return( cmp ? (ModModule *) NULL : ptr);
} /** End of 'FindModule' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: AddName **
** **
** Description: Add a new entry to the name queue **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *name Name of the new entry **
** ModName **start Start of the queue **
** ModModule *module Parent module record pointer **
** **
** Result: ModName* NULL Any error **
** Else Pointer to the new record **
** **
** ************************************************************************ **
++++*/
static ModName *AddName( char *name,
ModName **start,
ModModule *module)
{
ModName *app_ptr, *ptr;
/**
** Check if the name already exists and save the 'prev' pointer
** for appending the new one.
**/
if( (ptr = FindName( name, *start, &app_ptr)) )
return( ptr);
/**
** Allocate a new guy
**/
if((ModName *) NULL == (ptr = (ModName *) module_malloc(sizeof(ModName)))) {
ErrorLogger( ERR_ALLOC, LOC, NULL);
return((ModName *) NULL);
}
/**
** Fill the name in and put it in the queue
**/
if((char *) NULL == (ptr->name = stringer(NULL,0, name, NULL))) {
ErrorLogger( ERR_ALLOC, LOC, NULL);
null_free((void *) &ptr);
return((ModName *) NULL);
}
if( app_ptr) {
ptr->next = app_ptr->next;
app_ptr->next = ptr;
} else {
ptr->next = *start;
*start = ptr;
}
ptr->module = module;
ptr->version = ptr->ptr = (ModName *) NULL;
/**
** Pass back the pointer to the new entry
**/
return( ptr);
} /** End of 'AddName' **/
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: FindName **
** **
** Description: Find a new entry in the modules queue **
** **
** First Edition: 1995/12/28 **
** **
** Parameters: char *name Name of be found **
** ModName *start Start of the name queue **
** ModName **prev Buffer for the 'previous' **
** pointer **
** **
** Result: ModName* NULL Any error or not found **
** Else Pointer to the record **
** **
** ************************************************************************ **
++++*/
static ModName *FindName( char *name,
ModName *start,
ModName **prev)
{
ModName *ptr = start;
int cmp = 1;
*prev = (ModName *) NULL;
while( ptr && 0 < (cmp = strcmp( name, ptr->name))) {
*prev = ptr;
ptr = ptr->next;
}
return( cmp ? (ModName *) NULL : ptr);
} /** End of 'FindName' **/