scyther/src/termlists.c

703 lines
12 KiB
C
Raw Normal View History

2004-04-23 11:58:43 +01:00
#include <stdlib.h>
#include <stdio.h>
#include "termlists.h"
#include "debug.h"
#include "memory.h"
/* system constants.
* declared in compiler.c
*/
extern Term TERM_Function;
extern Term TERM_Hidden;
void
termlistsInit (void)
{
return;
}
void
termlistsDone (void)
{
return;
}
/* inline candidate */
Termlist
makeTermlist ()
{
return (Termlist) memAlloc (sizeof (struct termlist));
}
/*
termlistDuplicate
A deep copy.
*/
Termlist
termlistDuplicate (Termlist tl)
{
Termlist newtl;
if (tl == NULL)
return NULL;
newtl = makeTermlist ();
newtl->term = termDuplicate (tl->term);
newtl->prev = NULL;
newtl->next = termlistDuplicate (tl->next);
if (newtl->next != NULL)
(newtl->next)->prev = newtl;
return newtl;
}
/*
termlistShallow
A shallow copy, because I gather we won't be modifying any terms, only
termlists. Oh, and it reverses the order :) Don't forget!
*/
Termlist
termlistShallow (Termlist tl)
{
Termlist newtl;
newtl = NULL;
while (tl != NULL)
{
newtl = termlistAdd (newtl, tl->term);
tl = tl->next;
}
return newtl;
}
/*
termlistDelete
(shallow)
*/
void
termlistDelete (Termlist tl)
{
if (tl == NULL)
return;
termlistDelete (tl->next);
memFree (tl, sizeof (struct termlist));
}
/*
termlistDestroy
(deep)
*/
void
termlistDestroy (Termlist tl)
{
if (tl == NULL)
return;
termlistDestroy (tl->next);
termDelete (tl->term);
memFree (tl, sizeof (struct termlist));
}
/*
inTermlist
check whether a term occurs in a termlist
*/
int
inTermlist (Termlist tl, Term term)
{
if (tl == NULL)
{
if (term == NULL)
return 1;
else
return 0;
}
else
{
if (isTermEqual (tl->term, term))
return 1;
else
return inTermlist (tl->next, term);
}
}
/* are all elements of list 1 in list 2, and vice versa?
Note that we assume unique elements !
*/
int
isTermlistEqual (Termlist tl1, Termlist tl2)
{
if (termlistLength (tl1) != termlistLength (tl2))
return 0;
while (tl2 != NULL)
{
if (!inTermlist (tl1, tl2->term))
return 0;
tl2 = tl2->next;
}
return 1;
}
/*
termlistAdd
Adds a term. Duplicates are allowed.
A new list pointer is returned.
*/
Termlist
termlistAdd (Termlist tl, Term term)
{
Termlist newtl;
newtl = makeTermlist ();
newtl->term = term;
newtl->next = tl;
if (tl == NULL)
{
newtl->prev = NULL;
}
else
{
newtl->prev = tl->prev;
if (newtl->prev != NULL)
(newtl->prev)->next = newtl;
tl->prev = newtl;
}
return newtl;
}
/*
termlistAppend
Appends a term to the end of the list. Duplicates are allowed.
A new list pointer is returned.
*/
Termlist
termlistAppend (const Termlist tl, const Term term)
{
Termlist newtl;
Termlist scantl;
newtl = makeTermlist ();
newtl->term = term;
newtl->next = NULL;
if (tl == NULL)
{
newtl->prev = NULL;
return newtl;
}
else
{
scantl = tl;
while (scantl->next != NULL)
scantl = scantl->next;
scantl->next = newtl;
newtl->prev = scantl;
}
return tl;
}
Termlist
termlistConcat (Termlist tl1, Termlist tl2)
{
if (tl1 == NULL)
return tl2;
if (tl2 == NULL)
return tl1;
Termlist scan = tl1;
while (scan->next != NULL)
scan = scan->next;
scan->next = tl2;
return tl1;
}
/*
termlistDelTerm
remove the current element from the termlist. Easier because of the
double linked list.
*/
Termlist
termlistDelTerm (Termlist tl)
{
Termlist newhead;
if (tl == NULL)
return NULL;
if (tl->prev != NULL)
{
(tl->prev)->next = tl->next;
newhead = tl->prev;
while (newhead->prev != NULL)
newhead = newhead->prev;
}
else
{
newhead = tl->next;
}
if (tl->next != NULL)
(tl->next)->prev = tl->prev;
memFree (tl, sizeof (struct termlist));
return newhead;
}
Termlist
termlistConjunct (Termlist tl1, Termlist tl2)
{
Termlist newtl;
Termlist scan;
scan = tl1;
newtl = NULL;
while (scan != NULL)
{
if (inTermlist (tl2, scan->term))
newtl = termlistAdd (newtl, scan->term);
scan = scan->next;
}
return newtl;
}
Termlist
termlistConjunctType (Termlist tl1, Termlist tl2, int termtype)
{
Termlist newtl;
Termlist scan;
scan = tl1;
newtl = NULL;
while (scan != NULL)
{
if (((scan->term)->type == termtype) && (inTermlist (tl2, scan->term)))
newtl = termlistAdd (newtl, scan->term);
scan = scan->next;
}
return newtl;
}
Termlist
termlistType (Termlist tl, int termtype)
{
Termlist newtl;
Termlist scan;
scan = tl;
newtl = NULL;
while (scan != NULL)
{
if ((scan->term)->type == termtype)
newtl = termlistAdd (newtl, scan->term);
scan = scan->next;
}
return newtl;
}
void
termlistPrint (Termlist tl)
{
if (tl == NULL)
{
printf ("[Empty]");
return;
}
printf ("[");
while (tl != NULL)
{
termPrint (tl->term);
tl = tl->next;
if (tl != NULL)
printf(", ");
}
printf ("]");
}
Termlist
termlistAddVariables (Termlist tl, Term t)
{
if (t == NULL)
return tl;
t = deVar (t);
if (isTermLeaf (t))
{
if (isTermVariable (t) && !inTermlist (tl, t))
return termlistAdd (tl, t);
else
return tl;
}
else
{
if (isTermEncrypt (t))
return termlistAddVariables (termlistAddVariables (tl, t->op),
t->key);
else
return
termlistAddVariables (termlistAddVariables (tl, t->op1), t->op2);
}
}
Termlist
termlistAddRealVariables (Termlist tl, Term t)
{
if (t == NULL)
return tl;
if (realTermLeaf (t))
{
if (realTermVariable (t))
{
Term tbuf = t->subst;
t->subst = NULL;
if (!inTermlist (tl,t))
{
tl = termlistAdd (tl,t);
}
t->subst = tbuf;
return termlistAddRealVariables (tl,t->subst);
}
else
{
return tl;
}
}
else
{
if (realTermEncrypt (t))
return termlistAddVariables (termlistAddVariables (tl, t->op),
t->key);
else
return
termlistAddVariables (termlistAddVariables (tl, t->op1), t->op2);
}
}
Termlist
termlistAddBasic (Termlist tl, Term t)
{
if (t == NULL)
return tl;
if (!isTermLeaf (t))
{
if (isTermEncrypt (t))
return termlistAddBasic (termlistAddBasic (tl, t->op), t->key);
else
return termlistAddBasic (termlistAddBasic (tl, t->op1), t->op2);
}
else
{
if (!inTermlist (tl, t))
{
return termlistAdd (tl, t);
}
}
return tl;
}
Termlist
termlistAddBasics (Termlist tl, Termlist scan)
{
while (scan != NULL)
{
tl = termlistAddBasic (tl, scan->term);
scan = scan->next;
}
return tl;
}
/*
* termlistMinusTerm
*
* Remove a term from a termlist, and yield a new termlist pointer.
* Semantics: remove the first occurrence of the term.
*/
Termlist
termlistMinusTerm (Termlist tl, Term t)
{
Termlist scan;
scan = tl;
while (scan != NULL)
{
if (isTermEqual (scan->term, t))
return termlistDelTerm (scan);
else
scan = scan->next;
}
return tl;
}
int
termlistLength (Termlist tl)
{
int i = 0;
while (tl != NULL)
{
tl = tl->next;
i++;
}
return i;
}
/*
inverseKey
Gives the inverse Key of some term (which is used to encrypt something), as is defined
by the termlist, which is a list of key1,key1inv, key2, key2inv, etc...
*/
Term
inverseKey (Termlist inverses, Term key)
{
key = deVar (key);
/* is this a function application? i.e. hash? */
if (isTermLeaf (key) && inTermlist (key->stype, TERM_Function))
{
/* functions cannot be inverted by default */
return termDuplicate (TERM_Hidden);
}
/* check for the special case first: when it is effectively a function application */
if (isTermEncrypt (key) && isTermLeaf (key->key)
&& inTermlist (deVar (key->key)->stype, TERM_Function))
{
/* we are scanning for functions */
/* scan the list */
/* key is function application kk(op), or {op}kk */
Term funKey (Term orig, Term newk)
{
/* in: {op}kk, nk
* out: {op'}nk */
return makeTermEncrypt (termDuplicate (orig->op),
termDuplicate (newk));
}
while (inverses != NULL && inverses->next != NULL)
{
if (isTermEqual (key->key, inverses->term))
return funKey (key, inverses->next->term);
if (isTermEqual (key->key, inverses->next->term))
return funKey (key, inverses->term);
inverses = inverses->next->next;
}
}
else
{
/* scanning for a direct inverse */
/* scan the list */
while (inverses != NULL && inverses->next != NULL)
{
if (isTermEqual (key, inverses->term))
return termDuplicate (inverses->next->term);
if (isTermEqual (key, inverses->next->term))
return termDuplicate (inverses->term);
inverses = inverses->next->next;
}
}
return termDuplicate (key); /* defaults to symmetrical */
}
/*
* localTerm
*
* Creates a term local to a run.
* We assume that at this point, no variables have been instantiated yet that occur in this term.
* We also assume that fromlist, tolist and locals only hold real leaves.
*/
Term
termLocal (const Term t, Termlist fromlist, Termlist tolist,
const Termlist locals, const int runid)
{
if (t == NULL)
return NULL;
if (realTermLeaf (t))
{
while (fromlist != NULL && tolist != NULL)
{
if (isTermEqual (fromlist->term, t))
{
// matches!
return tolist->term;
}
fromlist = fromlist->next;
tolist = tolist->next;
}
if (inTermlist (locals, t))
{
// return termRunid(t,runid);
}
return t;
}
else
{
Term newt = termDuplicate (t);
if (realTermTuple (t))
{
newt->op1 = termLocal (t->op1, fromlist, tolist, locals, runid);
newt->op2 = termLocal (t->op2, fromlist, tolist, locals, runid);
}
else
{
newt->op = termLocal (t->op, fromlist, tolist, locals, runid);
newt->key = termLocal (t->key, fromlist, tolist, locals, runid);
}
return newt;
}
}
/*
* termlistLocal
*
* We expand the previous concept to termlists.
*/
Termlist
termlistLocal (Termlist tl, const Termlist fromlist, const Termlist tolist,
const Termlist locals, int runid)
{
Termlist newtl = NULL;
while (tl != NULL)
{
newtl =
termlistAdd (newtl,
termLocal (tl->term, fromlist, tolist, locals, runid));
tl = tl->next;
}
return newtl;
}
/*
* Check whether tl2 is contained in tl1.
*/
int
termlistContained (const Termlist tlbig, Termlist tlsmall)
{
while (tlsmall != NULL)
{
if (!inTermlist (tlbig, tlsmall->term))
return 0;
tlsmall = tlsmall->next;
}
return 1;
}
/*
* Determine whether a variable has been substituted with something with
* the right type.
*/
int
validSubst (const int matchmode, const Term term)
{
if (!realTermVariable (term) || term->subst == NULL)
return 1;
else
{
switch (matchmode)
{
case 0: /* real type match */
return realTermLeaf (term->subst)
&& termlistContained (term->stype, term->subst->stype);
case 1: /* basic type match */
/* subst must be a leaf */
/* TODO: what about functions? */
return realTermLeaf (term->subst);
case 2: /* no type match */
/* anything goes */
return 1;
default:
return 0;
}
}
}
/*
* termFunction
*
* An assist function that helps to simulate Term->Term functions, using
* termlists. One termlist functions as the domain, and the other as the
* range.
*
* Extending a function with a value y = f(x) amounts to extending the
* domain with x, and the range with y.
*/
Term
termFunction (Termlist fromlist, Termlist tolist, Term tx)
{
while (fromlist != NULL && tolist != NULL)
{
if (isTermEqual (fromlist->term, tx))
{
return tolist->term;
}
fromlist = fromlist->next;
tolist = tolist->next;
}
return NULL;
}
/*
* Forward the termlist pointer to the last item
*/
Termlist
termlistForward (Termlist tl)
{
if (tl == NULL)
{
return NULL;
}
else
{
while (tl->next != NULL)
{
tl = tl->next;
}
return tl;
}
}