[comp.sources.misc] v18i017: cdl - COFF Dynamic Loader, Part01/02

mauro@netcom.COM (Mauro DePalma) (04/14/91)

Submitted-by: Mauro DePalma <mauro@netcom.COM>
Posting-number: Volume 18, Issue 17
Archive-name: cdl/part01

This package is a COFF Dynamic Loader for System V.3 
object files.  See README file for more details.

Mauro
---- Cut Here and unpack ----
#!/bin/sh
# This is CDL -1.2, a shell archive (shar 3.24)
# made 02/11/1991 02:45 UTC by mauro@olympus
# Source directory /u/mauro/src/craft
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    505 -rw-r--r-- Makefile
#   3783 -r--r--r-- README
#  13681 -r--r--r-- avl.c
#   1993 -r--r--r-- avl.h
#   6945 -r--r--r-- craft.c
#   4500 -r--r--r-- craft.h
#   4789 -r--r--r-- llist.c
#    417 -r--r--r-- llist.h
#    797 -rw-r--r-- load.c
#  21155 -r--r--r-- loader.c
#   4799 -r--r--r-- loader.h
#    676 -rw-r--r-- simple.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= Makefile ==============
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#
X# Dynamic Loader project makefile
X#
X
X      CC = gcc
X GCFLAGS = -fstrength-reduce -fpcc-struct-return -g -pipe
X  CFLAGS = -DDEBUG -O $(GCFLAGS)
X  LFLAGS = #-x
X    LIBS = -lld
X    OBJS = load.o loader.o avl.o craft.o llist.o
X      RM = rm -f
X
Xload : $(OBJS)
X	$(CC) $(LFLAGS) -o $@ $(OBJS) $(LIBS)
X
Xclean :
X	$(RM) load core $(OBJS)
X
X# DO NOT DELETE
X
Xload.o   : load.c craft.h
Xloader.o : loader.c craft.h loader.h
Xavl.o    : avl.c craft.h avl.h
Xcraft.o  : craft.c craft.h
Xllist.o  : llist.c craft.h llist.h
SHAR_EOF
$TOUCH -am 0206004391 Makefile &&
chmod 0644 Makefile ||
echo "restore of Makefile failed"
set `wc -c Makefile`;Wc_c=$1
if test "$Wc_c" != "505"; then
	echo original size 505, current size $Wc_c
fi
# ============= README ==============
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
X +----------------------------------------------------------------------------+
X | Permission to use, copy, modify, distribute, and sell this software and its|
X | documentation for any purpose is hereby granted without fee, provided that |
X | credit is given to the original author.                                    |
X |                                                                            |
X | DePalma SoftCraft DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,   |
X | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO     |
X | EVENT SHALL DePalma SoftCraft BE LIABLE FOR ANY SPECIAL, INDIRECT OR       |
X | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,|
X | DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER     |
X | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR           |
X | PERFORMANCE OF THIS SOFTWARE.                                              |
X |                                                                            |
X |                                                                            |
X | Mauro DePalma           (mauro@netcom.COM or apple!netcom!mauro)           |
X |                                                                            |
X | DePalma SoftCraft      (UNIX System V/386 GNU, X11R4, InterViews)          |
X | 2923 Cohansey Drive                                                        |
X | San Jose, CA 95132                                                         |
X |                                                                            |
X | (408) 259-4789                                                             |
X +----------------------------------------------------------------------------+
X
X
X COFF Dynamic Loader (CDL) 1.2 consists of the following:
X
X      file       version  date       comment
X      --------------------------------------------------------
X      avl.c      1.3      1/13/91    by DePalma SoftCraft
X      avl.h      1.3      1/13/91    by DePalma SoftCraft
X      craft.c    1.4      1/18/91    by DePalma SoftCraft
X      craft.h    1.4      1/17/91    by DePalma SoftCraft
X      llist.c    1.2      1/18/91    by DePalma SoftCraft
X      llist.h    1.2      1/17/91    by DePalma SoftCraft
X      loader.c   1.5      1/18/91    by DePalma SoftCraft
X      loader.h   1.5      1/18/91    by DePalma SoftCraft
X
X  Additionally a 'Makefile', this README file, 'simple.c', and 'load.c'
X  are included.
X
X    The simplest test case can be accomplished by first creating the driver
X  program 'load' by entering 'make'; simple.c needs to be manually compiled
X  to produce simple.o which can be used to exercise the 'load' CDL driver
X  as follows:
X
X                $ load simple.o:voyage
X
X
X
X  CDL 1.2                                                         1/18/91
X
X
X   The public interface consists of the following routines:
X
X    int   load(char* object)   // an object file or an archive of object files
X    void* symbol(char* name)   // either an entry point or global data
X    int   unload(char* module) // an object file or archive member
X
X   all are declared in 'craft.h' header file; the library libld.a is needed
X   during the linking phase.
X
X     When an archive of object files is given to load(3L) every member of
X   the archive is examined thus, symbols used by one member can be referenced
X   by others.
X
X    At present unload(3L) can only handle an object file or a member of an
X    archive identified by, "<archive>[<member]". For example if we wish to
X    unload member 'debt.o' from archive 'national.a' we'd use:
X
X             int status = unload("national.a[debt.o]");
X
X     Note: unload(3L) indiscriminately removes all symbols without regard
X           where they're being referenced.
SHAR_EOF
$TOUCH -am 0210174891 README &&
chmod 0444 README ||
echo "restore of README failed"
set `wc -c README`;Wc_c=$1
if test "$Wc_c" != "3783"; then
	echo original size 3783, current size $Wc_c
