- New claim: CLAIM_Reachable
- Added new switches: -G,--generate-statespace -C,--generate-claims - Claims are now allowed to have no label (they will be generated automatically) - Output summary shows parameter of claims - Internally, new symbols can now be generated by symbolNextFree(prefixsymbol)
This commit is contained in:
		
							parent
							
								
									ccc4c34823
								
							
						
					
					
						commit
						0505aaacd6
					
				
							
								
								
									
										276
									
								
								src/compiler.c
									
									
									
									
									
								
							
							
						
						
									
										276
									
								
								src/compiler.c
									
									
									
									
									
								
							@ -355,15 +355,130 @@ levelTacDeclaration (Tac tc, int isVar)
 | 
				
			|||||||
      /* declare this variable/constant with the previously derived type list */
 | 
					      /* declare this variable/constant with the previously derived type list */
 | 
				
			||||||
      t = symbolDeclare (tscan->t1.sym, isVar);
 | 
					      t = symbolDeclare (tscan->t1.sym, isVar);
 | 
				
			||||||
      t->stype = typetl;
 | 
					      t->stype = typetl;
 | 
				
			||||||
      if (isVar && level == 2)
 | 
					      /* local to the role? */
 | 
				
			||||||
 | 
					      if (level == 2)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  if (isVar)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
	      /* it is a role variable, so add it to the nicely declared variables */
 | 
						      /* it is a role variable, so add it to the nicely declared variables */
 | 
				
			||||||
	  thisRole->declaredvars = termlistAdd (thisRole->declaredvars, t);
 | 
						      thisRole->declaredvars =
 | 
				
			||||||
 | 
							termlistAdd (thisRole->declaredvars, t);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      /* it is a role constant, so add it to the nicely declared constants */
 | 
				
			||||||
 | 
						      thisRole->declaredconsts =
 | 
				
			||||||
 | 
							termlistAdd (thisRole->declaredconsts, t);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
      tscan = tscan->next;
 | 
					      tscan = tscan->next;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Check whether a claim label already occurs
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					isClaimlabelUsed (const System sys, const Term label)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Claimlist cl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (label == NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* we assign this 'occurs' because it is an invalid label */
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  cl = sys->claimlist;
 | 
				
			||||||
 | 
					  while (cl != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (isTermEqual (cl->label, label))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      cl = cl->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Generate a fresh claim label
 | 
				
			||||||
 | 
					Term
 | 
				
			||||||
 | 
					generateFreshClaimlabel (const System sys, const Role role, const Term claim)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  /* Simply use the role as a prefix */
 | 
				
			||||||
 | 
					  return freshTermPrefix (role->nameterm);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Create a claim and add it to the claims list, and add the role event.
 | 
				
			||||||
 | 
					Claimlist
 | 
				
			||||||
 | 
					claimCreate (const System sys, const Protocol protocol, const Role role,
 | 
				
			||||||
 | 
						     const Term claim, Term label, const Term msg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Claimlist cl;
 | 
				
			||||||
 | 
					  Term labeltuple;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* check for ignored claim types */
 | 
				
			||||||
 | 
					  if (switches.filterClaim != NULL && switches.filterClaim != claim)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* abort the construction of the node */
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* generate full unique label */
 | 
				
			||||||
 | 
					  /* is the label empty or used? */
 | 
				
			||||||
 | 
					  if (label == NULL || isClaimlabelUsed (sys, label))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      /* simply generate a fresh one */
 | 
				
			||||||
 | 
					      label = generateFreshClaimlabel (sys, role, claim);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Assert: label is unique, add claimlist info
 | 
				
			||||||
 | 
					  cl = memAlloc (sizeof (struct claimlist));
 | 
				
			||||||
 | 
					  cl->type = claim;
 | 
				
			||||||
 | 
					  cl->label = label;
 | 
				
			||||||
 | 
					  cl->parameter = msg;
 | 
				
			||||||
 | 
					  cl->protocol = thisProtocol;
 | 
				
			||||||
 | 
					  cl->rolename = role->nameterm;
 | 
				
			||||||
 | 
					  cl->role = role;
 | 
				
			||||||
 | 
					  cl->roledef = NULL;
 | 
				
			||||||
 | 
					  cl->count = 0;
 | 
				
			||||||
 | 
					  cl->complete = 0;
 | 
				
			||||||
 | 
					  cl->timebound = 0;
 | 
				
			||||||
 | 
					  cl->failed = 0;
 | 
				
			||||||
 | 
					  cl->prec = NULL;
 | 
				
			||||||
 | 
					  cl->roles = NULL;
 | 
				
			||||||
 | 
					  cl->alwaystrue = false;
 | 
				
			||||||
 | 
					  cl->warnings = false;
 | 
				
			||||||
 | 
					  cl->next = sys->claimlist;
 | 
				
			||||||
 | 
					  sys->claimlist = cl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* add the role event */
 | 
				
			||||||
 | 
					  role->roledef = roledefAdd (role->roledef, CLAIM, label,
 | 
				
			||||||
 | 
								      role->nameterm, claim, msg, cl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* possible special handlers for each claim */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (claim == CLAIM_Secret)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      Termlist claimvars;
 | 
				
			||||||
 | 
					      Termlist readvars;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* now check whether the claim contains variables that can actually be influenced by the intruder */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Parse a communication event tc of type event, and add a role definition event for it.
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
commEvent (int event, Tac tc)
 | 
					commEvent (int event, Tac tc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -382,7 +497,12 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
  /* Construct label, if any */
 | 
					  /* Construct label, if any */
 | 
				
			||||||
  if (tc->t1.sym == NULL)
 | 
					  if (tc->t1.sym == NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      label = NULL;
 | 
					      /* right, now this should not be NULL anyway, if so we construct a fresh one.
 | 
				
			||||||
 | 
					       * This can be a weird choice if it is a read or send, because in that case
 | 
				
			||||||
 | 
					       * we cannot chain them anymore and the send-read correspondence is lost.
 | 
				
			||||||
 | 
					       */
 | 
				
			||||||
 | 
					      warning ("Generated fresh label for line %i.", tc->lineno);
 | 
				
			||||||
 | 
					      label = freshTermPrefix (thisRole->nameterm);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -398,21 +518,10 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	  /* we already had this label constant */
 | 
					 | 
				
			||||||
	  /* leaves a garbage tuple. dunnoh what to do with it */
 | 
						  /* leaves a garbage tuple. dunnoh what to do with it */
 | 
				
			||||||
	  label = makeTermTuple (thisProtocol->nameterm, label);
 | 
						  label = makeTermTuple (thisProtocol->nameterm, label);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * 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
 | 
					   * Parse the specific event type
 | 
				
			||||||
@ -422,6 +531,17 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    case READ:
 | 
					    case READ:
 | 
				
			||||||
    case SEND:
 | 
					    case SEND:
 | 
				
			||||||
 | 
					      /**
 | 
				
			||||||
 | 
					       * We 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);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      /* now parse triplet info */
 | 
					      /* now parse triplet info */
 | 
				
			||||||
      if (trip == NULL || trip->next == NULL || trip->next->next == NULL)
 | 
					      if (trip == NULL || trip->next == NULL || trip->next->next == NULL)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -461,8 +581,13 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
	  linfo->readrole = torole;
 | 
						  linfo->readrole = torole;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /* and make that read/send event */
 | 
				
			||||||
 | 
					      thisRole->roledef = roledefAdd (thisRole->roledef, event, label,
 | 
				
			||||||
 | 
									      fromrole, torole, msg, cl);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case CLAIM:
 | 
					    case CLAIM:
 | 
				
			||||||
 | 
					      /* switch can be used to remove all *parsed* claims */
 | 
				
			||||||
      if (!switches.removeclaims)
 | 
					      if (!switches.removeclaims)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	  /* now parse tuple info */
 | 
						  /* now parse tuple info */
 | 
				
			||||||
@ -477,13 +602,6 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
	  claim = tupleProject (claimbig, 0);
 | 
						  claim = tupleProject (claimbig, 0);
 | 
				
			||||||
	  torole = claim;
 | 
						  torole = claim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  /* check for ignored claim types */
 | 
					 | 
				
			||||||
	  if (switches.filterClaim != NULL && switches.filterClaim != claim)
 | 
					 | 
				
			||||||
	    {
 | 
					 | 
				
			||||||
	      /* abort the construction of the node */
 | 
					 | 
				
			||||||
	      return;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	  /* check for obvious flaws */
 | 
						  /* check for obvious flaws */
 | 
				
			||||||
	  if (claim == NULL)
 | 
						  if (claim == NULL)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
@ -491,7 +609,7 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
	    }
 | 
						    }
 | 
				
			||||||
	  if (!inTermlist (claim->stype, TERM_Claim))
 | 
						  if (!inTermlist (claim->stype, TERM_Claim))
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
	      printf ("error: unknown claim type ");
 | 
						      printf ("error: claim term is not of claim type ");
 | 
				
			||||||
	      termPrint (claim);
 | 
						      termPrint (claim);
 | 
				
			||||||
	      errorTac (trip->next->lineno);
 | 
						      errorTac (trip->next->lineno);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
@ -514,50 +632,21 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  /* store claim in claim list */
 | 
						  // check whether label is unique
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if (label == NULL)
 | 
						  if (isClaimlabelUsed (sys, label))
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
	      error ("Claim should have label on line %i.",
 | 
						      warning
 | 
				
			||||||
		     trip->next->lineno);
 | 
							("Claim label is not unique at line %i, generating fresh label.",
 | 
				
			||||||
 | 
							 tc->lineno);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	  // 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.
 | 
					 | 
				
			||||||
		   */
 | 
					 | 
				
			||||||
		  error ("Claim label is not unique at line %i.", tc->lineno);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	      cl = cl->next;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	  // Assert: label is unique, add claimlist info
 | 
					 | 
				
			||||||
	  cl = memAlloc (sizeof (struct claimlist));
 | 
					 | 
				
			||||||
	  cl->type = claim;
 | 
					 | 
				
			||||||
	  cl->label = label;
 | 
					 | 
				
			||||||
	  cl->protocol = thisProtocol;
 | 
					 | 
				
			||||||
	  cl->rolename = fromrole;
 | 
					 | 
				
			||||||
	  cl->role = thisRole;
 | 
					 | 
				
			||||||
	  if (!isTermEqual (fromrole, thisRole->nameterm))
 | 
						  if (!isTermEqual (fromrole, thisRole->nameterm))
 | 
				
			||||||
	    error
 | 
						    error
 | 
				
			||||||
	      ("Claim role does not correspond to execution role at line %i.",
 | 
						      ("Claim role does not correspond to execution role at line %i.",
 | 
				
			||||||
	       tc->lineno);
 | 
						       tc->lineno);
 | 
				
			||||||
	  cl->roledef = NULL;
 | 
					 | 
				
			||||||
	  cl->count = 0;
 | 
					 | 
				
			||||||
	  cl->complete = 0;
 | 
					 | 
				
			||||||
	  cl->timebound = 0;
 | 
					 | 
				
			||||||
	  cl->failed = 0;
 | 
					 | 
				
			||||||
	  cl->prec = NULL;
 | 
					 | 
				
			||||||
	  cl->roles = NULL;
 | 
					 | 
				
			||||||
	  cl->alwaystrue = false;
 | 
					 | 
				
			||||||
	  cl->warnings = false;
 | 
					 | 
				
			||||||
	  cl->next = sys->claimlist;
 | 
					 | 
				
			||||||
	  sys->claimlist = cl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  /* handles all claim types differently */
 | 
						  /* handles claim types with different syntactic claims */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if (claim == CLAIM_Secret)
 | 
						  if (claim == CLAIM_Secret)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
@ -573,26 +662,6 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
		    ("Secrecy claim on line %i should not contain tuples (for Arachne) until it is officially supported.",
 | 
							    ("Secrecy claim on line %i should not contain tuples (for Arachne) until it is officially supported.",
 | 
				
			||||||
		     trip->next->lineno);
 | 
							     trip->next->lineno);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	      /* 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;
 | 
					 | 
				
			||||||
		  }
 | 
					 | 
				
			||||||
	      }
 | 
					 | 
				
			||||||
	      break;
 | 
					 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	  if (claim == CLAIM_Nisynch)
 | 
						  if (claim == CLAIM_Nisynch)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
@ -601,7 +670,6 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
		  error ("NISYNCH claim requires no parameters at line %i.",
 | 
							  error ("NISYNCH claim requires no parameters at line %i.",
 | 
				
			||||||
			 trip->next->lineno);
 | 
								 trip->next->lineno);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	      break;
 | 
					 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	  if (claim == CLAIM_Niagree)
 | 
						  if (claim == CLAIM_Niagree)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
@ -610,25 +678,14 @@ commEvent (int event, Tac tc)
 | 
				
			|||||||
		  error ("NIAGREE claim requires no parameters at line %i.",
 | 
							  error ("NIAGREE claim requires no parameters at line %i.",
 | 
				
			||||||
			 trip->next->lineno);
 | 
								 trip->next->lineno);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	      break;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	  if (claim == CLAIM_Empty)
 | 
					 | 
				
			||||||
	    {
 | 
					 | 
				
			||||||
	      break;
 | 
					 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  /* hmm, no handler yet */
 | 
						  /* create the event */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  printf ("error: No know handler for this claim type: ");
 | 
						  cl = claimCreate (sys, thisProtocol, thisRole, claim, label, msg);
 | 
				
			||||||
	  termPrint (claim);
 | 
					 | 
				
			||||||
	  printf (" ");
 | 
					 | 
				
			||||||
	  errorTac (trip->next->lineno);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  /* and make that event */
 | 
					 | 
				
			||||||
  thisRole->roledef = roledefAdd (thisRole->roledef, event, label,
 | 
					 | 
				
			||||||
				  fromrole, torole, msg, cl);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
@ -663,6 +720,28 @@ normalDeclaration (Tac tc)
 | 
				
			|||||||
  return 1;
 | 
					  return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Add all sorts of claims to this role
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					claimAddAll (const System sys, const Protocol protocol, const Role role)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  /* first: secrecy claims for all locally declared things */
 | 
				
			||||||
 | 
					  void addSecrecyList (Termlist tl)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    while (tl != NULL)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
						claimCreate (sys, protocol, role, CLAIM_Secret, NULL, tl->term);
 | 
				
			||||||
 | 
						tl = tl->next;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  addSecrecyList (role->declaredconsts);
 | 
				
			||||||
 | 
					  addSecrecyList (role->declaredvars);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* full non-injective agreement and ni-synch */
 | 
				
			||||||
 | 
					  claimCreate (sys, protocol, role, CLAIM_Niagree, NULL, NULL);
 | 
				
			||||||
 | 
					  claimCreate (sys, protocol, role, CLAIM_Nisynch, NULL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
roleCompile (Term nameterm, Tac tc)
 | 
					roleCompile (Term nameterm, Tac tc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -726,6 +805,19 @@ roleCompile (Term nameterm, Tac tc)
 | 
				
			|||||||
	tc = tc->next;
 | 
						tc = tc->next;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* add any claims according to the switches */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (switches.addreachableclaim)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      claimCreate (sys, thisProtocol, thisRole, CLAIM_Reachable, NULL, NULL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  if (switches.addallclaims)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      claimAddAll (sys, thisProtocol, thisRole);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* last bits */
 | 
				
			||||||
  compute_role_variables (sys, thisProtocol, thisRole);
 | 
					  compute_role_variables (sys, thisProtocol, thisRole);
 | 
				
			||||||
  levelDone ();
 | 
					  levelDone ();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										101
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/main.c
									
									
									
									
									
								
							@ -370,47 +370,104 @@ timersPrint (const System sys)
 | 
				
			|||||||
  /* Note that if the output is set to empty, the claim output is redirected to stdout (for e.g. processing)
 | 
					  /* Note that if the output is set to empty, the claim output is redirected to stdout (for e.g. processing)
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  cl_scan = sys->claimlist;
 | 
					  cl_scan = sys->claimlist;
 | 
				
			||||||
  anyclaims = 0;
 | 
					  anyclaims = false;
 | 
				
			||||||
  while (cl_scan != NULL)
 | 
					  while (cl_scan != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      if (!isTermEqual (cl_scan->type, CLAIM_Empty))
 | 
					      if (!isTermEqual (cl_scan->type, CLAIM_Empty))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	  anyclaims = 1;
 | 
						  Protocol protocol;
 | 
				
			||||||
 | 
						  Term pname;
 | 
				
			||||||
 | 
						  Term rname;
 | 
				
			||||||
 | 
						  Termlist labellist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  anyclaims = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  eprintf ("claim\t");
 | 
						  eprintf ("claim\t");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  /* claim label is tuple */
 | 
						  protocol = (Protocol) cl_scan->protocol;
 | 
				
			||||||
	  if (realTermTuple (cl_scan->label))
 | 
						  pname = protocol->nameterm;
 | 
				
			||||||
 | 
						  rname = cl_scan->rolename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  labellist = tuple_to_termlist (cl_scan->label);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  /* maybe the label contains duplicate info: if so, we remove it here */
 | 
				
			||||||
	  {
 | 
						  {
 | 
				
			||||||
	      /* modern version: claim label is tuple (protocname, label) */
 | 
						    Termlist tl;
 | 
				
			||||||
	      /* first print protocol.role */
 | 
						    tl = labellist;
 | 
				
			||||||
	      termPrint (TermOp1 (cl_scan->label));
 | 
						    while (tl != NULL)
 | 
				
			||||||
	      eprintf (",");
 | 
						      {
 | 
				
			||||||
	      termPrint (cl_scan->rolename);
 | 
							if (isTermEqual (tl->term, pname)
 | 
				
			||||||
	      eprintf ("\t");
 | 
							    || isTermEqual (tl->term, rname))
 | 
				
			||||||
	      /* second print event_label */
 | 
							  {
 | 
				
			||||||
	      termPrint (cl_scan->type);
 | 
							    tl = termlistDelTerm (tl);
 | 
				
			||||||
	      eprintf ("_");
 | 
							    labellist = tl;
 | 
				
			||||||
	      termPrint (TermOp2 (cl_scan->label));
 | 
					 | 
				
			||||||
	      eprintf ("\t");
 | 
					 | 
				
			||||||
		  }
 | 
							  }
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		  {
 | 
							  {
 | 
				
			||||||
	      /* old-fashioned output */
 | 
							    tl = tl->next;
 | 
				
			||||||
	      termPrint (cl_scan->type);
 | 
							  }
 | 
				
			||||||
 | 
						      }
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  termPrint (pname);
 | 
				
			||||||
 | 
						  eprintf (",");
 | 
				
			||||||
 | 
						  termPrint (rname);
 | 
				
			||||||
	  eprintf ("\t");
 | 
						  eprintf ("\t");
 | 
				
			||||||
	      termPrint (cl_scan->rolename);
 | 
						  /* second print event_label */
 | 
				
			||||||
	      eprintf (" (");
 | 
						  termPrint (cl_scan->type);
 | 
				
			||||||
	      termPrint (cl_scan->label);
 | 
					
 | 
				
			||||||
	      eprintf (")\t");
 | 
						  eprintf ("_");
 | 
				
			||||||
 | 
						  if (labellist != NULL)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      Termlist tl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						      tl = labellist;
 | 
				
			||||||
 | 
						      while (tl != NULL)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  termPrint (tl->term);
 | 
				
			||||||
 | 
							  tl = tl->next;
 | 
				
			||||||
 | 
							  if (tl != NULL)
 | 
				
			||||||
 | 
							    {
 | 
				
			||||||
 | 
							      eprintf (",");
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      /* clean up */
 | 
				
			||||||
 | 
						      termlistDelete (labellist);
 | 
				
			||||||
 | 
						      labellist = NULL;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      eprintf ("?");
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  /* add parameter */
 | 
				
			||||||
 | 
						  eprintf ("\t");
 | 
				
			||||||
 | 
						  if (cl_scan->parameter != NULL)
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      termPrint (cl_scan->parameter);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  else
 | 
				
			||||||
 | 
						    {
 | 
				
			||||||
 | 
						      eprintf ("-");
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  /* now report the status */
 | 
						  /* now report the status */
 | 
				
			||||||
 | 
						  eprintf ("\t");
 | 
				
			||||||
	  eprintf ("attacks: ");
 | 
						  eprintf ("attacks: ");
 | 
				
			||||||
	  if (cl_scan->count > 0 && cl_scan->failed > 0)
 | 
						  if (cl_scan->count > 0 && cl_scan->failed > 0)
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
	      /* there is an attack */
 | 
						      /* there is an attack */
 | 
				
			||||||
	      eprintf ("yes\t(at least %i)", cl_scan->failed);
 | 
						      eprintf ("yes\t");
 | 
				
			||||||
 | 
						      /* are these all attacks? */
 | 
				
			||||||
 | 
						      eprintf ("(");
 | 
				
			||||||
 | 
						      if (cl_scan->complete)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  eprintf ("exactly");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  eprintf ("at least");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						      eprintf (" %i)", cl_scan->failed);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    {
 | 
						    {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										11
									
								
								src/parser.y
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/parser.y
									
									
									
									
									
								
							@ -48,6 +48,7 @@ int yylex(void);
 | 
				
			|||||||
%type	<tac>	roleref
 | 
					%type	<tac>	roleref
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%type	<symb>	label
 | 
					%type	<symb>	label
 | 
				
			||||||
 | 
					%type	<symb>	optlabel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%start spdlcomplete
 | 
					%start spdlcomplete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -142,7 +143,7 @@ event		: READT label '(' termlist ')' ';'
 | 
				
			|||||||
			t->t2.tac = $4;
 | 
								t->t2.tac = $4;
 | 
				
			||||||
			$$ = t;
 | 
								$$ = t;
 | 
				
			||||||
		  }
 | 
							  }
 | 
				
			||||||
		| CLAIMT label '(' termlist ')' ';'
 | 
							| CLAIMT optlabel '(' termlist ')' ';'
 | 
				
			||||||
		/* TODO maybe claims should be in the syntax */
 | 
							/* TODO maybe claims should be in the syntax */
 | 
				
			||||||
		  {	Tac t = tacCreate(TAC_CLAIM);
 | 
							  {	Tac t = tacCreate(TAC_CLAIM);
 | 
				
			||||||
		  	t->t1.sym = $2;
 | 
							  	t->t1.sym = $2;
 | 
				
			||||||
@ -226,11 +227,17 @@ typeinfoN	: /* empty */
 | 
				
			|||||||
		  }
 | 
							  }
 | 
				
			||||||
		;
 | 
							;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Previously, the label could be omitted. It is now required. */
 | 
					 | 
				
			||||||
label		: '_' ID
 | 
					label		: '_' ID
 | 
				
			||||||
		  { $$ = $2; }
 | 
							  { $$ = $2; }
 | 
				
			||||||
		;
 | 
							;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					optlabel        : /* empty */
 | 
				
			||||||
 | 
					                 { $$ = NULL; }
 | 
				
			||||||
 | 
					               | label
 | 
				
			||||||
 | 
							  { }
 | 
				
			||||||
 | 
					                ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
term  		: ID
 | 
					term  		: ID
 | 
				
			||||||
		  {
 | 
							  {
 | 
				
			||||||
		  	Tac t = tacCreate(TAC_STRING);
 | 
							  	Tac t = tacCreate(TAC_STRING);
 | 
				
			||||||
 | 
				
			|||||||
@ -241,6 +241,7 @@ roleCreate (Term name)
 | 
				
			|||||||
  r->locals = NULL;
 | 
					  r->locals = NULL;
 | 
				
			||||||
  r->variables = NULL;
 | 
					  r->variables = NULL;
 | 
				
			||||||
  r->declaredvars = NULL;
 | 
					  r->declaredvars = NULL;
 | 
				
			||||||
 | 
					  r->declaredconsts = NULL;
 | 
				
			||||||
  r->initiator = 1;		//! Will be determined later, if a read is the first action (in compiler.c)
 | 
					  r->initiator = 1;		//! Will be determined later, if a read is the first action (in compiler.c)
 | 
				
			||||||
  r->next = NULL;
 | 
					  r->next = NULL;
 | 
				
			||||||
  return r;
 | 
					  return r;
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,8 @@ struct claimlist
 | 
				
			|||||||
  Term type;
 | 
					  Term type;
 | 
				
			||||||
  //! The term element for this node.
 | 
					  //! The term element for this node.
 | 
				
			||||||
  Term label;
 | 
					  Term label;
 | 
				
			||||||
 | 
					  //! Any parameters
 | 
				
			||||||
 | 
					  Term parameter;
 | 
				
			||||||
  //! The pointer to the protocol (not defined typically, because
 | 
					  //! The pointer to the protocol (not defined typically, because
 | 
				
			||||||
  //! at compile time of the claim the protocol structure is not known yet.)
 | 
					  //! at compile time of the claim the protocol structure is not known yet.)
 | 
				
			||||||
  void *protocol;
 | 
					  void *protocol;
 | 
				
			||||||
@ -124,6 +126,8 @@ struct role
 | 
				
			|||||||
  Termlist locals;
 | 
					  Termlist locals;
 | 
				
			||||||
  //! Local variables for this role.
 | 
					  //! Local variables for this role.
 | 
				
			||||||
  Termlist variables;
 | 
					  Termlist variables;
 | 
				
			||||||
 | 
					  //! Declared constants for this role
 | 
				
			||||||
 | 
					  Termlist declaredconsts;
 | 
				
			||||||
  //! Declared variables for this role
 | 
					  //! Declared variables for this role
 | 
				
			||||||
  Termlist declaredvars;
 | 
					  Termlist declaredvars;
 | 
				
			||||||
  //! Flag for initiator roles
 | 
					  //! Flag for initiator roles
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,7 @@ Term CLAIM_Secret;
 | 
				
			|||||||
Term CLAIM_Nisynch;
 | 
					Term CLAIM_Nisynch;
 | 
				
			||||||
Term CLAIM_Niagree;
 | 
					Term CLAIM_Niagree;
 | 
				
			||||||
Term CLAIM_Empty;
 | 
					Term CLAIM_Empty;
 | 
				
			||||||
 | 
					Term CLAIM_Reachable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//! Init special terms
 | 
					//! Init special terms
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -50,4 +51,5 @@ specialTermInit (const System sys)
 | 
				
			|||||||
  langcons (CLAIM_Nisynch, "Nisynch", TERM_Claim);
 | 
					  langcons (CLAIM_Nisynch, "Nisynch", TERM_Claim);
 | 
				
			||||||
  langcons (CLAIM_Niagree, "Niagree", TERM_Claim);
 | 
					  langcons (CLAIM_Niagree, "Niagree", TERM_Claim);
 | 
				
			||||||
  langcons (CLAIM_Empty, "Empty", TERM_Claim);
 | 
					  langcons (CLAIM_Empty, "Empty", TERM_Claim);
 | 
				
			||||||
 | 
					  langcons (CLAIM_Reachable, "Reachable", TERM_Claim);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,5 +18,6 @@ extern Term CLAIM_Secret;
 | 
				
			|||||||
extern Term CLAIM_Nisynch;
 | 
					extern Term CLAIM_Nisynch;
 | 
				
			||||||
extern Term CLAIM_Niagree;
 | 
					extern Term CLAIM_Niagree;
 | 
				
			||||||
extern Term CLAIM_Empty;
 | 
					extern Term CLAIM_Empty;
 | 
				
			||||||
 | 
					extern Term CLAIM_Reachable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -75,6 +75,8 @@ switchesInit (int argc, char **argv)
 | 
				
			|||||||
  switches.switchP = 0;		// multi-purpose parameter
 | 
					  switches.switchP = 0;		// multi-purpose parameter
 | 
				
			||||||
  switches.experimental = 0;	// experimental stuff defaults to 0, whatever that means.
 | 
					  switches.experimental = 0;	// experimental stuff defaults to 0, whatever that means.
 | 
				
			||||||
  switches.removeclaims = false;	// default: leave claims from spdl file
 | 
					  switches.removeclaims = false;	// default: leave claims from spdl file
 | 
				
			||||||
 | 
					  switches.addreachableclaim = false;	// add 'reachable' claims
 | 
				
			||||||
 | 
					  switches.addallclaims = false;	// add all sorts of claims
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Output
 | 
					  // Output
 | 
				
			||||||
  switches.output = SUMMARY;	// default is to show a summary
 | 
					  switches.output = SUMMARY;	// default is to show a summary
 | 
				
			||||||
@ -395,6 +397,37 @@ switcher (const int process, int index)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (detect ('C', "generate-claims", 0))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (!process)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  helptext ("-C,--generate-claims",
 | 
				
			||||||
 | 
							    "ignore any existing claims and automatically generate new claims");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  switches.removeclaims = true;
 | 
				
			||||||
 | 
						  switches.addallclaims = true;
 | 
				
			||||||
 | 
						  return index;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (detect ('G', "generate-semibundles", 0))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      if (!process)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  helptext ("-G,--generate-statespace",
 | 
				
			||||||
 | 
							    "ignore any existing claims and add 'reachable' claims to generate the full state space");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  switches.removeclaims = true;	// remove parsed claims
 | 
				
			||||||
 | 
						  switches.addreachableclaim = true;	// add reachability claims
 | 
				
			||||||
 | 
						  switches.prune = 0;	// do not prune anything
 | 
				
			||||||
 | 
						  return index;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* ==================
 | 
					  /* ==================
 | 
				
			||||||
   *  Bounding options
 | 
					   *  Bounding options
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
				
			|||||||
@ -54,6 +54,8 @@ struct switchdata
 | 
				
			|||||||
  int switchP;			//!< A multi-purpose integer parameter, passed to the partial order reduction method selected.
 | 
					  int switchP;			//!< A multi-purpose integer parameter, passed to the partial order reduction method selected.
 | 
				
			||||||
  int experimental;		//!< Experimental stuff goes here until it moves into main stuff.
 | 
					  int experimental;		//!< Experimental stuff goes here until it moves into main stuff.
 | 
				
			||||||
  int removeclaims;		//!< Remove any claims in the spdl file
 | 
					  int removeclaims;		//!< Remove any claims in the spdl file
 | 
				
			||||||
 | 
					  int addreachableclaim;	//!< Adds 'reachable' claims to each role
 | 
				
			||||||
 | 
					  int addallclaims;		//!< Adds all sorts of claims to the roles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Output
 | 
					  // Output
 | 
				
			||||||
  int output;			//!< From enum outputs: what should be produced. Default ATTACK.
 | 
					  int output;			//!< From enum outputs: what should be produced. Default ATTACK.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										54
									
								
								src/symbol.c
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/symbol.c
									
									
									
									
									
								
							@ -211,6 +211,60 @@ symbolSysConst (const char *str)
 | 
				
			|||||||
  return symb;
 | 
					  return symb;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Generate the first fresh free number symbol, prefixed by a certain symbol's string.
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Note that there is an upper limit to this, to avoid some problems with buffer overflows etc.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Symbol
 | 
				
			||||||
 | 
					symbolNextFree (Symbol prefixsymbol)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  char *prefixstr;
 | 
				
			||||||
 | 
					  int n;
 | 
				
			||||||
 | 
					  int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (prefixsymbol != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      prefixstr = (char *) prefixsymbol->text;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      prefixstr = "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  len = strlen (prefixstr);
 | 
				
			||||||
 | 
					  n = 1;
 | 
				
			||||||
 | 
					  while (n <= 9999)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      char buffer[len + 5];	// thus we must enforce a maximum of 9.999 (allowing for storage of \0 )
 | 
				
			||||||
 | 
					      Symbol symb;
 | 
				
			||||||
 | 
					      int slen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      slen = sprintf (buffer, "%s%i", prefixstr, n);
 | 
				
			||||||
 | 
					      symb = lookup (buffer);
 | 
				
			||||||
 | 
					      if (symb == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  char *newstring;
 | 
				
			||||||
 | 
						  // Copy the buffer to something that will survive
 | 
				
			||||||
 | 
						  /**
 | 
				
			||||||
 | 
						   * Memory leak: although this routine should not be called recursively, it will never de-allocate this memory.
 | 
				
			||||||
 | 
						   * Thus, some precaution is necessary.
 | 
				
			||||||
 | 
						   * [x][CC]
 | 
				
			||||||
 | 
						   */
 | 
				
			||||||
 | 
						  newstring = (char *) memAlloc (slen + 1);
 | 
				
			||||||
 | 
						  memcpy (newstring, buffer, slen + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  /* This persistent string can be used to return a fresh symbol */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  return symbolSysConst (newstring);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Try next one
 | 
				
			||||||
 | 
					      n++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  error ("We ran out of numbers (%i) when trying to generate a fresh symbol.",
 | 
				
			||||||
 | 
						 n);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//! Fix all the unset keylevels
 | 
					//! Fix all the unset keylevels
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
symbol_fix_keylevels (void)
 | 
					symbol_fix_keylevels (void)
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ void symbolPrint (const Symbol s);
 | 
				
			|||||||
void symbolPrintAll (void);
 | 
					void symbolPrintAll (void);
 | 
				
			||||||
Symbol symbolSysConst (const char *str);
 | 
					Symbol symbolSysConst (const char *str);
 | 
				
			||||||
void symbol_fix_keylevels (void);
 | 
					void symbol_fix_keylevels (void);
 | 
				
			||||||
 | 
					Symbol symbolNextFree (Symbol prefixsymbol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void eprintf (char *fmt, ...);
 | 
					void eprintf (char *fmt, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								src/term.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/term.c
									
									
									
									
									
								
							@ -1336,3 +1336,19 @@ isLeafNameEqual (Term t1, Term t2)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  return (TermSymb (t1) == TermSymb (t2));
 | 
					  return (TermSymb (t1) == TermSymb (t2));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Generate a fresh term, that does not occur yet, prefixed with the string of the given term.
 | 
				
			||||||
 | 
					Term
 | 
				
			||||||
 | 
					freshTermPrefix (Term prefixterm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Symbol prefixsymbol;
 | 
				
			||||||
 | 
					  Symbol freshsymbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  prefixsymbol = NULL;
 | 
				
			||||||
 | 
					  if (prefixterm != NULL && realTermLeaf (prefixterm))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      prefixsymbol = TermSymb (prefixterm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  freshsymbol = symbolNextFree (prefixsymbol);
 | 
				
			||||||
 | 
					  return makeTermType (GLOBAL, freshsymbol, -1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -196,5 +196,6 @@ float term_constrain_level (const Term term);
 | 
				
			|||||||
void term_set_keylevels (const Term term);
 | 
					void term_set_keylevels (const Term term);
 | 
				
			||||||
void termPrintDiff (Term t1, Term t2);
 | 
					void termPrintDiff (Term t1, Term t2);
 | 
				
			||||||
int isLeafNameEqual (Term t1, Term t2);
 | 
					int isLeafNameEqual (Term t1, Term t2);
 | 
				
			||||||
 | 
					Term freshTermPrefix (Term prefixterm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user