756 lines
15 KiB
C
756 lines
15 KiB
C
/** antclass.c **/
|
|
|
|
/*
|
|
* Manipulacje klasami abstrakcyjnymi, tworzenie nowych,
|
|
* modyfikowanie ich parametrow, sprawdzanie, etc.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <assert.h>
|
|
#include "antclass.h"
|
|
#include "anpsmod.h"
|
|
#include "anproc.h"
|
|
#include "antypes.h"
|
|
#include "anmacro.h"
|
|
#include "macro.h"
|
|
#include "dbm.h"
|
|
|
|
/*
|
|
* Tworzenie klasy
|
|
*/
|
|
TimedClass_set *
|
|
tclass_create(ProdLoc_set *loc, DBM_elem *zone, DBM_elem *cor, dpt_t depth)
|
|
{
|
|
TimedClass_set *new_tclass;
|
|
|
|
new_tclass = tclass_create_nd(loc, zone, cor);
|
|
new_tclass->depth = depth;
|
|
|
|
return new_tclass;
|
|
}
|
|
|
|
/*
|
|
* Tworzenie klasy bez okreslania glebokosci
|
|
*/
|
|
TimedClass_set *
|
|
tclass_create_nd(ProdLoc_set *loc, DBM_elem *zone, DBM_elem *cor)
|
|
{
|
|
TimedClass_set *new_tclass;
|
|
|
|
new_tclass = smalloc(sizeof(TimedClass_set));
|
|
new_tclass->dbm = zone;
|
|
new_tclass->cor_dbm = cor;
|
|
/*new_tclass->depth = depth;*/
|
|
new_tclass->loc_set = loc;
|
|
new_tclass->rs = NULL;
|
|
new_tclass->stable_pre = NULL;
|
|
new_tclass->stable_succ = NULL;
|
|
new_tclass->next = NULL;
|
|
|
|
return new_tclass;
|
|
}
|
|
|
|
/*
|
|
* Tworzenie domyslnej klasy wyjsciowej dla odkrytej lokacji
|
|
*/
|
|
TimedClass_set *
|
|
tclass_create_base(ProdLoc_set *loc)
|
|
{
|
|
/* Nowa klasa rowna niezmiennikowi (z cor rownym rowniez niezmiennikowi) */
|
|
return tclass_create(loc, NULL, NULL, DEPTH_INF);
|
|
}
|
|
|
|
/*
|
|
* Dodawanie klasy do zbioru klas (przyczepianie do odpowiedniej lokacji)
|
|
*/
|
|
void
|
|
tclass_add(TimedClass_set *tclass)
|
|
{
|
|
ProdLoc_set *loc;
|
|
|
|
#ifdef TC_VERBOSE
|
|
printf("tclass_add (%p): ", tclass); tclass_print(tclass); printf("\n");
|
|
#endif
|
|
|
|
loc = tclass->loc_set;
|
|
|
|
if (!loc->classes)
|
|
loc->classes = tclass;
|
|
else
|
|
loc->last_class->next = tclass;
|
|
loc->last_class = tclass;
|
|
}
|
|
|
|
/*
|
|
* Usuwanie klasy ze zbioru wszystkich klas nalezacych do podzialu
|
|
*
|
|
* przez koniecznosc szukania poprzedniego elementu listy moze byc
|
|
* nieco bolesne, ale oszczedzamy troche pamieci ;)
|
|
*
|
|
* W praktyce na razie funkcja okazuje sie raczej nieprzydatna, bo
|
|
* wykorzystujemy istniejace klasy i zmieniamy w nich strefy.
|
|
*
|
|
* UWAGA: brakuje usuwania informacji o klasach stabilnych (trzeba
|
|
* zwolnic pamiec).
|
|
*/
|
|
// void
|
|
// tclass_del(TimedClass_set *tclass)
|
|
// {
|
|
// ProdLoc_set *loc;
|
|
// TimedClass_set *tmp, *prev = NULL;
|
|
//
|
|
// loc = tclass->loc_set;
|
|
//
|
|
// for (tmp = loc->classes; tmp; prev = tmp, tmp = tmp->next)
|
|
// {
|
|
// if (tmp == tclass)
|
|
// {
|
|
// if (prev) /* usuwamy dalej niz z poczatku */
|
|
// {
|
|
// prev->next = tmp->next;
|
|
//
|
|
// /* usuwamy z konca */
|
|
// if (tmp == loc->last_class)
|
|
// loc->last_class = prev;
|
|
// }
|
|
// else /* usuwamy z poczatku */
|
|
// {
|
|
// loc->classes = tmp->next;
|
|
// /* tutaj nie aktualizujemy last_class, bo jak korzen
|
|
// * bedzie NULL, to nie patrzymy na last_class.
|
|
// */
|
|
// }
|
|
//
|
|
// if (tmp->dbm) dbm_destroy(tmp->dbm);
|
|
// if (tmp->cor_dbm) dbm_destroy(tmp->cor_dbm);
|
|
// free(tmp);
|
|
//
|
|
// return;
|
|
// }
|
|
// }
|
|
//
|
|
// assert(0); /* jesli jestesmy tutaj, to nie znalezlismy klasy do usuniecia */
|
|
// }
|
|
|
|
void
|
|
tclass_print(TimedClass_set *tc)
|
|
{
|
|
printf("{"); prod_loc_show(tc->loc_set->loc);
|
|
printf(" Z=");
|
|
dbm_xprint(tclass_readZoneDBM(tc), dbm_size);
|
|
if (!tc->dbm) printf("=(inv)");
|
|
printf(" Cor=");
|
|
if (tc->cor_dbm)
|
|
dbm_xprint(tc->cor_dbm, dbm_size);
|
|
else
|
|
printf("(zone)");
|
|
printf(" dpt=");
|
|
if (tc->depth != DEPTH_INF)
|
|
printf("%u", tc->depth);
|
|
else
|
|
printf("inf");
|
|
printf("} ");
|
|
}
|
|
|
|
/*
|
|
* Funkcja zwracajaca adres DBM ze strefa klasy w celu jego ODCZYTANIA
|
|
* UWAGA: nie jest tworzona kopia, uwazac zeby nie zmodyfikowac!
|
|
*/
|
|
DBM_elem *
|
|
tclass_readZoneDBM(TimedClass_set *tclass)
|
|
{
|
|
if (!tclass->dbm) return tclass->loc_set->inv;
|
|
else return tclass->dbm;
|
|
}
|
|
|
|
/*
|
|
* Funkcja zwracajaca adres DBM z cor klasy w celu jego ODCZYTANIA
|
|
* UWAGA: nie jest tworzona kopia, uwazac zeby nie zmodyfikowac!
|
|
*/
|
|
DBM_elem *
|
|
tclass_readCorDBM(TimedClass_set *tclass)
|
|
{
|
|
/* jesli cor == NULL, to jest taki sam jak zone */
|
|
if (!tclass->cor_dbm) return tclass_readZoneDBM(tclass);
|
|
else return tclass->cor_dbm; /* cor ustawiony jawnie (niedomyslny) */
|
|
}
|
|
|
|
/*
|
|
* Funkcja zwracajaca strefe klasy gotowa do modyfikowania
|
|
*/
|
|
DBM_elem *
|
|
tclass_writeZoneDBM(TimedClass_set *tclass)
|
|
{
|
|
if (!tclass->dbm) tclass->dbm = dbm_copy(tclass->loc_set->inv, dbm_size);
|
|
|
|
return tclass->dbm;
|
|
}
|
|
|
|
/*
|
|
* Funkcja zwracajaca cor klasy gotowy do modyfikowania
|
|
*/
|
|
DBM_elem *
|
|
tclass_writeCorDBM(TimedClass_set *tclass)
|
|
{
|
|
if (!tclass->cor_dbm) tclass->cor_dbm = dbm_copy(tclass_readZoneDBM(tclass), dbm_size);
|
|
|
|
return tclass->cor_dbm;
|
|
}
|
|
|
|
/*
|
|
* Funkcje pomocnicze do przenoszenia DBM-ow do nowych klas
|
|
* (unikanie kopiowania)
|
|
*
|
|
* Po uzyciu ktorejs z nich klasa jest zdegenerowana,
|
|
* tzn. cor i zone moga nie odpowiadac wlasciwej klasie.
|
|
*/
|
|
/*
|
|
DBM_elem *
|
|
tclass_consumeZoneDBM(TimedClass_set *tclass)
|
|
{
|
|
DBM_elem *rlt;
|
|
|
|
rlt = tclass_writeZoneDBM(tclass);
|
|
tclass->dbm = NULL;
|
|
|
|
return rlt;
|
|
}
|
|
|
|
DBM_elem *
|
|
tclass_consumeCorDBM(TimedClass_set *tclass)
|
|
{
|
|
DBM_elem *rlt;
|
|
|
|
rlt = tclass_writeCorDBM(tclass);
|
|
tclass->cor_dbm = NULL;
|
|
|
|
return rlt;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
* Podmienianie strefy klasy, cor domyslnie taki sam jak calosc klasy
|
|
*/
|
|
void
|
|
tclass_replaceZoneDBM(TimedClass_set *tclass, DBM_elem *new_dbm)
|
|
{
|
|
DBM_elem *tmp;
|
|
|
|
assert(!dbm_empty(new_dbm, dbm_size));
|
|
|
|
#ifdef TC_VERBOSE
|
|
printf("tclass_replaceZoneDBM: nowy zone dla klasy (%p) ", tclass); tclass_print(tclass);
|
|
printf("; nowy zone: "); dbm_xprint(new_dbm, dbm_size); printf("\n");
|
|
#endif
|
|
|
|
tmp = tclass->dbm;
|
|
tclass->dbm = dbm_copy(new_dbm, dbm_size);
|
|
if (tmp) dbm_destroy(tmp);
|
|
|
|
if (tclass->cor_dbm) dbm_destroy(tclass->cor_dbm);
|
|
tclass->cor_dbm = NULL;
|
|
}
|
|
|
|
/*
|
|
* Podmienianie cor klasy
|
|
*/
|
|
void
|
|
tclass_replaceCorDBM(TimedClass_set *tclass, DBM_elem *new_cor)
|
|
{
|
|
DBM_elem *tmp;
|
|
|
|
assert(!dbm_empty(new_cor, dbm_size));
|
|
|
|
tmp = tclass->cor_dbm;
|
|
tclass->cor_dbm = dbm_copy(new_cor, dbm_size);
|
|
|
|
if (tmp) dbm_destroy(tmp);
|
|
}
|
|
|
|
void
|
|
tclass_depthUpdateIncr(TimedClass_set *tclass, TimedClass_set *pre_tclass)
|
|
{
|
|
dpt_t new_depth;
|
|
|
|
if (pre_tclass->depth < DEPTH_INF-1)
|
|
{
|
|
new_depth = pre_tclass->depth+1;
|
|
if (new_depth < tclass->depth)
|
|
{
|
|
tclass->depth = new_depth;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FERROR("Depth overflow!");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Ustawianie glebokosci klasy na inf jesli nie zawiera
|
|
* ona stanu poczatkowego q0
|
|
*/
|
|
void
|
|
tclass_depthUpdateInf(TimedClass_set *tclass)
|
|
{
|
|
if (!tclass_hasInit(tclass))
|
|
{
|
|
assert(!tclass->rs); /* jak inf, to nie moze byc w RS */
|
|
tclass->depth = DEPTH_INF;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Sprawdzanie czy klasa zawiera stan poczatkowy q0
|
|
*/
|
|
bool
|
|
tclass_hasInit(TimedClass_set *tclass)
|
|
{
|
|
DBM_elem *tmp;
|
|
bool has_init = false;
|
|
|
|
if (tclass->loc_set == init_loc_set) /* zgodnosc lokacji */
|
|
{
|
|
/*dbm_print(tclass_readZoneDBM(tclass), dbm_size);*/
|
|
|
|
assert(dbm_is_canonical(tclass_readZoneDBM(tclass), dbm_size));
|
|
|
|
tmp = dbm_intersection_cf(tclass_readZoneDBM(tclass), zeroDBM, dbm_size);
|
|
if (!dbm_empty(tmp, dbm_size)) has_init = true;
|
|
dbm_destroy(tmp);
|
|
}
|
|
|
|
return has_init;
|
|
}
|
|
|
|
/*
|
|
* Do poprawy. Trzeba troche zmienic struktury danych, bo to szukanie jest mordercze.
|
|
*/
|
|
bool
|
|
tclass_is_in_ReachStable(TimedClass_set *tclass)
|
|
{
|
|
if (tclass->rs) return true;
|
|
else return false;
|
|
}
|
|
|
|
/*
|
|
* Dodawanie klasy do zbioru reachable+stable klas
|
|
*/
|
|
void
|
|
tclass_ReachStable_add(TimedClass_set *new_class, TimedClassRS_set **root, TimedClassRS_set **cur)
|
|
{
|
|
assert(new_class->depth != DEPTH_INF);
|
|
assert(tclass_ReachStable_is_sorted(*root));
|
|
|
|
if (!tclass_is_in_ReachStable(new_class))
|
|
{
|
|
TimedClassRS_set *new, *pred;
|
|
|
|
new = smalloc(sizeof(TimedClassRS_set));
|
|
new->tclass = new_class;
|
|
new->stable = false;
|
|
|
|
new_class->rs = new;
|
|
|
|
if (!*root)
|
|
{
|
|
new->prev = NULL;
|
|
new->next = NULL;
|
|
*root = *cur = new;
|
|
}
|
|
else
|
|
{
|
|
/* cofamy sie do elementu o glebokosci nie wiekszej od naszej (po ktorym chcemy dodac nowy element) > */
|
|
for (pred = *cur; pred->tclass->depth > new_class->depth; pred = pred->prev);
|
|
|
|
new->next = pred->next;
|
|
new->prev = pred; /* poprzedni element to ostatnio dodany */
|
|
if (pred->next) {
|
|
pred->next->prev = new;
|
|
}
|
|
pred->next = new;
|
|
|
|
if (pred == *cur) *cur = new;
|
|
}
|
|
|
|
}
|
|
|
|
assert(tclass_ReachStable_is_sorted(*root));
|
|
}
|
|
|
|
/*
|
|
* Dodawanie klasy zawierajacej stan q0 do zbioru
|
|
*/
|
|
void
|
|
tclass_ReachStable_addInit(TimedClass_set *new_class, TimedClassRS_set **root, TimedClassRS_set **cur)
|
|
{
|
|
TimedClassRS_set *new;
|
|
|
|
if (!tclass_is_in_ReachStable(new_class))
|
|
{
|
|
assert(new_class->depth != DEPTH_INF);
|
|
|
|
new = smalloc(sizeof(TimedClassRS_set));
|
|
new->tclass = new_class;
|
|
new->stable = false;
|
|
new->next = *root; /* pod nowy element podczepiamy korzen */
|
|
new->prev = NULL; /* bo dodajemy na poczatku */
|
|
|
|
new_class->rs = new;
|
|
|
|
if (!*root) /* jesli lista byla pusta, to trzeba zaktualizowac cur, bo nowy bedzie ostatni */
|
|
{
|
|
*cur = new;
|
|
}
|
|
else
|
|
{
|
|
assert(*root != NULL);
|
|
(*root)->prev = new;
|
|
}
|
|
*root = new; /* lista zaczyna sie od nowego elementu */
|
|
|
|
assert(tclass_ReachStable_is_sorted(*root));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Usuwanie klasy ze zbioru klas
|
|
*/
|
|
void
|
|
tclass_ReachStable_delete(TimedClass_set *del_class, TimedClassRS_set **root, TimedClassRS_set **cur)
|
|
{
|
|
#ifdef TC_VERBOSE
|
|
printf("Usuwam klase (%p) ze zbioru ReachStable: ", del_class);
|
|
tclass_print(del_class);
|
|
#endif
|
|
|
|
if (tclass_is_in_ReachStable(del_class))
|
|
{
|
|
TimedClassRS_set *tmpRS;
|
|
|
|
tmpRS = del_class->rs;
|
|
|
|
if (tmpRS->next)
|
|
tmpRS->next->prev = tmpRS->prev;
|
|
if (tmpRS->prev)
|
|
tmpRS->prev->next = tmpRS->next;
|
|
|
|
if (tmpRS == *root)
|
|
*root = NULL;
|
|
else
|
|
if (tmpRS == *cur) *cur = tmpRS->prev;
|
|
|
|
free(tmpRS);
|
|
del_class->rs = NULL;
|
|
|
|
#ifdef TC_VERBOSE
|
|
printf("faktycznie usuwana\n");
|
|
tclass_ReachStable_print(*root);
|
|
#endif
|
|
|
|
}
|
|
#ifdef TC_VERBOSE
|
|
else
|
|
{
|
|
printf("nie bylo co usuwac\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Zwalnianie pamieci przydzielonej na strukture zbioru (bez faktycznych klas)
|
|
*/
|
|
/*void
|
|
tclass_ReachStable_free(TimedClassRS_set **root)
|
|
{
|
|
}*/
|
|
|
|
/*
|
|
* Oznaczanie klasy jako osiagalna i niestabilna (czyli dodawanie do zbioru)
|
|
*/
|
|
void
|
|
tclass_mark_reach_unst(TimedClass_set *tclass, TimedClassRS_set **root, TimedClassRS_set **cur)
|
|
{
|
|
tclass_ReachStable_add(tclass, root, cur);
|
|
}
|
|
|
|
/*
|
|
* Oznaczanie klasy jako osiagalna (dodawanie klasy do zbioru reachable)
|
|
*/
|
|
void
|
|
tclass_rs_mark_stable(TimedClassRS_set *tclass_rs)
|
|
{
|
|
tclass_rs->stable = true;
|
|
}
|
|
|
|
/*
|
|
* Znajdowanie klasy tclass i oznaczanie jako stabilna
|
|
*/
|
|
void
|
|
tclass_mark_stable(TimedClass_set *tclass)
|
|
{
|
|
assert(tclass->rs != NULL);
|
|
|
|
tclass->rs->stable = true;
|
|
}
|
|
|
|
/*
|
|
* Znajdowanie klasy tclass i oznaczanie jako niestabilna
|
|
*/
|
|
void
|
|
tclass_mark_unstable(TimedClass_set *tclass)
|
|
{
|
|
if (tclass->rs)
|
|
tclass->rs->stable = false;
|
|
}
|
|
|
|
/*
|
|
* Oznaczanie wszystkich poprzednikow danej klasy jako niestabilne
|
|
*/
|
|
void
|
|
tclass_mark_preds_unstable(TimedClass_set *tclass)
|
|
{
|
|
SrcLoc_set *src_loc;
|
|
TimedClass_set *tclass_src;
|
|
ProdTrans_set *trans_e;
|
|
|
|
for (src_loc = tclass->loc_set->src_locs; src_loc; src_loc = src_loc->next)
|
|
{
|
|
for (tclass_src = src_loc->loc_set->classes; tclass_src; tclass_src = tclass_src->next)
|
|
{
|
|
for (trans_e = src_loc->trans; trans_e; trans_e = trans_e->next)
|
|
{
|
|
if (!psmodel_pre_empty(trans_e, src_loc->loc_set, tclass->loc_set,
|
|
tclass_readZoneDBM(tclass_src), tclass_readZoneDBM(tclass)))
|
|
{
|
|
tclass_mark_unstable(tclass_src);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TimedClassRS_set *
|
|
tclass_pickReachUnst(TimedClassRS_set *root)
|
|
{
|
|
TimedClassRS_set *curRS;
|
|
|
|
assert(tclass_ReachStable_is_sorted(root));
|
|
|
|
/* szukamy pierwszego niestabilnego elementu (od korzenia) */
|
|
for (curRS = root; curRS; curRS = curRS->next)
|
|
{
|
|
if (curRS->stable == false)
|
|
{
|
|
return curRS;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Sprawdzanie czy lista ReachStable jest posortowana
|
|
*/
|
|
bool
|
|
tclass_ReachStable_is_sorted(TimedClassRS_set *root)
|
|
{
|
|
TimedClassRS_set *curRS;
|
|
dpt_t min_depth = 0;
|
|
|
|
for (curRS = root; curRS; curRS = curRS->next)
|
|
{
|
|
if (curRS->tclass->depth < min_depth)
|
|
return false;
|
|
|
|
min_depth = curRS->tclass->depth;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Wyswietlanie wszystkich stabilnych klas nalezacych do zbioru RS
|
|
*/
|
|
void
|
|
tclass_ReachStable_print(TimedClassRS_set *root)
|
|
{
|
|
TimedClassRS_set *curRS;
|
|
idx_t i;
|
|
|
|
for (curRS = root, i = 1; curRS; curRS = curRS->next, i++)
|
|
{
|
|
printf("(%u) (%p) ", i, curRS->tclass); tclass_print(curRS->tclass);
|
|
if (!curRS->stable) printf("UNSTABLE!!!");
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Zapamietywanie stabilnego nastepnika
|
|
*/
|
|
void
|
|
tclass_saveStable(TimedClass_set *tcX, TimedClass_set *tcY)
|
|
{
|
|
TClassPtr_set *new;
|
|
|
|
assert(tclass_isReallyStableSucc(tcX, tcY));
|
|
|
|
if (!tclass_is_in_tcPtrs(tcY, tcX->stable_succ))
|
|
{
|
|
new = smalloc(sizeof(TClassPtr_set));
|
|
new->tclass = tcY;
|
|
new->next = tcX->stable_succ;
|
|
tcX->stable_succ = new;
|
|
}
|
|
|
|
if (!tclass_is_in_tcPtrs(tcX, tcY->stable_pre))
|
|
{
|
|
new = smalloc(sizeof(TClassPtr_set));
|
|
new->tclass = tcX;
|
|
new->next = tcY->stable_pre;
|
|
tcY->stable_pre = new;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Usuwanie informacji o poprzednikach stabilnych
|
|
* wzgledem danej klasy tcY.
|
|
*/
|
|
void
|
|
tclass_forgetPreStability(TimedClass_set *tcY)
|
|
{
|
|
TClassPtr_set *tcptr;
|
|
|
|
if (tcY->stable_pre)
|
|
{
|
|
for (tcptr = tcY->stable_pre; tcptr; )
|
|
{
|
|
TClassPtr_set *tmp;
|
|
|
|
/* zagladamy do kazdego poprzednika i usuwamy sie z jego stable_succ */
|
|
tclass_tcPtrDel(tcY, &tcptr->tclass->stable_succ);
|
|
|
|
tmp = tcptr;
|
|
tcptr = tcptr->next;
|
|
free(tmp);
|
|
}
|
|
tcY->stable_pre = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Usuwanie informacji o nastepnikach wzgledem
|
|
* ktorych jest stabilna dana klasa tcX.
|
|
*/
|
|
void
|
|
tclass_forgetSuccStability(TimedClass_set *tcX)
|
|
{
|
|
TClassPtr_set *tcptr;
|
|
|
|
if (tcX->stable_succ)
|
|
{
|
|
for (tcptr = tcX->stable_succ; tcptr; )
|
|
{
|
|
TClassPtr_set *tmp;
|
|
|
|
/* zagladamy do kazdego nastepnika i usuwamy sie z jego stable_pre */
|
|
tclass_tcPtrDel(tcX, &tcptr->tclass->stable_pre);
|
|
|
|
tmp = tcptr;
|
|
tcptr = tcptr->next;
|
|
free(tmp);
|
|
}
|
|
tcX->stable_succ = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
tclass_tcPtrDel(TimedClass_set *tc, TClassPtr_set **tcptr)
|
|
{
|
|
TClassPtr_set *tmp, *prev = NULL;
|
|
|
|
for (tmp = *tcptr; tmp; prev = tmp, tmp = tmp->next)
|
|
{
|
|
if (tmp->tclass == tc)
|
|
{
|
|
if (prev)
|
|
prev->next = tmp->next;
|
|
else
|
|
*tcptr = tmp->next;
|
|
|
|
free(tmp);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
tclass_is_in_tcPtrs(TimedClass_set *tc, TClassPtr_set *tcptr)
|
|
{
|
|
TClassPtr_set *tmp;
|
|
|
|
for (tmp = tcptr; tmp; tmp = tmp->next)
|
|
if (tmp->tclass == tc) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Sprawdzanie czy klasa tcY jest stabilnym nastepnikiem tcX
|
|
*/
|
|
bool
|
|
tclass_isStableSucc(TimedClass_set *tcX, TimedClass_set *tcY)
|
|
{
|
|
if(tclass_is_in_tcPtrs(tcY, tcX->stable_succ))
|
|
{
|
|
assert(tclass_isReallyStableSucc(tcX, tcY));
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Sprawdzanie czy faktycznie mamy wlasciwie zapamietana stabilnosc
|
|
*/
|
|
bool
|
|
tclass_isReallyStableSucc(TimedClass_set *tcX, TimedClass_set *tcY)
|
|
{
|
|
ProdTrans_set *trans_h;
|
|
|
|
/* W rzeczywistosci interesuje nas tylko istnienie jakiegos przejscia dla ktorego jest AE */
|
|
for (trans_h = trans_get(tcX->loc_set, tcY->loc_set); trans_h; trans_h = trans_h->next)
|
|
{
|
|
if (psmodel_pre_eq(tclass_readCorDBM(tcX), trans_h, tcX->loc_set, tcY->loc_set,
|
|
tclass_readCorDBM(tcX), tclass_readCorDBM(tcY)))
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
unsigned int
|
|
tclass_count(ProdLoc_set *locs)
|
|
{
|
|
ProdLoc_set *loc;
|
|
unsigned int nclasses = 0;
|
|
|
|
for (loc = locs; loc; loc = loc->next)
|
|
{
|
|
TimedClass_set *tclass;
|
|
|
|
for (tclass = loc->classes; tclass; tclass = tclass->next)
|
|
{
|
|
nclasses++;
|
|
}
|
|
}
|
|
|
|
return nclasses;
|
|
}
|