fi
# ============= avl.c ==============
echo "x - extracting avl.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > avl.c &&
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) avl.c 1.3 1/13/91 by DePalma SoftCraft";
X#endif
X
X/* Adelson-Velskii and Landis (AVL) balanced binary tree routines.
X*/
X#include "craft.h"
X#include "avl.h"
X
X
X/*
X   NAME
X       AVLdispose -- AVL Tree disposal.
X
X   SYNOPSIS
X*/
X       void AVLdispose(seed, destruct)
X       caddr_t  seed;
X       agent_t  destruct;
X/*
X   DESCRIPTION
X*/
X{
X  AVLnode_t tree = (AVLnode_t) seed;
X
X  if (tree)
X    {
X      AVLdispose((caddr_t) tree->left,  destruct);
X      AVLdispose((caddr_t) tree->right, destruct);
X
X      if (destruct)
X        (*destruct)(tree->key, tree->item);
X
X      deallocate((caddr_t) tree);
X    }
X} /* AVLdispose */
X
X
X
X/*
X   NAME
X       AVLdump -- AVL Tree dump.
X
X   SYNOPSIS
X*/
X       void AVLdump(seed, routine, ark)
X       caddr_t  seed;
X       agent_t  routine;
X       caddr_t  ark;
X/*
X   DESCRIPTION
X       Wrapper for the recursive 'AVLtree()'.
X
X   SEE ALSO
X       AVLtree.
X*/
X{
X  AVLtree((AVLnode_t) seed, routine, 0, ark);
X} /* AVLdump */
X
X
X
X/*
X   NAME
X       AVLinsert -- AVL Tree insertion.
X
X   SYNOPSIS
X*/
X       int AVLinsert(root, key, item, compare)
X       caddr_t *  root;
X       caddr_t    key;
X       caddr_t    item;
X       agent_t    compare;
X/*
X   DESCRIPTION
X*/
X{
X  struct _AVLagent client;
X  AVLagent_t       agent = &client;
X  boolean_t        height;
X
X  agent->request = INSERT;
X  agent->key     = key;
X  agent->item    = item;
X  height         = False;
X  
X  return AVLtraverse((AVLnode_t *) root, agent, &height, compare);
X} /* AVLinsert */
X
X
X
X/*
X   NAME
X       AVLremove -- AVL Tree node removal.
X
X   SYNOPSIS
X*/
X       int AVLremove(root, key, compare, destruct)
X       caddr_t *  root;
X       caddr_t    key;
X       agent_t    compare;
X       agent_t    destruct;
X/*
X   DESCRIPTION
X*/
X{
X  struct _AVLagent  client;
X  AVLagent_t        agent = &client;
X  boolean_t         height;
X  int               result;
X
X  agent->request = DELETE;
X  agent->key     = key;
X  agent->item    = (caddr_t) 0;
X  height         = False;
X
X  result = AVLtraverse((AVLnode_t *) root, agent, &height, compare);
X
X  if (result == SUCCESS && destruct)
X    (*destruct)(agent->key, agent->item);
X
X  return result;
X} /* AVLremove */
X
X
X
X/*
X   NAME
X       AVLreplace -- AVL Tree replacement.
X
X   SYNOPSIS
X*/
X       int AVLreplace(seed, key, item, compare)
X       caddr_t    seed;
X       caddr_t    key;
X       caddr_t    item;
X       agent_t    compare;
X/*
X   DESCRIPTION
X*/
X{
X  struct _AVLagent client;
X  AVLagent_t       agent = &client;
X
X  agent->request = REPLACE;
X  agent->key     = key;
X  agent->item    = item;
X
X  return AVLtravel((AVLnode_t) seed, agent, compare);
X} /* AVLreplace */
X
X
X
X/*
X   NAME
X       AVLsearch -- AVL Tree search.
X
X   SYNOPSIS
X*/
X       int AVLsearch(seed, key, situs, compare)
X       caddr_t    seed;
X       caddr_t    key;
X       caddr_t *  situs;
X       agent_t    compare;
X/*
X   DESCRIPTION
X*/
X{
X  struct _AVLagent client;
X  AVLagent_t       agent = &client;
X  int              result;
X
X  agent->request = SEARCH;
X  agent->key     = key;
X  agent->item    = (caddr_t) 0;
X
X  result = AVLtravel((AVLnode_t) seed, agent, compare);
X
X  if (result == SUCCESS && situs)
X    *situs = agent->item;
X
X  return result;
X} /* AVLsearch */
X
X
X
X
X/*
X   NAME
X       AVLwalk -- walk the tree executing a given routine.
X
X   SYNOPSIS
X*/
X       void AVLwalk(seed, routine, ark)
X       caddr_t  seed;
X       agent_t  routine;
X       caddr_t  ark;
X/*
X   DESCRIPTION
X       Recursive routine which provides preorder traversal of an AVL tree
X       invoking the 'routine' given with 'ark' upon visit of the root.
X*/
X{
X  AVLnode_t  node = (AVLnode_t) seed;
X
X  if (node)
X    {
X      AVLwalk((caddr_t) node->left, routine, ark);
X      (*routine)(node->key, node->item, ark);
X      AVLwalk((caddr_t) node->right, routine, ark);
X    }
X} /* AVLwalk */
X
X
X
X/*
X   NAME
X       AVLdelete -- AVL Tree delete.
X
X   SYNOPSIS
X*/
X       static void AVLdelete(root, node, change)
X       AVLnode_t *  root;
X       AVLnode_t    node;
X       boolean_t *  change;
X/*
X   DESCRIPTION
X*/
X{
X  if (node)
X    {
X      if (node->right == (AVLnode_t) 0)
X        {
X          *root   = node->left;
X          *change = True;
X          deallocate((caddr_t) node);
X        }
X      else if (node->left == (AVLnode_t) 0)
X        {
X          *root   = node->right;
X          *change = True;
X          deallocate((caddr_t) node);
X        }
X      else
X        {
X          AVLerase(&(node->left), node, change);
X
X          if (*change == True)
X            AVLrightBalance(root, change, DELETE);
X        }
X    }
X} /* AVLdelete */
X
X
X
X/*
X   NAME
X       AVLerase -- AVL Tree delete (supplemental).
X
X   SYNOPSIS
X*/
X       static void AVLerase(root, link, change)
X       AVLnode_t * root;
X       AVLnode_t   link;
X       boolean_t * change;
X/*
X   DESCRIPTION
X*/
X{
X  AVLnode_t node = *root;
X
X  if (node->right)
X    {
X      AVLerase(&(node->right), link, change);
X
X      if (*change == True)
X        AVLleftBalance(root, change, DELETE);
X    }
X  else
X    {
X      link->key  = node->key;
X      link->item = node->item;
X      *root      = node->left;
X      *change    = True;
X      deallocate((caddr_t) node);
X    }
X} /* AVLerase */
X
X
X
X/*
X   NAME
X       AVLleftBalance -- AVL Tree left balance.
X
X   SYNOPSIS
X*/
X       static void AVLleftBalance(root, change, reason)
X       AVLnode_t *   root;
X       boolean_t *   change;
X       AVLrequest_t  reason;
X/*
X   DESCRIPTION
X*/
X{
X  AVLnode_t    child;
X  AVLnode_t    link;
X  AVLnode_t    node = *root;
X  AVLadjust_t  scale;
X
X  switch (node->balance)
X    {
X      case LEFT:                                  /* rebalance          */
X        child = node->left;
X        scale = child->balance;
X
X        if (scale == LEFT || (scale == CENTER && reason == DELETE))
X          {                                       /* single LL rotation */
X            node->left   = child->right;
X            child->right = node;
X
X            AVLsideBalance(node, child, change,
X                            (reason == DELETE) ? LEFT : CENTER);
X            node = child;
X          }
X        else
X          {                                       /* double LR rotation */
X            link           = child->right;
X            child->right   = link->left;
X            link->left     = child;
X            node->left     = link->right;
X            link->right    = node;
X            node->balance  = (link->balance == LEFT) ? RIGHT : CENTER;
X            child->balance = (link->balance == RIGHT) ? LEFT : CENTER;
X            node           = link;
X
X            if (reason == DELETE)
X              link->balance = CENTER;
X          }
X
X        if (reason != DELETE)
X          {
X            node->balance = CENTER;
X            *change       = False;
X          }
X
X        *root = node;
X      break;
X
X      case CENTER:
X        node->balance = LEFT;
X
X        if (reason == DELETE)
X          *change = False;
X      break;
X
X      case RIGHT:
X        node->balance = CENTER;
X
X        if (reason != DELETE)
X          *change = False;
X      break;
X    }
X} /* AVLleftBalance */
X
X
X
X/*
X   NAME
X       AVLrightBalance -- AVL Tree right balance.
X
X   SYNOPSIS
X*/
X       static void AVLrightBalance(root, change, reason)
X       AVLnode_t *   root;
X       boolean_t *   change;
X       AVLrequest_t  reason;
X/*
X   DESCRIPTION
X*/
X{
X  AVLnode_t    child;
X  AVLnode_t    link;
X  AVLnode_t    node = *root;
X  AVLadjust_t  scale;
X
X  switch (node->balance)
X    {
X      case LEFT:
X        node->balance = CENTER;
X
X        if (reason != DELETE)
X          *change = False;
X      break;
X
X      case CENTER:
X        node->balance = RIGHT;
X
X        if (reason == DELETE)
X          *change = False;
X      break;
X
X      case RIGHT:                                 /* rebalance          */
X        child = node->right;
X        scale = child->balance;
X
X        if (scale == RIGHT || (scale == CENTER && reason == DELETE))
X          {                                       /* single RR rotation */
X            node->right = child->left;
X            child->left = node;
X
X            AVLsideBalance(node, child, change,
X                            (reason == DELETE) ? RIGHT : CENTER);
X            node = child;
X          }
X        else
X          {                                       /* double RL rotation */
X            link           = child->left;
X            child->left    = link->right;
X            link->right    = child;
X            node->right    = link->left;
X            link->left     = node;
X            node->balance  = (link->balance == RIGHT) ? LEFT : CENTER;
X            child->balance = (link->balance == LEFT) ? RIGHT : CENTER;
X            node           = link;
X
X            if (reason == DELETE)
X              link->balance = CENTER;
X          }
X
X        if (reason != DELETE)
X          {
X            node->balance = CENTER;
X            *change       = False;
X          }
X
X        *root = node;
X      break;
X    }    
X} /* AVLrightBalance */
X
X
X
X/*
X   NAME
X       AVLsideBalance -- AVL Tree height balance.
X
X   SYNOPSIS
X*/
X       static void AVLsideBalance(node, child, change, side)
X       AVLnode_t    node;
X       AVLnode_t    child;
X       boolean_t *  change;
X       AVLadjust_t  side;
X/*
X   DESCRIPTION
X*/
X{
X  switch (side)
X    {
X      case LEFT:                          /* AVL Tree Deletion  */
X      case RIGHT:
X        if (child->balance == CENTER)
X          {
X            node->balance  = side;
X            child->balance = (side == RIGHT) ? LEFT : RIGHT;
X            *change        = False;
X          }
X        else
X          {
X            node->balance  = CENTER;
X            child->balance = CENTER;
X          }
X      break;
X
X      default:                            /* AVL Tree Insertion */
X        node->balance = CENTER;
X    }
X} /* AVLsideBalance */
X
X
X
X/*
X   NAME
X       AVLtravel -- readonly AVL Tree traversal.
X
X   SYNOPSIS
X*/
X       static int AVLtravel(node, agent, compare)
X       AVLnode_t    node;
X       AVLagent_t   agent;
X       agent_t      compare;
X/*
X   DESCRIPTION
X       Routine used for REPLACE and SEARCH operations.
X*/
X{
X  AVLnode_t    link;
X  int          comparison;
X  int          result;
X
X  if (node)                           /* search           */
X    {
X      if ((comparison = (*compare)(agent->key, node->key)) < 0)
X        {
X          result = AVLtravel(node->left, agent, compare);
X        }
X      else if (comparison > 0)
X        {
X          result = AVLtravel(node->right, agent, compare);
X        }
X      else                            /* found a match    */
X        {
X          if (agent->request == REPLACE)
X            node->item = agent->item;
X          else
X            agent->item = node->item;
X
X          result = SUCCESS;
X        }
X    }
X  else                                /* search exhausted */
X    {
X       result = EAVLNOKEY;
X    }
X
X  return result;
X} /* AVLtravel */
X
X
X
X/*
X   NAME
X       AVLtraverse -- read/write AVL Tree traversal.
X
X   SYNOPSIS
X*/
X       static int AVLtraverse(root, agent, change, compare)
X       AVLnode_t *  root;
X       AVLagent_t   agent;
X       boolean_t *  change;
X       agent_t      compare;
X/*
X   DESCRIPTION
X       Routine used for DELETE and INSERT operations.
X*/
X{
X  AVLnode_t    link;
X  AVLnode_t    node = *root;
X  int          comparison;
X  int          result;
X
X  if (node)                           /* search           */
X    {
X      if ((comparison = (*compare)(agent->key, node->key)) < 0)
X        {
X          result = AVLtraverse(&(node->left), agent, change, compare);
X
X          if (*change == True)
X            if (agent->request == DELETE)
X              AVLrightBalance(root, change, agent->request);
X            else
X              AVLleftBalance(root, change, agent->request);
X        }
X      else if (comparison > 0)
X        {
X          result = AVLtraverse(&(node->right), agent, change, compare);
X
X          if (*change == True)
X            if (agent->request == DELETE)
X              AVLleftBalance(root, change, agent->request);
X            else
X              AVLrightBalance(root, change, agent->request);
X        }
X      else                            /* found a match    */
X        {
X          if (agent->request == DELETE)
X            {
X              AVLdelete(root, node, change);
X
X              agent->key  = node->key;
X              agent->item = node->item;
X
X              result = SUCCESS;
X            }
X          else
X            {
X              result = EAVLDUPKEY;
X            }
X        }
X    }
X  else                                /* search exhausted */
X    {
X      if (agent->request == DELETE)
X        {
X          result = EAVLNOKEY;
X        }
X      else
X        {
X          if (link = (AVLnode_t) allocate(NIL, sizeof(struct _AVLnode)))
X            {
X              link->balance = CENTER;
X              link->key     = agent->key;
X              link->item    = agent->item;
X              link->left    = (AVLnode_t) 0;
X              link->right   = (AVLnode_t) 0;
X
X              *change       = True;
X              *root         = link;
X
X              result = SUCCESS;
X            }
X           else
X            {
X              result = EAVLNOMEM;
X            }
X        }
X    }
X
X  return result;
X} /* AVLtraverse */
X
X
X
X/*
X   NAME
X       AVLtree -- AVL Tree dump.
X
X   SYNOPSIS
X*/
X       static void AVLtree(node, routine, nest, ark)
X       AVLnode_t  node;
X       agent_t    routine;
X       int        nest;
X       caddr_t    ark;
X/*
X   DESCRIPTION
X       Recursive routine which provides traversal of an AVL tree in
X       natural order invoking the 'routine' given with nesting level
X       and 'ark' (client data) upon visit of the root.
X*/
X{
X  if (node)
X    {
X      AVLtree(node->right, routine, ++nest, ark);
X      (*routine)(node->key, node->item, nest, ark);
X      AVLtree(node->left, routine, nest, ark);
X    }
X} /* AVLtree */
X
SHAR_EOF
$TOUCH -am 0113170391 avl.c &&
chmod 0444 avl.c ||
echo "restore of avl.c failed"
set `wc -c avl.c`;Wc_c=$1
if test "$Wc_c" != "13681"; then
	echo original size 13681, current size $Wc_c
