2004-04-23 11:58:43 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "tac.h"
|
2004-07-24 20:07:29 +01:00
|
|
|
#include "term.h"
|
|
|
|
#include "termlist.h"
|
2004-08-27 13:36:23 +01:00
|
|
|
#include "label.h"
|
2004-06-14 23:08:47 +01:00
|
|
|
#include "memory.h"
|
2004-07-24 16:08:35 +01:00
|
|
|
#include "system.h"
|
2004-04-23 11:58:43 +01:00
|
|
|
#include "knowledge.h"
|
2004-07-24 20:07:29 +01:00
|
|
|
#include "symbol.h"
|
|
|
|
#include "substitution.h"
|
2004-04-23 11:58:43 +01:00
|
|
|
#include "compiler.h"
|
2005-06-07 16:02:27 +01:00
|
|
|
#include "switches.h"
|
2005-06-16 15:10:07 +01:00
|
|
|
#include "specialterm.h"
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Simple sys pointer as a global. Yields cleaner code although it's against programming standards.
|
|
|
|
It is declared as static to hide it from the outside world, and to indicate its status.
|
|
|
|
Other modules will just see a nicely implemented sys parameter of compile, so we can always change
|
|
|
|
it later if somebody complains. Which they won't.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static System sys;
|
2004-08-09 10:42:58 +01:00
|
|
|
static Tac tac_root;
|
2004-04-23 11:58:43 +01:00
|
|
|
|
2004-08-27 11:08:03 +01:00
|
|
|
/*
|
|
|
|
* Declaration from system.c
|
|
|
|
*/
|
|
|
|
extern int protocolCount;
|
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
/*
|
|
|
|
Forward declarations.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void tacProcess (Tac tc);
|
|
|
|
void levelInit (void);
|
|
|
|
void levelDone (void);
|
|
|
|
Term levelFind (Symbol s, int i);
|
|
|
|
Term symbolFind (Symbol s);
|
|
|
|
Term tacTerm (Tac tc);
|
|
|
|
Termlist tacTermlist (Tac tc);
|
2004-08-12 12:55:03 +01:00
|
|
|
Term levelDeclare (Symbol s, int isVar, int level);
|
2004-08-12 10:14:31 +01:00
|
|
|
void compute_role_variables (const System sys, Protocol p, Role r);
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Global stuff
|
|
|
|
*/
|
|
|
|
|
2004-06-14 10:15:42 +01:00
|
|
|
//! Levels of scope: global, protocol, role
|
2004-04-23 11:58:43 +01:00
|
|
|
#define MAXLEVELS 3
|
|
|
|
static Termlist leveltl[MAXLEVELS];
|
|
|
|
static int level;
|
|
|
|
static int maxruns;
|
|
|
|
static Protocol thisProtocol;
|
|
|
|
static Role thisRole;
|
|
|
|
|
2004-08-09 10:42:58 +01:00
|
|
|
//! Init terms and such
|
2004-04-23 11:58:43 +01:00
|
|
|
void
|
2004-08-09 10:42:58 +01:00
|
|
|
compilerInit (const System mysys)
|
2004-04-23 11:58:43 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* transfer to global static variable */
|
|
|
|
sys = mysys;
|
|
|
|
/* init levels */
|
|
|
|
for (i = 0; i < MAXLEVELS; i++)
|
|
|
|
leveltl[i] = NULL;
|
|
|
|
level = -1;
|
|
|
|
levelInit ();
|
|
|
|
|
2005-06-16 15:10:07 +01:00
|
|
|
/* create special terms */
|
|
|
|
specialTermInit (sys);
|
2004-08-09 10:42:58 +01:00
|
|
|
}
|
|
|
|
|
2004-08-12 12:55:03 +01:00
|
|
|
//! Make a global constant
|
2004-08-15 15:07:34 +01:00
|
|
|
Term
|
|
|
|
makeGlobalConstant (const char *s)
|
2004-08-12 12:55:03 +01:00
|
|
|
{
|
2004-08-15 15:07:34 +01:00
|
|
|
return levelDeclare (symbolSysConst (s), 0, 0);
|
2004-08-12 12:55:03 +01:00
|
|
|
}
|
|
|
|
|
2004-08-18 15:06:14 +01:00
|
|
|
//! Make a global variable
|
|
|
|
Term
|
|
|
|
makeGlobalVariable (const char *s)
|
|
|
|
{
|
|
|
|
return levelDeclare (symbolSysConst (s), 1, 0);
|
|
|
|
}
|
|
|
|
|
2004-08-09 10:42:58 +01:00
|
|
|
//! Clean up afterwards
|
|
|
|
void
|
|
|
|
compilerDone (void)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-12-27 13:44:12 +00:00
|
|
|
//! Compute read variables for a role
|
|
|
|
Termlist
|
|
|
|
compute_read_variables (const Role r)
|
|
|
|
{
|
|
|
|
Termlist tl;
|
|
|
|
|
|
|
|
int process_event (Roledef rd)
|
|
|
|
{
|
|
|
|
if (rd->type == READ)
|
|
|
|
{
|
|
|
|
tl = termlistAddVariables (tl, rd->from);
|
|
|
|
tl = termlistAddVariables (tl, rd->to);
|
|
|
|
tl = termlistAddVariables (tl, rd->message);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
tl = NULL;
|
|
|
|
roledef_iterate_events (r->roledef, process_event);
|
|
|
|
return tl;
|
|
|
|
}
|
|
|
|
|
2004-08-09 10:42:58 +01:00
|
|
|
/* ------------------------------------------------------------------- */
|
2004-04-23 11:58:43 +01:00
|
|
|
|
2004-08-09 10:42:58 +01:00
|
|
|
//! Compile the tac into the system
|
|
|
|
/**
|
|
|
|
*@todo Currently, the semantics assume all labels are globally unique, but this is not enforced yet. There should be some automatic renaming when compositing protocols.
|
|
|
|
*\sa oki_nisynch
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
compile (Tac tc, int maxrunsset)
|
|
|
|
{
|
|
|
|
/* Init globals */
|
|
|
|
maxruns = maxrunsset;
|
|
|
|
tac_root = tc;
|
2004-08-12 10:14:31 +01:00
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
/* process the tac */
|
2004-08-09 10:42:58 +01:00
|
|
|
tacProcess (tac_root);
|
2004-04-23 11:58:43 +01:00
|
|
|
|
2004-08-20 20:16:56 +01:00
|
|
|
/* Clean up keylevels */
|
|
|
|
symbol_fix_keylevels ();
|
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
/* cleanup */
|
|
|
|
levelDone ();
|
|
|
|
}
|
|
|
|
|
2004-06-14 10:15:42 +01:00
|
|
|
//! Print error line number.
|
|
|
|
/**
|
|
|
|
*@todo This is obsolete, and should all go to stderr
|
|
|
|
*/
|
2004-04-23 11:58:43 +01:00
|
|
|
void
|
|
|
|
errorTac (int lineno)
|
|
|
|
{
|
|
|
|
printf (" on line %i.\n", lineno);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
|
2004-06-14 10:15:42 +01:00
|
|
|
//! Enter nested scope.
|
2004-04-23 11:58:43 +01:00
|
|
|
void
|
|
|
|
levelInit (void)
|
|
|
|
{
|
|
|
|
level++;
|
|
|
|
if (level >= MAXLEVELS)
|
|
|
|
{
|
2004-06-13 22:42:29 +01:00
|
|
|
error ("level is increased too much.");
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
leveltl[level] = NULL;
|
|
|
|
}
|
|
|
|
|
2004-06-14 10:15:42 +01:00
|
|
|
//! Leave nested scope.
|
2004-04-23 11:58:43 +01:00
|
|
|
void
|
|
|
|
levelDone (void)
|
|
|
|
{
|
|
|
|
if (level < 0)
|
|
|
|
{
|
2004-06-13 22:42:29 +01:00
|
|
|
error ("level is decreased too much.");
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
leveltl[level] = NULL;
|
|
|
|
level--;
|
|
|
|
}
|
|
|
|
|
|
|
|
Term
|
|
|
|
levelDeclare (Symbol s, int isVar, int level)
|
|
|
|
{
|
|
|
|
Term t;
|
|
|
|
|
|
|
|
t = levelFind (s, level);
|
|
|
|
if (t == NULL)
|
|
|
|
{
|
|
|
|
/* new! */
|
|
|
|
if (isVar)
|
|
|
|
{
|
|
|
|
t = makeTermType (VARIABLE, s, -(level + 1));
|
|
|
|
sys->variables = termlistAdd (sys->variables, t);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t = makeTermType (GLOBAL, s, -(level + 1));
|
|
|
|
}
|
|
|
|
leveltl[level] = termlistAdd (leveltl[level], t);
|
|
|
|
|
|
|
|
/* add to relevant list */
|
|
|
|
switch (level)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
sys->locals = termlistAdd (sys->locals, t);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
thisProtocol->locals = termlistAdd (thisProtocol->locals, t);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
thisRole->locals = termlistAdd (thisRole->locals, t);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2005-12-27 13:44:12 +00:00
|
|
|
//! Generate a term from a symbol
|
2004-04-23 11:58:43 +01:00
|
|
|
Term
|
|
|
|
symbolDeclare (Symbol s, int isVar)
|
|
|
|
{
|
|
|
|
return levelDeclare (s, isVar, level);
|
|
|
|
}
|
|
|
|
|
|
|
|
Term
|
|
|
|
levelFind (Symbol s, int level)
|
|
|
|
{
|
|
|
|
Termlist tl;
|
|
|
|
|
|
|
|
tl = leveltl[level];
|
|
|
|
while (tl != NULL)
|
|
|
|
{
|
|
|
|
if (isTermLeaf (tl->term))
|
|
|
|
{
|
2004-11-16 12:07:55 +00:00
|
|
|
if (TermSymb (tl->term) == s)
|
2004-04-23 11:58:43 +01:00
|
|
|
{
|
|
|
|
return tl->term;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tl = tl->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Term
|
|
|
|
symbolFind (Symbol s)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Term t;
|
|
|
|
|
|
|
|
i = level;
|
|
|
|
while (i >= 0)
|
|
|
|
{
|
|
|
|
t = levelFind (s, i);
|
|
|
|
if (t != NULL)
|
|
|
|
return t;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-08-09 10:42:58 +01:00
|
|
|
//! Yield a basic global constant term (we suppose it exists) or NULL, given a string
|
2004-08-09 11:05:58 +01:00
|
|
|
Term
|
|
|
|
findGlobalConstant (const char *s)
|
2004-08-09 10:42:58 +01:00
|
|
|
{
|
|
|
|
return levelFind (lookup (s), 0);
|
|
|
|
}
|
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
void
|
|
|
|
defineUsertype (Tac tcdu)
|
|
|
|
{
|
|
|
|
Tac tc;
|
|
|
|
Term t;
|
|
|
|
Term tfind;
|
|
|
|
|
2004-05-26 09:26:40 +01:00
|
|
|
tc = tcdu->t1.tac;
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
if (tc == NULL)
|
|
|
|
{
|
2004-06-13 22:42:29 +01:00
|
|
|
error ("Empty usertype declaration on line %i.", tcdu->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
while (tc != NULL && tc->op == TAC_STRING)
|
|
|
|
{
|
|
|
|
/* check whether this term is already declared in the same way
|
|
|
|
* (i.e. as a type) */
|
|
|
|
|
2004-05-26 09:26:40 +01:00
|
|
|
tfind = levelFind (tc->t1.sym, 0);
|
2004-04-23 11:58:43 +01:00
|
|
|
if (tfind == NULL)
|
|
|
|
{
|
|
|
|
/* this is what we expected: this type is not declared yet */
|
2004-05-26 09:26:40 +01:00
|
|
|
t = levelDeclare (tc->t1.sym, 0, 0);
|
2004-04-23 11:58:43 +01:00
|
|
|
t->stype = termlistAdd (NULL, TERM_Type);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* oi!, there's already one. Let's hope is is a type too. */
|
|
|
|
if (inTermlist (tfind->stype, TERM_Type))
|
|
|
|
{
|
|
|
|
/* phew. warn anyway */
|
2004-10-19 13:03:40 +01:00
|
|
|
globalError++;
|
2005-12-27 13:44:12 +00:00
|
|
|
eprintf ("warning: double declaration of usertype ");
|
2004-04-23 11:58:43 +01:00
|
|
|
termPrint (tfind);
|
2004-10-19 13:03:40 +01:00
|
|
|
eprintf ("\n");
|
|
|
|
globalError--;
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* that's not right! */
|
2004-08-09 11:05:58 +01:00
|
|
|
error
|
|
|
|
("Conflicting definitions in usertype definition on line %i.",
|
|
|
|
tc->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
tc = tc->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-27 13:44:12 +00:00
|
|
|
//! Declare a variable at the current level
|
2004-04-23 11:58:43 +01:00
|
|
|
void
|
|
|
|
levelTacDeclaration (Tac tc, int isVar)
|
|
|
|
{
|
|
|
|
Tac tscan;
|
|
|
|
Termlist typetl = NULL;
|
|
|
|
Term t;
|
|
|
|
|
2005-12-27 13:44:12 +00:00
|
|
|
// tscan contains the type list (as is const x,z: Term or var y: Term,Ding)
|
2004-05-26 09:26:40 +01:00
|
|
|
tscan = tc->t2.tac;
|
2004-04-23 11:58:43 +01:00
|
|
|
if (!isVar && tscan->next != NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Multiple type definition for constant on line %i.",
|
|
|
|
tscan->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
2005-12-27 13:44:12 +00:00
|
|
|
// scan the whole type info list
|
2004-04-23 11:58:43 +01:00
|
|
|
while (tscan != NULL && tscan->op == TAC_STRING)
|
|
|
|
{
|
|
|
|
/* apparently there is type info, termlist? */
|
2004-05-26 09:26:40 +01:00
|
|
|
t = levelFind (tscan->t1.sym, 0);
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
if (t == NULL)
|
|
|
|
{
|
|
|
|
/* not declared, that is unacceptable. */
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Undeclared type on line %i.", tscan->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!inTermlist (t->stype, TERM_Type))
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Non-type constant in type declaration on line %i.",
|
|
|
|
tscan->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
typetl = termlistAdd (typetl, t);
|
|
|
|
tscan = tscan->next;
|
|
|
|
}
|
2005-12-27 13:44:12 +00:00
|
|
|
/* parse all constants and vars, because a single declaration can contain multiple ones */
|
2004-05-26 09:26:40 +01:00
|
|
|
tscan = tc->t1.tac;
|
2004-04-23 11:58:43 +01:00
|
|
|
while (tscan != NULL)
|
|
|
|
{
|
2005-12-27 13:44:12 +00:00
|
|
|
/* declare this variable/constant with the previously derived type list */
|
2004-05-26 09:26:40 +01:00
|
|
|
t = symbolDeclare (tscan->t1.sym, isVar);
|
2004-04-23 11:58:43 +01:00
|
|
|
t->stype = typetl;
|
2005-12-27 13:44:12 +00:00
|
|
|
if (isVar && level == 2)
|
|
|
|
{
|
|
|
|
/* it is a role variable, so add it to the nicely declared variables */
|
|
|
|
thisRole->declaredvars = termlistAdd (thisRole->declaredvars, t);
|
|
|
|
}
|
2004-04-23 11:58:43 +01:00
|
|
|
tscan = tscan->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
commEvent (int event, Tac tc)
|
|
|
|
{
|
|
|
|
/* Add an event to the roledef, send or read */
|
2004-06-14 23:08:47 +01:00
|
|
|
Claimlist cl;
|
2004-04-23 11:58:43 +01:00
|
|
|
Term fromrole = NULL;
|
|
|
|
Term torole = NULL;
|
|
|
|
Term msg = NULL;
|
|
|
|
Term label = NULL;
|
|
|
|
Term claim = NULL;
|
|
|
|
Term claimbig = NULL;
|
|
|
|
int n = 0;
|
|
|
|
Tac trip;
|
2004-08-27 13:36:23 +01:00
|
|
|
Labelinfo linfo;
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
/* Construct label, if any */
|
2004-05-26 09:26:40 +01:00
|
|
|
if (tc->t1.sym == NULL)
|
2004-04-23 11:58:43 +01:00
|
|
|
{
|
|
|
|
label = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-05-26 09:26:40 +01:00
|
|
|
label = levelFind (tc->t1.sym, level - 1);
|
2004-04-23 11:58:43 +01:00
|
|
|
if (label == NULL)
|
|
|
|
{
|
|
|
|
/* effectively, labels are bound to the protocol */
|
|
|
|
level--;
|
2004-08-27 11:08:03 +01:00
|
|
|
/* leaves a garbage tuple. dunnoh what to do with it */
|
|
|
|
label =
|
|
|
|
makeTermTuple (thisProtocol->nameterm, levelConst (tc->t1.sym));
|
2004-04-23 11:58:43 +01:00
|
|
|
level++;
|
|
|
|
}
|
2004-08-27 11:24:19 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* we already had this label constant */
|
|
|
|
/* leaves a garbage tuple. dunnoh what to do with it */
|
2004-11-16 12:07:55 +00:00
|
|
|
label = makeTermTuple (thisProtocol->nameterm, label);
|
2004-08-27 11:24:19 +01:00
|
|
|
}
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
2004-08-27 13:36:23 +01:00
|
|
|
/**
|
|
|
|
* We now know the label. Find the corresponding labelinfo bit or make a new one
|
|
|
|
*/
|
|
|
|
linfo = label_find (sys->labellist, label);
|
|
|
|
if (linfo == NULL)
|
|
|
|
{
|
|
|
|
/* Not found, make a new one */
|
|
|
|
linfo = label_create (label, thisProtocol);
|
|
|
|
sys->labellist = list_append (sys->labellist, linfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse the specific event type
|
|
|
|
*/
|
2004-05-26 09:26:40 +01:00
|
|
|
trip = tc->t2.tac;
|
2004-04-23 11:58:43 +01:00
|
|
|
switch (event)
|
|
|
|
{
|
|
|
|
case READ:
|
|
|
|
case SEND:
|
|
|
|
/* now parse triplet info */
|
|
|
|
if (trip == NULL || trip->next == NULL || trip->next->next == NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Problem with %i event on line %i.", event, tc->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
fromrole = tacTerm (trip);
|
|
|
|
torole = tacTerm (trip->next);
|
|
|
|
msg = tacTerm (tacTuple ((trip->next->next)));
|
2004-06-16 16:28:20 +01:00
|
|
|
cl = NULL;
|
2004-04-23 11:58:43 +01:00
|
|
|
|
2004-08-20 20:16:56 +01:00
|
|
|
if (event == SEND)
|
|
|
|
{
|
2004-08-27 13:36:23 +01:00
|
|
|
/* set sendrole */
|
2004-08-27 14:40:46 +01:00
|
|
|
if (!isTermEqual (fromrole, thisRole->nameterm))
|
2004-11-16 12:07:55 +00:00
|
|
|
error
|
|
|
|
("Send role does not correspond to execution role at line %i.",
|
|
|
|
tc->lineno);
|
2004-08-27 13:36:23 +01:00
|
|
|
if (linfo->sendrole != NULL)
|
2004-11-16 12:07:55 +00:00
|
|
|
error ("Label defined twice for sendrole!");
|
2004-08-27 13:36:23 +01:00
|
|
|
linfo->sendrole = fromrole;
|
|
|
|
|
2004-08-20 20:16:56 +01:00
|
|
|
/* set keylevels based on send events */
|
|
|
|
term_set_keylevels (fromrole);
|
|
|
|
term_set_keylevels (torole);
|
|
|
|
term_set_keylevels (msg);
|
|
|
|
}
|
2004-08-27 13:36:23 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// READ
|
|
|
|
/* set readrole */
|
2004-08-27 14:40:46 +01:00
|
|
|
if (!isTermEqual (torole, thisRole->nameterm))
|
2004-11-16 12:07:55 +00:00
|
|
|
error
|
|
|
|
("Read role does not correspond to execution role at line %i.",
|
|
|
|
tc->lineno);
|
2004-08-27 13:36:23 +01:00
|
|
|
if (linfo->readrole != NULL)
|
2004-11-16 12:07:55 +00:00
|
|
|
error ("Label defined twice for readrole!");
|
2004-08-27 13:36:23 +01:00
|
|
|
linfo->readrole = torole;
|
|
|
|
}
|
2004-08-20 20:16:56 +01:00
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case CLAIM:
|
|
|
|
/* now parse tuple info */
|
|
|
|
if (trip == NULL || trip->next == NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Problem with claim %i event on line %i.", event,
|
|
|
|
tc->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
fromrole = tacTerm (trip);
|
|
|
|
claimbig = tacTerm (tacTuple ((trip->next)));
|
|
|
|
/* check for several types */
|
|
|
|
claim = tupleProject (claimbig, 0);
|
|
|
|
torole = claim;
|
2004-08-09 10:42:58 +01:00
|
|
|
|
|
|
|
/* check for ignored claim types */
|
2005-06-07 16:02:27 +01:00
|
|
|
if (switches.filterClaim != NULL && switches.filterClaim != claim)
|
2004-08-09 10:42:58 +01:00
|
|
|
{
|
|
|
|
/* abort the construction of the node */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
/* check for obvious flaws */
|
|
|
|
if (claim == NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Invalid claim specification on line %i.", tc->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
if (!inTermlist (claim->stype, TERM_Claim))
|
|
|
|
{
|
|
|
|
printf ("ERROR: unknown claim type ");
|
|
|
|
termPrint (claim);
|
|
|
|
errorTac (trip->next->lineno);
|
|
|
|
}
|
|
|
|
/* unfold parameters to msg */
|
|
|
|
msg = NULL;
|
|
|
|
n = tupleCount (claimbig) - 1;
|
|
|
|
if (n < 1)
|
|
|
|
{
|
|
|
|
/* no parameters */
|
|
|
|
n = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* n parameters */
|
2004-11-16 12:07:55 +00:00
|
|
|
msg = TermOp2 (deVar (claimbig));
|
2004-04-23 11:58:43 +01:00
|
|
|
if (tupleCount (msg) != n)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Problem with claim tuple unfolding at line %i.",
|
|
|
|
trip->next->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-14 23:08:47 +01:00
|
|
|
/* store claim in claim list */
|
2004-08-09 11:05:58 +01:00
|
|
|
|
2004-08-31 13:35:05 +01:00
|
|
|
if (label == NULL)
|
|
|
|
{
|
|
|
|
error ("Claim should have label on line %i.", trip->next->lineno);
|
|
|
|
}
|
2004-06-14 23:08:47 +01:00
|
|
|
// First check whether label is unique
|
|
|
|
cl = sys->claimlist;
|
|
|
|
while (cl != NULL)
|
|
|
|
{
|
|
|
|
if (isTermEqual (cl->label, label))
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
*@todo This should not error exit, but automatically generate a fresh claim label.
|
|
|
|
*/
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("Claim label is not unique at line %i.", tc->lineno);
|
2004-06-14 23:08:47 +01:00
|
|
|
}
|
|
|
|
cl = cl->next;
|
|
|
|
}
|
|
|
|
// Assert: label is unique, add claimlist info
|
|
|
|
cl = memAlloc (sizeof (struct claimlist));
|
2004-07-24 21:30:00 +01:00
|
|
|
cl->type = claim;
|
2004-06-14 23:08:47 +01:00
|
|
|
cl->label = label;
|
2004-08-14 16:59:14 +01:00
|
|
|
cl->protocol = thisProtocol;
|
2004-06-14 23:08:47 +01:00
|
|
|
cl->rolename = fromrole;
|
2004-08-14 16:59:14 +01:00
|
|
|
cl->role = thisRole;
|
2004-08-27 14:40:46 +01:00
|
|
|
if (!isTermEqual (fromrole, thisRole->nameterm))
|
2004-11-16 12:07:55 +00:00
|
|
|
error ("Claim role does not correspond to execution role at line %i.",
|
|
|
|
tc->lineno);
|
2004-08-14 20:19:23 +01:00
|
|
|
cl->roledef = NULL;
|
2004-06-14 23:08:47 +01:00
|
|
|
cl->count = 0;
|
2004-08-19 14:09:35 +01:00
|
|
|
cl->complete = 0;
|
2005-01-14 13:01:31 +00:00
|
|
|
cl->timebound = 0;
|
2004-06-14 23:08:47 +01:00
|
|
|
cl->failed = 0;
|
|
|
|
cl->prec = NULL;
|
2004-08-27 13:36:23 +01:00
|
|
|
cl->roles = NULL;
|
2005-12-27 13:44:12 +00:00
|
|
|
cl->alwaystrue = false;
|
|
|
|
cl->warnings = false;
|
2004-06-14 23:08:47 +01:00
|
|
|
cl->next = sys->claimlist;
|
|
|
|
sys->claimlist = cl;
|
|
|
|
|
2004-04-23 11:58:43 +01:00
|
|
|
/* handles all claim types differently */
|
|
|
|
|
|
|
|
if (claim == CLAIM_Secret)
|
|
|
|
{
|
|
|
|
if (n == 0)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error
|
|
|
|
("Secrecy claim requires a list of terms to be secret on line %i.",
|
|
|
|
trip->next->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
2005-02-19 14:31:15 +00:00
|
|
|
if (n > 1)
|
|
|
|
{
|
|
|
|
error
|
|
|
|
("Secrecy claim on line %i should not contain tuples (for Arachne) until it is officially supported.",
|
|
|
|
trip->next->lineno);
|
|
|
|
}
|
2005-12-27 13:44:12 +00:00
|
|
|
/* now check whether the claim contains variables that can actually be influenced by the intruder */
|
|
|
|
{
|
|
|
|
Termlist claimvars;
|
|
|
|
Termlist readvars;
|
|
|
|
|
|
|
|
claimvars = termlistAddVariables (NULL, msg);
|
|
|
|
readvars = compute_read_variables (thisRole);
|
|
|
|
while (claimvars != NULL)
|
|
|
|
{
|
|
|
|
if (!inTermlist (readvars, claimvars->term))
|
|
|
|
{
|
|
|
|
/* this claimvar does not occur in the reads? */
|
|
|
|
/* then we should ignore it later */
|
|
|
|
cl->alwaystrue = true;
|
|
|
|
cl->warnings = true;
|
|
|
|
}
|
|
|
|
claimvars = claimvars->next;
|
|
|
|
}
|
|
|
|
}
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (claim == CLAIM_Nisynch)
|
|
|
|
{
|
|
|
|
if (n != 0)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("NISYNCH claim requires no parameters at line %i.",
|
|
|
|
trip->next->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2004-07-25 19:24:50 +01:00
|
|
|
if (claim == CLAIM_Niagree)
|
|
|
|
{
|
|
|
|
if (n != 0)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error ("NIAGREE claim requires no parameters at line %i.",
|
|
|
|
trip->next->lineno);
|
2004-07-25 19:24:50 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2005-06-16 12:59:44 +01:00
|
|
|
if (claim == CLAIM_Empty)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
/* hmm, no handler yet */
|
|
|
|
|
|
|
|
printf ("ERROR: No know handler for this claim type: ");
|
|
|
|
termPrint (claim);
|
|
|
|
printf (" ");
|
|
|
|
errorTac (trip->next->lineno);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* and make that event */
|
|
|
|
thisRole->roledef = roledefAdd (thisRole->roledef, event, label,
|
2004-06-16 16:28:20 +01:00
|
|
|
fromrole, torole, msg, cl);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
normalDeclaration (Tac tc)
|
|
|
|
{
|
|
|
|
switch (tc->op)
|
|
|
|
{
|
|
|
|
case TAC_VAR:
|
|
|
|
levelDeclareVar (tc);
|
2004-05-26 09:26:40 +01:00
|
|
|
if (level < 2 && tc->t3.tac == NULL)
|
|
|
|
knowledgeAddTermlist (sys->know, tacTermlist (tc->t1.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case TAC_CONST:
|
|
|
|
levelDeclareConst (tc);
|
2004-05-26 09:26:40 +01:00
|
|
|
if (level < 2 && tc->t3.tac == NULL)
|
|
|
|
knowledgeAddTermlist (sys->know, tacTermlist (tc->t1.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case TAC_SECRET:
|
|
|
|
levelDeclareConst (tc);
|
|
|
|
break;
|
|
|
|
case TAC_COMPROMISED:
|
2004-05-26 09:26:40 +01:00
|
|
|
knowledgeAddTermlist (sys->know, tacTermlist (tc->t1.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case TAC_INVERSEKEYS:
|
2004-08-09 11:05:58 +01:00
|
|
|
knowledgeAddInverse (sys->know, tacTerm (tc->t1.tac),
|
|
|
|
tacTerm (tc->t2.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* abort with false */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
roleCompile (Term nameterm, Tac tc)
|
|
|
|
{
|
2004-11-16 12:51:23 +00:00
|
|
|
/* locate the role, protocol into thisRole */
|
|
|
|
/* scan through role list */
|
|
|
|
thisRole = thisProtocol->roles;
|
|
|
|
while (thisRole != NULL && !isTermEqual (thisRole->nameterm, nameterm))
|
|
|
|
{
|
|
|
|
thisRole = thisRole->next;
|
|
|
|
}
|
|
|
|
if (thisRole == NULL)
|
|
|
|
{
|
|
|
|
printf ("ERROR: undeclared role name ");
|
|
|
|
termPrint (nameterm);
|
|
|
|
printf (" in line ");
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
/* parse the content of the role */
|
|
|
|
levelInit ();
|
|
|
|
|
2005-09-09 11:05:29 +01:00
|
|
|
{
|
|
|
|
int firstEvent;
|
|
|
|
|
|
|
|
/* initiator/responder flag not set */
|
|
|
|
firstEvent = 1;
|
|
|
|
|
|
|
|
while (tc != NULL)
|
|
|
|
{
|
|
|
|
switch (tc->op)
|
|
|
|
{
|
|
|
|
case TAC_READ:
|
|
|
|
if (firstEvent)
|
|
|
|
{
|
|
|
|
// First a read, thus responder
|
|
|
|
/*
|
|
|
|
* Semantics: defaults (in role.c) to initiator _unless_ the first event is a read,
|
|
|
|
* in which case we assume that the agent names are possibly received as variables
|
|
|
|
*/
|
|
|
|
thisRole->initiator = 0;
|
|
|
|
}
|
|
|
|
commEvent (READ, tc);
|
|
|
|
break;
|
|
|
|
case TAC_SEND:
|
|
|
|
commEvent (SEND, tc);
|
|
|
|
break;
|
|
|
|
case TAC_CLAIM:
|
|
|
|
commEvent (CLAIM, tc);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!normalDeclaration (tc))
|
|
|
|
{
|
|
|
|
printf ("ERROR: illegal command %i in role ", tc->op);
|
|
|
|
termPrint (thisRole->nameterm);
|
|
|
|
printf (" ");
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
firstEvent = 0;
|
|
|
|
tc = tc->next;
|
|
|
|
}
|
|
|
|
}
|
2004-08-12 10:14:31 +01:00
|
|
|
compute_role_variables (sys, thisProtocol, thisRole);
|
2004-04-23 11:58:43 +01:00
|
|
|
levelDone ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runInstanceCreate (Tac tc)
|
|
|
|
{
|
|
|
|
/* create an instance of an existing role
|
|
|
|
* tac1 is the dot-separated reference to the role.
|
|
|
|
* tac2 is the list of parameters to be filled in.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Protocol p;
|
|
|
|
Role r;
|
|
|
|
Symbol psym, rsym;
|
|
|
|
Termlist instParams;
|
|
|
|
|
|
|
|
/* check whether we can still do it */
|
|
|
|
if (sys->maxruns >= maxruns)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* first, locate the protocol */
|
2004-05-26 09:26:40 +01:00
|
|
|
psym = tc->t1.tac->t1.sym;
|
2004-04-23 11:58:43 +01:00
|
|
|
p = sys->protocols;
|
2004-11-16 12:07:55 +00:00
|
|
|
while (p != NULL && TermSymb (p->nameterm) != psym)
|
2004-04-23 11:58:43 +01:00
|
|
|
p = p->next;
|
|
|
|
if (p == NULL)
|
|
|
|
{
|
|
|
|
printf ("Trying to create a run of a non-declared protocol ");
|
|
|
|
symbolPrint (psym);
|
|
|
|
printf (" ");
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* locate the role */
|
2004-05-26 09:26:40 +01:00
|
|
|
rsym = tc->t1.tac->t2.sym;
|
2004-04-23 11:58:43 +01:00
|
|
|
r = p->roles;
|
2004-11-16 12:07:55 +00:00
|
|
|
while (r != NULL && TermSymb (r->nameterm) != rsym)
|
2004-04-23 11:58:43 +01:00
|
|
|
r = r->next;
|
|
|
|
if (r == NULL)
|
|
|
|
{
|
|
|
|
printf ("Protocol ");
|
|
|
|
symbolPrint (psym);
|
|
|
|
printf (" has no role called ");
|
|
|
|
symbolPrint (rsym);
|
|
|
|
printf (" ");
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we now know what we are instancing, equal numbers? */
|
2004-05-26 09:26:40 +01:00
|
|
|
instParams = tacTermlist (tc->t2.tac);
|
2004-04-23 11:58:43 +01:00
|
|
|
if (termlistLength (instParams) != termlistLength (p->rolenames))
|
|
|
|
{
|
|
|
|
printf
|
|
|
|
("Run instance has different number of parameters than protocol ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
printf (" ");
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* equal numbers, so it seems to be safe */
|
2004-08-15 20:58:26 +01:00
|
|
|
roleInstance (sys, p, r, instParams, NULL); // technically, we don't need to do this for Arachne [fix later]
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
/* after creation analysis */
|
|
|
|
/* AC1: untrusted agents */
|
|
|
|
/* first: determine whether the run is untrusted,
|
|
|
|
* by checking whether one of the untrusted agents occurs
|
|
|
|
* in the run instance */
|
2005-07-01 14:25:54 +01:00
|
|
|
if (!isAgentlistTrusted (sys, instParams))
|
2004-04-23 11:58:43 +01:00
|
|
|
{
|
|
|
|
/* nothing yet */
|
|
|
|
/* claims handle this themselves */
|
|
|
|
|
|
|
|
/* some reduction might be possible, by cutting of the last few actions
|
|
|
|
* of such an untrusted run */
|
|
|
|
|
|
|
|
/* but most of it might be handled dynamically */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* AC2: originator assumption for CLP ? */
|
|
|
|
/* TODO */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
protocolCompile (Symbol prots, Tac tc, Tac tcroles)
|
|
|
|
{
|
|
|
|
Protocol pr;
|
|
|
|
Term t;
|
|
|
|
|
|
|
|
if (levelFind (prots, level) != NULL)
|
|
|
|
{
|
|
|
|
printf ("ERROR: Double declaration of protocol ");
|
|
|
|
symbolPrint (prots);
|
|
|
|
printf (" ");
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
/* make new (empty) current protocol with name */
|
|
|
|
pr = protocolCreate (levelConst (prots));
|
|
|
|
thisProtocol = pr;
|
|
|
|
/* add protocol to list */
|
|
|
|
pr->next = sys->protocols;
|
|
|
|
sys->protocols = pr;
|
2004-08-27 11:08:03 +01:00
|
|
|
protocolCount++;
|
2004-04-23 11:58:43 +01:00
|
|
|
|
|
|
|
levelInit ();
|
|
|
|
/* add the role names */
|
|
|
|
pr->rolenames = NULL;
|
|
|
|
while (tcroles != NULL)
|
|
|
|
{
|
2004-11-16 12:51:23 +00:00
|
|
|
Term rolename;
|
|
|
|
Role r;
|
|
|
|
|
2005-06-07 16:02:27 +01:00
|
|
|
if (switches.engine == ARACHNE_ENGINE)
|
2004-08-12 10:14:31 +01:00
|
|
|
{
|
2004-08-15 17:08:53 +01:00
|
|
|
rolename = levelVar (tcroles->t1.sym);
|
|
|
|
rolename->stype = termlistAdd (NULL, TERM_Agent);
|
2004-08-12 10:14:31 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-11-16 12:51:23 +00:00
|
|
|
rolename = levelConst (tcroles->t1.sym);
|
2004-08-12 10:14:31 +01:00
|
|
|
}
|
2004-11-16 12:51:23 +00:00
|
|
|
/* add name to list of role names */
|
|
|
|
pr->rolenames = termlistAppend (pr->rolenames, rolename);
|
|
|
|
/* make new (empty) current protocol with name */
|
|
|
|
r = roleCreate (rolename);
|
|
|
|
/* add role to role list of the protocol */
|
|
|
|
r->next = thisProtocol->roles;
|
|
|
|
thisProtocol->roles = r;
|
|
|
|
|
|
|
|
/* next role name */
|
2004-04-23 11:58:43 +01:00
|
|
|
tcroles = tcroles->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse the content of the protocol */
|
|
|
|
while (tc != NULL)
|
|
|
|
{
|
|
|
|
switch (tc->op)
|
|
|
|
{
|
|
|
|
case TAC_UNTRUSTED:
|
|
|
|
sys->untrusted =
|
2004-05-26 09:26:40 +01:00
|
|
|
termlistConcat (sys->untrusted, tacTermlist (tc->t1.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case TAC_ROLE:
|
2004-05-26 09:26:40 +01:00
|
|
|
t = levelFind (tc->t1.sym, level);
|
2004-04-23 11:58:43 +01:00
|
|
|
if (t != NULL)
|
|
|
|
{
|
2004-05-26 09:26:40 +01:00
|
|
|
roleCompile (t, tc->t2.tac);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf ("ERROR: undeclared role ");
|
2004-05-26 09:26:40 +01:00
|
|
|
symbolPrint (tc->t1.sym);
|
2004-04-23 11:58:43 +01:00
|
|
|
printf (" in protocol ");
|
|
|
|
termPrint (pr->nameterm);
|
2004-05-26 09:26:40 +01:00
|
|
|
errorTac (tc->t1.sym->lineno);
|
2004-04-23 11:58:43 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!normalDeclaration (tc))
|
|
|
|
{
|
|
|
|
printf ("ERROR: illegal command %i in protocol ", tc->op);
|
|
|
|
termPrint (thisProtocol->nameterm);
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tc = tc->next;
|
|
|
|
}
|
|
|
|
levelDone ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tacProcess (Tac tc)
|
|
|
|
{
|
|
|
|
while (tc != NULL)
|
|
|
|
{
|
|
|
|
switch (tc->op)
|
|
|
|
{
|
|
|
|
case TAC_PROTOCOL:
|
2004-05-26 09:26:40 +01:00
|
|
|
protocolCompile (tc->t1.sym, tc->t2.tac, tc->t3.tac);
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case TAC_UNTRUSTED:
|
|
|
|
sys->untrusted =
|
2004-05-26 09:26:40 +01:00
|
|
|
termlistConcat (sys->untrusted, tacTermlist (tc->t1.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
break;
|
|
|
|
case TAC_RUN:
|
|
|
|
runInstanceCreate (tc);
|
|
|
|
break;
|
|
|
|
case TAC_USERTYPE:
|
|
|
|
defineUsertype (tc);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!normalDeclaration (tc))
|
|
|
|
{
|
|
|
|
printf ("ERROR: illegal command %i at the global level.\n",
|
|
|
|
tc->op);
|
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tc = tc->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Term
|
|
|
|
tacTerm (Tac tc)
|
|
|
|
{
|
|
|
|
switch (tc->op)
|
|
|
|
{
|
|
|
|
case TAC_ENCRYPT:
|
2004-05-26 09:26:40 +01:00
|
|
|
return makeTermEncrypt (tacTerm (tc->t1.tac), tacTerm (tc->t2.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
case TAC_TUPLE:
|
2004-05-26 09:26:40 +01:00
|
|
|
return makeTermTuple (tacTerm (tc->t1.tac), tacTerm (tc->t2.tac));
|
2004-04-23 11:58:43 +01:00
|
|
|
case TAC_STRING:
|
|
|
|
{
|
2004-05-26 09:26:40 +01:00
|
|
|
Term t = symbolFind (tc->t1.sym);
|
2004-04-23 11:58:43 +01:00
|
|
|
if (t == NULL)
|
|
|
|
{
|
|
|
|
printf ("Undeclared symbol ");
|
2004-05-26 09:26:40 +01:00
|
|
|
symbolPrint (tc->t1.sym);
|
2004-04-23 11:58:43 +01:00
|
|
|
errorTac (tc->lineno);
|
|
|
|
}
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Termlist
|
|
|
|
tacTermlist (Tac tc)
|
|
|
|
{
|
|
|
|
Termlist tl = NULL;
|
|
|
|
|
|
|
|
while (tc != NULL)
|
|
|
|
{
|
|
|
|
tl = termlistAppend (tl, tacTerm (tc));
|
|
|
|
tc = tc->next;
|
|
|
|
}
|
|
|
|
return tl;
|
|
|
|
}
|
2004-06-14 23:08:47 +01:00
|
|
|
|
2004-08-12 10:14:31 +01:00
|
|
|
//! Compute variables for a roles (for Arachne)
|
|
|
|
void
|
|
|
|
compute_role_variables (const System sys, Protocol p, Role r)
|
|
|
|
{
|
|
|
|
if (r->variables == NULL)
|
|
|
|
{
|
|
|
|
// Not computed before, for some reason
|
|
|
|
Termlist tl;
|
|
|
|
|
|
|
|
int process_event (Roledef rd)
|
|
|
|
{
|
|
|
|
tl = termlistAddVariables (tl, rd->from);
|
|
|
|
tl = termlistAddVariables (tl, rd->to);
|
|
|
|
tl = termlistAddVariables (tl, rd->message);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
tl = NULL;
|
|
|
|
roledef_iterate_events (r->roledef, process_event);
|
|
|
|
r->variables = tl;
|
|
|
|
|
2004-08-18 21:22:55 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (5))
|
|
|
|
{
|
|
|
|
eprintf ("All variables for role ");
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
eprintf (" are ");
|
|
|
|
termlistPrint (tl);
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-12 10:14:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-27 13:36:23 +01:00
|
|
|
//! Compute term list of rolenames involved in a given term list of labels
|
2004-11-16 12:07:55 +00:00
|
|
|
Termlist
|
2004-08-27 13:36:23 +01:00
|
|
|
compute_label_roles (Termlist labels)
|
|
|
|
{
|
|
|
|
Termlist roles;
|
|
|
|
|
|
|
|
roles = NULL;
|
|
|
|
while (labels != NULL)
|
|
|
|
{
|
|
|
|
Labelinfo linfo;
|
|
|
|
|
|
|
|
linfo = label_find (sys->labellist, labels->term);
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (linfo == NULL)
|
2004-11-16 12:07:55 +00:00
|
|
|
error ("Label in prec list not found in label info list");
|
2004-08-27 13:36:23 +01:00
|
|
|
#endif
|
|
|
|
roles = termlistAddNew (roles, linfo->sendrole);
|
|
|
|
roles = termlistAddNew (roles, linfo->readrole);
|
|
|
|
|
|
|
|
labels = labels->next;
|
|
|
|
}
|
|
|
|
return roles;
|
|
|
|
}
|
|
|
|
|
2004-08-27 14:40:46 +01:00
|
|
|
//! Order the label roles for a given claim
|
|
|
|
void
|
|
|
|
order_label_roles (const Claimlist cl)
|
|
|
|
{
|
|
|
|
Termlist roles_remaining;
|
|
|
|
Termlist roles_ordered;
|
|
|
|
int distance;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (4))
|
|
|
|
{
|
|
|
|
eprintf ("Ordering label roles for claim ");
|
|
|
|
termPrint (cl->label);
|
|
|
|
eprintf ("; 0: ");
|
|
|
|
termPrint (cl->rolename);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
roles_remaining = termlistShallow (cl->roles);
|
|
|
|
roles_ordered = termlistAdd (NULL, cl->rolename);
|
2004-11-16 12:07:55 +00:00
|
|
|
roles_remaining =
|
|
|
|
termlistDelTerm (termlistFind (roles_remaining, cl->rolename));
|
2004-08-27 14:40:46 +01:00
|
|
|
|
|
|
|
distance = 0;
|
|
|
|
while (roles_remaining != NULL)
|
|
|
|
{
|
|
|
|
distance++;
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (4))
|
|
|
|
{
|
|
|
|
eprintf (" %i:", distance);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int scan_label (void *data)
|
2004-11-16 12:07:55 +00:00
|
|
|
{
|
|
|
|
Labelinfo linfo;
|
2005-05-17 19:45:01 +01:00
|
|
|
Termlist tl;
|
2004-08-27 14:40:46 +01:00
|
|
|
|
2004-11-16 12:07:55 +00:00
|
|
|
linfo = (Labelinfo) data;
|
2005-05-17 19:45:01 +01:00
|
|
|
if (linfo == NULL)
|
|
|
|
return 1;
|
|
|
|
tl = cl->prec;
|
|
|
|
if (inTermlist (tl, linfo->label))
|
2004-11-16 12:07:55 +00:00
|
|
|
{
|
|
|
|
if (linfo->protocol == cl->protocol)
|
|
|
|
{
|
|
|
|
// If it's not the same protocol, the labels can't match
|
2004-08-27 14:40:46 +01:00
|
|
|
|
2004-11-16 12:07:55 +00:00
|
|
|
// This function checks whether the newrole can connect to the connectedrole, and whether they fulfil their requirements.
|
|
|
|
void roles_test (const Term connectedrole, const Term newrole)
|
|
|
|
{
|
|
|
|
if (inTermlist (roles_ordered, connectedrole) &&
|
|
|
|
inTermlist (roles_remaining, newrole))
|
2004-08-27 14:40:46 +01:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
2004-11-16 12:07:55 +00:00
|
|
|
if (DEBUGL (4))
|
|
|
|
{
|
|
|
|
eprintf (" ");
|
|
|
|
termPrint (newrole);
|
2004-08-27 14:40:46 +01:00
|
|
|
}
|
2004-11-16 12:07:55 +00:00
|
|
|
#endif
|
|
|
|
roles_ordered = termlistAppend (roles_ordered, newrole);
|
|
|
|
roles_remaining =
|
|
|
|
termlistDelTerm (termlistFind
|
|
|
|
(roles_remaining, newrole));
|
2004-08-27 14:40:46 +01:00
|
|
|
}
|
|
|
|
}
|
2004-11-16 12:07:55 +00:00
|
|
|
|
|
|
|
roles_test (linfo->sendrole, linfo->readrole);
|
|
|
|
roles_test (linfo->readrole, linfo->sendrole);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2004-08-27 14:40:46 +01:00
|
|
|
|
|
|
|
list_iterate (sys->labellist, scan_label);
|
|
|
|
}
|
|
|
|
cl->roles = roles_ordered;
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (4))
|
|
|
|
{
|
|
|
|
eprintf ("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2004-06-14 23:08:47 +01:00
|
|
|
//! Compute prec() sets for each claim.
|
2004-06-16 11:39:13 +01:00
|
|
|
/**
|
|
|
|
* Generates two auxiliary structures. First, a table that contains
|
|
|
|
* a mapping from all events to event/claim labels.
|
|
|
|
* A second table is used to compute the precedence order, and
|
|
|
|
* Warshall's algorithm is used to compute the transitive closure.
|
2004-08-27 12:52:43 +01:00
|
|
|
* Then, for each claim, the in the preceding labels occurring roles are stored,
|
|
|
|
* which is useful later.
|
2004-06-16 11:39:13 +01:00
|
|
|
*@returns For each claim in the claim list, a preceding label set is defined.
|
|
|
|
*/
|
2004-06-14 23:08:47 +01:00
|
|
|
void
|
|
|
|
compute_prec_sets (const System sys)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
Term *eventlabels; // array: maps events to labels
|
|
|
|
int *prec; // array: maps event*event to precedence
|
|
|
|
int size; // temp constant: rolecount * roleeventmax
|
|
|
|
int r1, r2, ev1, ev2; // some counters
|
|
|
|
int i, j;
|
2004-06-14 23:08:47 +01:00
|
|
|
Claimlist cl;
|
|
|
|
|
2004-06-16 11:39:13 +01:00
|
|
|
// Assist: compute index from role, lev
|
2004-08-09 11:05:58 +01:00
|
|
|
int index (int r, int lev)
|
|
|
|
{
|
|
|
|
return r * sys->roleeventmax + lev;
|
|
|
|
}
|
2004-06-16 11:39:13 +01:00
|
|
|
|
|
|
|
// Assist: compute matrix index from i*i
|
2004-08-09 11:05:58 +01:00
|
|
|
int index2 (int i1, int i2)
|
|
|
|
{
|
|
|
|
return i1 * size + i2;
|
|
|
|
}
|
2004-06-16 11:39:13 +01:00
|
|
|
// Assist: yield roledef from r, lev
|
2004-08-09 11:05:58 +01:00
|
|
|
Roledef roledef_re (int r, int lev)
|
|
|
|
{
|
|
|
|
Protocol pr;
|
|
|
|
Role ro;
|
|
|
|
Roledef rd;
|
|
|
|
|
|
|
|
pr = sys->protocols;
|
|
|
|
ro = pr->roles;
|
|
|
|
while (r > 0 && ro != NULL)
|
|
|
|
{
|
|
|
|
ro = ro->next;
|
|
|
|
if (ro == NULL)
|
|
|
|
{
|
|
|
|
pr = pr->next;
|
|
|
|
if (pr != NULL)
|
|
|
|
{
|
|
|
|
ro = pr->roles;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ro = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r--;
|
|
|
|
}
|
|
|
|
if (ro != NULL)
|
|
|
|
{
|
|
|
|
rd = ro->roledef;
|
|
|
|
while (lev > 0 && rd != NULL)
|
|
|
|
{
|
|
|
|
rd = rd->next;
|
|
|
|
lev--;
|
|
|
|
}
|
|
|
|
return rd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-06-16 11:39:13 +01:00
|
|
|
|
|
|
|
// Assist: print matrix
|
2004-08-09 11:05:58 +01:00
|
|
|
void show_matrix (void)
|
|
|
|
{
|
|
|
|
int r1, r2, ev1, ev2;
|
|
|
|
|
|
|
|
r1 = 0;
|
|
|
|
while (r1 < sys->rolecount)
|
|
|
|
{
|
|
|
|
ev1 = 0;
|
|
|
|
while (ev1 < sys->roleeventmax)
|
|
|
|
{
|
|
|
|
printf ("prec %i,%i: ", r1, ev1);
|
|
|
|
r2 = 0;
|
|
|
|
while (r2 < sys->rolecount)
|
|
|
|
{
|
|
|
|
ev2 = 0;
|
|
|
|
while (ev2 < sys->roleeventmax)
|
|
|
|
{
|
|
|
|
printf ("%i ",
|
|
|
|
prec[index2 (index (r2, ev2), index (r1, ev1))]);
|
|
|
|
ev2++;
|
|
|
|
}
|
|
|
|
printf (" ");
|
|
|
|
r2++;
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
ev1++;
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
r1++;
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
}
|
2004-06-16 11:39:13 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Phase 1: Allocate structures and map to labels
|
|
|
|
*/
|
2004-07-12 14:57:59 +01:00
|
|
|
//printf ("Rolecount: %i\n", sys->rolecount);
|
|
|
|
//printf ("Maxevent : %i\n", sys->roleeventmax);
|
2004-06-16 11:39:13 +01:00
|
|
|
size = sys->rolecount * sys->roleeventmax;
|
2004-08-09 11:05:58 +01:00
|
|
|
eventlabels = memAlloc (size * sizeof (Term));
|
|
|
|
prec = memAlloc (size * size * sizeof (int));
|
2004-06-16 11:39:13 +01:00
|
|
|
// Clear tables
|
|
|
|
i = 0;
|
|
|
|
while (i < size)
|
|
|
|
{
|
|
|
|
eventlabels[i] = NULL;
|
|
|
|
j = 0;
|
|
|
|
while (j < size)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
prec[index2 (i, j)] = 0;
|
2004-06-16 11:39:13 +01:00
|
|
|
j++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
// Assign labels
|
|
|
|
r1 = 0;
|
|
|
|
while (r1 < sys->rolecount)
|
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
|
|
|
|
ev1 = 0;
|
|
|
|
rd = roledef_re (r1, ev1);
|
|
|
|
while (rd != NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
eventlabels[index (r1, ev1)] = rd->label;
|
2004-07-12 14:57:59 +01:00
|
|
|
//termPrint (rd->label);
|
|
|
|
//printf ("\t");
|
2004-06-16 11:39:13 +01:00
|
|
|
ev1++;
|
|
|
|
rd = rd->next;
|
|
|
|
}
|
2004-07-12 14:57:59 +01:00
|
|
|
//printf ("\n");
|
2004-06-16 11:39:13 +01:00
|
|
|
r1++;
|
|
|
|
}
|
|
|
|
// Set simple precedence (progress within a role)
|
|
|
|
r1 = 0;
|
|
|
|
while (r1 < sys->rolecount)
|
|
|
|
{
|
|
|
|
ev1 = 0;
|
|
|
|
while (ev1 < (sys->roleeventmax - 1))
|
2004-08-09 11:05:58 +01:00
|
|
|
{
|
|
|
|
prec[index2 (index (r1, ev1), index (r1, ev1 + 1))] = 1;
|
2004-06-16 11:39:13 +01:00
|
|
|
ev1++;
|
|
|
|
}
|
|
|
|
r1++;
|
|
|
|
}
|
|
|
|
// Scan for label correspondence
|
|
|
|
r1 = 0;
|
|
|
|
while (r1 < sys->rolecount)
|
|
|
|
{
|
|
|
|
ev1 = 0;
|
|
|
|
while (ev1 < sys->roleeventmax)
|
|
|
|
{
|
|
|
|
Roledef rd1;
|
|
|
|
|
2004-08-09 11:05:58 +01:00
|
|
|
rd1 = roledef_re (r1, ev1);
|
2004-07-05 10:37:31 +01:00
|
|
|
if (rd1 != NULL && rd1->type == SEND)
|
2004-06-16 11:39:13 +01:00
|
|
|
{
|
|
|
|
r2 = 0;
|
|
|
|
while (r2 < sys->rolecount)
|
|
|
|
{
|
|
|
|
ev2 = 0;
|
|
|
|
while (ev2 < sys->roleeventmax)
|
|
|
|
{
|
|
|
|
Roledef rd2;
|
|
|
|
|
2004-08-09 11:05:58 +01:00
|
|
|
rd2 = roledef_re (r2, ev2);
|
|
|
|
if (rd2 != NULL && rd2->type == READ
|
|
|
|
&& isTermEqual (rd1->label, rd2->label))
|
2004-06-16 11:39:13 +01:00
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
prec[index2 (index (r1, ev1), index (r2, ev2))] = 1;
|
2004-06-16 11:39:13 +01:00
|
|
|
}
|
|
|
|
ev2++;
|
|
|
|
}
|
|
|
|
r2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ev1++;
|
|
|
|
}
|
|
|
|
r1++;
|
|
|
|
}
|
|
|
|
//[x] show_matrix ();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute transitive closure (Warshall).
|
|
|
|
*/
|
2004-08-15 15:07:34 +01:00
|
|
|
warshall (prec, size);
|
2004-06-16 11:39:13 +01:00
|
|
|
|
|
|
|
// [x] show_matrix ();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Last phase: Process all individual claims
|
|
|
|
*/
|
2004-06-14 23:08:47 +01:00
|
|
|
cl = sys->claimlist;
|
|
|
|
while (cl != NULL)
|
|
|
|
{
|
2004-06-16 11:39:13 +01:00
|
|
|
Term t;
|
|
|
|
Roledef rd;
|
|
|
|
Term label;
|
2004-07-25 19:24:50 +01:00
|
|
|
int claim_index;
|
2004-06-16 11:39:13 +01:00
|
|
|
|
|
|
|
label = cl->label;
|
|
|
|
// Locate r,lev from label, requires (TODO) unique labeling of claims!
|
|
|
|
r1 = 0;
|
|
|
|
ev1 = -1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ev1++;
|
|
|
|
if (ev1 == sys->roleeventmax)
|
|
|
|
{
|
|
|
|
ev1 = 0;
|
|
|
|
r1++;
|
|
|
|
}
|
|
|
|
}
|
2004-08-09 11:05:58 +01:00
|
|
|
while (r1 < sys->rolecount
|
|
|
|
&& !isTermEqual (label, eventlabels[index (r1, ev1)]));
|
2004-06-16 11:39:13 +01:00
|
|
|
if (r1 == sys->rolecount)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error
|
|
|
|
("Prec() setup: Could not find the event corresponding to a claim label.");
|
2004-06-16 11:39:13 +01:00
|
|
|
}
|
2004-08-09 11:05:58 +01:00
|
|
|
rd = roledef_re (r1, ev1);
|
2004-06-16 11:39:13 +01:00
|
|
|
if (rd->type != CLAIM)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
error
|
|
|
|
("Prec() setup: First event with claim label doesn't seem to be a claim.");
|
2004-06-16 11:39:13 +01:00
|
|
|
}
|
|
|
|
// Store in claimlist structure
|
|
|
|
cl->r = r1;
|
|
|
|
cl->ev = ev1;
|
2004-08-14 20:19:23 +01:00
|
|
|
cl->roledef = rd;
|
|
|
|
|
2004-06-16 11:39:13 +01:00
|
|
|
/*
|
|
|
|
* We have found the claim roledef, and r1,ev1
|
|
|
|
* Now we compute the preceding label set
|
|
|
|
*/
|
|
|
|
cl->prec = NULL; // clear first
|
2004-08-09 11:05:58 +01:00
|
|
|
claim_index = index (r1, ev1);
|
2004-06-16 11:39:13 +01:00
|
|
|
r2 = 0;
|
|
|
|
while (r2 < sys->rolecount)
|
|
|
|
{
|
|
|
|
Roledef rd2;
|
|
|
|
|
|
|
|
ev2 = 0;
|
2004-08-09 11:05:58 +01:00
|
|
|
rd = roledef_re (r2, ev2);
|
2004-06-16 11:39:13 +01:00
|
|
|
while (rd != NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
if (prec[index2 (index (r2, ev2), claim_index)] == 1)
|
2004-06-16 11:39:13 +01:00
|
|
|
{
|
|
|
|
// This event precedes the claim
|
2004-08-09 11:05:58 +01:00
|
|
|
|
|
|
|
if (rd->type == READ)
|
2004-06-16 11:39:13 +01:00
|
|
|
{
|
|
|
|
// Only store read labels (but send would work as well)
|
|
|
|
cl->prec = termlistAdd (cl->prec, rd->label);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rd = rd->next;
|
|
|
|
ev2++;
|
|
|
|
}
|
|
|
|
r2++;
|
|
|
|
}
|
2004-08-27 14:40:46 +01:00
|
|
|
|
2004-08-27 13:36:23 +01:00
|
|
|
/**
|
2004-08-27 14:40:46 +01:00
|
|
|
* ----------------------------------------
|
2004-08-27 13:36:23 +01:00
|
|
|
* cl->prec is done, now we infer cl->roles
|
2004-08-27 14:40:46 +01:00
|
|
|
* Next, we nicely order them
|
|
|
|
* ----------------------------------------
|
2004-08-27 13:36:23 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
cl->roles = compute_label_roles (cl->prec);
|
2004-08-27 14:40:46 +01:00
|
|
|
order_label_roles (cl);
|
2004-08-27 13:36:23 +01:00
|
|
|
|
2004-07-25 19:24:50 +01:00
|
|
|
/**
|
|
|
|
* ---------------------------
|
|
|
|
* Distinguish types of claims
|
|
|
|
* ---------------------------
|
|
|
|
*/
|
|
|
|
|
2004-07-24 21:30:00 +01:00
|
|
|
// For ni-synch, the preceding label sets are added to the synchronising_labels sets.
|
|
|
|
if (cl->type == CLAIM_Nisynch)
|
|
|
|
{
|
|
|
|
Termlist tl_scan;
|
|
|
|
|
|
|
|
tl_scan = cl->prec;
|
|
|
|
while (tl_scan != NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
sys->synchronising_labels =
|
|
|
|
termlistAddNew (sys->synchronising_labels, tl_scan->term);
|
2004-07-25 19:24:50 +01:00
|
|
|
tl_scan = tl_scan->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// For ni-agree, the preceding set is also important, but we furthermore need a restricted
|
|
|
|
// synchronising_labels set
|
|
|
|
|
|
|
|
//@todo Fix ni-agree synchronising label sets
|
|
|
|
if (cl->type == CLAIM_Niagree)
|
|
|
|
{
|
|
|
|
int r_scan;
|
|
|
|
|
|
|
|
// Scan each role (except the current one) and pick out the last prec events.
|
|
|
|
r_scan = 0;
|
|
|
|
while (r_scan < sys->rolecount)
|
|
|
|
{
|
|
|
|
// Only other roles
|
|
|
|
if (r_scan != r1)
|
2004-07-24 21:30:00 +01:00
|
|
|
{
|
2004-07-25 19:24:50 +01:00
|
|
|
// Scan fully
|
|
|
|
int ev_scan;
|
|
|
|
Term t_buf;
|
|
|
|
|
|
|
|
t_buf = NULL;
|
|
|
|
ev_scan = 0;
|
|
|
|
while (ev_scan < sys->roleeventmax)
|
|
|
|
{
|
|
|
|
// if this event preceds the claim, replace the label term
|
2004-08-09 11:05:58 +01:00
|
|
|
if (prec[index2 (index (r_scan, ev_scan), claim_index)]
|
|
|
|
== 1)
|
2004-07-25 19:24:50 +01:00
|
|
|
{
|
|
|
|
Roledef rd;
|
|
|
|
|
2004-08-09 11:05:58 +01:00
|
|
|
rd = roledef_re (r_scan, ev_scan);
|
2004-07-25 19:24:50 +01:00
|
|
|
if (rd->label != NULL)
|
|
|
|
{
|
|
|
|
t_buf = rd->label;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ev_scan++;
|
|
|
|
}
|
|
|
|
// Store only the last label
|
|
|
|
if (t_buf != NULL)
|
|
|
|
{
|
2004-08-09 11:05:58 +01:00
|
|
|
sys->synchronising_labels =
|
|
|
|
termlistAddNew (sys->synchronising_labels, t_buf);
|
2004-07-25 19:24:50 +01:00
|
|
|
}
|
2004-07-24 21:30:00 +01:00
|
|
|
}
|
2004-07-25 19:24:50 +01:00
|
|
|
r_scan++;
|
2004-07-24 21:30:00 +01:00
|
|
|
}
|
|
|
|
}
|
2004-07-25 19:24:50 +01:00
|
|
|
|
2004-07-25 16:30:58 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
// Porparam = 100 (weirdness) [x][cc][debug] can turn of the synchronising label sets (override).
|
2005-06-07 16:02:27 +01:00
|
|
|
if (switches.switchP == 100)
|
2004-07-25 16:30:58 +01:00
|
|
|
{
|
|
|
|
termlistDelete (sys->synchronising_labels);
|
|
|
|
sys->synchronising_labels = NULL;
|
2004-08-09 11:05:58 +01:00
|
|
|
warning
|
|
|
|
("Emptied synchronising labels set manually because --pp=100.");
|
2004-07-25 16:30:58 +01:00
|
|
|
}
|
|
|
|
#endif
|
2004-06-16 11:39:13 +01:00
|
|
|
// Check for empty stuff
|
|
|
|
//@todo This is for debugging, mainly.
|
|
|
|
if (cl->prec == NULL)
|
|
|
|
{
|
2004-10-19 13:03:40 +01:00
|
|
|
globalError++;
|
2005-12-27 13:44:12 +00:00
|
|
|
eprintf ("warning: claim with empty prec() set at r:%i, ev:%i\n",
|
2004-08-09 11:05:58 +01:00
|
|
|
r1, ev1);
|
2004-10-19 13:03:40 +01:00
|
|
|
globalError--;
|
2005-12-27 13:44:12 +00:00
|
|
|
cl->warnings = true;
|
2004-06-16 11:39:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-27 13:36:23 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (DEBUGL (3))
|
|
|
|
{
|
|
|
|
Protocol p;
|
|
|
|
|
2004-11-16 12:07:55 +00:00
|
|
|
printf ("Preceding label set for r:%i, ev:%i = ", r1, ev1);
|
2004-08-27 13:36:23 +01:00
|
|
|
termlistPrint (cl->prec);
|
|
|
|
printf (", involving roles ");
|
|
|
|
termlistPrint (cl->roles);
|
|
|
|
printf (", from protocol ");
|
|
|
|
p = (Protocol) cl->protocol;
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
printf ("\n");
|
|
|
|
}
|
|
|
|
#endif
|
2004-06-16 11:39:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Proceed to next claim
|
|
|
|
cl = cl->next;
|
2004-06-14 23:08:47 +01:00
|
|
|
}
|
2004-06-16 11:39:13 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup
|
|
|
|
*/
|
2004-08-09 11:05:58 +01:00
|
|
|
memFree (eventlabels, size * sizeof (Term));
|
|
|
|
memFree (prec, size * size * sizeof (int));
|
2004-07-24 21:30:00 +01:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2004-08-09 11:05:58 +01:00
|
|
|
if (DEBUGL (2))
|
2004-07-25 16:30:58 +01:00
|
|
|
{
|
|
|
|
printf ("Synchronising labels set: ");
|
|
|
|
termlistPrint (sys->synchronising_labels);
|
|
|
|
printf ("\n");
|
|
|
|
}
|
2004-07-24 21:30:00 +01:00
|
|
|
#endif
|
|
|
|
|
2004-06-14 23:08:47 +01:00
|
|
|
}
|
|
|
|
|
2005-12-27 13:44:12 +00:00
|
|
|
//! Check unused variables
|
|
|
|
void
|
|
|
|
checkRoleVariables (const System sys, const Protocol p, const Role r)
|
|
|
|
{
|
|
|
|
Termlist vars;
|
|
|
|
Termlist declared;
|
|
|
|
|
|
|
|
int process_event (Roledef rd)
|
|
|
|
{
|
|
|
|
if (rd->type == READ)
|
|
|
|
{
|
|
|
|
vars = termlistAddVariables (vars, rd->from);
|
|
|
|
vars = termlistAddVariables (vars, rd->to);
|
|
|
|
vars = termlistAddVariables (vars, rd->message);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Gather all variables occurring in the reads */
|
|
|
|
vars = NULL;
|
|
|
|
roledef_iterate_events (r->roledef, process_event);
|
|
|
|
|
|
|
|
/* Now, all variables for this role should be in the reads */
|
|
|
|
declared = r->declaredvars;
|
|
|
|
while (declared != NULL)
|
|
|
|
{
|
|
|
|
if (!inTermlist (vars, declared->term))
|
|
|
|
{
|
|
|
|
// Warning
|
|
|
|
globalError++;
|
|
|
|
eprintf ("warning: variable ");
|
|
|
|
termPrint (declared->term);
|
|
|
|
eprintf (" was declared in role ");
|
|
|
|
termPrint (p->nameterm);
|
|
|
|
eprintf (",");
|
|
|
|
termPrint (r->nameterm);
|
|
|
|
eprintf (" but never used in a read event.\n");
|
|
|
|
globalError--;
|
|
|
|
}
|
|
|
|
declared = declared->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
termlistDelete (vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Check unused variables
|
|
|
|
/**
|
|
|
|
* This is checked per role
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
checkUnusedVariables (const System sys)
|
|
|
|
{
|
|
|
|
Protocol p;
|
|
|
|
|
|
|
|
p = sys->protocols;
|
|
|
|
while (p != NULL)
|
|
|
|
{
|
|
|
|
Role r;
|
|
|
|
r = p->roles;
|
|
|
|
while (r != NULL)
|
|
|
|
{
|
|
|
|
checkRoleVariables (sys, p, r);
|
|
|
|
r = r->next;
|
|
|
|
}
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-06-14 23:08:47 +01:00
|
|
|
//! Preprocess after system compilation
|
2004-08-09 11:05:58 +01:00
|
|
|
void
|
2004-06-14 23:08:47 +01:00
|
|
|
preprocess (const System sys)
|
|
|
|
{
|
2004-06-16 16:28:20 +01:00
|
|
|
/*
|
|
|
|
* init some counters
|
|
|
|
*/
|
2004-08-09 11:05:58 +01:00
|
|
|
sys->rolecount = compute_rolecount (sys);
|
|
|
|
sys->roleeventmax = compute_roleeventmax (sys);
|
2004-06-16 16:28:20 +01:00
|
|
|
/*
|
|
|
|
* compute preceding label sets
|
|
|
|
*/
|
2004-08-09 11:05:58 +01:00
|
|
|
compute_prec_sets (sys);
|
2005-12-27 13:44:12 +00:00
|
|
|
/*
|
|
|
|
* check for ununsed variables
|
|
|
|
*/
|
|
|
|
checkUnusedVariables (sys);
|
2004-06-14 23:08:47 +01:00
|
|
|
}
|