scyther/src/tracebuf.c

203 lines
4.2 KiB
C

/*
* tracebuf.c
*
* trace buffer operations
*/
#include <stdio.h>
#include <stdlib.h>
#include "system.h"
#include "memory.h"
#include "tracebuf.h"
#include "varbuf.h"
/* reconstruct the knowledge sequence, -1 if it can be done, event nr of last depending read otherwise.
* There is one exception: if it returns tb->length, the required terms are not in the last knowledge
*/
int
tracebufRebuildKnow (struct tracebuf *tb)
{
Knowledge k;
Roledef rd;
int i;
int flag;
Termlist tl;
if (tb == NULL || tb->length == 0)
{
/* stupid, but true */
return -1;
}
flag = -1;
k = knowledgeDuplicate (tb->know[0]);
i = 0;
while (i < tb->length)
{
rd = tb->event[i];
if (tb->status[i] != S_RED)
{
/* simulate execution of the event */
switch (rd->type)
{
case READ:
if (!inKnowledge (k, rd->message))
{
flag = i;
}
break;
case SEND:
knowledgeAddTerm (k, rd->message);
break;
case CLAIM:
/* TODO parse term requirements ? */
/* Probably not needed */
break;
default:
/* Anything else */
break;
}
}
/* write the new knowledge, overwriting old stuff */
knowledgeDelete (tb->know[i + 1]);
tb->know[i + 1] = knowledgeDuplicate (k);
i++;
}
tl = tb->requiredterms;
while (tl != NULL)
{
if (!inKnowledge (k, tl->term))
{
flag = tb->length;
}
tl = tl->next;
}
knowledgeDelete (k);
return flag;
}
/*
* traceBufInit
*
* initializes the trace buffer.
*/
struct tracebuf *
tracebufInit (void)
{
struct tracebuf *tb =
(struct tracebuf *) memAlloc (sizeof (struct tracebuf));
tb->length = 0;
tb->reallength = 0;
tb->event = NULL;
tb->know = NULL;
tb->run = NULL;
tb->status = NULL;
tb->link = NULL;
tb->requiredterms = NULL;
tb->violatedclaim = 0;
tb->variables = NULL;
return tb;
}
void
tracebufDone (struct tracebuf *tb)
{
Roledef rd;
if (tb == NULL)
{
return;
}
varbufDone (tb->variables);
if (tb->length > 0)
{
int i;
i = 0;
/* note: knowledge domain is length+1 */
knowledgeDelete (tb->know[0]);
while (i < tb->length)
{
rd = tb->event[i];
termDelete (rd->from);
termDelete (rd->to);
termDelete (rd->message);
roledefDelete (rd);
knowledgeDelete (tb->know[i + 1]);
i++;
}
memFree (tb->know, (i + 1) * sizeof (struct knowledge *));
memFree (tb->event, i * sizeof (struct roledef *));
memFree (tb->run, i * sizeof (int));
memFree (tb->status, i * sizeof (int));
memFree (tb->link, i * sizeof (int));
}
memFree (tb, sizeof (tracebuf));
}
struct tracebuf *
tracebufSet (const System sys, int length, int claimev)
{
struct tracebuf *tb;
int i;
Roledef rd;
/* TODO For the constraint logic approach, we would simply insert
* any constant from the constraint for a variable.
*/
tb = tracebufInit ();
if (length == 0)
{
return tb;
}
tb->length = length;
tb->reallength = length;
tb->variables = (Varbuf) varbufInit (sys);
tb->event = (Roledef *) memAlloc (length * sizeof (struct roledef *));
tb->status = (int *) memAlloc (length * sizeof (int));
tb->link = (int *) memAlloc (length * sizeof (int));
tb->run = (int *) memAlloc (length * sizeof (int));
tb->know =
(Knowledge *) memAlloc ((length + 1) * sizeof (struct knowledge *));
/* when duplicating the knowledge, we want to instantiate the variables as well
*/
tb->know[0] = knowledgeSubstDo (sys->traceKnow[0]);
i = 0;
while (i < length)
{
rd = roledefDuplicate1 (sys->traceEvent[i]);
if (rd == NULL)
{
printf ("Empty event in trace at %i of %i?\n", i, length);
exit (1);
}
/* make a copy without variables */
rd->to = termDuplicateUV (rd->to);
rd->from = termDuplicateUV (rd->from);
rd->message = termDuplicateUV (rd->message);
tb->event[i] = rd;
tb->link[i] = -1;
tb->status[i] = S_UNK;
tb->run[i] = sys->traceRun[i];
tb->know[i + 1] = NULL;
i++;
}
/* mark claim */
tb->violatedclaim = claimev;
tb->status[claimev] = S_OKE;
tracebufRebuildKnow (tb);
return tb;
}