fi
# ============= avl.h ==============
echo "x - extracting avl.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > avl.h &&
X
X/* @(#)avl.h 1.3 1/13/91 by DePalma SoftCraft
X
X   Adelson-Velskii and Landis (AVL) balanced binary tree header file.
X*/
X
X#ifndef __AVL_H__                   /* guard against multiple includes     */
X#define __AVL_H__
X
Xtypedef enum                        /* possible sort of balance required  */
X  {
X          LEFT,
X          CENTER,
X          RIGHT
X  } AVLadjust_t;
X
Xtypedef enum                        /* various operation requests          */
X  {
X          DELETE,
X          INSERT,
X          REPLACE,
X          SEARCH
X  } AVLrequest_t;
X
Xtypedef struct _AVLnode             /* structure of a node in the tree     */
X  {
X          caddr_t           key;
X          caddr_t           item;
X          AVLadjust_t       balance;
X          struct _AVLnode * left;
X          struct _AVLnode * right;
X  } *AVLnode_t;
X
Xtypedef struct _AVLagent            /* convenience structure for traversal */
X  {
X          AVLrequest_t      request;
X          caddr_t           key;
X          caddr_t           item;
X  } *AVLagent_t;
X
X
X/* AVL Specific Errors (should be read from a message file)
X*/
Xstatic char *avlErrorList[] =
X  {
X    "",
X    "An attempt was made to insert a duplicate key",
X    "Can't allocate enough memory to create a new AVL node",
X    "Search failure, can't locate the specified key",
X    0
X  };
X
X#define EAVLDUPKEY  ERROR(avlErrorList, 1)
X#define EAVLNOMEM   ERROR(avlErrorList, 2)
X#define EAVLNOKEY   ERROR(avlErrorList, 3)
X
X
X/* AVL Private
X*/
Xstatic void AVLdelete(AVLnode_t *, AVLnode_t, boolean_t *);
Xstatic void AVLerase(AVLnode_t *, AVLnode_t, boolean_t *);
Xstatic void AVLleftBalance(AVLnode_t *, boolean_t *, AVLrequest_t);
Xstatic void AVLrightBalance(AVLnode_t *, boolean_t *, AVLrequest_t);
Xstatic void AVLsideBalance(AVLnode_t, AVLnode_t, boolean_t *, AVLadjust_t);
Xstatic int  AVLtravel(AVLnode_t, AVLagent_t, agent_t);
Xstatic int  AVLtraverse(AVLnode_t *, AVLagent_t, boolean_t *, agent_t);
Xstatic void AVLtree(AVLnode_t, agent_t, int, caddr_t);
X#endif /* not __AVL_H__ */
SHAR_EOF
$TOUCH -am 0117230191 avl.h &&
chmod 0444 avl.h ||
echo "restore of avl.h failed"
set `wc -c avl.h`;Wc_c=$1
if test "$Wc_c" != "1993"; then
	echo original size 1993, current size $Wc_c
