Blame tools/rea.c

Packit 022b05
/*
Packit 022b05
 * rea.c --
Packit 022b05
 *
Packit 022b05
 *      This file holds the reverse engineering algorithm common for
Packit 022b05
 *      dump-cm.c and dump-svg.c.
Packit 022b05
 *
Packit 022b05
 * Copyright (c) 2000 A. Mueller, Technical University of Braunschweig.
Packit 022b05
 * Copyright (c) 2005 K. Sperner, Technical University of Braunschweig.
Packit 022b05
 *
Packit 022b05
 * See the file "COPYING" for information on usage and redistribution
Packit 022b05
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Packit 022b05
 *
Packit 022b05
 * @(#) $Id: rea.c 7823 2008-03-01 13:53:12Z schoenw $
Packit 022b05
 */
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
#include <config.h>
Packit 022b05
Packit 022b05
#include <stdio.h>
Packit 022b05
#include <stdlib.h>
Packit 022b05
#include <string.h>
Packit 022b05
#include <ctype.h>
Packit 022b05
#ifdef HAVE_WIN_H
Packit 022b05
#include "win.h"
Packit 022b05
#endif
Packit 022b05
Packit 022b05
#include "smi.h"
Packit 022b05
#include "smidump.h"
Packit 022b05
#include "rea.h"
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * Constants used by the reverse engineering algorithm.
Packit 022b05
 */
