[comp.sources.unix] v10i040: Interpreted Functional Programming lanuage, Part 07/07

rs@uunet.UU.NET (Rich Salz) (07/08/87)

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 <stdio.h>
#include <ctype.h>
#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; T<ArrayEnd(FormTable); T++) 
	 if (T->FormNode == 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 <stdio.h>
#include <ctype.h>
#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 <stdio.h>

#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<<INT)|(1<<FLOAT)|(1<<BOOLEAN)|(1<<STRING))

void StatApply (InOut)
   ObjectPtr InOut;
   {
      ListPtr P;
      long L;
 
      StatArg [InOut->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<<P->Val.Tag) & SCALAR) Stat1Simple++;
	    if ((1<<P->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<StatLimLen; k++) printf ("%ld [%ld], ",Stat_Apply [k],k);
      printf ("%ld [>=%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 <stdio.h>
#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<<FLOAT)|(1<<INT))
#define ATOMIC (NUMERIC | (1<<BOOLEAN) | (1<<STRING))


#define MAXTAG  7
#define SEQUENCE (1<<LIST)


/* Tag checking expressions dependent upon tag value assignments above */
#define Scalar(Tag) ((Tag) < 4)
#define Numeric(Tag) (((Tag)&~1)^2==0)
#define NotNumPair(Tag1,Tag2) ((((Tag1)^2)|((Tag2)^2))&~1) 
#define IntPair(Tag1,Tag2) ((Tag1+Tag2) == 4)
 
typedef struct CodeCell {
   int (*CodePtr) ();           /* (*CodePtr) (InOut,CodeParam) */
   int CodeParam;
} CodeCell;

typedef union {
   FPfloat _Float;
   FPint _Int;
   FPboolean _Bool;
   struct ListCell *_List;
   StrPtr _String;
   struct NodeDesc *_Node;
   CodeCell _Code;
} ObUnion;              

#define Float Data._Float
#define Int Data._Int
#define Bool Data._Bool
#define List Data._List
#define String Data._String
#define Node Data._Node
#define Code Data._Code

/*
 * Note on ARRAYS structures.  Cells with the ARRAY tag use the List field
 * to point to an array descriptor list.  The first element of the list
 * uses the APtr field, subsequent elements use the ADim field.
 */

/*
 * Object 
 *
 * An Object is a union which stores an IFP object.  The _LRef field is not 
 * logically part of an * object, but rather part of a ListCell.  We get much 
 * better packing by including it in Object, since it fits in a 32-bit word 
 * along with the Tag field.
 *
 * Likewise, for the UMAX version the _LRefLock field is physically part
 * of Object though it should be part of ListCell.
 *
 * Note that P->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 <stdio.h>
#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 <stdio.h>
#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 = <lhs rhs function>
 *
 * 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