fi
# ============= craft.c ==============
echo "x - extracting craft.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > craft.c &&
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) craft.c 1.4 1/18/91 by DePalma SoftCraft";
X#endif
X
X/* Base routines for SoftCraft library.
X*/
X
X#include "craft.h"
X
X#define ErrorClass(mask)       ((mask & 0xffff0000) >> 16)
X#define ErrorIndex(mask)       (mask & 0xffff)
X#define ErrorMask(class, code) ((class << 16) | code)
X
Xstatic agent_t Displayer = (agent_t) scribe;
Xstatic assoc_t Diagnosis = (assoc_t) 0;
X
X
X
X/*
X   NAME
X       allocate -- memory allocation.
X
X   SYNOPSIS
X*/
X       caddr_t  allocate(memory, bytes)
X       caddr_t  memory;
X       size_t   bytes;
X/*
X   DESCRIPTION
X       Changes the size of a previously allocated memory block or
X       allocates and clears a new one when none is specified.
X*/
X{
X  caddr_t  saga;
X
X  if (memory)
X    {
X      saga = (caddr_t) realloc((void *) memory, bytes);
X    }
X  else
X    {
X      if (saga = (caddr_t) malloc(bytes))
X        (void) memset((void *) saga, (char) 0, bytes);
X    }
X
X  return saga;
X} /* allocate */
X
X
X
X/*
X   NAME
X       deallocate -- memory deallocation.
X
X   SYNOPSIS
X*/
X       void deallocate(memory)
X       caddr_t  memory;
X/*
X   DESCRIPTION
X*/
X{
X  if (memory)
X    {
X      (void) free((void *) memory);
X    }
X} /* deallocate */
X
X
X
X/*
X   NAME
X       error(3L) -- output error message.
X
X   SYNOPSIS
X*/
X       void error(code)
X       int code;
X/*
X   DESCRIPTION
X       The 'code' argument is a 32 bit quantity which contains a
X       unique error class (ex.: sys_errlist) in the upper 16 bits
X       and an index (starting at 1) into the list of error messages
X       in the lower 16 bits.
X
X       ERRMSG is a special 'code' which allows for using only
X       optional arguments in the formation of the error message.
X
X   SEE ALSO
X       errorCode(3L).
X*/
X{
X  static char buffer[BLOCK];         /* Watch: may not be large enough */
X
X  va_list  args;
X  va_start(args, code);
X
X  if (code == FAILURE || code == SUCCESS || !Displayer)
X    return;
X
X  if (code == ERRMSG)
X    {
X      char* format = va_arg(args, char*);
X
X      (void) vsprintf(buffer, format, args);
X    }
X  else
X    {
X      caddr_t  key;
X      ushort   cast = ErrorClass(code);
X      ushort   mark = ErrorIndex(code);
X
X      if (LLvisit(Diagnosis->key, &key, (caddr_t) cast, minus) == SUCCESS)
X        {
X          (void) vsprintf(buffer, ((char**)key)[mark], args);
X
X          if (Diagnosis->item)
X            (void) strcat(buffer, Diagnosis->item);
X        }
X      else
X        {
X          (void) strcpy(buffer, form("in error (code=%x)", code));
X          (void) strcpy(buffer, DANGER(buffer));
X        }
X    }
X
X  (*Displayer)(buffer);    /* project: allow client to change 'Displayer' */
X  va_end(args);
X} /* error */
X
X
X/*
X   NAME
X       errorCode(3L) -- generation of error codes.
X
X   SYNOPSIS
X*/
X       int errorCode(module, line, list, code)
X       char *  module;
X       int     line;
X       char ** list;
X       int     code;
X/*
X   DESCRIPTION
X       Beyond yielding the correct error code errorCode(3L)
X       generates unique error classes for different error
X       message 'list's given.
X*/
X{
X  static boolean_t debug;
X  static int       increment = 100;
X  static int       sequence  = 0;
X
X  caddr_t  item;
X  int      cast;
X
X
X  if (Diagnosis == (assoc_t) 0)
X    { 
X      Diagnosis = (assoc_t) allocate(NIL, sizeof(struct _assoc));
X
X      if (debug = (boolean_t) getenv("DEBUG"))
X        Diagnosis->item = allocate(NIL, BLOCK * sizeof(char));
X    }
X
X  if (LLsearch(Diagnosis->key, (caddr_t) list, &item, minus) != SUCCESS)
X    {
X      item = (caddr_t) sequence + increment;
X
X      if (LLinsert(&(Diagnosis->key), (caddr_t) list, item) == SUCCESS)
X        {
X          sequence += increment;
X          cast = sequence;
X        }
X      else
X        {
X          (void) puts(DANGER("internal error"));
X          return FAILURE;
X        }
X    }
X  else
X    {
X      cast = (int) item;
X    }
X
X  if (debug)
X    (void) sprintf((char *) Diagnosis->item, " (%s line %d)", module, line);
X
X  return ErrorMask(cast, code);
X} /* errorCode */
X
X
X
X/*
X   NAME
X       errorNote(3L) -- change error message.
X
X   SYNOPSIS
X*/
X       int errorNote(module, line, code)
X       char *  module;
X       int     line;
X       int     code;
X/*
X   DESCRIPTION
X       When DEBUG environment variable is set the error message generated
X       includes the file name and line number. The purpose of this routine
X       is to update this information with the current file name and line
X       number.
X
X   SEE ALSO
X       errorCode(3L).
X*/
X{
X  if (Diagnosis)
X    if (Diagnosis->item)
X      (void) sprintf((char *) Diagnosis->item, " (%s line %d)", module, line);
X
X  return code;
X} /* errorNote */
X
X
X/*
X   NAME
X       form -- simple displayer.
X
X   SYNOPSIS
X*/
X       char * form(rule)
X       char * rule;
X/*
X   DESCRIPTION
X*/
X{
X  static char buffer[BLOCK];
X
X  va_list args;
X  va_start(args, rule);
X
X  (void) vsprintf(buffer, rule, args);
X  va_end(args);
X
X  return buffer;
X} /* form */
X
X
X
X/*
X   NAME
X       minus -- difference between two numbers.
X
X   SYNOPSIS
X*/
X       int minus(left, right)
X       int  left;
X       int  right;
X/*
X   DESCRIPTION
X       Comparison routine for two numbers.
X
X   SEE ALSO
X       AVLinsert(3L), AVLsearch(3L).
X*/
X{
X  return (left - right);
X} /* minus */
X
X
X/*
X   NAME
X       scribe -- simple displayer.
X
X   SYNOPSIS
X*/
X       int scribe(message)
X       char* message;
X/*
X   DESCRIPTION
X*/
X{ 
X  return puts(message);
X} /* scribe */
X
X
X
X/*
X   NAME
X       which - locate a program file.
X
X   SYNOPSIS
X*/
X       char * which(name)
X       char * name;
X
X/*
X   DESCRIPTION
X       Which looks for the file which be executed had the given
X       'name' been issued as a command.
X*/
X{
X  static boolean_t stub;
X  static char*     home;
X  static char*     path = (char*) 0;
X  static char      string[BLOCK];
X
X  char   buffer[BLOCK];
X  char*  token;
X  ushort mark;
X
X  if (name[0] == '.' || name[0] == '/')   /* trivial: absolute path   */
X    return name;
X
X  if (path == (char*) 0)                  /* once: save environment   */
X    {
X      home = getenv("HOME");
X      path = getenv("PATH");
X      stub = (boolean_t) (path[strlen(path) - 1] == ':');
X    }
X
X  if (stub)                               /* check special case       */
X    {
X      (void) sprintf(string, "./%s", name);
X
X      if (access(string, 0) == 0)
X        return string;
X    }
X
X  (void) strcpy(buffer, path);            /* always make a copy       */
X  mark = 0;                               /* initialize 'path' marker */
X
X  for (token = strtok(buffer, ":"); token; token = strtok((char*) 0, ":"))
X    {
X      if (path[mark] == ':')
X        {
X          (void) sprintf(string, "./%s", name);
X
X          if (access(string, 0) == 0)
X            break;
X        }
X
X      if (token[0] == '~')
X        (void) sprintf(string, "%s%s%s", home, &token[1], name);
X      else
X        (void) sprintf(string, "%s/%s", token, name);
X
X      if (access(string, 0) == 0)
X        break;
X
X      mark += strlen(token) + 1;
X    }
X
X  return ((token) ? string : (char*) 0);
X} /* which */
SHAR_EOF
$TOUCH -am 0118000591 craft.c &&
chmod 0444 craft.c ||
echo "restore of craft.c failed"
set `wc -c craft.c`;Wc_c=$1
if test "$Wc_c" != "6945"; then
	echo original size 6945, current size $Wc_c