Packit 022b05
Packit 022b05
static char *pointer[] = {
Packit 022b05
    "Index", NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
static char *suffix[] = {
Packit 022b05
    "OrZero", NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
static char *supportObjs[] = {
Packit 022b05
    "RowStatus", "StorageType", NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
static char *baseTypes[] = {
Packit 022b05
    "Integer32", "OctetString", "Unsigned32", "Integer64",
Packit 022b05
    "Unsigned64", "Float32", "Float64", "Float128",
Packit 022b05
    "Enumeration", "Counter32", "Counter64","Bits",
Packit 022b05
    "Gauge", "Gauge32", "Integer", "TimeTicks",
Packit 022b05
    "IpAddress", "Opaque", "ObjectIdentifier",
Packit 022b05
    NULL
Packit 022b05
};
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * driver output control
Packit 022b05
 */
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * variables for svg-output
Packit 022b05
 *
Packit 022b05
 * When you change CANVASHEIGHT, CANVASWIDTH values here, you should
Packit 022b05
 * also change them in initSvg() and the cgi-script.
Packit 022b05
 */
Packit 022b05
Packit 022b05
int       CANVASHEIGHT          = 700; /* height of the svg */
Packit 022b05
int       CANVASWIDTH           = 1100; /* width of the svg */
Packit 022b05
int       SHOW_DEPRECATED       = 0; /* false, show deprecated objects */
Packit 022b05
int       SHOW_DEPR_OBSOLETE    = 0; /* false, show deprecated and
Packit 022b05
					obsolete objects */
Packit 022b05
int       STATIC_OUTPUT         = 0; /* false, enable interactivity */
Packit 022b05
/* variables for cm-driver */
Packit 022b05
int       XPLAIN                = 0; /* false, generates ASCII output */
Packit 022b05
int       XPLAIN_DEBUG          = 0; /* false, generates additional
Packit 022b05
					       output in xplain-mode */
Packit 022b05
int       SUPPRESS_DEPRECATED   = 1; /* true, suppresses deprecated
Packit 022b05
					       objects */
Packit 022b05
/* common variables */
Packit 022b05
int       PRINT_DETAILED_ATTR   = 1; /* true, prints all column
Packit 022b05
					       objects */
Packit 022b05
int       IGNORE_IMPORTED_NODES = 1; /* true, ignores nodes which are
Packit 022b05
					       imported from other MIBs*/
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * global variables
Packit 022b05
 */
Packit 022b05
Graph     *graph  = NULL;            /* the graph */
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/* ------ Misc. -----------------                                            */
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * cmpSmiNodes
Packit 022b05
 *
Packit 022b05
 * Compares two SmiNode and returns 1 if they are equal and 0 otherwise.
Packit 022b05
 */
Packit 022b05
int cmpSmiNodes(SmiNode *node1, SmiNode *node2)
Packit 022b05
{
Packit 022b05
    SmiModule *module1, *module2;
Packit 022b05
Packit 022b05
    module1 = smiGetNodeModule(node1);
Packit 022b05
    module2 = smiGetNodeModule(node2);
Packit 022b05
    
Packit 022b05
    if (!node1 || !node2 || !module1 || !module2) return 0;
Packit 022b05
    
Packit 022b05
    return (strcmp(node1->name, node2->name) == 0 &&
Packit 022b05
	    strcmp(module1->name, module2->name) == 0);
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * strpfxlen
Packit 022b05
 *
Packit 022b05
 * Returns the number of identical characters at the beginning of s1 and s2.
Packit 022b05
 */
Packit 022b05
static int strpfxlen(const char *s1, const char *s2)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
Packit 022b05
    for (i = 0; s1[i] && s2[i]; i++) {
Packit 022b05
	if (s1[i] != s2[i]) {
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    return i;
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/* ------ Graph primitives ------                                            */
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphInsertNode
Packit 022b05
 *
Packit 022b05
 *          Inserts a new node into an existing graph.
Packit 022b05
 *
Packit 022b05
 * Result : pointer to the new node
Packit 022b05
 */
Packit 022b05
GraphNode *graphInsertNode(Graph *graph, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    GraphNode *newNode;
Packit 022b05
    GraphNode *tNode;
Packit 022b05
    GraphNode *lastNode;
Packit 022b05
Packit 022b05
    newNode = xmalloc(sizeof(GraphNode));
Packit 022b05
    memset(newNode, 0, sizeof(GraphNode));
Packit 022b05
    newNode->smiNode = smiNode;
Packit 022b05
Packit 022b05
    if (graph->nodes == NULL) {
Packit 022b05
	graph->nodes = newNode;
Packit 022b05
	return newNode;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    lastNode = NULL; 
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	lastNode = tNode;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    lastNode->nextPtr = newNode;
Packit 022b05
Packit 022b05
    return newNode;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphInsertComponent
Packit 022b05
 *
Packit 022b05
 *          Inserts a new component into an existing graph.
Packit 022b05
 *
Packit 022b05
 * Result : pointer to the new component
Packit 022b05
 */
Packit 022b05
GraphComponent *graphInsertComponent(Graph *graph)
Packit 022b05
{
Packit 022b05
    GraphComponent *newComponent;
Packit 022b05
    GraphComponent *tComponent;
Packit 022b05
    GraphComponent *lastComponent;
Packit 022b05
Packit 022b05
    newComponent = xmalloc(sizeof(GraphComponent));
Packit 022b05
    memset(newComponent, 0, sizeof(GraphComponent));
Packit 022b05
Packit 022b05
    if (graph->components == NULL) {
Packit 022b05
	graph->components = newComponent;
Packit 022b05
	return newComponent;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    lastComponent = NULL;
Packit 022b05
    for (tComponent = graph->components; tComponent;
Packit 022b05
					    tComponent = tComponent->nextPtr) {
Packit 022b05
	lastComponent = tComponent;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    lastComponent->nextPtr = newComponent;
Packit 022b05
Packit 022b05
    return newComponent;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphInsertEdge
Packit 022b05
 *
Packit 022b05
 *          Inserts a new edge into an existing list of edges.
Packit 022b05
 *
Packit 022b05
 * Input  : graph     = pointer to an edge structure
Packit 022b05
 *          startNode = pointer to the starting node of the edge
Packit 022b05
 *          endNode   = pointer to the ending node of the edge
Packit 022b05
 *          indexkind = type of relationship between the two nodes
Packit 022b05
 *
Packit 022b05
 * Result : pointer to the new edge
Packit 022b05
 */
Packit 022b05
static GraphEdge *graphInsertEdge(Graph *graph, GraphNode *startNode,
Packit 022b05
			      GraphNode *endNode,
Packit 022b05
			      SmiIndexkind indexkind,
Packit 022b05
			      GraphEnhIndex enhancedindex)
Packit 022b05
{
Packit 022b05
    GraphEdge *newEdge;
Packit 022b05
    GraphEdge *tEdge;
Packit 022b05
    GraphEdge *lastEdge;
Packit 022b05
Packit 022b05
    newEdge = xmalloc(sizeof(GraphEdge));
Packit 022b05
    memset(newEdge, 0, sizeof(GraphEdge));
Packit 022b05
    newEdge->startNode = startNode;
Packit 022b05
    newEdge->endNode = endNode;
Packit 022b05
    newEdge->indexkind = indexkind;
Packit 022b05
    newEdge->connection = GRAPH_CON_ASSOCIATION;
Packit 022b05
    newEdge->enhancedindex = enhancedindex;
Packit 022b05
Packit 022b05
    switch (newEdge->indexkind) {
Packit 022b05
    case SMI_INDEX_AUGMENT : 
Packit 022b05
	newEdge->cardinality = GRAPH_CARD_ONE_TO_ONE; 
Packit 022b05
	break;
Packit 022b05
    case SMI_INDEX_SPARSE  : 
Packit 022b05
	newEdge->cardinality = GRAPH_CARD_ONE_TO_ZERO_OR_ONE; 
Packit 022b05
	break;
Packit 022b05
    case SMI_INDEX_EXPAND  : 
Packit 022b05
	newEdge->cardinality = GRAPH_CARD_UNKNOWN; 
Packit 022b05
	break;
Packit 022b05
    case SMI_INDEX_REORDER : 
Packit 022b05
	newEdge->cardinality = GRAPH_CARD_ONE_TO_ONE; 
Packit 022b05
	break;
Packit 022b05
    case SMI_INDEX_INDEX   : 
Packit 022b05
	newEdge->cardinality = GRAPH_CARD_UNKNOWN; 
Packit 022b05
	break;
Packit 022b05
    case SMI_INDEX_UNKNOWN : 
Packit 022b05
	newEdge->cardinality = GRAPH_CARD_UNKNOWN; 
Packit 022b05
	break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (graph->edges == NULL) {
Packit 022b05
	graph->edges = newEdge;
Packit 022b05
	return newEdge;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    lastEdge = NULL; 
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
	lastEdge = tEdge;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    lastEdge->nextPtr = newEdge;
Packit 022b05
Packit 022b05
    return newEdge;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphExit
Packit 022b05
 *
Packit 022b05
 * Frees all memory allocated by the graph.
Packit 022b05
 */
Packit 022b05
void graphExit(Graph *graph)
Packit 022b05
{
Packit 022b05
    GraphEdge *tEdge, *dummyEdge;
Packit 022b05
    GraphNode *tNode, *dummyNode;
Packit 022b05
    GraphComponent *tComponent, *dummyComponent;
Packit 022b05
Packit 022b05
    if (graph) {
Packit 022b05
Packit 022b05
	dummyNode = NULL;
Packit 022b05
	tNode = graph->nodes;
Packit 022b05
	while (tNode != NULL) {
Packit 022b05
	    dummyNode = tNode;
Packit 022b05
	    tNode = tNode->nextPtr;
Packit 022b05
      
Packit 022b05
	    xfree(dummyNode);
Packit 022b05
	}
Packit 022b05
    
Packit 022b05
	dummyEdge = NULL;
Packit 022b05
	tEdge = graph->edges;
Packit 022b05
	while (tEdge != NULL) {
Packit 022b05
	    dummyEdge = tEdge;
Packit 022b05
	    tEdge = tEdge->nextPtr;
Packit 022b05
      
Packit 022b05
	    xfree(dummyEdge);
Packit 022b05
	}
Packit 022b05
    
Packit 022b05
	dummyComponent = NULL;
Packit 022b05
	tComponent = graph->components;
Packit 022b05
	while (tComponent != NULL) {
Packit 022b05
	    dummyComponent = tComponent;
Packit 022b05
	    tComponent = tComponent->nextPtr;
Packit 022b05
      
Packit 022b05
	    xfree(dummyComponent);
Packit 022b05
	}
Packit 022b05
    
Packit 022b05
	xfree(graph);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphGetFirstEdgeByNode
Packit 022b05
 *
Packit 022b05
 * Returns the first edge adjacent to the given node (as startNode or EndNode).
Packit 022b05
 */
Packit 022b05
GraphEdge *graphGetFirstEdgeByNode(Graph *graph, GraphNode *node)
Packit 022b05
{
Packit 022b05
    GraphEdge *tEdge;
Packit 022b05
Packit 022b05
    if (!graph || !node) {
Packit 022b05
	return NULL;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
	/*if (tEdge->startNode->smiNode->name == node->smiNode->name ||
Packit 022b05
	  tEdge->endNode->smiNode->name == node->smiNode->name) break;*/
Packit 022b05
	if (cmpSmiNodes(tEdge->startNode->smiNode, node->smiNode) ||
Packit 022b05
	    cmpSmiNodes(tEdge->endNode->smiNode, node->smiNode)) break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return tEdge;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphGetNextEdgeByNode
Packit 022b05
 *
Packit 022b05
 * Returns the next edge adjacent to the given node (as startNode or EndNode)
Packit 022b05
 * after the given edge.
Packit 022b05
 */
Packit 022b05
GraphEdge *graphGetNextEdgeByNode(Graph *graph, 
Packit 022b05
					 GraphEdge *edge,
Packit 022b05
					 GraphNode *node) 
Packit 022b05
{
Packit 022b05
    GraphEdge *tEdge;
Packit 022b05
Packit 022b05
    if (!graph || !node) {
Packit 022b05
	return NULL;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
	/*if (tEdge->startNode->smiNode->name ==
Packit 022b05
	    edge->startNode->smiNode->name &&
Packit 022b05
	    tEdge->endNode->smiNode->name ==
Packit 022b05
	    edge->endNode->smiNode->name) break;*/
Packit 022b05
	if (cmpSmiNodes(tEdge->startNode->smiNode,edge->startNode->smiNode) &&
Packit 022b05
	    cmpSmiNodes(tEdge->endNode->smiNode,edge->endNode->smiNode))
Packit 022b05
	    break;
Packit 022b05
    }
Packit 022b05
  
Packit 022b05
    for (tEdge = tEdge->nextPtr; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
	/*if (tEdge->startNode->smiNode->name == node->smiNode->name ||
Packit 022b05
	  tEdge->endNode->smiNode->name == node->smiNode->name) break;*/
Packit 022b05
	if (cmpSmiNodes(tEdge->startNode->smiNode, node->smiNode) ||
Packit 022b05
	    cmpSmiNodes(tEdge->endNode->smiNode, node->smiNode)) break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return tEdge;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphCheckForRedundantEdge
Packit 022b05
 *
Packit 022b05
 * Finds redundant edges and returns 1 if one is found and 0 otherwise.
Packit 022b05
 */
Packit 022b05
static int graphCheckForRedundantEdge(Graph *graph,
Packit 022b05
			       GraphNode *startNode,
Packit 022b05
			       GraphNode *endNode)
Packit 022b05
{
Packit 022b05
    GraphEdge *tEdge;
Packit 022b05
Packit 022b05
    if (!graph || !startNode || !endNode) {
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
	/*if (tEdge->startNode->smiNode->name == startNode->smiNode->name &&
Packit 022b05
	  tEdge->endNode->smiNode->name == endNode->smiNode->name) {*/
Packit 022b05
	if (cmpSmiNodes(tEdge->startNode->smiNode, startNode->smiNode) &&
Packit 022b05
	    cmpSmiNodes(tEdge->endNode->smiNode, endNode->smiNode)) {
Packit 022b05
	    
Packit 022b05
	    return 1;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphGetNode
Packit 022b05
 *
Packit 022b05
 * Returns the graph node containing smiNode.
Packit 022b05
 */
Packit 022b05
static GraphNode *graphGetNode(Graph *graph, SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
Packit 022b05
    if (!smiNode || !graph) {
Packit 022b05
	return NULL;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->smiNode->name == smiNode->name) {
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return tNode;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphShowNodes
Packit 022b05
 *
Packit 022b05
 * Prints the nodes of the graph.
Packit 022b05
 */
Packit 022b05
void graphShowNodes(Graph *graph) 
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
  
Packit 022b05
    if (!graph->nodes) {
Packit 022b05
	printf("No nodes!\n");
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE)
Packit 022b05
	    printf(" [TABLE]");
Packit 022b05
	else printf("[SCALAR]");
Packit 022b05
	printf("%40s [%s]\n", tNode->smiNode->name,
Packit 022b05
	       smiGetNodeModule(tNode->smiNode)->name);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * graphShowEdges
Packit 022b05
 *
Packit 022b05
 * Prints the edges with their attributes in the following order :
Packit 022b05
 *    - start node
Packit 022b05
 *    - reason for the link
Packit 022b05
 *    - connection type in UML
Packit 022b05
 *    - cardinality
Packit 022b05
 *    - index relationship derived from the row-objects of the tables
Packit 022b05
 *
Packit 022b05
 */
Packit 022b05
static void graphShowEdges(Graph *graph) 
Packit 022b05
{
Packit 022b05
    GraphEdge  *tEdge;
Packit 022b05
    
Packit 022b05
    if (!graph->edges) {
Packit 022b05
	printf("No edges!\n");
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
  
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
Packit 022b05
	if (XPLAIN_DEBUG) {
Packit 022b05
	    switch (tEdge->enhancedindex) {
Packit 022b05
	    case GRAPH_ENHINDEX_UNKNOWN :
Packit 022b05
		printf("[UNKNOWN] ");
Packit 022b05
		break;
Packit 022b05
	    case GRAPH_ENHINDEX_NOTIFICATION :
Packit 022b05
		break;
Packit 022b05
	    case GRAPH_ENHINDEX_NAMES :
Packit 022b05
		printf("  [NAMES] ");
Packit 022b05
		break;
Packit 022b05
	    case GRAPH_ENHINDEX_TYPES :
Packit 022b05
		printf("  [TYPES] ");
Packit 022b05
		break;
Packit 022b05
	    case GRAPH_ENHINDEX_INDEX :
Packit 022b05
		printf("  [INDEX] ");
Packit 022b05
		break;
Packit 022b05
	    case GRAPH_ENHINDEX_REROUTE :
Packit 022b05
		printf("[REROUTE] ");
Packit 022b05
		break;
Packit 022b05
	    case GRAPH_ENHINDEX_POINTER :
Packit 022b05
		printf("[POINTER] ");
Packit 022b05
		break;	    
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	switch (tEdge->connection) {
Packit 022b05
	case GRAPH_CON_AGGREGATION:
Packit 022b05
	    printf("AG.");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CON_DEPENDENCY:
Packit 022b05
	    printf("D. ");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CON_ASSOCIATION:
Packit 022b05
	    printf("A. ");
Packit 022b05
	    break;    
Packit 022b05
	case GRAPH_CON_UNKNOWN:
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
Packit 022b05
	switch (tEdge->cardinality) {
Packit 022b05
	case GRAPH_CARD_UNKNOWN      :
Packit 022b05
	    printf("  (-:-)  ");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CARD_ONE_TO_ONE   :
Packit 022b05
	    printf("  (1:1)  ");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CARD_ONE_TO_MANY  :
Packit 022b05
	    printf("  (1:n)  ");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CARD_ZERO_TO_ONE  :
Packit 022b05
	    printf("  (0:1)  ");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CARD_ZERO_TO_MANY :
Packit 022b05
	    printf("  (0:n)  ");
Packit 022b05
	    break;
Packit 022b05
	case GRAPH_CARD_ONE_TO_ZERO_OR_ONE :
Packit 022b05
	    printf("(1:0..1) ");
Packit 022b05
	    break;	    
Packit 022b05
	}
Packit 022b05
Packit 022b05
	switch (tEdge->indexkind) {
Packit 022b05
	case SMI_INDEX_UNKNOWN  :
Packit 022b05
	    printf("GENERIC ");
Packit 022b05
	    break;
Packit 022b05
	case SMI_INDEX_INDEX    :
Packit 022b05
	    printf("  INDEX ");
Packit 022b05
	    break;
Packit 022b05
	case SMI_INDEX_AUGMENT  :
Packit 022b05
	    printf("AUGMENT ");
Packit 022b05
	    break;
Packit 022b05
	case SMI_INDEX_SPARSE   :
Packit 022b05
	    printf(" SPARSE ");
Packit 022b05
	    break;
Packit 022b05
	case SMI_INDEX_EXPAND   :
Packit 022b05
	    printf(" EXPAND ");
Packit 022b05
	    break;
Packit 022b05
	case SMI_INDEX_REORDER  :
Packit 022b05
	    printf("REORDER ");
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
	printf("%29s - ",tEdge->startNode->smiNode->name);
Packit 022b05
	printf("%s\n",tEdge->endNode->smiNode->name);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/* ------ algorithm primitives ------                                        */
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCountIndexElements
Packit 022b05
 *
Packit 022b05
 * Returns the number of index elements in a given row entry.
Packit 022b05
 */
Packit 022b05
Packit 022b05
static int algCountIndexElements(SmiNode *smiNode) 
Packit 022b05
{
Packit 022b05
    int          count;
Packit 022b05
    SmiElement   *smiElement;
Packit 022b05
Packit 022b05
    if (smiNode->nodekind != SMI_NODEKIND_ROW) {
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    count = 0;
Packit 022b05
    for (smiElement = smiGetFirstElement(smiNode);
Packit 022b05
	 smiElement;
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	count++;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return count;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algInsertEdge
Packit 022b05
 *
Packit 022b05
 * Inserts an edge in a given graph. The edge is adjacent to snode 
Packit 022b05
 * and enode.
Packit 022b05
 * The type of edge is given in indexkind and the enhanced index as
Packit 022b05
 * an additional information in enhancedindex.
Packit 022b05
 * Nodes which are not loaded yet into the node list of the graph
Packit 022b05
 * are added (nodes from imported MIBs).
Packit 022b05
 */
Packit 022b05
static void algInsertEdge(SmiNode *snode, SmiNode *enode, 
Packit 022b05
			  SmiIndexkind indexkind,
Packit 022b05
			  GraphEnhIndex enhancedindex) 
Packit 022b05
{
Packit 022b05
    GraphNode *startNode;
Packit 022b05
    GraphNode *endNode;
Packit 022b05
Packit 022b05
    if (!graph) return;
Packit 022b05
Packit 022b05
    startNode = graphGetNode(graph, snode);
Packit 022b05
    endNode   = graphGetNode(graph, enode);
Packit 022b05
Packit 022b05
    /* insert imported nodes into graph if needed */
Packit 022b05
    if (startNode == NULL) {
Packit 022b05
	if (IGNORE_IMPORTED_NODES) return;
Packit 022b05
	
Packit 022b05
	startNode = graphInsertNode(graph, snode);
Packit 022b05
    }
Packit 022b05
    if (endNode == NULL) {
Packit 022b05
	if (IGNORE_IMPORTED_NODES) return;
Packit 022b05
	
Packit 022b05
	endNode = graphInsertNode(graph, enode);
Packit 022b05
    }  
Packit 022b05
Packit 022b05
    if (graphCheckForRedundantEdge(graph, startNode, endNode) == 0 &&
Packit 022b05
	graphCheckForRedundantEdge(graph, endNode, startNode) == 0) {
Packit 022b05
	graphInsertEdge(graph, startNode, endNode, indexkind, enhancedindex); 
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetGroupByFatherNode
Packit 022b05
 *
Packit 022b05
 * Returns the group number associated with the father node of the
Packit 022b05
 * given node. If there is no group the result is 0 for no
Packit 022b05
 * grouping.
Packit 022b05
 */
Packit 022b05
static int algGetGroupByFatherNode(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
    
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
Packit 022b05
	    !graphGetFirstEdgeByNode(graph, tNode)) {
Packit 022b05
	    if (cmpSmiNodes(smiGetParentNode(smiNode),
Packit 022b05
			    smiGetParentNode(tNode->smiNode))) {
Packit 022b05
		return tNode->group;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetNumberOfGroups
Packit 022b05
 *
Packit 022b05
 * Returns the number of groups.
Packit 022b05
 */
Packit 022b05
int algGetNumberOfGroups()
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
    int       maxGroup;
Packit 022b05
Packit 022b05
    maxGroup = 0;
Packit 022b05
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	maxGroup = max(maxGroup, tNode->group); 
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return maxGroup;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algPrintGroup
Packit 022b05
 *
Packit 022b05
 * Prints the group with the number group.
Packit 022b05
 */
Packit 022b05
static void algPrintGroup(int group)
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
    
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->group == group) {
Packit 022b05
	    printf("%2d - %35s\n", group, tNode->smiNode->name);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetTypeDescription
Packit 022b05
 *
Packit 022b05
 * Returns the description of the data type used in smiNode.
Packit 022b05
 */
Packit 022b05
char *algGetTypeDescription(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiType *smiType, *parentType;
Packit 022b05
  
Packit 022b05
    smiType = smiGetNodeType(smiNode);
Packit 022b05
  
Packit 022b05
    if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
Packit 022b05
	return NULL;
Packit 022b05
  
Packit 022b05
    if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
Packit 022b05
	parentType = smiGetParentType(smiType);
Packit 022b05
	smiType = parentType;
Packit 022b05
    }
Packit 022b05
  
Packit 022b05
    return smiType->description;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetTypeName
Packit 022b05
 *
Packit 022b05
 * Returns the name of the data type used in smiNode.
Packit 022b05
 */
Packit 022b05
char *algGetTypeName(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiType *smiType, *parentType;
Packit 022b05
  
Packit 022b05
    smiType = smiGetNodeType(smiNode);
Packit 022b05
  
Packit 022b05
    if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
Packit 022b05
	return NULL;
Packit 022b05
  
Packit 022b05
    if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
Packit 022b05
	parentType = smiGetParentType(smiType);
Packit 022b05
	smiType = parentType;
Packit 022b05
    }
Packit 022b05
  
Packit 022b05
    return smiType->name;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetTypeModule
Packit 022b05
 *
Packit 022b05
 * Returns the module which defines the data type used in smiNode.
Packit 022b05
 */
Packit 022b05
SmiModule *algGetTypeModule(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiType *smiType, *parentType;
Packit 022b05
    SmiModule *smiModule;
Packit 022b05
  
Packit 022b05
    smiType = smiGetNodeType(smiNode);
Packit 022b05
  
Packit 022b05
    if (!smiType || smiNode->nodekind == SMI_NODEKIND_TABLE)
Packit 022b05
	return NULL;
Packit 022b05
  
Packit 022b05
    if (smiType->decl == SMI_DECL_IMPLICIT_TYPE) {
Packit 022b05
	parentType = smiGetParentType(smiType);
Packit 022b05
	smiType = parentType;
Packit 022b05
    }
Packit 022b05
  
Packit 022b05
    smiModule = smiGetTypeModule(smiType);
Packit 022b05
Packit 022b05
    return smiModule;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCountElementsFromOtherTables
Packit 022b05
 *
Packit 022b05
 * Returns the number of index objects derived from other tables than
Packit 022b05
 * the given one.
Packit 022b05
 */
Packit 022b05
static int algCountElementsFromOtherTables(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    SmiNode    *tNode;
Packit 022b05
    int        elems = 0;
Packit 022b05
    
Packit 022b05
    for (smiElement = smiGetFirstElement(smiNode);
Packit 022b05
	 smiElement;
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
Packit 022b05
	tNode = smiGetElementNode(smiElement);
Packit 022b05
	
Packit 022b05
	if (cmpSmiNodes(smiGetParentNode(smiGetParentNode(tNode)),
Packit 022b05
			smiGetParentNode(smiNode)) != 1) {
Packit 022b05
	    elems++;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return elems;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetNumberOfRows
Packit 022b05
 *
Packit 022b05
 * Returns the number of rows =
Packit 022b05
 *   number of elements in smiNode - number of rows 
Packit 022b05
 *   + RowStatus-Objects + StorageType-Objects
Packit 022b05
 *
Packit 022b05
 * If the number is > 0 it is only a supporting table (like entLPMappingTable) 
Packit 022b05
 * and if the number is < 0 it is a "full" table (like ifTable).
Packit 022b05
 *
Packit 022b05
 * Subroutine for algCheckForDependency.
Packit 022b05
 */
Packit 022b05
static int algGetNumberOfRows(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode *tSmiNode;
Packit 022b05
    SmiNode *table;
Packit 022b05
    int     i, elemCount;
Packit 022b05
Packit 022b05
    elemCount = 0;
Packit 022b05
    table = smiNode;
Packit 022b05
    tSmiNode = smiGetFirstChildNode(table);
Packit 022b05
Packit 022b05
    elemCount = algCountIndexElements(tSmiNode) -
Packit 022b05
	algCountElementsFromOtherTables(tSmiNode);
Packit 022b05
Packit 022b05
    for (tSmiNode = smiGetNextNode(tSmiNode, SMI_NODEKIND_COLUMN);
Packit 022b05
	 tSmiNode;
Packit 022b05
	 tSmiNode = smiGetNextNode(tSmiNode, SMI_NODEKIND_COLUMN)) {
Packit 022b05
Packit 022b05
	if (cmpSmiNodes(table, smiGetParentNode(smiGetParentNode(tSmiNode)))
Packit 022b05
	    != 1) {
Packit 022b05
	    break;
Packit 022b05
	}
Packit 022b05
	
Packit 022b05
	for (i = 0; supportObjs[i]; i++) {
Packit 022b05
	    char *typeName = algGetTypeName(tSmiNode);
Packit 022b05
	    if (typeName && (strcasecmp(typeName, supportObjs[i]) == 0)) {
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
Packit 022b05
	if (!supportObjs[i]) elemCount--;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return elemCount;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * isBaseType
Packit 022b05
 *
Packit 022b05
 * returns 1 if smiElement is a basetype used in SMIv2/SMIng. Otherwise
Packit 022b05
 * the result is 0.
Packit 022b05
 */
Packit 022b05
int isBaseType(SmiNode *node)
Packit 022b05
{
Packit 022b05
    int i;
Packit 022b05
Packit 022b05
    for (i = 0; baseTypes[i]; i++) {
Packit 022b05
	if (strcasecmp(algGetTypeName(node), baseTypes[i]) == 0) {
Packit 022b05
	    return 1;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algFindEqualType
Packit 022b05
 *
Packit 022b05
 * Looks in all tables indices for an equal type to the type used in typeNode.
Packit 022b05
 * It returns the first table found which is different to startTable.
Packit 022b05
 *
Packit 022b05
 * Subroutine for algCheckForDependency. 
Packit 022b05
 */
Packit 022b05
static SmiNode *algFindEqualType(SmiNode *startTable, SmiNode *typeNode)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    SmiNode    *tSmiNode;
Packit 022b05
    char       *typeName;
Packit 022b05
    GraphNode  *tNode;
Packit 022b05
    
Packit 022b05
    typeName = algGetTypeName(typeNode);
Packit 022b05
    /* if (isBaseType(typeNode)) return NULL; */
Packit 022b05
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
Packit 022b05
	    tSmiNode = tNode->smiNode;
Packit 022b05
	    if (cmpSmiNodes(tSmiNode, startTable) == 1) break;
Packit 022b05
	    
Packit 022b05
	    for (smiElement = smiGetFirstElement(
Packit 022b05
		smiGetFirstChildNode(tSmiNode));
Packit 022b05
		 smiElement;
Packit 022b05
		 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
		/* found type matching ? */
Packit 022b05
		if (strcmp(typeName,
Packit 022b05
			       algGetTypeName(smiGetElementNode
Packit 022b05
					      (smiElement))) == 0) {
Packit 022b05
		    return tSmiNode;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	    
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    return NULL;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * 0 = totaly equal (order and objects)
Packit 022b05
 * 1 = equal objects but different order
Packit 022b05
 * 2 = inequal
Packit 022b05
 * 3 = error;
Packit 022b05
 */
Packit 022b05
 static int equalElements(SmiNode *firstRow, SmiNode *secondRow)
Packit 022b05
{
Packit 022b05
    int i,j,number1, number2;
Packit 022b05
    SmiElement *elemFirst, *elemSecond;
Packit 022b05
Packit 022b05
    if (!firstRow->nodekind == SMI_NODEKIND_ROW ||
Packit 022b05
	!secondRow->nodekind == SMI_NODEKIND_ROW) {
Packit 022b05
	/* printf("no row entries\n"); */
Packit 022b05
	return 3;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (cmpSmiNodes(firstRow, secondRow) == 1) {
Packit 022b05
	/* printf("same objects\n"); */
Packit 022b05
	return 3;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    number1 = algCountIndexElements(firstRow);
Packit 022b05
    number2 = algCountIndexElements(secondRow);
Packit 022b05
Packit 022b05
    if (number1 != number2) {
Packit 022b05
	/* printf("Different number of elements\n"); */
Packit 022b05
	return 2;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    i = 0;
Packit 022b05
    for (elemFirst = smiGetFirstElement(firstRow);
Packit 022b05
	 elemFirst;
Packit 022b05
	 elemFirst = smiGetNextElement(elemFirst)) {
Packit 022b05
	i++;
Packit 022b05
Packit 022b05
	j = 0;
Packit 022b05
	for (elemSecond = smiGetFirstElement(secondRow);
Packit 022b05
	     elemSecond;
Packit 022b05
	     elemSecond = smiGetNextElement(elemSecond)) {
Packit 022b05
	    j++;
Packit 022b05
	    if (i == j && cmpSmiNodes(smiGetElementNode(elemFirst),
Packit 022b05
				      smiGetElementNode(elemSecond)) == 1) {
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
Packit 022b05
	/* maybe same elements but in different order */
Packit 022b05
	if (!elemSecond) break;
Packit 022b05
    }
Packit 022b05
    if (!elemFirst) {
Packit 022b05
	/* printf("totaly equal\n"); */
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (elemFirst = smiGetFirstElement(firstRow);
Packit 022b05
	 elemFirst;
Packit 022b05
	 elemFirst = smiGetNextElement(elemFirst)) {
Packit 022b05
Packit 022b05
	for (elemSecond = smiGetFirstElement(secondRow);
Packit 022b05
	     elemSecond;
Packit 022b05
	     elemSecond = smiGetNextElement(elemSecond)) {
Packit 022b05
Packit 022b05
	    if (cmpSmiNodes(smiGetElementNode(elemFirst),
Packit 022b05
			    smiGetElementNode(elemSecond)) == 1) {
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
Packit 022b05
	/* maybe same elements but in different order */
Packit 022b05
	if (!elemSecond) break;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (!elemFirst) {
Packit 022b05
	/* printf("Equal\n"); */
Packit 022b05
	return 1;
Packit 022b05
    }
Packit 022b05
    else {
Packit 022b05
	/* printf("inequal"); */
Packit 022b05
	return 2;
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algIsIndexElement
Packit 022b05
 *
Packit 022b05
 * Tests whether a given node is part of the index of a particular
Packit 022b05
 * table. Returns 1 if the node is an index node and 0 otherwise.
Packit 022b05
 */
Packit 022b05
Packit 022b05
int algIsIndexElement(SmiNode *table, SmiNode *node)
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    SmiNode    *row;
Packit 022b05
Packit 022b05
    if (node->nodekind != SMI_NODEKIND_TABLE) {
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    row = smiGetFirstChildNode(table);
Packit 022b05
    if (!row || row->nodekind != SMI_NODEKIND_ROW) {
Packit 022b05
	return 0;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    for (smiElement = smiGetFirstElement(row);
Packit 022b05
	 smiElement;
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	SmiNode *indexNode = smiGetElementNode(smiElement);
Packit 022b05
	if (cmpSmiNodes(indexNode, node)) {
Packit 022b05
	    return 1;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
/* -------------- main functions ------------------------------------------- */
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCheckForExpandRel
Packit 022b05
 *
Packit 022b05
 * Checks the given table for an expand relationship to an other table.
Packit 022b05
 *
Packit 022b05
 * 1. gets the expanded table (father node of smiNode)
Packit 022b05
 * 2. gets the base table by walking through the elements of the smiNode
Packit 022b05
 *    starting at the end. The first table found which is different from the
Packit 022b05
 *    expanded table is the first candidate for the base table.
Packit 022b05
 * 3. comparing the number of elements in both tables
Packit 022b05
 *    if the number in the expanded table is greater -> 5.
Packit 022b05
 *    if the number in the base table is greater     -> 4.
Packit 022b05
 * 4. getting a second base table candidate :
Packit 022b05
 *    It is possible that a table expands an other table which is expanded
Packit 022b05
 *    by this.
Packit 022b05
 *    Therefore it is hard to track the base table.
Packit 022b05
 *    - scanning all tables which are different from the expanded table
Packit 022b05
 *    - the base table must have :
Packit 022b05
 *         - least elements
Packit 022b05
 *         - the same elementes must occur as in the expanded table
Packit 022b05
 * 5. the elements in both tables are checked for equality 
Packit 022b05
 */
Packit 022b05
static void algCheckForExpandRel(SmiNode *smiNode) 
Packit 022b05
{
Packit 022b05
    SmiNode      *tNode;
Packit 022b05
    SmiNode      *baseTable;
Packit 022b05
    SmiNode      *expTable;
Packit 022b05
    SmiElement   *smiElement;
Packit 022b05
    SmiElement   *findElement;
Packit 022b05
    unsigned int refcounter;
Packit 022b05
    unsigned int basecounter;
Packit 022b05
Packit 022b05
    if (!smiNode) return;
Packit 022b05
Packit 022b05
    expTable = smiGetParentNode(smiNode);  
Packit 022b05
Packit 022b05
    /* count the elements in the given table <- father of smiNode */
Packit 022b05
    refcounter = algCountIndexElements(smiNode);
Packit 022b05
Packit 022b05
    /* find the base table <- via the last element which does not refer to 
Packit 022b05
       the expTable */
Packit 022b05
    baseTable = NULL;
Packit 022b05
    for (smiElement = smiGetFirstElement(smiNode); 
Packit 022b05
	 smiElement; 
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {  
Packit 022b05
	tNode = smiGetElementNode(smiElement);
Packit 022b05
	tNode = smiGetParentNode(tNode);
Packit 022b05
	tNode = smiGetParentNode(tNode);
Packit 022b05
Packit 022b05
	if (cmpSmiNodes(tNode, expTable) == 1) break;
Packit 022b05
	
Packit 022b05
	baseTable = tNode;
Packit 022b05
    }  
Packit 022b05
Packit 022b05
    if (!baseTable) return;
Packit 022b05
Packit 022b05
    /* count the elements in the basetable */
Packit 022b05
    basecounter = algCountIndexElements(smiGetFirstChildNode(baseTable));
Packit 022b05
Packit 022b05
    /* are baseTable and expTable identical ? */
Packit 022b05
    if (basecounter >= refcounter) {
Packit 022b05
Packit 022b05
	/* searching for new base table candidate in order to handle multiple
Packit 022b05
	   indices */
Packit 022b05
	for (baseTable = smiGetNextNode(baseTable, SMI_NODEKIND_TABLE);
Packit 022b05
	     baseTable;
Packit 022b05
	     baseTable = smiGetNextNode(baseTable, SMI_NODEKIND_TABLE)) {
Packit 022b05
      
Packit 022b05
	    basecounter = algCountIndexElements(smiGetFirstChildNode(baseTable));
Packit 022b05
      
Packit 022b05
	    if (basecounter < refcounter) {
Packit 022b05
Packit 022b05
		for (smiElement = smiGetFirstElement(
Packit 022b05
		    smiGetFirstChildNode(expTable)); 
Packit 022b05
		     smiElement; 
Packit 022b05
		     smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
		    tNode = smiGetElementNode(smiElement);
Packit 022b05
Packit 022b05
		    /*if (smiGetParentNode(smiGetParentNode(tNode))->name == 
Packit 022b05
		      expTable->name) break; */
Packit 022b05
		    if (cmpSmiNodes(smiGetParentNode(smiGetParentNode(tNode)),
Packit 022b05
				    expTable) == 1) break;
Packit 022b05
	  
Packit 022b05
		    for (findElement = smiGetFirstElement(
Packit 022b05
			smiGetFirstChildNode(baseTable)); 
Packit 022b05
			 findElement; 
Packit 022b05
			 findElement = smiGetNextElement(findElement)) {
Packit 022b05
			if (cmpSmiNodes(tNode, smiGetElementNode(findElement))
Packit 022b05
			    == 1) break;
Packit 022b05
		    }
Packit 022b05
	  
Packit 022b05
		    if (!findElement) {
Packit 022b05
			return;
Packit 022b05
		    }
Packit 022b05
		}	
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    
Packit 022b05
	if (!baseTable) {
Packit 022b05
	    return;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (smiElement = smiGetFirstElement(smiGetFirstChildNode(baseTable)); 
Packit 022b05
	 smiElement; 
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	tNode = smiGetElementNode(smiElement);
Packit 022b05
Packit 022b05
	for (findElement = smiGetFirstElement(smiGetFirstChildNode(expTable)); 
Packit 022b05
	     findElement; 
Packit 022b05
	     findElement = smiGetNextElement(findElement)) {
Packit 022b05
	    if (cmpSmiNodes(tNode, smiGetElementNode(findElement)) == 1)
Packit 022b05
		break;
Packit 022b05
	}
Packit 022b05
    
Packit 022b05
	if (!findElement) {
Packit 022b05
	    return;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    algInsertEdge(baseTable, expTable, SMI_INDEX_EXPAND,
Packit 022b05
		  GRAPH_ENHINDEX_INDEX);  
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCheckForSparseRel
Packit 022b05
 *
Packit 022b05
 * Checks the given table for a sparse relationship to an other table. 
Packit 022b05
 *
Packit 022b05
 * Criterias for a sparse relationship :
Packit 022b05
 *    - same number of index elements in both tables
Packit 022b05
 *    - the same order of this elements
Packit 022b05
 * 1. Getting the basetable via the last element in the index of smiNode.
Packit 022b05
 * 2. comparing the number of elements
Packit 022b05
 */
Packit 022b05
static void algCheckForSparseRel(SmiNode *smiNode) 
Packit 022b05
{
Packit 022b05
    SmiNode      *tNode = NULL;
Packit 022b05
    SmiNode      *table;
Packit 022b05
    SmiElement   *smiElement;
Packit 022b05
    unsigned int basecounter;
Packit 022b05
Packit 022b05
    if (!smiNode) return;
Packit 022b05
Packit 022b05
    table = smiGetParentNode(smiNode);
Packit 022b05
Packit 022b05
    basecounter = algCountIndexElements(smiNode);
Packit 022b05
Packit 022b05
    /* getting the basetable via the father node of the last element
Packit 022b05
       to handle multiple instanceing */
Packit 022b05
    for (smiElement = smiGetFirstElement(smiNode);
Packit 022b05
	 smiElement; 
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	tNode = smiGetElementNode(smiElement);    
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (! tNode) {
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
    
Packit 022b05
    tNode = smiGetParentNode(tNode);
Packit 022b05
    if (equalElements(smiNode, tNode) == 0) {
Packit 022b05
	algInsertEdge(smiGetParentNode(tNode), smiGetParentNode(smiNode), 
Packit 022b05
		      SMI_INDEX_SPARSE, GRAPH_ENHINDEX_INDEX);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCheckForReOrderRel
Packit 022b05
 *
Packit 022b05
 * Checks the given table for a reorder relationship to an other table.
Packit 022b05
 *
Packit 022b05
 * Criterias for reoder relationships :
Packit 022b05
 *    - same number of elements
Packit 022b05
 *    - same elements must occur in a different order
Packit 022b05
 */
Packit 022b05
static void algCheckForReorderRel(SmiNode *smiNode)
Packit 022b05
{
Packit 022b05
    SmiNode   *tNode;
Packit 022b05
    GraphNode *graphNode;
Packit 022b05
    
Packit 022b05
    if (!smiNode) {
Packit 022b05
	return;
Packit 022b05
    }
Packit 022b05
Packit 022b05
    for (graphNode = graph->nodes;
Packit 022b05
	 graphNode;
Packit 022b05
	 graphNode = graphNode->nextPtr) {	
Packit 022b05
	tNode = graphNode->smiNode;
Packit 022b05
	if (tNode->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
	    if (equalElements(smiNode, smiGetFirstChildNode(tNode)) == 1) {
Packit 022b05
		algInsertEdge(smiGetParentNode(smiNode), tNode,
Packit 022b05
			      SMI_INDEX_REORDER, GRAPH_ENHINDEX_INDEX);
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGetIndexkind
Packit 022b05
 *
Packit 022b05
 * Gets the indexkind of the given table. The row object of the table is
Packit 022b05
 * passed to this function.
Packit 022b05
 * Therefore three subfunctions are called to get the indexkind. 
Packit 022b05
 *   - algChechForExpandRel
Packit 022b05
 *   - algCheckForSparseRel
Packit 022b05
 *   - algCheckForReOrderRel
Packit 022b05
 * Look there for further information.
Packit 022b05
 */
Packit 022b05
static void algGetIndexkind(SmiNode *row) 
Packit 022b05
{
Packit 022b05
    algCheckForExpandRel(row);
Packit 022b05
    algCheckForSparseRel(row);
Packit 022b05
    algCheckForReorderRel(row);
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algLinkTables
Packit 022b05
 *
Packit 022b05
 * Links the tables of the given module.
Packit 022b05
 *
Packit 022b05
 *  1. Getting the tables and the scalars from the given module.
Packit 022b05
 *  2. Linking the tables :
Packit 022b05
 *     - AUGMENT no work to do just adding the corresponding edge
Packit 022b05
 *     - for other relationships the subfunction algGetIndexkind is called
Packit 022b05
 *       look there for further information  
Packit 022b05
 */
Packit 022b05
void algLinkTables() 
Packit 022b05
{
Packit 022b05
    GraphNode  *tGraphNode;
Packit 022b05
    SmiNode    *node; 
Packit 022b05
    SmiNode    *tSmiNode;
Packit 022b05
Packit 022b05
    /* linking the tables */
Packit 022b05
    for (tGraphNode = graph->nodes;
Packit 022b05
	 tGraphNode;
Packit 022b05
	 tGraphNode = tGraphNode->nextPtr) {
Packit 022b05
	node = tGraphNode->smiNode;
Packit 022b05
Packit 022b05
	if (node->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
	    node = smiGetFirstChildNode(node);
Packit 022b05
Packit 022b05
	    if (node->nodekind == SMI_NODEKIND_ROW) {
Packit 022b05
Packit 022b05
		/* get the relationship between the tables and insert
Packit 022b05
		   the edges */
Packit 022b05
		if (node->indexkind == SMI_INDEX_INDEX) {
Packit 022b05
		    algGetIndexkind(node);
Packit 022b05
		} else {
Packit 022b05
		    tSmiNode = node;
Packit 022b05
		    node = smiGetRelatedNode(node);
Packit 022b05
		    node = smiGetParentNode(node);
Packit 022b05
		    algInsertEdge(node,
Packit 022b05
				  smiGetParentNode(tSmiNode), 
Packit 022b05
				  tSmiNode->indexkind,
Packit 022b05
				  GRAPH_ENHINDEX_INDEX);	    
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
   if (XPLAIN) {
Packit 022b05
       printf("--- Second Phase - linking the tables\n\n");
Packit 022b05
       graphShowEdges(graph);
Packit 022b05
   } 
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCheckLinksByName
Packit 022b05
 *
Packit 022b05
 * Reordering the connections by looking at the names.
Packit 022b05
 * Related objects are linked (if their names are related).
Packit 022b05
 * Every expand relationship is examined. Therefore number of
Packit 022b05
 * identical characters at the beginning of the both table names is
Packit 022b05
 * counted.
Packit 022b05
 * Then every sparse relationship (only the ending node) is checked if 
Packit 022b05
 * there is better connection with more identical characters at the beginning.
Packit 022b05
 * The starting node must be same as in the expand relationship to make sure
Packit 022b05
 * that there are no unrelated tables are linked.
Packit 022b05
 * Only legal overlappings lead to a new edge. A illegal overlap is :
Packit 022b05
 * - when the next character in both strings is a lower case character
Packit 022b05
 *   because if something like this is detected the two strings are
Packit 022b05
 *   corresponding in the middle of their names and not at defined points
Packit 022b05
 *   like suffix or prefix (-> the next character must be upper case or NULL)
Packit 022b05
 */
Packit 022b05
void algCheckLinksByName() 
Packit 022b05
{
Packit 022b05
    GraphEdge *tEdge, *tEdge2, *newEdge;
Packit 022b05
    char      *start, *end, *end2;
Packit 022b05
    int       overlap, longestOverlap, i;
Packit 022b05
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
Packit 022b05
	if (tEdge->indexkind == SMI_INDEX_EXPAND) {
Packit 022b05
Packit 022b05
	    start = tEdge->startNode->smiNode->name;
Packit 022b05
	    end = tEdge->endNode->smiNode->name;
Packit 022b05
Packit 022b05
	    overlap = strpfxlen(start,end);
Packit 022b05
      
Packit 022b05
	    /*
Packit 022b05
	     * looking for better connection with longer overlap
Packit 022b05
	     * maybe better to traverse the edges with graphGetNextEdgeByNode
Packit 022b05
	     * using tEdge->startNode
Packit 022b05
	     */  
Packit 022b05
	    newEdge = NULL;
Packit 022b05
	    longestOverlap = overlap;
Packit 022b05
	    for (tEdge2 = graphGetFirstEdgeByNode(graph,tEdge->startNode);
Packit 022b05
		 tEdge2;
Packit 022b05
		 tEdge2 = graphGetNextEdgeByNode(graph, tEdge2,
Packit 022b05
						 tEdge->startNode)) {
Packit 022b05
	
Packit 022b05
		/*
Packit 022b05
		 * must be a sparse relationship to get a correct new edge
Packit 022b05
		 */
Packit 022b05
		if (tEdge2->indexkind == SMI_INDEX_SPARSE) {
Packit 022b05
		    end2 = tEdge2->endNode->smiNode->name;
Packit 022b05
	  
Packit 022b05
		    /*
Packit 022b05
		     * new overlap longer and different tables ? 
Packit 022b05
		     */
Packit 022b05
		    i = strpfxlen(end,end2);
Packit 022b05
		    if (overlap < i &&
Packit 022b05
			!cmpSmiNodes(tEdge->endNode->smiNode,
Packit 022b05
				     tEdge2->endNode->smiNode)) {
Packit 022b05
			/*
Packit 022b05
			 * legal overlap ?
Packit 022b05
			 */
Packit 022b05
			if (islower((int)end[i]) && islower((int)end2[i])) {
Packit 022b05
			    break;
Packit 022b05
			}
Packit 022b05
Packit 022b05
			longestOverlap=i;
Packit 022b05
			newEdge = tEdge2;
Packit 022b05
		    }
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
      
Packit 022b05
	    /* better connection found -> changing the edge */
Packit 022b05
	    if (newEdge) {
Packit 022b05
		tEdge->startNode = newEdge->endNode;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (XPLAIN) {
Packit 022b05
	printf("\n--- Third Phase - reordering the connections\n\n");
Packit 022b05
	graphShowEdges(graph);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algLinkObjectsByNames
Packit 022b05
 *
Packit 022b05
 * Links Scalars to Tables using the prefix
Packit 022b05
 * Links Tables to Tables using the prefix
Packit 022b05
 */
Packit 022b05
static void algLinkObjectsByNames()
Packit 022b05
{
Packit 022b05
    GraphNode *tNode, *tNode2;
Packit 022b05
    int       overlap,minoverlap,new;
Packit 022b05
Packit 022b05
    /* getting the minimum overlap for all nodes */
Packit 022b05
    minoverlap = 10000;
Packit 022b05
    tNode2 = graph->nodes;
Packit 022b05
    if (tNode2) {
Packit 022b05
	for (tNode = tNode2->nextPtr; tNode; tNode = tNode->nextPtr) {	
Packit 022b05
	    minoverlap = min(minoverlap, strpfxlen(tNode->smiNode->name,
Packit 022b05
						   tNode2->smiNode->name));
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    /*
Packit 022b05
     * prefix overlap of one is too short to create any usefull edges
Packit 022b05
     */
Packit 022b05
    if (minoverlap == 1) return;
Packit 022b05
    
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {    
Packit 022b05
	if (!graphGetFirstEdgeByNode(graph, tNode)) {
Packit 022b05
	    overlap = minoverlap;
Packit 022b05
Packit 022b05
	    for (tNode2 = graph->nodes; tNode2; tNode2 = tNode2->nextPtr) {
Packit 022b05
		if (cmpSmiNodes(tNode->smiNode, tNode2->smiNode)) continue;
Packit 022b05
		
Packit 022b05
		new = strpfxlen(tNode->smiNode->name, tNode2->smiNode->name);
Packit 022b05
		
Packit 022b05
		if (new >= overlap) {
Packit 022b05
Packit 022b05
		    /*
Packit 022b05
		     * no scalar - scalar edges
Packit 022b05
		     */
Packit 022b05
		    if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
Packit 022b05
			tNode2->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
Packit 022b05
			continue;
Packit 022b05
		    }
Packit 022b05
Packit 022b05
		    /*
Packit 022b05
		     * is it a legal prefix
Packit 022b05
		     * (if the next char is NULL || uppercase)
Packit 022b05
		     */
Packit 022b05
		    if (tNode->smiNode->name[new] &&
Packit 022b05
			tNode2->smiNode->name[new]) {
Packit 022b05
			if (!isupper((int)tNode->smiNode->name[new]) ||
Packit 022b05
			    !isupper((int)tNode2->smiNode->name[new])) continue;
Packit 022b05
		    }
Packit 022b05
		    
Packit 022b05
		    overlap = new;
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
Packit 022b05
	    if (overlap == minoverlap) continue;
Packit 022b05
	    
Packit 022b05
	    new = 0;
Packit 022b05
	    for (tNode2 = graph->nodes; tNode2; tNode2 = tNode2->nextPtr) {
Packit 022b05
		if (cmpSmiNodes(tNode->smiNode, tNode2->smiNode)) continue;
Packit 022b05
Packit 022b05
		new = strpfxlen(tNode->smiNode->name, tNode2->smiNode->name);
Packit 022b05
		
Packit 022b05
		if (new == overlap && new > minoverlap) {
Packit 022b05
Packit 022b05
		    /*
Packit 022b05
		     * a scalar should only be adjacent to one node
Packit 022b05
		     */
Packit 022b05
		    if (tNode2->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
Packit 022b05
			graphGetFirstEdgeByNode(graph,tNode2)) continue;
Packit 022b05
		    if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
Packit 022b05
			graphGetFirstEdgeByNode(graph,tNode)) continue;    
Packit 022b05
Packit 022b05
		    /*
Packit 022b05
		     * adding only table -> scalar edges
Packit 022b05
		     */
Packit 022b05
		    if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR &&
Packit 022b05
			tNode2->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
Packit 022b05
			continue;
Packit 022b05
		    }
Packit 022b05
		    
Packit 022b05
		    if (tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
Packit 022b05
			algInsertEdge(tNode2->smiNode, tNode->smiNode,
Packit 022b05
				      SMI_INDEX_UNKNOWN,
Packit 022b05
				      GRAPH_ENHINDEX_NAMES);
Packit 022b05
		    } else {
Packit 022b05
			algInsertEdge(tNode->smiNode, tNode2->smiNode,
Packit 022b05
				      SMI_INDEX_UNKNOWN,
Packit 022b05
				      GRAPH_ENHINDEX_NAMES);
Packit 022b05
		    }
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algGroupScalars
Packit 022b05
 *
Packit 022b05
 * Grouping the scalars using a common fathernode.
Packit 022b05
 */
Packit 022b05
static void algGroupScalars()
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
    int       actGroup, fGroup;
Packit 022b05
    
Packit 022b05
    actGroup = 0;
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {	
Packit 022b05
	if (!graphGetFirstEdgeByNode(graph, tNode) &&
Packit 022b05
	    tNode->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
Packit 022b05
	    fGroup = algGetGroupByFatherNode(tNode->smiNode);
Packit 022b05
	    if (fGroup == 0) {
Packit 022b05
		tNode->group = ++actGroup;
Packit 022b05
	    }
Packit 022b05
	    else {
Packit 022b05
		tNode->group = fGroup; 
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (XPLAIN) {
Packit 022b05
	printf("Scalar Groups : \n");
Packit 022b05
Packit 022b05
	if (algGetNumberOfGroups() != 0) {
Packit 022b05
	    for (actGroup = 1;
Packit 022b05
		 actGroup <= algGetNumberOfGroups();
Packit 022b05
		 actGroup++) {
Packit 022b05
		algPrintGroup(actGroup);
Packit 022b05
		printf("\n");
Packit 022b05
	    }
Packit 022b05
	} else printf("No groups!\n");
Packit 022b05
	printf("\n");
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algLinkLonelyTables
Packit 022b05
 *
Packit 022b05
 * Links isolated tables with other tables via the types of the
Packit 022b05
 * index objects.
Packit 022b05
 * If no type is found the types are checked via the suffix if they differ
Packit 022b05
 * only in the range (-OrZero). Therefore the suffix-vector is checked.
Packit 022b05
 * Basetypes used in SMIv1/v2/ng are sorted out.
Packit 022b05
 */
Packit 022b05
static void algLinkLonelyTables()
Packit 022b05
{
Packit 022b05
    SmiElement *smiElement, *smiElement2 = NULL;
Packit 022b05
    GraphNode  *tNode, *tNode2;
Packit 022b05
    int        i;
Packit 022b05
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (!graphGetFirstEdgeByNode(graph, tNode) &&
Packit 022b05
	    tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
Packit 022b05
	    for (smiElement = smiGetFirstElement(
Packit 022b05
		smiGetFirstChildNode(tNode->smiNode));
Packit 022b05
		 smiElement;
Packit 022b05
		 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
Packit 022b05
		for (tNode2 = graph->nodes;
Packit 022b05
		     tNode2;
Packit 022b05
		     tNode2 = tNode2->nextPtr) {
Packit 022b05
		    if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE &&
Packit 022b05
			tNode != tNode2) {
Packit 022b05
Packit 022b05
			for (smiElement2 = smiGetFirstElement(
Packit 022b05
			    smiGetFirstChildNode(tNode2->smiNode));
Packit 022b05
			     smiElement2;
Packit 022b05
			     smiElement2 = smiGetNextElement(smiElement2)) {
Packit 022b05
Packit 022b05
			    if (strcasecmp(algGetTypeName(
Packit 022b05
				           smiGetElementNode(smiElement2)),
Packit 022b05
				       algGetTypeName(
Packit 022b05
					   smiGetElementNode(smiElement)))
Packit 022b05
				== 0) {
Packit 022b05
Packit 022b05
				if (isBaseType(smiGetElementNode(smiElement))
Packit 022b05
				    == 1){
Packit 022b05
				    continue;
Packit 022b05
				}
Packit 022b05
				
Packit 022b05
				graphInsertEdge(graph,tNode2, tNode,
Packit 022b05
						SMI_INDEX_UNKNOWN,
Packit 022b05
						GRAPH_ENHINDEX_TYPES);
Packit 022b05
				break;
Packit 022b05
			    }
Packit 022b05
			    else {
Packit 022b05
				for (i = 0; suffix[i]; i++) {
Packit 022b05
				    if (strstr(
Packit 022b05
					algGetTypeName(
Packit 022b05
					    smiGetElementNode(smiElement)),
Packit 022b05
					suffix[i])) {
Packit 022b05
					graphInsertEdge(graph,tNode2,
Packit 022b05
							tNode,
Packit 022b05
							SMI_INDEX_UNKNOWN,
Packit 022b05
							GRAPH_ENHINDEX_TYPES);
Packit 022b05
					break;
Packit 022b05
				    }
Packit 022b05
				}
Packit 022b05
				
Packit 022b05
				if (suffix[i]) break;
Packit 022b05
			    }
Packit 022b05
			}
Packit 022b05
		    }
Packit 022b05
		    if (smiElement2) break;
Packit 022b05
		}
Packit 022b05
		if (tNode2) break;
Packit 022b05
	    }
Packit 022b05
		
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algConnectLonelyNodes
Packit 022b05
 *
Packit 022b05
 * Connect the isolated nodes (scalars and tables)
Packit 022b05
 *
Packit 022b05
 * 1. Trying to link tables via the type of the index objects
Packit 022b05
 * 2. Trying to link scalars to tables using the names
Packit 022b05
 * 3. Trying to group scalars which have not been adjacent to any edge.
Packit 022b05
 */
Packit 022b05
void algConnectLonelyNodes() 
Packit 022b05
{
Packit 022b05
    if (XPLAIN) {
Packit 022b05
	printf("\n--- Fourth Phase -  connecting isolated nodes\n\n");
Packit 022b05
    }
Packit 022b05
Packit 022b05
    algLinkLonelyTables();
Packit 022b05
Packit 022b05
    algLinkObjectsByNames();
Packit 022b05
Packit 022b05
    algGroupScalars();
Packit 022b05
Packit 022b05
    if (XPLAIN) {
Packit 022b05
	graphShowEdges(graph);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * Subfunction of algCheckForDependencies
Packit 022b05
 *
Packit 022b05
 * change UML-edges to dependecy if possible
Packit 022b05
 */
Packit 022b05
static void createDependencies()
Packit 022b05
{
Packit 022b05
    GraphEdge *tEdge;
Packit 022b05
    int       elemCount;
Packit 022b05
    
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
	
Packit 022b05
	if (tEdge->indexkind == SMI_INDEX_UNKNOWN) {
Packit 022b05
Packit 022b05
	    if (tEdge->startNode->smiNode->nodekind == SMI_NODEKIND_TABLE &&
Packit 022b05
		tEdge->endNode->smiNode->nodekind   == SMI_NODEKIND_TABLE) {
Packit 022b05
		
Packit 022b05
		elemCount = algGetNumberOfRows(tEdge->startNode->smiNode);
Packit 022b05
		if (elemCount >= 0) tEdge->connection = GRAPH_CON_DEPENDENCY;
Packit 022b05
		
Packit 022b05
		elemCount = algGetNumberOfRows(tEdge->endNode->smiNode);
Packit 022b05
		if (elemCount >= 0) tEdge->connection = GRAPH_CON_DEPENDENCY;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * returns 1 if a new rerouting edge creates a loop and 0 otherwise
Packit 022b05
 */
Packit 022b05
static int isloop(GraphEdge *tEdge, SmiNode *depTable)
Packit 022b05
{
Packit 022b05
    GraphEdge *loopEdge;
Packit 022b05
Packit 022b05
    for (loopEdge = graphGetFirstEdgeByNode(graph, tEdge->endNode);
Packit 022b05
	 loopEdge;
Packit 022b05
	 loopEdge = graphGetNextEdgeByNode(graph,loopEdge,tEdge->endNode)) {
Packit 022b05
Packit 022b05
	if ((cmpSmiNodes(loopEdge->startNode->smiNode, depTable)) ||
Packit 022b05
	    (cmpSmiNodes(loopEdge->endNode->smiNode, depTable) &&
Packit 022b05
	     (loopEdge != tEdge))) {
Packit 022b05
	    return 1;
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    return 0;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * subfunction of algCheckForDependency
Packit 022b05
 */
Packit 022b05
static void rerouteDependencyEdge(GraphEdge *tEdge)
Packit 022b05
{
Packit 022b05
    SmiNode    *startTable, *endTable, *depTable;
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    
Packit 022b05
    startTable = tEdge->startNode->smiNode;
Packit 022b05
    endTable = tEdge->endNode->smiNode;
Packit 022b05
    
Packit 022b05
    for (smiElement = smiGetFirstElement(
Packit 022b05
	smiGetFirstChildNode(endTable));
Packit 022b05
	 smiElement;
Packit 022b05
	 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
	
Packit 022b05
	/* look only at expanded indices (only present in endTable) */
Packit 022b05
	if (cmpSmiNodes(endTable, smiGetParentNode(
Packit 022b05
	    smiGetParentNode(smiGetElementNode(smiElement)))) == 1) {
Packit 022b05
	    depTable = algFindEqualType(startTable,
Packit 022b05
					smiGetElementNode(smiElement));
Packit 022b05
	    
Packit 022b05
	    /* depTable different to endTable? */
Packit 022b05
	    if (depTable && !cmpSmiNodes(depTable, endTable)) {
Packit 022b05
Packit 022b05
		/* prevent loops */
Packit 022b05
		if (isloop(tEdge, depTable)) continue;
Packit 022b05
		
Packit 022b05
		algInsertEdge(depTable,
Packit 022b05
			      startTable, SMI_INDEX_UNKNOWN,
Packit 022b05
			      GRAPH_ENHINDEX_REROUTE);
Packit 022b05
		break;
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * algCheckForDependency
Packit 022b05
 *
Packit 022b05
 * Tries to change connection types from association to dependency by
Packit 022b05
 * looking at the types.
Packit 022b05
 *
Packit 022b05
 * 1. Supporting tables are revealed. Supporting tables consist only
Packit 022b05
 *    index objects and RowStatus-Objects and/or Storage-Type/Objects.
Packit 022b05
 * 2. If a supporting table is found the connection type is changed to
Packit 022b05
 *    dependency.
Packit 022b05
 * 3. Now the types of the index objects are checked (only in the end-table).
Packit 022b05
 *    If the same type is found in an other table the start-table is going to
Packit 022b05
 *    be connected with it (inserting a new edge). 
Packit 022b05
 *    The end-table is still connected to the start-table.
Packit 022b05
 */
Packit 022b05
void algCheckForDependency() 
Packit 022b05
{
Packit 022b05
    GraphEdge  *tEdge;
Packit 022b05
Packit 022b05
    createDependencies();
Packit 022b05
    
Packit 022b05
    for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
Packit 022b05
Packit 022b05
	if (tEdge->connection == GRAPH_CON_DEPENDENCY) {
Packit 022b05
Packit 022b05
	    rerouteDependencyEdge(tEdge);
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (XPLAIN) {
Packit 022b05
	printf("\n--- Fifth Phase - checking for dependency relationships\n\n");
Packit 022b05
	graphShowEdges(graph);
Packit 022b05
    }
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 *
Packit 022b05
 */
Packit 022b05
static SmiNode *algFindTable(SmiNode *node)
Packit 022b05
{
Packit 022b05
    GraphNode  *tNode;
Packit 022b05
    SmiNode    *smiNode;
Packit 022b05
    SmiElement *smiElement;
Packit 022b05
    char       *toFind;
Packit 022b05
    
Packit 022b05
    if (!node) return NULL;
Packit 022b05
Packit 022b05
    toFind = xstrdup(node->name
Packit 022b05
		     + strpfxlen(node->name, smiGetParentNode(node)->name));
Packit 022b05
		     
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
	    if (cmpSmiNodes(node, tNode->smiNode)) continue;
Packit 022b05
	    smiNode = smiGetFirstChildNode(tNode->smiNode);
Packit 022b05
	    
Packit 022b05
	    for (smiElement = smiGetFirstElement(smiNode);
Packit 022b05
		 smiElement;
Packit 022b05
		 smiElement = smiGetNextElement(smiElement)) {
Packit 022b05
		smiNode = smiGetElementNode(smiElement);
Packit 022b05
		if (strstr(smiNode->name, toFind)) {
Packit 022b05
		    xfree(toFind);
Packit 022b05
		    return smiGetParentNode(smiGetParentNode(smiNode));
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    xfree(toFind);
Packit 022b05
    
Packit 022b05
    return NULL;
Packit 022b05
}
Packit 022b05
Packit 022b05
/*
Packit 022b05
 * Creates edges based on column-objects pointing to other tables.
Packit 022b05
 * Column-objects with a substring "Index" are examined.
Packit 022b05
 */
Packit 022b05
void algCheckForPointerRels()
Packit 022b05
{
Packit 022b05
    GraphNode *tNode;
Packit 022b05
    SmiModule *module;
Packit 022b05
    SmiNode   *smiNode = NULL;
Packit 022b05
    SmiNode   *ppNode, *table;
Packit 022b05
    int       i;
Packit 022b05
    
Packit 022b05
    for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
Packit 022b05
	if (tNode->smiNode->nodekind == SMI_NODEKIND_TABLE) {
Packit 022b05
Packit 022b05
	    module  = smiGetNodeModule(tNode->smiNode);
Packit 022b05
Packit 022b05
	    for (smiNode = smiGetFirstNode(module, SMI_NODEKIND_COLUMN);
Packit 022b05
		 smiNode;
Packit 022b05
		 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COLUMN)) {
Packit 022b05
		ppNode = smiGetParentNode(smiNode);
Packit 022b05
		ppNode = smiGetParentNode(ppNode);
Packit 022b05
	
Packit 022b05
		if (!algIsIndexElement(tNode->smiNode, smiNode) &&
Packit 022b05
		    cmpSmiNodes(tNode->smiNode, ppNode)) {
Packit 022b05
Packit 022b05
		    for (i = 0; pointer[i]; i++) {
Packit 022b05
			if (strstr(smiNode->name, pointer[i])) {
Packit 022b05
			    /* printf("%s \n",smiNode->name); */
Packit 022b05
			    table = algFindTable(smiNode);
Packit 022b05
			    if (table) {
Packit 022b05
				algInsertEdge(table, tNode->smiNode,
Packit 022b05
					      SMI_INDEX_UNKNOWN,
Packit 022b05
					      GRAPH_ENHINDEX_POINTER);
Packit 022b05
			    }
Packit 022b05
			}
Packit 022b05
		    }
Packit 022b05
		}
Packit 022b05
	    }
Packit 022b05
	}
Packit 022b05
    }
Packit 022b05
Packit 022b05
    if (XPLAIN) {
Packit 022b05
	printf("\n--- Sixth Phase - checking for pointer relationships\n\n");
Packit 022b05
	graphShowEdges(graph);	
Packit 022b05
    }
Packit 022b05
}