scheduler: avoid using a poisoned macro
[aversive.git] / modules / ihm / parse / parse_string.c
1 #include <stdio.h>
2 #include <inttypes.h>
3 #include <ctype.h>
4 #include <string.h>
5
6 #include "parse.h"
7 #include "parse_string.h"
8
9 struct token_ops token_string_ops = {
10         .parse = parse_string,
11         .complete_get_nb = complete_get_nb_string,
12         .complete_get_elt = complete_get_elt_string,
13         .get_help = get_help_string,
14 };
15
16 #define MULTISTRING_HELP PSTR("Mul-choice STRING")
17 #define ANYSTRING_HELP   PSTR("Any STRING")
18 #define FIXEDSTRING_HELP PSTR("Fixed STRING")
19
20 static uint8_t
21 get_token_len(const char * s)
22 {
23         char c;
24         uint8_t i=0;
25
26         c = pgm_read_byte(s+i);
27         while (c!='#' && c!='\0') {
28                 i++;
29                 c = pgm_read_byte(s+i);
30         }
31         return i;
32 }
33
34 static const char *
35 get_next_token(PGM_P s)
36 {
37         uint8_t i;
38         i = get_token_len(s);
39         if (pgm_read_byte(s+i) == '#')
40                 return s+i+1;
41         return NULL;
42 }
43
44 int8_t 
45 parse_string(PGM_P tk, const char * buf, void * res)
46 {
47         struct token_string_data sd;
48         uint8_t token_len;
49         PGM_P str;
50
51         if (! *buf)
52                 return -1;
53
54         memcpy_P(&sd, &((struct token_string *)tk)->string_data, sizeof(sd));
55
56         /* fixed string */
57         if (sd.str) {
58                 str = sd.str;
59                 do {
60                         token_len = get_token_len(str);
61                         
62                         /* if token is too big... */
63                         if (token_len >= STR_TOKEN_SIZE - 1) {
64                                 continue;
65                         }
66                         
67                         if ( strncmp_P(buf, str, token_len) ) {
68                                 continue;
69                         }
70                         
71                         if ( !isendoftoken(*(buf+token_len)) ) {
72                                 continue;
73                         }
74
75                         break;
76                 } while ( (str = get_next_token(str)) != NULL );
77
78                 if (!str)
79                         return -1;
80         }
81         /* unspecified string */
82         else {
83                 token_len=0;
84                 while(!isendoftoken(buf[token_len]) && 
85                       token_len < (STR_TOKEN_SIZE-1))
86                         token_len++;
87
88                 /* return if token too long */
89                 if (token_len >= STR_TOKEN_SIZE - 1) {
90                         return -1;
91                 }
92         }
93         
94         if (res) {
95                 /* we are sure that token_len is < STR_TOKEN_SIZE-1 */
96                 strncpy(res, buf, token_len);
97                 *((char *)res + token_len) = 0;
98         }
99
100         return token_len;
101 }
102
103 int8_t complete_get_nb_string(PGM_P tk)
104 {
105         struct token_string_data sd;
106         int8_t ret=1;
107
108         memcpy_P(&sd, &((struct token_string *)tk)->string_data, sizeof(sd));
109
110         if (!sd.str)
111                 return 0;
112
113         while( (sd.str = get_next_token(sd.str)) != NULL ) {
114                 ret++;
115         }
116         return ret;
117 }
118
119 int8_t complete_get_elt_string(PGM_P tk, int8_t idx, 
120                               char * dstbuf, uint8_t size)
121 {
122         struct token_string_data sd;
123         PGM_P s;
124         uint8_t len;
125
126         memcpy_P(&sd, &((struct token_string *)tk)->string_data, sizeof(sd));
127         s = sd.str;
128
129         while (idx-- && s)
130                 s = get_next_token(s);
131
132         if (!s)
133                 return -1;
134
135         len = get_token_len(s);
136         if (len > size - 1)
137                 return -1;
138
139         memcpy_P(dstbuf, s, len);
140         dstbuf[len] = '\0';
141
142         return 0;
143 }
144
145
146 int8_t get_help_string(PGM_P tk, char * dstbuf, uint8_t size)
147 {
148         struct token_string_data sd;
149         PGM_P s;
150         
151         memcpy_P(&sd, &((struct token_string *)tk)->string_data, sizeof(sd));
152         s = sd.str;
153
154         if (s) {
155                 if (get_next_token(s)) {
156                         strncpy_P(dstbuf, MULTISTRING_HELP, size);
157                 }
158                 else {
159                         strncpy_P(dstbuf, FIXEDSTRING_HELP, size);
160                 }
161         }
162         else {
163                 strncpy_P(dstbuf, ANYSTRING_HELP, size);
164         }
165         
166         dstbuf[size-1] = '\0';
167
168         return 0;
169 }