Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!seismo!uunet!rs
From: rs@uunet.UU.NET (Rich Salz)
Newsgroups: comp.sources.unix
Subject: v10i040: Interpreted Functional Programming lanuage, Part 07/07
Message-ID: <580@uunet.UU.NET>
Date: Tue, 7-Jul-87 19:23:10 EDT
Article-I.D.: uunet.580
Posted: Tue Jul 7 19:23:10 1987
Date-Received: Fri, 10-Jul-87 06:19:59 EDT
Organization: UUNET Communications Services, Arlington, VA
Lines: 2022
Approved: rs@uunet.uu.net
Mod.sources: Volume 10, Number 40
Submitted by: robison@b.cs.uiuc.edu (Arch Robison)
Archive-name: ifp/Part07
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh.
# The following files will be created:
# interp/outfun.c
# interp/outob.c
# interp/stats.c
# interp/stats.h
# interp/string.c
# interp/string.h
# interp/struct.h
# interp/trace.c
# interp/umax.h
# interp/xdef.c
export PATH; PATH=/bin:$PATH
mkdir interp
if test -f 'interp/outfun.c'
then
echo shar: over-writing existing file "'interp/outfun.c'"
fi
cat << \SHAR_EOF > 'interp/outfun.c'
/****** outfun.c ******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: June 30, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Dec 12, 1985 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
#include
#include
#include "struct.h"
#include "node.h"
/*
* OutLongNode - internal to OutNode
*/
void OutLongNode (N)
register NodePtr N;
{
if (N->NodeParent != NULL) {
OutLongNode (N->NodeParent);
printf ("/");
OutString (N->NodeName);
}
}
/*
* OutNode
*
* Output a node in UNIX path format.
* Abbreviate if it is in the current directory.
*/
void OutNode (N)
register NodePtr N;
{
register NodePtr M;
extern boolean LongPathFlag;
if (N == NULL) printf ("(NULL NODE)");
else {
if (!LongPathFlag && NULL != (M = FindNode (CurWorkDir,N->NodeName)) &&
(M->NodeType == IMPORT || M->NodeType == DEF))
OutString (N->NodeName);
else OutLongNode (N);
}
}
/*
* OutForm
*
* Print a functional form and its parameters.
*
* Input
* N = pointer to form node
* P = pointer to parameter list
* Depth = depth to print function (ellipses used at that depth)
*/
void OutForm (N,P,Depth)
register NodePtr N;
ListPtr P;
int Depth;
{
long L;
register FormEntry *T;
L = ListLength (P);
for (T=FormTable; TFormNode == N) {
switch (T-FormTable) {
case NODE_Comp:
while (P!=NULL) {
OutFun (&P->Val,Depth);
if (NULL != (P=P->Next)) printf ("|");
}
break;
case NODE_Cons:
printf ("[");
while (P!=NULL) {
OutFun (&P->Val,Depth);
if (NULL != (P=P->Next)) printf (",");
}
printf ("]");
break;
case NODE_RInsert:
case NODE_Filter:
case NODE_Each:
printf ("%s ",T->FormInPrefix);
OutFun (&P->Val,Depth);
printf (" END");
break;
case NODE_If:
printf ("IF "); OutFun (&P->Val,Depth);
printf (" THEN "); OutFun (&(P=P->Next)->Val,Depth);
printf (" ELSE "); OutFun (&P->Next->Val,Depth);
printf (" END");
break;
case NODE_C:
if (!L) {
printf ("?");
break;
}
/* else drop through */
#if FETCH
case NODE_Fetch:
#endif
case NODE_Out:
printf ("%s",T->FormInPrefix); OutObject (&P->Val);
break;
case NODE_Sel:
if (P->Val.Int >= 0) printf ("%d",P->Val.Int);
else printf ("%dr",-P->Val.Int);
break;
case NODE_While:
printf ("WHILE "); OutFun (&P->Val,Depth);
printf (" DO "); OutFun (&P->Next->Val,Depth);
printf (" END");
break;
#if XDEF
case NODE_XDef: {
extern void OutLHS ();
printf ("{"); OutLHS (&P->Val);
printf (" := "); OutFun (&P->Next->Val,Depth);
printf ("} ");
OutFun (&P->Next->Next->Val,Depth);
break;
}
#endif
}
return;
}
printf ("(");
OutNode (N);
for (; P != NULL; P=P->Next) {
printf (" ");
OutObject (&P->Val);
}
printf (")");
}
/*
* OutFun
*
* Print function *F. *F may be linked if it was unlinked.
*
* The possible representations for the function are described
* in the comments for "Apply" in apply.c.
*
* Input
* *F = function
* Depth = depth to print function, 0 = "..."
*
* Output
* *F = may be linked function
*/
void OutFun (F,Depth)
register ObjectPtr F;
int Depth;
{
register ListPtr P;
if (SysStop > 1) return;
if (F == NULL) printf ("(null)"); /* Internal error */
else if (--Depth < 0) printf ("..");
else
switch (F->Tag) {
default:
printf ("(tag = %d)",F->Tag); /* Internal error */
break;
case LIST:
P = F->List;
if (P == NULL) printf ("()");
else
switch (P->Val.Tag) {
case LIST: /* unlinked form */
LinkPath (&P->Val,DEF);
if (P->Val.Tag!=NODE||P->Val.Node->NodeType!=DEF) {
printf ("(");
OutObject (&P->Val);
for (; P != NULL; P=P->Next) {
printf (" ");
OutObject (&P->Val);
}
printf (")");
return;
} /* else drop down to case NODE */
case NODE: /* linked form */
OutForm (P->Val.Node,P->Next,Depth);
return;
case STRING:
LinkPath (F,DEF);
if (F->Tag == NODE) break; /* drop down to case NODE */
default: /* unlinked function or internal error */
for (; P!=NULL; P=P->Next) {
printf ("/");
OutObject (&P->Val);
}
return;
}
case NODE:
OutNode (F->Node);
break;
case STRING:
OutString (F->String);
break;
}
}
/******************************* end of outfun.c ******************************/
SHAR_EOF
if test -f 'interp/outob.c'
then
echo shar: over-writing existing file "'interp/outob.c'"
fi
cat << \SHAR_EOF > 'interp/outob.c'
/****** out.c *********************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Feb 8, 1987 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
#include
#include
#include "struct.h"
#include "string.h"
#define BerkMode 0
#define INDENT 3
/*
* OutIndent
*
* Indent N places
*/
void OutIndent (N)
int N;
{
for (; N >= 8; N-=8) printf ("\t");
while (--N >=0) printf (" ");
}
/*
* QuoteCheck
*
* Check if string should be quoted.
*
* Input
* S = string
* Output
* result = quote character ('\0','\'', or '\"');
*/
char QuoteCheck (S)
StrPtr S;
{
CharPtr U;
char Buf[256];
boolean Single=0,Double=0,Quote=0;
register char *T;
if (S==NULL) return ('\"');
else {
CPInit (&U,&S);
if (CPRead (&U,Buf,sizeof (Buf))) {
if (Buf [1] == '\0' && (Buf[0]=='f' || Buf[0]=='t' || Buf[0]=='?'))
return '\"';
do
for (T = Buf; *T; T++)
if (!isalpha (*T)) {
Quote=1;
if (*T == '\'') Single = 1;
if (*T == '\"') Double = 1;
}
while (CPRead (&U,Buf,sizeof (Buf)));
}
if (!Quote) return '\0';
else if (Single) return '\"';
else if (Double) return '\'';
else return '\"'; /* Should be something else */
}
}
/*
* OutString
*
* Output a string.
*/
void OutString (S)
StrPtr S;
{
char Buf[256];
CharPtr U;
if ((Debug & DebugRef) && S != NULL) printf ("[%d]",S->SRef);
CPInit (&U,&S);
while (CPRead (&U,Buf,sizeof (Buf))) printf ("%s",Buf);
}
/*
* OutList
*
* Input
* P = list to output
*/
void OutList (P)
register ListPtr P;
{
printf ("<");
if (P!=NIL)
while (1) {
if (Debug & DebugRef) printf ("{%d}",P->LRef + (1 - LRefOne));
OutObject (& P->Val);
if ((P=P->Next) == NULL) break;
else printf (",");
}
printf (">");
}
/*
* OutObject
*
* Output an object
*
* No reference counts change.
*/
void OutObject (X)
ObjectPtr X;
{
if (SysStop > 1) return;
else if (X == NULL) printf ("(NULL)");
else
switch (X->Tag) {
case BOTTOM: printf ("?"); break;
case BOOLEAN:
switch (X->Bool) {
case 0: printf (BerkMode ? "F" : "f"); break;
case 1: printf (BerkMode ? "T" : "t"); break;
default: printf ("(BOOLEAN %d)",X->Bool); break;
}
break;
case INT:
printf ("%ld",X->Int);
break;
case FLOAT:
printf ("%g",X->Float);
break;
case LIST:
OutList (X->List);
break;
case STRING: {
register char Q;
Q = QuoteCheck (X->String);
if (Q) printf ("%c",Q);
OutString (X->String);
if (Q) printf ("%c",Q);
} break;
case NODE:
OutNode (X->Node);
break;
default:
printf ("(tag = %d)",X->Tag);
break;
}
}
#define LineLength 80
/*
* OutLength
*
* Compute approximate number of characters required to output an object.
* The count is stopped prematurely if it goes over LineLength.
*
* No reference counts change.
*/
private int OutLength (X,Limit)
ObjectPtr X;
int Limit;
{
register ListPtr P;
register int K;
if (X == NULL) K = 6; /* "(null)" */
else
switch (X->Tag) {
case BOTTOM:
case BOOLEAN:
K = 1; /* "?","t","f" */
break;
case INT:
K = 5;
break;
case FLOAT:
K = 8;
break;
case LIST:
K = 2; /* <> */
for (P=X->List; P!=NULL && K <= Limit; P=P->Next)
K += 1 + OutLength (&P->Val,Limit); /* 1 for space between */
break;
case STRING:
K = 2 + LenStr (X->String); /* "'...'" */
break;
default:
K=0;
break;
}
return K;
}
/*
* OutPretty
*
* Output an object with indented sublists
*
* No reference counts change.
*/
void OutPretty (X,Indent)
ObjectPtr X;
int Indent;
{
register ListPtr P;
if (SysStop > 1) return;
OutIndent (Indent);
if (X == NULL) printf ("(null)");
else if (X->Tag != LIST) OutObject (X);
else {
if ((OutLength (X,LineLength) + Indent) > LineLength) {
printf ("<\n");
for (P = X->List; P!=NULL; P=P->Next)
OutPretty (&P->Val,Indent+INDENT);
OutIndent (Indent);
printf (">\n");
return;
} else OutList (X->List);
}
printf ("\n");
}
/************************** end of outob.c **************************/
SHAR_EOF
if test -f 'interp/stats.c'
then
echo shar: over-writing existing file "'interp/stats.c'"
fi
cat << \SHAR_EOF > 'interp/stats.c'
/****** stats.c *******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Dec 8, 1985 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/* Statistics collection routines */
#include "struct.h"
#include "stats.h"
#include
#if STATS
long StatRecycle=0,StatFresh=0;
long StatArg [MAXTAG+1];
long Stat_Apply [StatLimLen+1];
long Stat_NewList [StatLimLen+1];
long Stat_DelLPtrIn [StatLimLen+1];
long Stat_DelLPtrOut [StatLimLen+1];
long Stat_Construct [StatLimLen+1];
long Stat1Simple,Stat2Simple;
long StatC = 0;
void StatConstant (InOut)
ObjectPtr InOut;
{
StatC++;
}
void StatConstruct (P)
ListPtr P;
{
register int N;
N = ListLength (P);
if (N >= StatLimLen) N = StatLimLen;
++Stat_Construct[N];
}
void StatNewList (N)
long N;
{
StatFresh += N;
if (N > StatLimLen) N = StatLimLen;
++Stat_NewList [N];
}
void StatDelLPtr (P)
register ListPtr P;
{
register int N;
N = ListLength (P);
if (N >= StatLimLen) N = StatLimLen;
++Stat_DelLPtrIn [N];
for (N=0; P!=NULL; P=P->Next)
if (P->LRef > LRefOne || ++N >= StatLimLen) break;
++Stat_DelLPtrOut [N];
}
#define SCALAR ((1<Tag] ++;
if (InOut->Tag == LIST) {
L = ListLength (InOut->List);
if (L > StatLimLen) L = StatLimLen;
Stat_Apply [L] ++;
if (L == 2) {
P = InOut->List;
if ((1<Val.Tag) & SCALAR) Stat1Simple++;
if ((1<Next->Val.Tag) & SCALAR) Stat2Simple++;
}
}
}
/*
* ShowDist
*/
void ShowDist (Title,Dist)
char *Title;
long Dist[];
{
int k;
long S,Z;
for (S=0, k=0; k<=StatLimLen; k++) S += Dist[k];
printf (" %s (total = %ld)\n ",Title,S);
if (S)
for (k=0; k<=StatLimLen; k++) {
Z = 1000 * Dist[k]/S;
printf ("%ld.%ld%% [%s%ld] ",Z/10,Z%10,k==StatLimLen?">=":"",k);
Dist[k] = 0;
}
printf ("\n");
}
/*
* ShowStats
*/
void ShowStats ()
{
long Total;
int k;
printf ("\n");
Total = StatRecycle + StatFresh;
printf ("Memory management\n");
printf (" Total cells created = %ld\n",Total);
printf (" Percent of cells recycled = %ld\n",
Total ? 100*StatRecycle/Total : 0L);
ShowDist ("New list length distribution",Stat_NewList);
StatRecycle = StatFresh = 0;
ShowDist ("Deleted list (total) length distribution",Stat_DelLPtrIn);
ShowDist ("Deleted list (partial) length distribution",Stat_DelLPtrOut);
ShowDist ("Constructor list length distribution",Stat_Construct);
printf ("\n");
printf ("Constant function applications = %d\n",StatC);
StatC = 0;
printf ("\n");
if (Stat_Apply [2]) {
Stat1Simple = 100 * Stat1Simple / Stat_Apply [2];
Stat2Simple = 100 * Stat2Simple / Stat_Apply [2];
}
if (StatArg[LIST])
for (k=0; k<=StatLimLen; k++)
Stat_Apply [k] = 100 * Stat_Apply [k] / StatArg[LIST];
Total = 0;
for (k=0; k<=MAXTAG; k++) Total += StatArg [k];
if (Total)
for (k=0; k<=MAXTAG; k++) StatArg [k] = 100 * StatArg [k] / Total;
printf ("\n");
printf ("Apply arguments (Total = %ld)\n",Total);
printf (" Boolean = %ld, Int = %ld, Float = %ld, String = %ld\n",
StatArg[BOOLEAN],StatArg[INT],StatArg[FLOAT],StatArg[STRING]);
printf (" List = %ld\n",StatArg[LIST]);
printf (" ");
for (k=0; k=%d]\n",Stat_Apply [StatLimLen],StatLimLen);
printf (" Pair elements [scalar]<%ld,%ld>\n",Stat1Simple,Stat2Simple);
Stat1Simple = Stat2Simple = 0;
for (k=0; k<=StatLimLen; k++) Stat_NewList [k] = Stat_Apply[k] = 0;
for (k=0; k<=MAXTAG; k++) StatArg[k] = 0;
}
#endif
/**************************** end of stats.c ****************************/
SHAR_EOF
if test -f 'interp/stats.h'
then
echo shar: over-writing existing file "'interp/stats.h'"
fi
cat << \SHAR_EOF > 'interp/stats.h'
/****** stats.h *******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Dec 8, 1985 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/*
* Defining STATS=1 causes interpreter to collect statistics.
* Define STATS=0 for production work since statistics collection
* slows the interpreter.
*/
#define STATS 0
#if STATS
#define StatLimLen 5
#define Stat(X) X
extern long StatRecycle,StatFresh;
extern long StatArg [];
extern long Stat_Apply [];
extern long Stat_NewList [];
extern long Stat1Simple,Stat2Simple;
extern void ShowStats();
extern void StatApply(), StatConstruct(), StatConstant();
extern void StatNewList(), StatDelLPtr();
#else
#define Stat(X)
#endif
/**************************** end of stats.h ****************************/
SHAR_EOF
if test -f 'interp/string.c'
then
echo shar: over-writing existing file "'interp/string.c'"
fi
cat << \SHAR_EOF > 'interp/string.c'
/****** string.c ******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Jan 20, 1987 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
#include
#include "struct.h"
#include "node.h"
#include "umax.h"
#include "string.h"
/* Single character strings, CharString [0] = null string */
StrPtr *CharString;
/* Free string segments have SRef = 1 and are linked by StrNext link */
StrPtr FreeString = NULL;
/*
* NewSCell
*
* return pointer to fresh string cell with SRef = 1 and StrNext = NULL.
*
* A SysError may occur, in which case the NULL pointer is returned.
*/
private StrPtr NewSCell ()
{
extern StrPtr AllocStrPage ();
register StrPtr S;
semaphore_wait (SRefSemaphore);
if (FreeString != NULL || (FreeString = AllocStrPage ()) != NULL) {
S = FreeString;
FreeString = S->StrNext;
S->SRef = 1;
S->StrNext = NULL;
}
else {
SysError = NO_STR_FREE;
printf ("NO MORE STRING CELLS LEFT\n");
S = NULL;
}
semaphore_signal (SRefSemaphore);
return S;
}
/*
* CPInit
*
* Initialize a character pointer.
*/
void CPInit (U,S)
register CharPtr *U;
register StrPtr *S;
{
if ((U->CPSeg = *(U->CPStr = S)) == NULL) U->CPCount = 0;
else {
U->CPCount = StrHeadLen;
U->CPChar = (*S)->StrChar;
}
}
/*
* CPRead
*
* Read up to N-1 characters from and advance a character pointer.
* '\0' is returned as the last character of the string.
*
* Input
* *U = character pointer
* Buf = buffer into which to read characters
* N-1 = number of characters to read
*
* Output
* result = true if characters were read, 0 if end of string.
* Buf = string of characters terminated by '\0'
*/
boolean CPRead (U,Buf,N)
register CharPtr *U;
register char *Buf;
register int N;
{
register char *S;
register int K;
if (!U->CPCount && (NULL==U->CPSeg || NULL==U->CPSeg->StrNext) ||
!*(S = U->CPChar)) {
*Buf = '\0';
return 0;
} else {
--N;
while (N > 0) {
K = U->CPCount;
if (K > N) K = N;
N -= K;
U->CPCount -= K;
while (--K >= 0) *Buf++ = *S++;
if (!U->CPCount) {
if (NULL == (U->CPSeg = U->CPSeg->StrNext)) break;
else {
U->CPCount = StrTailLen;
S = U->CPSeg->StrChar;
}
}
}
U->CPChar = S;
*Buf = '\0';
return 1;
}
}
/*
* CPAppend
*
* Append a character to the end of a string.
*
* A SysError may occur.
*/
void CPAppend (U,C)
register CharPtr *U;
char C;
{
if (U->CPCount-- == 0)
if (C == '\0') return;
else {
register StrPtr S = NewSCell ();
if (SysError) return;
else {
U->CPChar = S->StrChar;
if (*U->CPStr == NULL) {
U->CPSeg = (*U->CPStr = S); /* Append head segment */
U->CPCount = StrHeadLen-1;
} else {
U->CPSeg = (U->CPSeg->StrNext = S); /* Append tail segment */
U->CPCount = StrTailLen-1;
}
}
}
*U->CPChar++ = C;
}
/*
* LenStr
*
* Find the length of a FP string
*
* Input
* S = IFP string
*
* Output
* result = length of string in characters
*/
FPint LenStr (S)
register StrPtr S;
{
register int J = StrHeadLen;
register FPint K = 0;
register char *T;
for (; S!=NULL; S = S->StrNext) {
for (T = S->StrChar; --J >= 0 && *T; T++) K++;
J = StrTailLen;
}
return K;
}
/*
* DelSPtr
*
* Delete a string pointer: decrement reference count and remove string
* if reference count is zero.
*/
void DelSPtr (S)
register StrPtr S;
{
register StrPtr T;
semaphore_wait (SRefSemaphore);
if (S != NULL && !-- S->SRef) {
for (T=S; T->StrChar[0]='\0', T->StrNext!=NULL; T=T->StrNext) continue;
T->StrNext = FreeString;
FreeString = S;
}
semaphore_signal (SRefSemaphore);
}
/*
* NewString
*
* Make a copy of a string. The old string retains its reference count.
*
* Input
* S = pointer to string
*
* Output
* result = pointer to new string
*
* A SysError may occur, in which case NULL is returned.
*/
private StrPtr NewString (S)
register StrPtr S;
{
extern char *strncpy ();
register StrPtr R,T;
if (S == NULL) return NULL;
R = T = NewSCell (); /* R = root of copy */
if (SysError) return NULL;
(void) strncpy (T->StrChar,S->StrChar,StrHeadLen);
while ((S=S->StrNext) != NULL) {
T->StrNext = NewSCell ();
T = T->StrNext;
(void) strncpy (T->StrChar,S->StrChar,StrTailLen);
if (SysError) {
DelSPtr (R); /* flush copy */
return NULL;
}
}
return R;
}
/*
* MakeString
*
* Make an IFP string from a C string.
*
* Input
* S = pointer to character array terminated by '\0'
*
* Output
* result = pointer to IFP (segmented) string
*
* A SysError may occur, in which case a NULL pointer is returned.
*/
StrPtr MakeString (S)
char *S;
{
extern char *strncpy ();
int L=strlen(S);
if (L <= 0) return NULL;
else {
StrPtr R,T;
int N = StrHeadLen;
R = T = NewSCell (); /* R = root of copy */
if (SysError) return NULL;
while (1) {
(void) strncpy (T->StrChar,S,N);
if ((L -= N) <= 0) return R;
else {
S += N;
T->StrNext = NewSCell ();
if (SysError) {
DelSPtr (R); /* flush copy */
return NULL;
}
T = T->StrNext;
N = StrTailLen;
}
}
}
}
/*
* StrComp
*
* Compares two strings. Returns P-Q
*/
int StrComp (P,Q)
StrPtr P,Q;
{
register int Diff,Len;
Len = StrHeadLen;
while (1) {
if (Q == NULL) return P!=NULL;
else if (P == NULL) return -(Q!=NULL);
else if (Diff = strncmp (P->StrChar,Q->StrChar,Len)) return Diff;
else {
Len = StrTailLen;
P = P->StrNext;
Q = Q->StrNext;
}
}
}
/*
* Make a copy of a non-null string pointer, incrementing the reference count.
*
* A SysError may occur, in in which case a NULL pointer is returned.
*/
StrPtr CopySPtr (S)
StrPtr S;
{
semaphore_wait (SRefSemaphore);
if (S != NULL && !++S->SRef) {
S->SRef--;
S = NewString (S);
}
semaphore_signal (SRefSemaphore);
return S;
}
/*
* InitString
*
* Initialize this module
*/
void InitString ()
{
int C;
StrPtr S;
CharString = (StrPtr *) malloc (128 * sizeof (StrPtr));
CharString [0] = NULL;
for (C = 1; C<128; C++) {
CharString [C] = S = NewSCell ();
S->StrChar [0] = C;
S->StrChar [1] = '\0';
}
}
/************************** end of string.c **************************/
SHAR_EOF
if test -f 'interp/string.h'
then
echo shar: over-writing existing file "'interp/string.h'"
fi
cat << \SHAR_EOF > 'interp/string.h'
/****** string.h ******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Jan 20, 1987 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/*
* CharPtr
*
* Character pointer
*
* Character pointers are for an IFP string what file pointers are
* for a UNIX file. Character pointers are used for both creating
* (writing) and scanning (reading) IFP strings. The structure of
* IFP strings (type String) is described in struct.h.
*/
typedef struct {
int CPCount; /* number of characters left in current segment */
char *CPChar; /* pointer to current character */
StrPtr *CPStr; /* pointer to root of string */
StrPtr CPSeg; /* pointer to current segment of string */
} CharPtr;
extern StrPtr *CharString; /* from string.c */
extern StrPtr MakeString ();
extern void DelSPtr ();
extern StrPtr CopySPtr ();
extern void CPInit (), CPAppend ();
extern boolean CPRead ();
extern FPint LenStr ();
/************************* end of string.h *************************/
SHAR_EOF
if test -f 'interp/struct.h'
then
echo shar: over-writing existing file "'interp/struct.h'"
fi
cat << \SHAR_EOF > 'interp/struct.h'
/****** struct.h ******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Aug 4, 1986 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/*
* There are some preprocessor variables which must be defined either
* here or in the cc command. The following options are not available
* in the public domain release:
*
* ARRAYS, COMPILE, UMAX, VECTOR, OUTBERKELEY
*
* Some of the code for these options are removed from the source by
* unifdef(1), so the source may look strange in places. (E.g. degenerate
* switch statements).
*
* The preprocessor variables are listed below.
*
* OPSYS (UNIX, MSDOS, CTSS) - specifies operating system
* PCAT - for compiling on PC/ATs
* SQUEEZE - put space at a premium
* DEBUG - incorporate interpreter debugging spy points
* DUMP - incoporate dump command for debugging (see debug.c)
* REFCHECK - incorporate reference checking command (see apply.c)
* COMPILE - incorporate IFP compiler (see C_comp.h)
* ARRAYS - incorporate array representation of sequences
* VECTOR - define APL-style vector operations (must define ARRAYS also)
* UMAX - make parallel version for Encore Multimax
*
* There are also preprocessor variables which may be turned on or off
* in the following files:
*
* ECACHE in cache.h - implement expression cache
* STATS in stats.h - collect run time statistics
* FETCH in node.h - implement "fetch" functional form
* OUTBERKELEY in outberkely.h - implement routine to print functions in
* Berkeley FP format.
*
* WARNING: Some of the compiling options may interfere with each other.
* Some options have not been tested for many revisions, so
* new bugs may creep out of the woodwork!
*/
#define UMAX 0 /* Must not enable ARRAYS, ECACHE, or STATS if set */
#define DUMP 0
#define ARRAYS 0 /* Must also define VECTOR=1 if set */
#define VECTOR 0
#define DEBUG 0
#define REFCHECK 0
/*
* Possible values for OPSYS preprocessor variable.
*/
#define UNIX 10
#define MSDOS 11
#define CTSS 12
#define OPSYS UNIX
#if OPSYS==CTSS
/*
* PARAMBUG is defined to indicate that the C compiler can not
* take the address (&) of parameter variables correctly.
* When this bug is removed from the CRAY C compiler, this define
* and dependent code should be removed.
*/
#define PARAMBUG 1
#endif
#if OPSYS==MSDOS || OPSYS==CTSS
#define MAXPATH 65 /* Maximum pathname length allowed (in characters) */
#endif
#if OPSYS==UNIX
#define MAXPATH 256 /* Maximum pathname length allowed (in characters) */
#endif
#if OPSYS==CTSS
#define index strchr
#endif
#ifdef PCAT
#define index strchr
#endif
/********** Fundamental Data Structures and Constants **********/
#define private static
#define forward extern /* for forward definitions which are not external */
typedef int boolean;
typedef long FPint;
typedef int FPboolean;
typedef short ushort;
/********************** MACHINE DEPENDENT CONSTANTS **********************/
/* These two definitions assume two's complement arithmetic! */
#define FPMaxInt (((FPint) 1 << 8 * sizeof(FPint) - 1) - 1)
#define MaxInt ((( int) 1 << 8 * sizeof( int) - 1) - 1)
#ifdef SQUEEZE
/* Maximum floating point value representable by an FPfloat */
typedef float FPfloat;
#define MAXFLOAT 1e38
#define LNMAXFLOAT 88.7
#define CompTol (1e-6)
#else
typedef double FPfloat;
/* Maximum floating point value representable by an FPfloat */
#define MAXFLOAT 1.8e308
#define LNMAXFLOAT 710.37 /* ln (MAXFLOAT) */
#define CompTol (1e-8)
#endif
/* if abs(A),abs(B) are both < MAXFACTOR then A*B will fit in FPInt */
#define MAXFACTOR 0xB504L
/****************** end of machine dependent constants *********************/
/********************************* Strings *********************************/
/*
* StrCell
*
* Each string is segmented into a linked list. The first record of the
* linked list contains the reference count for the string.
* The string is terminated by a segment with a null StrNext field or
* a '\0', whichever comes first. The empty string is represented
* by a null pointer. Segments have '\0' as their first character iff
* they are in the free string list.
*/
/*
* StrHeadLen is the maximum number of characters which can be contained in
* the first segment of a string list.
*/
#if OPSYS==CTSS
#define StrHeadLen 8 /* For 64-bit ushort and 64-bit pointer */
#else
#define StrHeadLen 10 /* For 16-bit ushort and 32-bit pointer */
#endif
#define StrTailLen (StrHeadLen + sizeof (ushort))
typedef struct StrCell {
struct StrCell *StrNext;
union {
char StrVar1 [StrTailLen];
struct {
char StrV1F1 [StrHeadLen];
ushort StrV1F2;
} StrVar2;
} StrUni1;
} StrCell;
typedef StrCell *StrPtr;
#define StrChar StrUni1.StrVar1
#define SRef StrUni1.StrVar2.StrV1F2
/****************************** Sequences ******************************/
/*
* Sequences are guaranteed not to have cycles by the definition of FP.
* Note that function representation lists may have a cycle, but the cycle
* will always contain a function name as a member. Cycle will be broken
* when the function definition is deleted.
*/
/* Object Tags */
#define BOTTOM 0
#define BOOLEAN 1
#define INT 2
#define FLOAT 3
#define LIST 4
#define STRING 5
#define NODE 6
#define CODE 7
#define JOIN 8
/* Bitmasks for PairTest */
#define NUMERIC ((1<Val = Q->Val will transfer the reference count!
*/
typedef struct {
ObUnion Data;
ushort _LRef;
char Tag; /* BOTTOM,BOOLEAN,INT,FLOAT,LIST,STRING,NODE,CODE,ARRAY */
} Object;
/*
* ListCell
*
* Sequences are represented as linked lists of objects. Each ListCell
* also contains a reference count (hidden in the Object field). The
* value stored in the reference count is offset by -1. The rationale is
* that reference counts are always compared against one, and comparing
* against zero is faster on some machines.
*/
typedef struct ListCell {
Object Val; /* Value of first element of sequence (CAR) */
struct ListCell *Next; /* Pointer tail of sequence (CDR) */
} ListCell;
#define LRef Val._LRef
#define LRefOne 0 /* value of LRef for reference count of 1 */
/*
* Most of the code uses subsets of the alphabet for certain types.
* For example, P,Q, and R are usually ListPtr.
*/
typedef ListCell *ListPtr; /* e.g. P,Q,R */
typedef ListPtr *MetaPtr; /* e.g. A,B,C */
typedef Object *ObjectPtr; /* e.g. X,Y,Z */
#define NIL ((ListPtr) NULL) /* empty list */
/******************************* Definitions ******************************/
/*
* DefDesc
*
* DefFlags = subset of {TRACE,RESOLVED}.
* DefCode = code for definition - BOTTOM if not resident.
*/
typedef struct DefDesc {
char DefFlags;
Object DefCode;
} DefDesc;
typedef DefDesc *DefPtr;
#define TRACE 1 /* Print input and output. */
#define RESOLVED 4 /* Mark bit used by reference checker */
/*
* All compiled FP functions have the following form:
*
* void F (InOut,CodeParam)
* ObjectPtr InOut;
* int CodeParam;
* {...};
*
* F replaces *InOut with the result of applying F to *InOut.
* CodeParam is optional.
*/
/******************************* Modules *******************************/
/*
* Modules are stored as lists of nodes. Each node has a pointer to
* its next sibling and its parent node.
*/
typedef struct { /* Module node descriptor */
struct NodeDesc *FirstChild;
} ModDesc;
/******************************** Imports ******************************/
/*
* Definition nodes are imported with IMPORT nodes. An import node in a
* module points to a definition node elsewhere.
*/
typedef struct {
Object ImpDef; /* Can be path list or node */
} ImpDesc;
/******************************** Nodes ********************************/
#define NEWNODE 0 /* Values for NodeType */
#define MODULE 1
#define DEF 2
#define IMPORT 3
/*
* NodeDesc
*
* See the top of node.c for the description of how these are linked together
* to form the function/module tree.
*
* NRef = reference count (references by objects)
* NodeNext = pointer to next sibling (or parent).
* NodeType = type of node (DEF, MODULE, IMPORT)
* NodeName = print name of node.
*/
typedef union {
DefDesc NodeDef; /* if DEF */
ModDesc NodeMod; /* if MODULE */
ImpDesc NodeImp; /* if IMPORT */
} NDunion;
typedef struct NodeDesc {
struct NodeDesc *NodeSib;
struct NodeDesc *NodeParent;
StrPtr NodeName;
short NRef;
char NodeType;
NDunion NodeData;
} NodeDesc;
typedef struct NodeDesc *NodePtr;
/*----------------- exception handling: see except.c -----------------*/
/* values for SysError, 0 == no error */
#define INTERNAL 1 /* Inexplicable internal error */
#define NO_LIST_FREE 2 /* Ran out of list cell storage */
#define NO_STR_FREE 3 /* " " " string " " */
#define NO_NODE_FREE 4 /* " " " node " " */
extern short SysError; /* An error occurred if SysError != 0 */
extern short SysStop; /* Stop evaluation if != 0 */
/*------------ debugging the interpreter: see debug.c ----------------*/
/*
* The interpreter may be compiled with internal spy points. These spy
* points print internal information on stdout. To include the spy * points,
* the interpreter must be compiled with #define DEBUG 1. To turn on a spy
* point when running ifp, use the command line option '-d' followed by the
* appropriate letters. The letters are defined by ``DebugOpt'' below.
* For example,
*
* ifp -dar
*
* will turn on spy points related to memory allocation (a) and
* reference counts (r).
*/
#define DebugParse (1<<0) /* parser */
#define DebugAlloc (1<<1) /* memory allocation */
#define DebugFile (1<<2) /* file io */
#define DebugRef (1<<3) /* reference counts */
#define DebugInit (1<<4) /* initialization */
#define DebugCache (1<<5) /* expression cache */
#define DebugXDef (1<<6) /* extended definitions */
#define DebugHyper (1<<7) /* hypercube */
#define DebugUMax (1<<8) /* multimax */
#define DebugSemaphore (1<<9) /* semaphores */
#define DebugFreeList (1<<10) /* free list */
#define DebugExpQueue (1<<11) /* expression queue */
#define DebugOpt "pafricxhusle" /* option letters for above */
#if DEBUG
extern int Debug; /* Bit-set of enabled spy points */
#else
#define Debug 0 /* Turn spy points into dead code */
#endif
/*--------------------------------------------------------------------*/
extern NodePtr CurWorkDir; /* Current working directory */
extern NodePtr SysDef ();
extern void DelLPtr (); /* Delete a list pointer */
extern ListPtr CopyLPtr (); /* Copy a list pointer */
extern void Rot3 (); /* list pointer rotation */
extern long ListLength (); /* from list.c */
extern void CopyObject ();
extern ListPtr Repeat ();
extern void NewList ();
extern void RepTag ();
extern boolean RepObject ();
extern void RepLPtr ();
extern void CopyTop ();
extern void Copy2Top ();
extern void RepBool ();
extern void Apply (); /* from apply.c */
extern NodePtr ApplyFun;
extern void NodeExpand ();
extern void ExecEdit (), ReadImport (); /* from file.c */
extern void OutObject (), OutList (); /* from outob.c */
extern void OutString (), OutNode ();
extern void OutForm (), OutFun (); /* from outfun.c */
extern void OutPretty ();
extern void InitIn (), InBlanks (); /* from inob.c */
extern void ReadDef (), DelImport ();
extern void InImport ();
extern int InError(); /* from error.c */
extern void DefError (), IntError ();
extern void FunError (), FormError ();
extern char ArgNotSeq[], ArgObSeq[], ArgSeqOb[], ArgNull[], ArgBottom[];
extern NodePtr PrimDef ();
extern char *malloc();
#define ArrayEnd(A) (A+(sizeof(A)/sizeof A[0]))
/************************** end of struct.h **************************/
SHAR_EOF
if test -f 'interp/trace.c'
then
echo shar: over-writing existing file "'interp/trace.c'"
fi
cat << \SHAR_EOF > 'interp/trace.c'
/****** trace.c *******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: May 1, 1985 **/
/** **/
/** Revised by: Arch D. Robison Date: Sept 9, 1986 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
#include
#include "struct.h"
#include "umax.h"
int TraceIndent = 0; /* Indentation level of trace */
int TraceDepth = 2; /* Depth to which functions are printed */
/*
* PrintTrace
*
* Print a trace messages "ENTER>" or "EXIT> " with their arguments.
* Each message is preceeded by an indentation pattern. Each '|' in
* the pattern represents one level of indentation; each '.' in the
* patttern represents DOTSIZE levels of indentation. The latter
* abbreviation keeps us from going off the deep end.
*/
#define DOTSIZE 20
void PrintTrace (F,InOut,EnterExit)
ObjectPtr F,InOut;
char *EnterExit;
{
int K;
/*
* A SysStop >= 2 indicates multiple user interrupts, i.e. the user
* does not want to see trace information.
*/
if (SysStop < 2) {
LineWait ();
for (K = TraceIndent; K>=DOTSIZE; K-=DOTSIZE) printf (".");
while (--K >= 0) printf (" |");
printf (EnterExit);
OutObject (InOut);
printf (" : ");
OutFun (F,TraceDepth);
printf ("\n");
LineSignal ();
}
}
/******************************* end of trace.c ******************************/
SHAR_EOF
if test -f 'interp/umax.h'
then
echo shar: over-writing existing file "'interp/umax.h'"
fi
cat << \SHAR_EOF > 'interp/umax.h'
/****** umax.h *******************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: Nov 4, 1986 **/
/** **/
/** Revised by: Arch D. Robison Date: Jan 27, 1987 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/*
* Defining UMAX=1 in "struct.h" compiles the ifp interpreter for parallel
* processing on the Multimax.
*/
#define semaphore_wait(s)
#define semaphore_signal(s)
#define rsemaphore_enter(r)
#define rsemaphore_exit(r)
#define spin_lock(s)
#define spin_unlock(s)
#define LineWait()
#define LineSignal()
#define Terminate()
/**************************** end of umax.h ****************************/
SHAR_EOF
if test -f 'interp/xdef.c'
then
echo shar: over-writing existing file "'interp/xdef.c'"
fi
cat << \SHAR_EOF > 'interp/xdef.c'
/****** xdef.c ********************************************************/
/** **/
/** University of Illinois **/
/** **/
/** Department of Computer Science **/
/** **/
/** Tool: IFP Version: 0.5 **/
/** **/
/** Author: Arch D. Robison Date: Aug 4, 1986 **/
/** **/
/** Revised by: Arch D. Robison Date: Aug 4, 1986 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/************************* Extended Definitions ************************/
#include
#include "struct.h"
#include "node.h"
#include "inob.h"
#if XDEF
ListPtr Environment = NIL;
/*
* OutLHS
*
* Input
* P = LHS to output
*/
void OutLHS (InOut)
ObjectPtr InOut;
{
switch (InOut->Tag) {
case LIST: {
register ListPtr P=InOut->List;
printf ("[");
if (P!=NIL)
while (1) {
if (Debug & DebugRef) printf ("{%d}",P->LRef + (1 - LRefOne));
OutLHS (& P->Val);
if ((P=P->Next) == NULL) break;
else printf (",");
}
printf ("]");
break;
}
default: OutObject (InOut);
}
}
/*
* Assign
*
* Assign functional variables.
*
* Input
* X = object to be matched with LHS.
* F = LHS
*/
private boolean Assign (X,F)
ObjectPtr X,F;
{
register ListPtr P,Q;
extern StrPtr CopySPtr();
switch (F->Tag) {
case STRING:
NewList (&Environment,2L);
P = Environment;
P->Val.Tag = STRING;
P->Val.String = CopySPtr (F->String);
CopyObject (&P->Next->Val,X);
return 1;
case LIST:
if (X->Tag != LIST) return 0;
else {
for (Q=X->List,P=F->List; P!=NULL; Q=Q->Next,P=P->Next)
if (Q==NULL || !Assign (&Q->Val,&P->Val)) return 0;
return 1;
}
default:
return 0;
}
}
/*
* FF_XDef
*
* Apply function F to each element of list InOut
*
* Input
* InOut = list of elements to apply function
* Funs =
*
* Output
* InOut = result
*/
FF_XDef (InOut,Funs)
ObjectPtr InOut;
register ListPtr Funs;
{
ListPtr P;
Object X;
boolean InRange;
if (3L != ListLength (Funs)) {
FormError (InOut,"invalid xdef",NULL,Funs);
return;
}
CopyObject (&X,InOut);
Apply (&X,&Funs->Next->Val);
P = Environment;
InRange = Assign (&X,&Funs->Val);
RepTag (&X,BOTTOM);
if (InRange)
Apply (InOut,&Funs->Next->Next->Val);
else if (PrintErr (InOut)) {
OutLHS (&Funs->Val);
printf (": domain error\n");
OutObject (InOut);
printf ("\n");
RepTag (InOut,BOTTOM);
}
RepLPtr (&Environment,P);
}
/*
* InLHSC
*
* Input
* F = input descriptor pointing to '['
*
* Output
* result = true iff no error occurs
* *X = sequence, or unchanged if error occurs.
*/
private boolean InLHSC (F,X,Env)
register InDesc *F;
ObjectPtr X;
ListPtr *Env;
{
register MetaPtr A;
ListPtr R;
*(A = &R) = NULL;
F->InPtr++;
InBlanks (F);
while (']' != *F->InPtr) {
if (!*F->InPtr) {
DelLPtr (R);
return InError (F,"unfinished construction");
}
NewList (A,1L);
if (SysError || !InLHS (F,&(*A)->Val,Env)) {
DelLPtr (R);
return 0;
}
A = & (*A)->Next;
if (*F->InPtr == ',') {
F->InPtr++;
InBlanks (F);
}
}
F->InPtr++; /* Skip closing ']' */
InBlanks (F);
RepTag (X,LIST);
X->List = R;
return 1;
}
/*
* InLHS
*
* Read a left-hand-side of a functional variable definition.
* Return true iff no error occurred.
*
* Input
* *F = input descriptor pointing to LHS
*
* Output
* *F = input descriptor pointing to next token
* *Lhs = left hand side
* *Env = list of functional variables in LHS
*
* A SysError may occur, in which case X is unchanged.
*/
boolean InLHS (F,LHS,Env)
register InDesc *F;
register ObjectPtr LHS;
ListPtr *Env;
{
register ListPtr P;
if (Debug & DebugParse) printf ("InLHS: %s",F->InPtr);
if (*F->InPtr == '[') return InLHSC (F,LHS,Env);
else {
if (NULL == InString (F,LHS,NodeDelim,0))
return InError (F,"variable name expected");
for (P= *Env; P!=NULL; P=P->Next)
if (ObEqual (&P->Val,LHS))
return InError (F,"redefinition of variable (to left of caret)");
NewList (Env,1L);
CopyObject (&(*Env)->Val,LHS);
return 1;
}
}
#endif /* XDEF */
/******************************* end of xdef.c *******************************/
SHAR_EOF
# End of shell archive
exit 0
--
Rich $alz "Anger is an energy"
Cronus Project, BBN Labs rsalz@pineapple.bbn.com
Moderator, comp.sources.unix sources@uunet.uu.net