fi
# ============= craft.h ==============
echo "x - extracting craft.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > craft.h &&
X
X/* Utility library header file.
X
X   @(#) craft.h 1.4 1/17/91 by DePalma SoftCraft
X*/
X
X#ifndef __CRAFT__                   /* guard against multiple includes      */
X#define __CRAFT__
X
X#include <stdarg.h>                 /* found in 'LIBDIR/gcc-include'        */
X#include <sys/types.h>
X
X#ifndef CTRL
X#  define CTRL(c)         ('c' & 037)
X#endif
X
X#define DANGER(msg)       form("panic: %s (%s line %d)", msg,__FILE__,__LINE__)
X#define DUBIOUS(code)     errorNote(__FILE__, __LINE__, code)
X
X#define ERRMSG            0x10000
X#define ERROR(list, code) errorCode(__FILE__, __LINE__, list, code)
X
X#ifndef False
X#  define False           0
X#  define True            1
X#endif
X
X#ifndef FAILURE
X#  define FAILURE         0
X#  define SUCCESS         1
X#endif
X
X#ifndef max
X#  define max(a, b)       (((a) > (b)) ? (a) : (b))
X#  define min(a, b)       (((a) < (b)) ? (a) : (b))
X#endif
X
X#define  NIL              (void *) 0
X
X#define  BACKSPACE        '\010'
X#define  ESCAPE           '\033'
X#define  RETURN           '\015'
X#define  SPACE            '\040'
X
X#define  BLOCK            512
X#define  MEGACYCLE        1000000L
X#define  TERMINATOR       '\200'
X
X/* SoftCraft Types
X*/
Xtypedef int (*agent_t)();           /* entry point for a procedure         */
X
Xtypedef struct _assoc               /* generic association structure       */
X  {
X          caddr_t key;              /* named (search) key                  */
X          caddr_t item;             /* associated item                     */
X  } *assoc_t;
X
Xtypedef unsigned char boolean_t;    /* boolean type (True or False)        */
X
Xtypedef struct _buffer              /* generic buffer structure            */
X  {
X          char *  base;             /* .. base address                     */
X          long    mark;             /* .. a marker (ex: number of entries) */
X  } *buffer_t;
X
X
X
X/* Key Definitions
X*/
X#define KEY_DOWN      0402          /* Sent by terminal down arrow key.     */
X#define KEY_UP        0403          /* Sent by terminal up arrow key.       */
X#define KEY_LEFT      0404          /* Sent by terminal left arrow key.     */
X#define KEY_RIGHT     0405          /* Sent by terminal right arrow key.    */
X#define KEY_HOME      0406          /* Sent by home key.                    */
X#define KEY_BACKSPACE 0407          /* Sent by backspace key.               */
X#define KEY_F0        0410          /* function key f0.                     */
X#define KEY_F(n)      (KEY_F0+(n))  /* Reserve space for 64 function keys.  */
X#define KEY_DC        0512          /* Sent by delete character key.        */
X#define KEY_IC        0513          /* Sent by ins char/enter ins mode key. */
X#define KEY_PGDN      0522          /* Sent by next-page key.               */
X#define KEY_PGUP      0523          /* Sent by previous-page key.           */
X#define KEY_PRINT     0532          /* Print or copy key.                   */
X#define KEY_END       0550          /* End key                              */
X
X
X
X/* SoftCraft Public Library
X
X   avl.o
X*/
Xvoid     AVLdispose(caddr_t, agent_t);
Xvoid     AVLdump(caddr_t, agent_t, caddr_t);
Xint      AVLinsert(caddr_t *, caddr_t, caddr_t, agent_t);
Xint      AVLremove(caddr_t *, caddr_t, agent_t, agent_t);
Xint      AVLreplace(caddr_t, caddr_t, caddr_t, agent_t);
Xint      AVLsearch(caddr_t, caddr_t, caddr_t *, agent_t);
Xvoid     AVLwalk(caddr_t, agent_t, caddr_t);
X
X/* craft.o
X*/
Xcaddr_t  allocate(caddr_t, size_t);
Xvoid     deallocate(caddr_t);
Xvoid     error(int, ...);
Xint      errorCode(char *, int, char **, int);
Xint      errorNote(char *, int, int);
Xchar *   form(char *, ...);
Xint      minus(int, int);
Xint      scribe(char *);
Xchar *   which(char *);
X
X/* llist.o
X*/
Xvoid     LLdispose(caddr_t, agent_t);
Xint      LLinsert(caddr_t *, caddr_t, caddr_t);
Xint      LLremove(caddr_t *, caddr_t, agent_t, agent_t);
Xint      LLsearch(caddr_t, caddr_t, caddr_t *, agent_t);
Xint      LLvisit(caddr_t, caddr_t *, caddr_t, agent_t);
Xvoid     LLwalk(caddr_t, agent_t, caddr_t);
Xcaddr_t  Stack(caddr_t *, caddr_t);
X
X/* loader.o
X*/
Xint      load(char *);
Xvoid *   symbol(char *);
Xint      unload(char *);
X
X
X/* Symbols used from standard libraries.
X*/
Xextern char *  ctime(time_t *);
Xextern char *  getenv(char *);
X
Xextern int     strcmp(char *, char *);
Xextern char *  strdup(char *);
Xextern char *  strchr(char *, int);
Xextern char *  strrchr(char *, int);
Xextern char *  strtok(char *, char *);
X
Xextern char *  optarg;
Xextern int     optind;
X
Xextern char *  sys_errlist[];
X#endif /* not __CRAFT__ */
SHAR_EOF
$TOUCH -am 0117225991 craft.h &&
chmod 0444 craft.h ||
echo "restore of craft.h failed"
set `wc -c craft.h`;Wc_c=$1
if test "$Wc_c" != "4500"; then
	echo original size 4500, current size $Wc_c
