6xxx strlen and 9xxx conclusions.
[libguestfs-talks.git] / 2020-frama-c / 6000-strverscmp.html
1 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
2 <link rel="stylesheet" href="style.css" type="text/css"/>
3 <script src="code.js" type="text/javascript"></script>
4
5 <h1>glibc strverscmp</h1>
6
7 <pre class="code">
8 <span class="comment">/* Compare S1 and S2 as strings holding indices/version numbers,
9    returning less than, equal to or greater than zero if S1 is less than,
10    equal to or greater than S2 (for more info, see the texinfo doc).
11 */</span>
12
13 int
14 __strverscmp (const char *s1, const char *s2)
15 {
16   const unsigned char *p1 = (const unsigned char *) s1;
17   const unsigned char *p2 = (const unsigned char *) s2;
18
19   /* Symbol(s)    0       [1-9]   others
20      Transition   (10) 0  (01) d  (00) x   */
21   static const uint8_t next_state[] =
22   {
23       /* state    x    d    0  */
24       /* S_N */  S_N, S_I, S_Z,
25       /* S_I */  S_N, S_I, S_I,
26       /* S_F */  S_N, S_F, S_F,
27       /* S_Z */  S_N, S_F, S_Z
28   };
29
30   static const int8_t result_type[] =
31   {
32       /* state   x/x  x/d  x/0  d/x  d/d  d/0  0/x  0/d  0/0  */
33
34       /* S_N */  CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP,
35       /* S_I */  CMP, -1,  -1,  +1,  LEN, LEN, +1,  LEN, LEN,
36       /* S_F */  CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
37       /* S_Z */  CMP, +1,  +1,  -1,  CMP, CMP, -1,  CMP, CMP
38   };
39
40   if (p1 == p2)
41     return 0;
42
43   unsigned char c1 = *p1++;
44   unsigned char c2 = *p2++;
45   /* Hint: '0' is a digit too.  */
46   int state = S_N + ((c1 == '0') + (__my_isdigit (c1) != 0));
47
48   int diff;
49   while ((diff = c1 - c2) == 0)
50     {
51       if (c1 == '\0')
52         return diff;
53
54       state = next_state[state];
55       c1 = *p1++;
56       c2 = *p2++;
57       state += (c1 == '0') + (__my_isdigit (c1) != 0);
58     }
59
60   state = result_type[state * 3 + (((c2 == '0') + (__my_isdigit (c2) != 0)))];
61
62   switch (state)
63   {
64     case CMP:
65       return diff;
66
67     case LEN:
68       while (__my_isdigit (*p1++))
69         if (!__my_isdigit (*p2++))
70           return 1;
71
72       return __my_isdigit (*p2) ? -1 : diff;
73
74     default:
75       return state;
76   }
77 }
78 </pre>