GCC Code Coverage Report


Directory: /home/runner/work/fsm/fsm/src/
File: /home/runner/work/fsm/fsm/src/fsm.c
Date: 2025-10-07 09:21:52
Exec Total Coverage
Lines: 48 48 100.0%
Branches: 34 34 100.0%

Line Branch Exec Source
1 /**
2 * @file fsm.c
3 * @brief Library to create Finite State Machines using composition.
4 *
5 * This library is expected to be used using composition
6 * @author Teachers from the Departamento de Ingeniería Electrónica. Original authors: José M. Moya and Pedro J. Malagón. Latest contributor: Román Cárdenas.
7 * @date 2023-09-20
8 */
9
10 /* Includes ------------------------------------------------------------------*/
11 /* Standard C includes */
12 #include <stdlib.h>
13
14 /* Other includes */
15 #include "fsm.h"
16
17 //GCOVR_EXCL_START
18 void* __attribute__((weak)) fsm_malloc(size_t s)
19 {
20 return malloc(s);
21 }
22 void __attribute__((weak)) fsm_free(void* p)
23 {
24 free(p);
25 }
26 //GCOVR_EXCL_STOP
27
28 /**
29 * @brief Valida las transiciones de la tabla y cuenta las válidas.
30 * @param p_tt Tabla de transiciones.
31 * @return Número de transiciones válidas, o 0 si excede el límite.
32 */
33 30 static int validate_transitions(fsm_trans_t *p_tt)
34 {
35 30 int valid_transitions = 0;
36 fsm_trans_t *p_t;
37
38 //Explicit int cast because otherwise it treats it as unsigned
39
4/4
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 30 times.
323 for (p_t = p_tt; !(((int) p_t->orig_state == -1) && ((int) p_t->dest_state == -1)); ++p_t)
40 {
41
4/4
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 289 times.
✓ Branch 3 taken 2 times.
293 if (( (int) p_t->orig_state >= 0) && ((int) p_t->dest_state >= 0))
42 {
43 289 ++valid_transitions;
44 }
45 }
46
47
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 28 times.
30 if (valid_transitions > FSM_MAX_TRANSITIONS)
48 {
49 2 return 0;
50 }
51
52 28 return valid_transitions;
53 }
54
55 17 fsm_t *fsm_new(fsm_trans_t *p_tt)
56 {
57 int valid_transitions;
58
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 16 times.
17 if (p_tt == NULL)
59 {
60 1 return NULL;
61 }
62
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13 times.
16 if ((p_tt->orig_state == -1) || (p_tt->dest_state == -1))
63 {
64 3 return NULL;
65 }
66
67 13 valid_transitions = validate_transitions(p_tt);
68
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if(valid_transitions <= 0)
69 {
70 1 return NULL;
71 }
72
73 12 fsm_t *p_fsm = fsm_malloc(sizeof(fsm_t));
74
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if (p_fsm != NULL)
75 {
76 11 fsm_init(p_fsm, p_tt);
77 }
78 12 return p_fsm;
79 }
80
81 1 void fsm_destroy(fsm_t *p_fsm)
82 {
83 1 fsm_free(p_fsm);
84 1 }
85
86 18 int fsm_init(fsm_t *p_fsm, fsm_trans_t *p_tt)
87 {
88 18 int valid_transitions = 0;
89 fsm_trans_t *p_t;
90
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
18 if (p_tt != NULL)
91 {
92 17 p_fsm->p_tt = p_tt;
93 17 p_fsm->current_state = p_tt->orig_state;
94 17 valid_transitions = validate_transitions(p_tt);
95 }
96 18 return valid_transitions;
97 }
98
99 10 int fsm_get_state(fsm_t *p_fsm)
100 {
101 10 return p_fsm->current_state;
102 }
103
104 1 void fsm_set_state(fsm_t *p_fsm, int state)
105 {
106 1 p_fsm->current_state = state;
107 1 }
108
109 12 int fsm_fire(fsm_t *p_fsm)
110 {
111 fsm_trans_t *p_t;
112 12 int transitions_found = 0;
113
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
17 for (p_t = p_fsm->p_tt; p_t->orig_state >= 0; ++p_t)
114 {
115
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
13 if ((p_fsm->current_state == p_t->orig_state))
116 {
117
118
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
11 if(p_t->in == NULL || p_t->in(p_fsm)){
119 8 p_fsm->current_state = p_t->dest_state;
120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (p_t->out)
121 {
122 1 p_t->out(p_fsm);
123 }
124 //Transition found and executed, return 1;
125 8 return 1;
126 } else {
127 //Transitions found but cannot be executed
128 3 transitions_found++;
129 }
130 }
131 }
132
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if(!transitions_found)
133 {
134 //No transition found, return -1
135 1 return -1;
136 } else {
137 //Transitions found, but not executed, return 0
138 3 return 0;
139 }
140 }
141