fi
# ============= llist.c ==============
echo "x - extracting llist.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > llist.c &&
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) llist.c 1.2 1/18/91 by DePalma SoftCraft";
X#endif
X
X/* Linear Lists (LL) routines.
X
X   ** DANGER **
X   Since these routines are used for error class registration,
X   introducing an error class for the LL module would result
X   in infinite recursion.
X*/
X
X#include "craft.h"
X#include "llist.h"
X
X
X/*
X   NAME
X       LLdispose -- list disposal.
X
X   SYNOPSIS
X*/
X       void LLdispose(seed, destruct)
X       caddr_t  seed;
X       agent_t  destruct;
X/*
X   DESCRIPTION
X*/
X{
X  llist_t  chain = (llist_t) seed;
X  llist_t  link;
X
X  while (chain)
X    {
X      link = chain->next;
X
X      if (destruct)
X        (*destruct)(chain->key, chain->item);
X
X      deallocate((caddr_t) chain);
X
X      chain = link;
X    }
X} /* LLdispose */
X
X
X
X/*
X   NAME
X       LLinsert -- link list insert.
X
X   SYNOPSIS
X*/
X       int LLinsert(head, key, item)
X       caddr_t *  head;
X       caddr_t    key;
X       caddr_t    item;
X/*
X   DESCRIPTION
X*/
X{
X  llist_t  chain = (llist_t) *head;
X  llist_t  link;
X
X  if (link = (llist_t) allocate(NIL, sizeof(struct _llist)))
X    {
X      link->key  = key;
X      link->item = item;
X      link->next = (llist_t) 0;
X
X      if (chain)             /* add another 'link' an existing 'chain' */
X        {
X          while (chain->next) chain = chain->next;
X          chain->next = link;
X        }
X      else                   /* start a new 'chain' (linear list)      */
X        {
X          *head = (caddr_t) link;
X        }
X    }
X
X  return ((link) ? SUCCESS : FAILURE);
X} /* LLinsert */
X
X
X
X/*
X   NAME
X       LLremove -- remove an item from a list.
X
X   SYNOPSIS
X*/
X       int LLremove(head, key, compare, destruct)
X       caddr_t * head;
X       caddr_t   key;
X       agent_t   compare;
X       agent_t   destruct;
X/*
X   DESCRIPTION
X*/
X{
X  llist_t  chain = (llist_t) *head;
X  llist_t  link;
X  llist_t  node;
X
X  for (link = chain, node = chain; link; link = link->next)
X    {
X      if ((*compare)(link->key, key) == 0)
X        {
X          if (link == chain)       /* match found at head of the list */
X            {
X              node = chain->next;
X
X              if (destruct)
X                (*destruct)(chain->key, chain->item);
X
X              deallocate((caddr_t) chain);
X              *head = (caddr_t)node;
X            }
X          else
X            {
X              node->next = link->next;
X
X              if (destruct)
X                (*destruct)(link->key, link->item);
X
X              deallocate((caddr_t) link);
X            }
X
X          break;
X        }
X
X      node = link;
X    }
X
X  return ((link) ? SUCCESS : FAILURE);
X} /* LLremove */
X
X
X
X/*
X   NAME
X       LLsearch -- list search for a key.
X
X   SYNOPSIS
X*/
X       int LLsearch(seed, key, situs, compare)
X       caddr_t    seed;
X       caddr_t    key;
X       caddr_t *  situs;
X       agent_t    compare;
X/*
X   DESCRIPTION
X*/
X{
X  register llist_t link;
X
X  for (link = (llist_t) seed; link; link = link->next)
X    if ((*compare)(link->key, key) == 0)
X      {
X        *situs = link->item;
X        break;
X      }
X
X  return ((link) ? SUCCESS : FAILURE);
X} /* LLsearch */
X
X
X
X/*
X   NAME
X       LLvisit -- list search for an item.
X
X   SYNOPSIS
X*/
X       int LLvisit(seed, situs, item, compare)
X       caddr_t    seed;
X       caddr_t *  situs;
X       caddr_t    item;
X       agent_t    compare;
X/*
X   DESCRIPTION
X*/
X{
X  register llist_t link;
X
X  for (link = (llist_t) seed; link; link = link->next)
X    if ((*compare)(link->item, item) == 0)
X      {
X        *situs = link->key;
X        break;
X      }
X
X  return ((link) ? SUCCESS : FAILURE);
X} /* LLvisit */
X
X
X
X/*
X   NAME
X       LLwalk -- walk through a list executing a given routine.
X
X   SYNOPSIS
X*/
X       void LLwalk(seed, routine, ark)
X       caddr_t  seed;
X       agent_t  routine;
X       caddr_t  ark;
X/*
X   DESCRIPTION
X*/
X{
X  register llist_t link;
X
X  for (link = (llist_t) seed; link; link = link->next)
X    (*routine)(link->key, link->item, ark);
X} /* LLwalk */
X
X
X
X/*
X   NAME
X       Stack -- stack operations.
X
X   SYNOPSIS
X*/
X       caddr_t Stack(seed, item)
X       caddr_t * seed;
X       caddr_t   item;
X/*
X   DESCRIPTION
X*/
X{
X  caddr_t epic = (caddr_t) 0;
X  stack_t head = (stack_t) *seed;
X  stack_t node = (stack_t) 0;
X
X  if (item)                        /* push operation                 */
X    {
X      if (node = (stack_t) allocate(NIL, sizeof(struct _stack)))
X        {
X          node->item = item;
X          node->next = head;
X          epic = item;             /* confirms success of operation  */
X        }
X    }
X  else                             /* pop operation                  */
X    {
X      if (head)
X        {
X          epic = head->item;
X          node = head->next;
X
X          deallocate((caddr_t) head);
X        }
X    }
X
X  *seed = (caddr_t) node;          /* always: establish top of stack */
X
X  return epic;
X} /* Stack */
SHAR_EOF
$TOUCH -am 0118091491 llist.c &&
chmod 0444 llist.c ||
echo "restore of llist.c failed"
set `wc -c llist.c`;Wc_c=$1
if test "$Wc_c" != "4789"; then
	echo original size 4789, current size $Wc_c
