home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume18
/
cdl
/
part01
next >
Wrap
Internet Message Format
|
1991-04-14
|
44KB
From: mauro@netcom.COM (Mauro DePalma)
Newsgroups: comp.sources.misc
Subject: v18i017: cdl - COFF Dynamic Loader, Part01/02
Message-ID: <1991Apr13.212554.15918@sparky.IMD.Sterling.COM>
Date: 13 Apr 91 21:25:54 GMT
Approved: kent@sparky.imd.sterling.com
X-Checksum-Snefru: 7a0b046a ac59c20c d330bc8d ba0d9a03
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.