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: v10i039: Interpreted Functional Programming lanuage, Part 06/07
Message-ID: <579@uunet.UU.NET>
Date: Tue, 7-Jul-87 19:23:00 EDT
Article-I.D.: uunet.579
Posted: Tue Jul 7 19:23:00 1987
Date-Received: Fri, 10-Jul-87 06:18:16 EDT
Organization: UUNET Communications Services, Arlington, VA
Lines: 2202
Approved: rs@uunet.uu.net
Mod.sources: Volume 10, Number 39
Submitted by: robison@b.cs.uiuc.edu (Arch Robison)
Archive-name: ifp/Part06
#! /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/infun.c
# interp/inimport.c
# interp/inob.c
# interp/inob.h
# interp/list.c
# interp/main.c
# interp/node.c
# interp/node.h
export PATH; PATH=/bin:$PATH
mkdir interp
if test -f 'interp/infun.c'
then
echo shar: over-writing existing file "'interp/infun.c'"
fi
cat << \SHAR_EOF > 'interp/infun.c'
/****** infun.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: 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. **/
/**********************************************************************/
#include
#include
#include "struct.h"
#include "node.h"
#include "string.h"
#include "inob.h"
/*
* PATTERN should be 0. Setting it to 1 enables a parser extension
* for experimental compiler work.
*/
#define PATTERN 0
/*
* MakeForm
*
* If correct, create form with node N and function list Funs.
*
* Output
* result = 1 if no error, 0 otherwise
*/
boolean MakeForm (Correct,N,Funs,InOut)
boolean Correct;
NodePtr N;
ListPtr Funs;
ObjectPtr InOut;
{
#ifdef PARAMBUG /* cure for CRAY C-compiler bug (see struct.h) */
{
ListPtr T = Funs;
NewList (&T,1L);
Funs = T;
}
#else
NewList (&Funs,1L);
#endif
if (SysError || !Correct) {
DelLPtr (Funs);
return 0;
} else {
Funs->Val.Tag = NODE;
Funs->Val.Node = CopyNPtr (N);
RepTag (InOut,LIST);
InOut->List = Funs;
return 1;
}
}
/*
* InNext
*
* Input next composition, which should be followed by Token.
*
* Input
* *F = input
* End = pointer to MetaPtr to end of list.
* Token = token expected.
* K = pointer to entry of form being parsed
*/
boolean InNext (F,End,Token,K,Env)
InDesc *F;
MetaPtr *End;
char *Token;
FormEntry *K;
ListPtr Env;
{
NewList (*End,1L);
if (SysError || !InComp (F,&(**End)->Val,Env)) return 0;
if (!IsTok (F,Token)) {
char Error [80];
extern char *sprintf();
(void) sprintf (Error,"'%s' part of '%s' expected",
Token,K->FormComment);
return InError (F,Error);
}
*End = &(**End)->Next;
return 1;
}
/*
* InPFO
*
* Input a PFO.
*
* Input
* F = input descriptor pointing to 1st token after 1st keyword of form
* K = index of form
* Env = environment list
*
* Output
* InOut = form
*/
private boolean InPFO (F,InOut,K,Env)
register InDesc *F;
ObjectPtr InOut;
FormEntry *K;
ListPtr Env;
{
ListPtr R = NIL;
MetaPtr A = &R;
boolean Correct;
switch (K-FormTable) {
case NODE_If:
Correct = 0;
if (InNext (F,&A,"THEN",K,Env) && InNext (F,&A,"\0",K,Env))
if (IsTok (F,"ELSIF")) {
NewList (A,1L);
Correct = !SysError && InPFO (F,&(*A)->Val,K,Env);
} else
if (IsTok (F,"ELSE")) Correct = InNext (F,&A,"END",K,Env);
else (void) InError (F,"'ELSE' or 'ELSIF' expected");
break;
case NODE_Each:
case NODE_RInsert:
case NODE_Filter:
Correct = InNext (F,&A,"END",K,NIL);
break;
case NODE_While:
Correct = InNext (F,&A,"DO",K,NIL) && InNext (F,&A,"END",K,NIL);
break;
#if XDEF
case NODE_XDef: {
ListPtr OldEnv = Env;
Correct = 0;
NewList (A,1L);
if (SysError || !InLHS (F,&(*A)->Val,&Env)) break;
if (!IsTok (F,":=")) (void) InError (F,"':=' expected");
else {
A = &(*A)->Next;
if (!InNext (F,&A,"}",K,OldEnv)) break;
NewList (A,1L);
if (InSimple (F,&(*A)->Val,Env)) Correct = 1;
}
break;
}
#endif
case NODE_C:
NewList (A,1L);
if (Correct = !SysError && InObject (F,&(*A)->Val))
if ((*A)->Val.Tag == BOTTOM) {
/* Convert #? to #(null) */
DelLPtr (R);
R = NIL;
}
break;
case NODE_Cons:
if (!(Correct = IsTok (F,"]"))) {
while ((Correct = InNext (F,&A,"\0",K,Env)) && IsTok (F,","))
continue;
if (Correct)
if (Correct = IsTok (F,"]"));
else (void) InError (F,"']' or ',' expected");
}
break;
#if FETCH
case NODE_Fetch:
#endif
case NODE_Out:
NewList (A,1L);
Correct = !SysError && InObject (F,&(*A)->Val);
break;
}
return MakeForm (Correct,K->FormNode,R,InOut);
}
/*
* InSelector
*
* Input
* F = input descriptor pointing to selector
*
* Output
* InOut = selector PFO
*/
private boolean InSelector (F,InOut)
register InDesc *F;
ObjectPtr InOut;
{
register ListPtr P;
long Index = 0;
do
Index = 10*Index + (*F->InPtr++) - '0';
while isdigit (*F->InPtr);
RepTag (InOut,LIST);
InOut->List = NIL;
NewList (&InOut->List,2L);
if (SysError) {
InOut->Tag = BOTTOM;
return 0;
}
P = InOut->List;
P->Val.Tag = NODE;
P->Val.Node = FormTable [NODE_Sel].FormNode;
P = P->Next;
P->Val.Tag = INT;
P->Val.Int = IsTok (F,"r") ? -Index : Index;
return 1;
}
/*
* InSimple
*
* Read a simple function
*
* Output
* result = 1 iff error occurs, 0 otherwise
* InOut = simple function if no error
*
* A SysError may occur, in which case InOut is unchanged.
*/
boolean InSimple (F,InOut,Env)
InDesc *F;
ObjectPtr InOut;
ListPtr Env;
{
static char InFirst[] = { /* First characters of InPrefix */
'I','E','W','#','[','F','@'
#if FETCH
,'^'
#endif
#if XDEF
,'{'
#endif
,'\0'
};
register FormEntry *K;
extern char *index ();
if (Debug & DebugParse) {
printf ("InSimple: Env = "); OutList (Env);
printf (", F = %s\n",F->InPtr);
}
InBlanks (F);
#ifdef PATTERN
if (IsTok (F,"!")) return InObject (F,InOut);
#endif
/*
* The "index" lookup below quickly rejects strings which
* cannot be key words.
*/
if (NULL != index (InFirst,*F->InPtr)) {
for (K=FormTable; K < ArrayEnd(FormTable); K++)
if (*K->FormInPrefix != '\0' && IsTok (F,K->FormInPrefix))
return InPFO (F,InOut,K,Env);
} else
if (isdigit (*F->InPtr))
return InSelector (F,InOut);
if (!InNode (F,InOut,Env))
return 0;
else if (InOut->List == NULL)
return InError (F,"'/' not a function");
else
return 1;
}
/*
* InComp
*
* Input a composition
*/
boolean InComp (F,InOut,Env)
register InDesc *F;
ObjectPtr InOut;
ListPtr Env;
{
Object X;
if (Debug & DebugParse) {
printf ("InComp: Env = ");
OutList (Env);
printf (", F = %s\n",F->InPtr);
}
X.Tag = BOTTOM;
if (!InSimple (F,&X,Env)) return 0;
else {
InBlanks (F);
if (!IsTok (F,"|")) {
RepObject (InOut,&X);
RepTag (&X,BOTTOM);
return !SysError;
} else {
ListPtr P,R=NIL;
boolean Correct;
NewList (&R,1L);
if (SysError) Correct = 0;
else {
CopyObject (&(P=R)->Val,&X);
RepTag (&X,BOTTOM);
do {
NewList (&P->Next,1L);
Correct = !SysError && InSimple (F,&(P=P->Next)->Val,NIL);
InBlanks (F);
} while (Correct && IsTok (F,"|"));
}
return MakeForm (Correct,FormTable[NODE_Comp].FormNode,R,InOut);
}
}
}
/*
* InDef
*
* Input a function definition
*
* Input
* FunName = Name of function
* Output
* InOut = function definition
* result = 1 iff successful, 0 otherwise
*/
boolean InDef (F,FunName,InOut)
register InDesc *F;
StrPtr FunName;
ObjectPtr InOut;
{
Object Fun,S;
Fun.Tag = BOTTOM;
S.Tag = BOTTOM;
F->InDefFun = FunName;
InBlanks (F);
if (!IsTok (F,"DEF")) return InError (F,"DEF expected");
else {
InBlanks (F);
(void) InString (F,&S,NodeDelim,0);
if (StrComp (S.String,FunName))
(void) InError (F,"Definition name wrong");
else {
InBlanks (F);
if (!IsTok (F,"AS")) (void) InError (F,"AS expected");
else {
InBlanks (F);
if (InComp (F,&Fun,NIL)) {
InBlanks (F);
if (!IsTok (F,";")) (void) InError (F,"semicolon expected");
else {
InBlanks (F);
if (*F->InPtr) (void) InError (F,"end of file expected");
else {
RepTag (&S,BOTTOM);
CopyObject (InOut,&Fun);
RepTag (&Fun,BOTTOM);
return 1;
}
}
}
}
}
}
RepTag (&S,BOTTOM);
RepTag (&Fun,BOTTOM);
return 0;
}
/********************************** infun.c **********************************/
SHAR_EOF
if test -f 'interp/inimport.c'
then
echo shar: over-writing existing file "'interp/inimport.c'"
fi
cat << \SHAR_EOF > 'interp/inimport.c'
/****** inimport.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: Oct 28, 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"
#include "string.h"
#include "inob.h"
/*
* DoubleDot
*
* Append a ".." to path list by deleting last element.
*
* Input
* *F = file descriptor
* *C = pointer to path list
*
* Output
* result = pointer to last null field, null if error.
*/
MetaPtr DoubleDot (F,C)
InDesc *F;
register MetaPtr C;
{
register MetaPtr A;
if (*C == NULL) {
(void) InError (F,"Too many ..'s.");
return NULL;
} else { /* Remove last element from path list R */
do {
A = C;
C = &(*A)->Next;
} while (*C != NULL);
DelLPtr (*A);
*A = NULL;
return A;
}
}
/*
* NodeDelim is the set of pathname delimiters. Note that '>' and '<' are not
* in the set since they are (perversely) legal function names.
*/
char NodeDelim[] = " ,[](){}|;:/\t\n";
/*
* InNode
*
* Input a path. A path may represent a module, function, or functional
* variable. Local functions are linked if possible to save time and space.
*
* The EBNF production definition for a node is:
*
* ["/"] string { "/" (string | "..") }
*
* Input
* *F = input descriptor pointing to path
* Env = environment
*
* Output
* InOut = node (path list or node format) or functional variable (string)
* *F = input descriptor pointing to next token after path
*
* A SysError may occur, in which case InOut is unchanged.
*/
boolean InNode (F,InOut,Env)
InDesc *F;
ObjectPtr InOut;
ListPtr Env;
{
ListPtr R = NULL; /* path list accumulator */
register MetaPtr A = &R; /* pointer to Next field at end of accumulator */
register NodePtr N;
boolean FirstSlash;
if (Debug & DebugParse) printf ("InNode: '%s'",F->InPtr);
if (!(FirstSlash = *F->InPtr == '/')) {
if (IsTok (F,"..")) {
if (F->InDefMod != NULL) R = MakePath (F->InDefMod);
if (NULL == (A = DoubleDot (F,&R))) goto Error;
} else {
Object S; /* relative path */
S.Tag = BOTTOM;
if (NULL == InString (F,&S,NodeDelim,0)) {
if (!SysError) (void) InError (F,"path expected");
goto Error;
}
if (!IsTok (F,"/")) {
for (; Env!=NULL; Env=Env->Next)
if (ObEqual (&Env->Val,&S)) {
RepObject (InOut,&Env->Val); /* functional variable */
return 1;
}
N = FindNode (F->InDefMod,S.String); /* local function */
if (N != NULL) {
if (N->NodeType == IMPORT) {
/* Imported function - resolve alias */
RepObject (InOut,&N->NodeData.NodeImp.ImpDef);
} else { /* Local function already linked */
RepTag (InOut,NODE);
InOut->Node = CopyNPtr (N);
}
RepTag (&S,BOTTOM);
return 1;
}
}
if (F->InDefMod != NULL) R = MakePath (F->InDefMod);
while (*A != NULL) A = &(*A)->Next;
NewList (A,1L);
(*A)->Val.Tag = STRING;
(*A)->Val.String = S.String;
}
}
while (IsTok (F,"/")) {
if (IsTok (F,".."))
if (NULL == (A = DoubleDot (F,&R))) return 0;
else continue;
else {
NewList (A,1L);
if (SysError) goto Error;
if (NULL == InString (F,&(*A)->Val,NodeDelim,0)) {
if (SysError) goto Error;
else if (*F->InPtr != '/' && FirstSlash) {
(void) DoubleDot (F,&R);
break;
} else {
(void) InError (F,"Invalid path name");
goto Error;
}
}
A = &(*A)->Next;
}
FirstSlash = 0;
}
RepTag (InOut,LIST);
InOut->List = R;
return 1;
Error:
DelLPtr (R);
return 0;
}
/*
* InImport
*
* Input from an import file.
*
* An import file has the following format:
*
* { 'FROM' path 'IMPORT' string {,string} ';' }
*
* Input
* F = input
* M = pointer to module node
*/
void InImport (F,M)
register InDesc *F;
register NodePtr M;
{
Object Path,Def;
register NodePtr N;
MetaPtr A;
F->InDefFun = NULL;
Path.Tag = BOTTOM;
Def.Tag = BOTTOM;
while (*F->InPtr) {
if (!IsTok (F,"FROM")) {
(void) InError (F,"FROM expected");
break;
}
(void) InNode (F,&Path,NIL);
if (!IsTok (F,"IMPORT")) {
(void) InError (F,"IMPORT expected");
break;
}
while (1) {
if (NULL == InString (F,&Def," ,;\n",0)) {
if (!SysError) (void) InError (F,"function name expected");
goto Return;
}
N = MakeChild (M,Def.String);
switch (N->NodeType) {
case IMPORT:
(void) InError (F,"duplicate imported identifier");
break;
case DEF:
if (N->NRef > 1) {
(void) InError (F,"identifies function elsewhere");
break;
} /* else continue on down to NEWNODE */
case NEWNODE: {
extern MetaPtr MakeCopy ();
N->NodeType = IMPORT;
N->NodeData.NodeImp.ImpDef.Tag = LIST;
A = MakeCopy (&N->NodeData.NodeImp.ImpDef.List, Path.List);
NewList (A,1L);
RepObject (&(*A)->Val,&Def);
break;
}
}
if (IsTok (F,";")) break;
if (!IsTok (F,",")) {
(void) InError (F,"comma or semicolon expected");
goto Return;
}
}
}
Return:
RepTag (&Path,BOTTOM);
RepTag (&Def,BOTTOM);
return;
}
/******************************* inimport.c *******************************/
SHAR_EOF
if test -f 'interp/inob.c'
then
echo shar: over-writing existing file "'interp/inob.c'"
fi
cat << \SHAR_EOF > 'interp/inob.c'
/****** inob.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: Aug 6, 1986 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
/*************** object input parser (recursive descent) ***************/
#include
#include
#include "struct.h"
#include "node.h"
#include "string.h"
#include "inob.h"
/*
* ObDelim
*
* Theses characters delimit objects.
* Compare with NodeDelim in inimport.c
*/
private char ObDelim[] = " ,<>|[](){};:\t\n";
/*
* InBlanks
*
* Skip to first non-blank character not in comment.
*
* Input
* F = input descriptor
*
* Output
* F = input descriptor pointing to non-blank character
*/
void InBlanks (F)
register InDesc *F;
{
while (1) {
while (1) {
if (!*F->InPtr)
if (F->InLineNum >= 0)
if (NULL != fgets (F->InBuf,INBUFSIZE,F->InFile)) {
F->InPtr = F->InBuf;
F->InLineNum++;
}
if (!isspace (*F->InPtr)) break;
F->InPtr++;
}
if (*F->InPtr == '(' && F->InPtr[1] == '*') {
F->ComLevel++;
F->InPtr+=2;
} else if (*F->InPtr == '*' && F->InPtr[1] == ')') {
F->ComLevel--;
F->InPtr+=2;
} else if (F->ComLevel && *F->InPtr) F->InPtr++;
else break;
}
}
/*
* IsTok
*
* Check if next token in input is S. Skip if found.
*/
boolean IsTok (F,S)
InDesc *F;
register char *S;
{
register char *T;
for (T = F->InPtr; *S; S++,T++)
if (*S != *T) return 0;
/* Check if alphabetic token is prefix of longer token */
if (isalpha (T[-1]) && isalpha (T[0])) return 0;
F->InPtr = T;
InBlanks (F);
return 1;
}
/*
* InString
*
* Input a string.
*
* Input
* *F = input descriptor pointing to first character of string
* Delim = string of non-alphanumeric delimiters
* Quoted = skip closing delimiter
*
* Output
* *F = input descriptor pointing to next token after string
* X = string object
* result = pointer to string, NULL if SysError or empty string.
*
* A SysError may occur, in which case X = bottom.
*/
StrPtr InString (F,X,Delim,Quoted)
register InDesc *F;
ObjectPtr X;
char *Delim;
boolean Quoted;
{
CharPtr U;
register char C;
RepTag (X,STRING);
X->String = NULL;
CPInit (&U,&X->String);
do {
extern char *index ();
C = *F->InPtr++;
if (!isalnum (C) && NULL != index (Delim,C)) C = '\0';
CPAppend (&U,C);
if (SysError) {RepTag (X,BOTTOM); return NULL;}
} while (C);
if (!Quoted) F->InPtr--;
InBlanks (F);
return X->String;
}
/*
* InList
*
* Input a list
*
* Input
* F = input descriptor pointing to first token after '<'
*
* Output
* result = true iff no error occurs
* *X = sequence, or unchanged if error occurs.
*/
private boolean InList (F,X)
register InDesc *F;
ObjectPtr X;
{
ListPtr R=NULL;
register MetaPtr A = &R;
while (!IsTok (F,">")) {
if (!*F->InPtr) {
DelLPtr (R);
return InError (F,"unfinished sequence");
}
NewList (A,1L);
if (SysError || !InObject (F,&(*A)->Val)) {
DelLPtr (R);
return 0;
}
A = & (*A)->Next;
(void) IsTok (F,",");
}
RepTag (X,LIST);
X->List = R;
return 1;
}
/*
* InObject
*
* Read an object.
*
* Input
* *F = input descriptor pointing to object
*
* Output
* *F = input descriptor pointing to next token
* result = true iff object is read successfully.
*
* A SysError may occur, in which case X is unchanged.
*/
boolean InObject (F,X)
register InDesc *F;
register ObjectPtr X;
{
if (IsTok (F,"<")) return InList (F,X);
else if (IsTok (F,"(")) {
(void) InComp (F,X,NIL);
if (!IsTok (F,")")) return InError (F,"')' expected");
} else {
/* Input atom */
static char Delim[2] = {'\0','\0'};
*Delim = *F->InPtr;
if (*Delim == '\"' || *Delim == '\'') {
F->InPtr++;
(void) InString (F,X,Delim,1);
} else {
FPint K;
register StrPtr S = InString (F,X,ObDelim,0);
if (S == NULL) return SysError || InError (F,"object expected");
if (S->StrChar[1] == '\0')
switch (S->StrChar[0]) {
case 'f':
RepBool (X,0);
return 1;
case 't':
RepBool (X,1);
return 1;
case '?':
RepTag (X,BOTTOM);
return 1;
}
if (StrToFloat (X) && !GetFPInt (X,&K)) {
X->Tag = INT;
X->Int = K;
}
}
}
return 1;
}
/*
* InitIn
*
* Initialize input descriptor for node N and file FileDesc.
* Advance the input pointer to the first token.
*
* Input
* *F = input descriptor
* M = module pointer
* FileDesc = open file descriptor
* LineNum = 0 for normal input, -1 if single-line mode
*/
void InitIn (F,M,FileDesc,LineNum)
register InDesc *F;
NodePtr M;
FILE *FileDesc;
int LineNum;
{
F->InFile = FileDesc;
F->InLineNum= LineNum;
F->InPtr = F->InBuf;
*F->InPtr = '\0';
F->InDefMod = M;
F->ComLevel = 0;
InBlanks (F);
}
/******************************* end of inob.c *******************************/
SHAR_EOF
if test -f 'interp/inob.h'
then
echo shar: over-writing existing file "'interp/inob.h'"
fi
cat << \SHAR_EOF > 'interp/inob.h'
/****** inob.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: 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. **/
/**********************************************************************/
#define INBUFSIZE 255 /* 65 <= INBUFSIZE <= 255 for DOS */
/*
* InDesc
*
* Input descriptor.
*
* Currently, there are three forms of IFP input:
*
* 1. Definition files
* 2. Import files
* 3. Terminal input
*
* All three forms are managed by input descriptors. An input descriptor
* buffers the file, and keeps track of context (e.g. line number).
*/
typedef struct {
char *InPtr; /* Pointer to current character being scanned */
int InLineNum; /* Line number of line being read [1] */
int ComLevel; /* Current comment nesting level [2] */
NodePtr InDefMod; /* Module node of current definition being read */
StrPtr InDefFun; /* Name of current definition */
FILE *InFile; /* File descriptor of file being read */
char InBuf[INBUFSIZE]; /* Buffer for current line being scanned */
} InDesc;
/*
* Footnotes
*
* [1] A line number of -1 indicates unnumbered lines, i.e. terminal input.
*
* [2] ComLevel should always be zero outside of function "InBlanks".
* A non-zero value indicates an "open comment" error.
*/
extern StrPtr InString ();
extern char NodeDelim[];
/******************************* end of inob.h *******************************/
SHAR_EOF
if test -f 'interp/list.c'
then
echo shar: over-writing existing file "'interp/list.c'"
fi
cat << \SHAR_EOF > 'interp/list.c'
/****** list.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 15, 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 "node.h"
#include "umax.h"
#include "string.h"
#include "stats.h"
/*
* FreeList
*
* ListCells in free-list always contain:
*
* LRef == LRefOne
* Val.Tag == BOTTOM
* Next == pointer to next cell in free list.
*/
ListPtr FreeList = NULL;
#define LRefAdd(P,Delta) ((P)->LRef+=(Delta))
/*************** Fundamental List Manipulation Routines ***************/
private ListPtr FixCopyLPtr (); /* forward reference */
/*
* Rot3
*/
void Rot3 (A,B,C)
MetaPtr A,B,C;
{
register ListPtr P;
P = *A; *A = *B; *B = *C; *C = P;
}
/*
* ListLength
*
* Input
* P = pointer to list
*
* Output
* result = length of list
*/
long ListLength (P)
register ListPtr P;
{
register long N;
for (N=0; P!=NULL; P=P->Next) N++;
return N;
}
/*
* CopyObject
*
* Copy object: X := Y
*
* A SysError may occur.
*/
void CopyObject (X,Y)
ObjectPtr X,Y;
{
register ListPtr P;
switch (X->Tag = Y->Tag) {
case BOTTOM: break;
case BOOLEAN: X->Bool = Y->Bool; break;
case INT: X->Int = Y->Int; break;
case FLOAT: X->Float = Y->Float; break;
case LIST:
/* CopyLPtr expanded inline for speed */
P = Y->List;
if (P!=NULL && LRefAdd (P,1) == LRefOne-1)
/*
* This won't work for multiprocessor version
* since other processors will not detect overflow.
*/
P = FixCopyLPtr (P);
X->List = P;
break;
case STRING: X->String = CopySPtr (Y->String); break;
case NODE: X->Node = CopyNPtr (Y->Node); break;
}
}
/*
* NewList
*
* Point *A to list of N cells with last cell's Next set to old value of *A.
*
* Each cell value is set to BOTTOM
*
* A SysError may occur, in which case *A remains unchanged.
*
* Implementation note:
* (x >= 0) is faster than (x > 0) on 16-bit machines since only
* the sign bit must be checked.
*/
void NewList (A,N)
MetaPtr A;
register long N;
{
extern ListPtr AllocListPage ();
register MetaPtr B;
ListPtr P;
Stat (StatNewList (N));
if (--N >= 0) {
B = &FreeList;
do {
if (*B == NULL && (*B = AllocListPage ()) == NULL) {
SysError = NO_LIST_FREE;
printf ("NO MORE LIST CELLS LEFT\n");
return;
}
B = &(*B)->Next;
} while (--N >= 0);
P = FreeList;
FreeList = *B;
*B = *A;
*A = P;
}
}
/*
* Repeat
*
* Create a new list containing N copies of an object
*
* Output
* result = pointer to list
*
* A SysError may occur, in which case NULL is returned.
*/
ListPtr Repeat (X,N)
register ObjectPtr X;
long N;
{
ListPtr P=NULL;
register ListPtr Q;
NewList (&P,N);
if (!SysError)
for (Q=P; Q!=NULL; Q=Q->Next)
CopyObject (&Q->Val,X);
return P;
}
/*
* DelLPtr
*
* Delete a list pointer: decrement reference count and return to free-list
* if not used anymore.
*
* Routine is "vectorized" in that it is optimized to return long lists
* to the freelist.
*/
void DelLPtr (P)
register ListPtr P;
{
register ListPtr Q,R;
Stat (StatDelLPtr (P));
for (R=P; R!=NULL; R=R->Next) {
if (R->LRef != LRefOne) {
R->LRef--;
break;
}
if (!Scalar (R->Val.Tag)) {
switch (R->Val.Tag) {
case LIST: DelLPtr (R->Val.List); break;
case STRING: DelSPtr (R->Val.String); break;
case NODE: DelNPtr (R->Val.Node); break;
}
R->Val.Tag = BOTTOM;
}
Q = R;
}
if (R != P) {
Q->Next = FreeList;
FreeList = P;
}
}
/*
* CopyLPtr
*
* Make a copy of a list pointer, incrementing the reference count.
* If the reference count would overflow, a new list cell is generated.
*
* A SysError may occur, in which case the result is NULL.
*/
ListPtr CopyLPtr (P)
ListPtr P;
{
if (P!=NULL) {
if (LRefAdd (P,1) == LRefOne-1) {
return FixCopyLPtr (P);
}
}
return P;
}
/*
* FixCopyLPtr
*
* Copy a list pointer which overflowed.
*
* Input
* P = pointer to list cell
*/
private ListPtr FixCopyLPtr (P)
ListPtr P;
{
ListPtr Q; /* Reference count overflowed */
LRefAdd (P,-1);
Q = CopyLPtr (P->Next);
if (SysError) return NULL;
NewList (&Q,1L);
if (SysError) return NULL;
CopyObject (&Q->Val,&P->Val);
return Q;
}
/*
* RepTag
*
* Replace an object tag with another tag.
*/
void RepTag (Dest,NewTag)
ObjectPtr Dest;
char NewTag;
{
switch (Dest->Tag) {
case LIST: DelLPtr (Dest->List); break;
case STRING: DelSPtr (Dest->String); break;
case NODE: DelNPtr (Dest->Node); break;
/* default: break; */
}
Dest->Tag = NewTag;
}
/*
* RepBool
*
* Replace an object with a boolean object
*/
void RepBool (Dest,Value)
ObjectPtr Dest;
boolean Value;
{
RepTag (Dest,BOOLEAN);
Dest->Bool = Value;
}
/*
* RepObject
*
* Replace an Object by another Object.
*
* A SysError may occur.
*/
boolean RepObject (Y,X)
register ObjectPtr Y,X;
{
Object Z;
switch (Z.Tag = Y->Tag) {
case LIST: Z.List = Y->List; break;
case STRING: Z.String = Y->String; break;
case NODE: Z.Node = Y->Node; break;
}
switch (Y->Tag = X->Tag) {
case BOTTOM: break;
case BOOLEAN: Y->Bool = X->Bool; break;
case INT: Y->Int = X->Int; break;
case FLOAT: Y->Float = X->Float; break;
case LIST: Y->List = CopyLPtr (X->List); break;
case STRING: Y->String = CopySPtr (X->String); break;
case NODE: Y->Node = CopyNPtr (X->Node); break;
}
switch (Z.Tag) {
case LIST: DelLPtr (Z.List); break;
case STRING: DelSPtr (Z.String); break;
case NODE: DelNPtr (Z.Node); break;
}
}
/*
* RepLPtr
*
* Replace pointer variable *A by value B.
*
* A SysError may occur, in which case *A remains unchanged.
*/
void RepLPtr (A,P)
MetaPtr A;
ListPtr P;
{
P = CopyLPtr (P); /* Copy P first so DelLPtr can't trash *P */
if (SysError) return;
DelLPtr (*A);
*A = P;
}
/*
* MakeCopy
*
* Make a copy of a non-empty list.
*
* Input
* P = pointer to list
*
* Output
* *A = pointer to identical list with LRef == LRefOne
* result = metapointer to Next field of end of result list
*
* A SysError may occur, in which case *A remains unchanged.
*
* All sublist-head reference-counts are incremented if no error occurs.
*/
MetaPtr MakeCopy (A,P)
register ListPtr *A,P;
{
register ListPtr Q;
ListPtr R=NULL; /* R = root of new list */
NewList (&R,ListLength (P));
if (SysError) return NULL;
Q = R;
while (1) {
if (Scalar (P->Val.Tag)) {
Q->Val.Data = P->Val.Data;
Q->Val.Tag = P->Val.Tag;
} else {
CopyObject (& Q->Val,& P->Val);
if (SysError) {DelLPtr (R); return NULL;};
}
P = P->Next;
if (P == NULL) break;
Q = Q->Next;
};
*A = R;
return &Q->Next;
}
/*
* CopyTop
*
* Replace *A with a pointer to a fresh (top level) copy of *A.
*
* Input
* *A = pointer to list
* Output
* *A = pointer to identical list with LRef == LRefOne for top level
*
* A SysError may occur, in which case *A remains unchanged.
*/
void CopyTop (A)
register MetaPtr A;
{
register ListPtr P;
while (1) { /* Search for shared part of list */
P = *A;
if (P == NULL) return;
if (P->LRef != LRefOne) break;
Stat (StatRecycle++);
A = & P->Next;
}
(void) MakeCopy (A,P);
P->LRef--;
if (SysError) (*A)->LRef++;
}
/*
* Copy2Top
*
* Replace *A with a pointer to a fresh (top 2 levels) of *A.
*
* Input
* *A = pointer to list
* Output
* *A = pointer to identical list with LRef == LRefOne
* for both top level and any immediate sublists.
*
* A SysError may occur, in which case *A remains unchanged.
*/
void Copy2Top (A)
register MetaPtr A;
{
register ListPtr P;
while (1) { /* Search for shared part of list */
P = *A;
if (P == NULL) return;
if (P->LRef != LRefOne) break;
if (P->Val.Tag == LIST) {
CopyTop (&P->Val.List);
if (SysError) return;
}
Stat (StatRecycle++);
A = & P->Next;
}
/* (*A) now points to shared list */
(void) MakeCopy (A,(P = *A));
if (SysError) return;
P->LRef--;
P = *A;
do
if (P->Val.Tag == LIST && *(A = &P->Val.List) != NULL) {
/*
* There must some more elegant way to efficiently merge these
* two cases.
*/
(*A)->LRef--; /* will be incremented by MakeCopy */
(void) MakeCopy (A,*A);
if (SysError) return;
}
while ((P=P->Next) != NULL);
}
/****************************** end of list.c ******************************/
SHAR_EOF
if test -f 'interp/main.c'
then
echo shar: over-writing existing file "'interp/main.c'"
fi
cat << \SHAR_EOF > 'interp/main.c'
/****** main.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 "cache.h"
#include "stats.h"
#if OPSYS!=CTSS
#endif
static char Version[] = "\nIllinois FP 0.5";
static char Author [] = " Arch D. Robison";
static char Date [] = " Dec 5, 1986\n";
#if OPSYS==UNIX
#define OPSYSTEM "UNIX"
#endif
#if OPSYS==MSDOS
#define OPSYSTEM "MS-DOS"
#endif
#if OPSYS==CTSS
#define OPSYSTEM "CTSS"
#endif
boolean LongPathFlag = 0;
#ifdef COMPILE
boolean CompilerFlag = 0; /* Enable compiler if set */
boolean RuleFlag = 0; /* Display rules if set */
#endif
private void Init ()
{
extern void D_arith (), D_form (), D_pred (), D_misc (), D_seq (),
D_ss (), D_subseq (), D_string (), D_cray (), D_vector ();
extern void InitString (), InitNode (), InitFile ();
extern char RootPath[]; /* from file.c */
#if OPSYS==MSDOS
char CWD [64];
#endif
#if OPSYS==UNIX
extern void EnvGet ();
#endif
if (Debug & DebugInit) printf ("enter Init\n");
InitString ();
#if OPSYS==MSDOS
CWDGet (CWD,MAXPATH);
#endif
#if OPSYS==UNIX
EnvGet ("IFProot",RootPath,MAXPATH); /* Check for RootPath */
#endif
#if ECACHE
InitCache ();
#endif
InitNode ();
D_arith ();
D_form ();
D_pred ();
D_seq ();
D_subseq ();
D_misc ();
D_ss ();
D_string ();
#if OPSYS==MSDOS
InitFile (CWD);
#endif
#if OPSYS==UNIX || OPSYS==CTSS
InitFile ();
#endif
#ifdef COMPILE
if (CompilerFlag) {
extern void InitSymTab (), InitCompiler ();
InitSymTab ();
InitCompiler ();
}
#endif
#ifdef GRAPHICS
InitDraw (); /* for CS9000 graphics only */
#endif
#if STATS
printf (" (stats)");
#endif
if (Debug & DebugInit) printf ("exit Init\n");
}
extern void UserLoop ();
/*
* GetOptions
*
* Process command line options.
*
* Input
* argv = command line arguments
* argc = argument count
*/
private void GetOptions (argc,argv)
int argc;
char *argv[];
{
int k;
char *P;
for (k=1; k= '0' && *P <= '2')
Cache[*P-'0'].Enable = 1;
else
printf ("[unknown -e option = %c] ",*P);
break;
#endif /* ECACHE */
case 'l': LongPathFlag = 1; break;
default:
printf ("[unknown option = %c] ",*P);
P = "";
break;
}
}
main (argc, argv)
int argc;
char *argv[];
{
printf ("%s: (%s)",Version,OPSYSTEM);
(void) fflush (stdout);
GetOptions (argc,argv);
Init ();
printf ("\n\n");
UserLoop ();
Terminate();
if (Debug & DebugInit) printf ("normal exit\n");
exit (0);
}
/************************** end of main.c **************************/
SHAR_EOF
if test -f 'interp/node.c'
then
echo shar: over-writing existing file "'interp/node.c'"
fi
cat << \SHAR_EOF > 'interp/node.c'
/****** node.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: Nov 23, 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 "struct.h"
#include "node.h"
#include "umax.h"
#include "string.h"
/********************************* NODE RULES ******************************
Function definitions are stored in nodes, which are arranged in a tree
structure mimicking the UNIX file structure. Below is an example:
Rm
|
Am---Bi----Cm-------Dd
| |
Xd Yd--Zd
Rm is the root node, with children Am,Bi,Cm, and Dd. Nodes can be one of three
types: module (m), import (i), or definition (d). Only definition nodes
have a reference count greater than 1. Only module nodes have children.
****************************** end of node rules **************************/
NodePtr RootNode,SysNode,LogicNode,ArithNode;
/* Free nodes have NREF == 0 and are linked by NodeSib field */
NodePtr FreeNode = NULL;
/*
* DelNPtr
*
* Note: node pointers always have a parent pointer to them, so
* we don't have to delete them here.
*
* Input
* N = pointer to node
*/
void DelNPtr (N)
NodePtr N;
{
rsemaphore_enter (NRefSemaphore);
if (N != NULL) N->NRef--;
rsemaphore_exit (NRefSemaphore);
}
/*
* CopyNPtr
*/
NodePtr CopyNPtr (N)
NodePtr N;
{
rsemaphore_enter (NRefSemaphore);
if (N != NULL && !++N->NRef) IntError ("CopyNPtr: too many refs");
rsemaphore_exit (NRefSemaphore);
return N;
}
/*
* NewNode
*
* Point *N to new node from free list. The input value of *N is
* put in the NodeSib field of the new node.
*
* A SysError may occur, in which case *N is unchanged.
*/
private void NewNode (N)
NodePtr *N;
{
extern NodePtr AllocNodePage ();
register NodePtr T;
rsemaphore_enter (NRefSemaphore);
if (FreeNode == NULL && (FreeNode = AllocNodePage ()) == NULL) {
printf ("NO MORE NODE CELLS LEFT\n");
SysError = NO_NODE_FREE;
} else {
T = FreeNode;
FreeNode = FreeNode->NodeSib;
T->NodeSib = *N;
*N = T;
}
rsemaphore_exit (NRefSemaphore);
}
/*
* FindNode
*
* Find a node within a module with a specified name.
*
* Input
* M = pointer to module node
* S = pointer to string
*
* Output
* result = NULL if node not found, pointer to node otherwise
*/
NodePtr FindNode (M,S)
register NodePtr M;
StrPtr S;
{
if (M->NodeType == MODULE)
for (M = M->NodeData.NodeMod.FirstChild; M!=NULL; M=M->NodeSib)
if (0==StrComp (M->NodeName,S)) return M;
return NULL;
}
/*
* MakePath
*
* Make the path list for a given node
*
* Input
* *N = module node
* Output
* *result = path list
*/
ListPtr MakePath (N)
NodePtr N;
{
ListPtr P;
rsemaphore_enter (NRefSemaphore);
P = NULL;
while (N->NodeParent != NULL) {
NewList (&P,1L);
P->Val.Tag = STRING;
P->Val.String = CopySPtr (N->NodeName);
N = N->NodeParent;
}
rsemaphore_exit (NRefSemaphore);
return P;
}
/*
* MakeChild
*
* Find (or create if necessary) a new child node with a specified name.
*
* Input
* M = Parent node
* S = name of child
*
* Output
* N = pointer to child
*
* A SysError may occur.
*/
NodePtr MakeChild (M,S)
NodePtr M;
StrPtr S;
{
register NodePtr N;
rsemaphore_enter (NRefSemaphore);
N = FindNode (M,S);
if (N==NULL) {
NewNode (&M->NodeData.NodeMod.FirstChild);
if (SysError) {
N = NULL;
goto exit;
}
N = M->NodeData.NodeMod.FirstChild;
N->NodeParent = M;
N->NodeName = CopySPtr (S);
N->NodeType = NEWNODE;
}
exit:
rsemaphore_exit (NRefSemaphore);
return N;
}
/*
* Initialize a module node
*
* Input
* M = pointer to new node
*/
void InitModule (M)
register NodePtr M;
{
M->NodeType = MODULE;
M->NodeData.NodeMod.FirstChild = NULL;
ReadImport (M);
}
/*
* MakeNode
*
* Create all nodes required by a path.
*
* Input
* Path = pointer to path list
* Type = type to make node if new node
* Output
* result = pointer to node specified by path or
* NULL if an error occurred.
*/
NodePtr MakeNode (Path,Type)
ListPtr Path;
int Type;
{
register NodePtr M;
register ListPtr P;
rsemaphore_enter (NRefSemaphore);
M = RootNode;
for (P=Path; P != NULL; P=P->Next)
if (P->Val.Tag != STRING) return NULL;
else {
M = MakeChild (M,P->Val.String);
if (M->NodeType == NEWNODE)
if (P->Next!=NULL) InitModule (M);
else
switch (M->NodeType = Type) {
case DEF:
M->NodeData.NodeDef.DefCode.Tag = BOTTOM;
M->NodeData.NodeDef.DefFlags = 0;
break;
case MODULE:
InitModule (M);
break;
}
}
rsemaphore_exit (NRefSemaphore);
return M;
}
/*
* DelImport
*
* Delete all information affected by the %IMPORT file for a module node
* in preparation for rereading the %IMPORT file.
*
* Input
* M = pointer to module node
*
* Notes
* IMPORT nodes can be returned to the free list since their
* reference counts are always 1.
*/
void DelImport (M)
NodePtr M;
{
register NodePtr *L;
register NodePtr N;
rsemaphore_enter (NRefSemaphore);
for (L = &M->NodeData.NodeMod.FirstChild; (N = *L)!= NULL; )
switch (N->NodeType) {
case IMPORT: /* Return IMPORT nodes to free list */
DelSPtr (N->NodeName);
RepTag (&N->NodeData.NodeImp.ImpDef,BOTTOM);
Rot3 ((MetaPtr) &FreeNode, (MetaPtr) L, (MetaPtr) &N->NodeSib);
break;
case DEF: /* Delete local function definitions */
if (N->NodeData.NodeDef.DefCode.Tag != CODE)
RepTag (&N->NodeData.NodeDef.DefCode,BOTTOM);
L = &N->NodeSib;
break;
case MODULE:
L = &N->NodeSib;
break;
default:
printf ("Invalid NodeType in node tree: %d\n",N->NodeType);
L = &N->NodeSib;
break;
}
rsemaphore_exit (NRefSemaphore);
}
/*
* LinkPath
*
* Convert a path list to a node if possible.
*
* Input
* *Def = path list
* Type = NodeType value if new node
*
* Output
* *Def = node or not changed if error occurs
*/
void LinkPath (Path,Type)
ObjectPtr Path;
int Type;
{
register NodePtr N;
rsemaphore_enter (NRefSemaphore);
N = MakeNode (Path->List,Type);
if (N != NULL) {
RepTag (Path,NODE);
Path->Node = CopyNPtr (N);
}
rsemaphore_exit (NRefSemaphore);
}
/*
* SignExtend
*
* Sign extend a byte. Not all machines have signed characters.
*/
#define SignExtend(B) ((((B) + 0x80) & 0xFF) - 0x80)
/*
* PrimDef
*
* Define a primitive function
*
* Input
* *F = object code for function
* S = name of function
* M = module to put function in
* K = code parameter value
*
* Output
* result = pointer to node containing function
*/
/* VARARGS3 */
NodePtr PrimDef (F,S,M,K)
int (*F) ();
char *S;
NodePtr M;
char K;
{
register NodePtr N;
StrPtr T;
T = MakeString (S);
N = MakeChild (M,T);
N->NodeType = DEF;
N->NodeData.NodeDef.DefCode.Tag = CODE;
N->NodeData.NodeDef.DefFlags = 0;
N->NodeData.NodeDef.DefCode.Code.CodePtr = F;
N->NodeData.NodeDef.DefCode.Code.CodeParam = SignExtend (K);
DelSPtr (T);
return N;
}
/*
* GroupDef
*
* Define a group of functions
*
* Input
* T = pointer to table of functions
* N = number entries in table
* M = module node
*/
void GroupDef (T,N,M)
register OpDef *T;
int N;
NodePtr M;
{
while (--N >= 0)
(void) PrimDef (T->OpPtr,T->OpName,M,T->OpParam),
T++;
}
/*
* Initialize root node and 'sys' subnode.
*/
void InitNode ()
{
register NodePtr R;
if (Debug & DebugInit) printf ("enter InitNode\n");
RootNode = NULL;
NewNode (&RootNode);
R = RootNode;
R->NodeSib = NULL;
R->NodeParent = NULL;
R->NodeType = MODULE;
R->NodeName = MakeString ("ROOT");
R->NodeData.NodeMod.FirstChild = NULL;
SysNode = MakeChild (R,MakeString ("sys"));
InitModule (SysNode);
R = MakeChild (R,MakeString ("math"));
InitModule (R);
ArithNode = MakeChild (R,MakeString ("arith"));
InitModule (ArithNode);
LogicNode = MakeChild (R,MakeString ("logic"));
InitModule (LogicNode);
if (Debug & DebugInit) printf ("exit InitNode\n");
}
/****************************** end of node.c ******************************/
SHAR_EOF
if test -f 'interp/node.h'
then
echo shar: over-writing existing file "'interp/node.h'"
fi
cat << \SHAR_EOF > 'interp/node.h'
/****** node.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: July 8, 1986 **/
/** **/
/** Principal Investigators: Prof. R. H. Campbell **/
/** Prof. W. J. Kubitz **/
/** **/
/** **/
/**------------------------------------------------------------------**/
/** (C) Copyright 1987 University of Illinois Board of Trustees **/
/** All Rights Reserved. **/
/**********************************************************************/
#ifndef INCLUDE_NODE_H
#define INCLUDE_NODE_H 1
/*
* Define FETCH as 1 to define "fetch" (^k) functional form, 0 otherwise.
* Define XDEF as 1 to define "xdef" ({...} f) functional form, 0 otherwise.
*/
#define FETCH 0
#define XDEF 1
extern ListPtr MakePath ();
extern NodePtr CopyNPtr (), FindNode ();
extern NodePtr MakeNode (), MakeChild (), PrimDef ();
extern NodePtr RootNode, SysNode, ArithNode, LogicNode;
extern void DelNPtr (), FormPath (), GroupDef (), LinkPath ();
void InitNode ();
typedef struct { /* Used for node initialization tables */
char *OpName;
char OpParam;
int (*OpPtr) (); /* Actually void, but compiler complains about void */
} OpDef; /* in static initializations of this structure */
#define OpCount(OpTable) (sizeof(OpTable)/sizeof(OpTable[0]))
extern NodePtr FormNode[];
/*
* Subscripts for FormNode
*
* These must correspond to the entries in the FormOpTable in forms.c
*/
#define NODE_C 0
#define NODE_Comp 1
#define NODE_Cons 2
#define NODE_Each 3
#define NODE_Fetch 4
#define NODE_Filter (4 + FETCH)
#define NODE_If (5 + FETCH)
#define NODE_RInsert (6 + FETCH)
#define NODE_Out (7 + FETCH)
#define NODE_Sel (8 + FETCH)
#define NODE_While (9 + FETCH)
#define NODE_XDef (9 + FETCH + XDEF)
#define FORM_TABLE_SIZE (10 + FETCH + XDEF)
typedef struct {
NodePtr FormNode; /* Node pointer for form */
char *FormInPrefix;
OpDef FormOp;
char *FormComment; /* Comment for `expected' error message */
} FormEntry;
extern FormEntry FormTable[FORM_TABLE_SIZE];
#endif
/****************************** end of node.h ******************************/
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@uund, d, das