fi
# ============= llist.h ==============
echo "x - extracting llist.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > llist.h &&
X
X/* Linear Lists (LL) routines header file.
X
X   @(#) llist.h 1.2 1/17/91 by DePalma SoftCraft
X*/
X
Xtypedef struct _llist              /* linear list structure */
X  {
X          caddr_t         key;
X          caddr_t         item;
X          struct _llist * next;
X} *llist_t;
X
Xtypedef struct _stack              /* stack data structure  */
X  {
X          caddr_t         item;
X          struct _stack * next;
X} *stack_t;
X
SHAR_EOF
$TOUCH -am 0117231791 llist.h &&
chmod 0444 llist.h ||
echo "restore of llist.h failed"
set `wc -c llist.h`;Wc_c=$1
if test "$Wc_c" != "417"; then
	echo original size 417, current size $Wc_c
fi
# ============= load.c ==============
echo "x - extracting load.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > load.c &&
X
X#include <stdio.h>
X#include "craft.h"
X
Xextern int printf();
X
Xstatic agent_t reference[] = {
X  printf,
X  0
X};
X
X
Xint main(argc, argv, envp)
Xunsigned int  argc;
Xchar **       argv;
Xchar **       envp;
X{
X  agent_t reagent;
X  char    module[BUFSIZ];
X  char *  scan;
X  int     status = SUCCESS;
X
X  while (*++argv)
X    {
X      (void) strcpy(module, *argv);
X
X      if (module[0] == '-')
X        {
X          status = unload(&module[1]);
X          error(status);
X          continue;
X        }
X
X      if (scan = strchr(module, ':'))
X        {
X          *scan = (char) 0;
X          ++scan;
X        }
X
X      if ((status = load(module)) == SUCCESS)
X        if (reagent = (agent_t) symbol(scan))
X          (*reagent)("CDL Test Driver");
X
X      error(status);
X    }
X
X  return (status == SUCCESS) ? 0 : status;
X}
SHAR_EOF
$TOUCH -am 0118102091 load.c &&
chmod 0644 load.c ||
echo "restore of load.c failed"
set `wc -c load.c`;Wc_c=$1
if test "$Wc_c" != "797"; then
	echo original size 797, current size $Wc_c
fi
echo "End of part 1, continue with part 2"
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.