Я пытаюсь сгенерировать контракты в C с плагином E-ACSL от FRAMA-C для следующей программы:
struct lnode {
int value;
struct lnode *next;
};
struct set {
int capacity;
int size;
struct lnode *elems;
};
struct set* new(int capacity) {
struct set *new_set;
new_set = (struct set*) malloc(sizeof(struct set));
if(new_set == NULL)
return NULL; /* no memory left */
new_set->capacity = capacity;
new_set->size = 0;
new_set->elems = NULL;
return new_set;
}
int insert(struct set *s, int x) {
struct lnode *new_node;
struct lnode *end_node;
struct lnode *n;
if(s==NULL)
return 0; /* NULL set */
if(s->size >= s->capacity)
return 0; /* no space left */
end_node = s->elems;
n = end_node;
while(n != NULL) {
if(n->value == x)
return 0; /* element already in the set */
end_node = n;
n = n->next;
}
/* Creation of new node */
new_node = (struct lnode*) malloc(sizeof(struct lnode));
if(new_node == NULL)
return 0; /* no memory left */
new_node->value = x;
new_node->next = s->elems;
s->elems = new_node;
s->size += 1;
return 1; /* element added */
}
int isnull(struct set *s) {
if(s==NULL)
return 1;
return 0;
}
int isempty(struct set *s) {
if(s==NULL)
return 0;
if(s->elems==NULL)
return 1; /* s is empty */
return 0;
}
int isfull(struct set *s) {
if(s==NULL)
return 0;
if(s->size >= s->capacity)
return 1; /* s is full */
return 0;
}
int contains(struct set *s, int x) {
struct lnode *n;
if(s==NULL)
return 0; /* s is NULL */
n = s->elems;
while(n != NULL){
if(n->value == x)
return 1; /* element found */
n = n->next;
}
return 0; /* element NOT found */
}
int length(struct set *s) {
struct lnode *n;
int count;
if(s==NULL)
return 0; /* s is NULL */
count = 0;
n = s->elems;
while(n != NULL){
count = count + 1;
n = n->next;
}
return count;
}
В руководстве ACSL (раздел 2.3.2) говорится, что правильный способ сделать это - добавить аннотацию перед функцией. Однако в мою спецификацию я намереваюсь включить предикаты, которые используют функции программы для определения окончательной аксиомы для функции insert . Например:
@ requires \valid(s);
@ behavior A:
@ ensures (isfull(s)=0 && length(s)=0 && contains(s,x)=0 && isnull(s)=0 && isempty(s)=1) ==>
(length(s)=1 && contains(s,x)=1 && isnull(s)=0 && isempty(s)=0 && \result==1);
Когда я пытаюсь скомпилировать, используя e-acsl-gcc.sh
, я получаю эту ошибку:
user@ubuntu-tmpl:~/Documents/Code$ e-acsl-gcc.sh -c insert.c -O exec
++ frama-c -variadic-no-translation -machdep gcc_x86_64 '-cpp-extra-args= -std=c99 -D_DEFAULT_SOURCE -D__NO_CTYPE -D__FC_MACHDEP_X86_64 ' -no-frama-c-stdlib insert.c axiomTes.c -e-acsl -e-acsl-share=/home/user/.opam/system/bin/../share/frama-c/e-acsl/ -then-last -print -ocode a.out.frama.c
[kernel] Parsing FRAMAC_SHARE/e-acsl//e_acsl_gmp_api.h (with preprocessing)
[kernel] Parsing FRAMAC_SHARE/e-acsl//e_acsl.h (with preprocessing)
[kernel] Parsing insert.c (with preprocessing)
insert.c:31:[kernel] user error: unbound function isempty
[kernel] user error: stopping on file "insert.c" that has errors. Add '-kernel-msg-key pp'
for preprocessing command.
[kernel] Frama-C aborted: invalid user input.
e-acsl-gcc: fatal error: aborted by Frama-C
Это заставляет меня думать, что вызов функции либо не разрешен внутри аннотации, либо имеет другую синтаксическую спецификацию. Есть ли способ использовать определенные функции программы для формирования предикатов? Другая возможность, которая все еще подходит для меня, - это получить результат вызова функции где-то еще и использовать его внутри аннотации.
Спасибо!