• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License. \n
14  *
15  * Description: Provides AT parse source \n
16  */
17 
18 #include "at_base.h"
19 #include "at_parse.h"
20 
21 #define AT_PARSE_STRING_END_FLAG_LEN 1
22 #define AT_PARSE_STRING_FORMAT_FLAG_LEN 1
23 #define AT_PARSE_UINT32_STRING_LENGTH 10
24 #define AT_PARSE_UINT32_BASE 0
25 #define AT_PARSE_S32_MAX (2147483647)
26 #define AT_PARSE_S32_MIN (-2147483648)
27 #define AT_PARSE_OCTET_BYTES 2
28 #define AT_PARSE_CH_NUMBER_PER_BYTE 2
29 #define AT_PARSE_BIT_STRING_MAX_LEN 32
30 #define AT_PARSE_OFFSET_1 1
31 #define AT_PARSE_OFFSET_2 2
32 #define AT_PARSE_OFFSET_4 4
33 #define AT_PARSE_NUM_OF_HEX_A 10
34 
35 typedef struct {
36     const char        *str;
37     uint32_t          str_len;
38 } at_parse_param_t;
39 
40 typedef struct {
41     uint16_t            param_count;
42     uint16_t            param_max_num;
43     at_parse_param_t    *params_array;
44 } at_parse_param_table_t;
45 
46 typedef at_ret_t(*at_parse_assign_fun_t)(const at_parse_param_t*, const void*, const at_para_parse_syntax_t*);
47 typedef at_ret_t(*at_parse_verify_fun_t)(const void*, const at_para_parse_syntax_t*);
48 
49 typedef struct {
50     at_parse_assign_fun_t    assign_func;
51     at_parse_verify_fun_t    verify_func;
52 } at_parse_args_t;
53 
54 at_cmd_info_t *g_at_remain_list = NULL;
55 
at_parse_has_remain_cmd(void)56 bool at_parse_has_remain_cmd(void)
57 {
58     return (g_at_remain_list != NULL);
59 }
60 
at_parse_get_next_remain_cmd(void)61 at_cmd_info_t* at_parse_get_next_remain_cmd(void)
62 {
63     if (g_at_remain_list == NULL) {
64         return NULL;
65     }
66 
67     at_cmd_info_t *cmd = g_at_remain_list;
68     g_at_remain_list = g_at_remain_list->next;
69     return cmd;
70 }
71 
at_parse_format_of_cmd(const at_cmd_info_t * cmd_info,uint16_t * offset)72 at_format_t at_parse_format_of_cmd(const at_cmd_info_t *cmd_info, uint16_t *offset)
73 {
74     switch (cmd_info->cmd_str[*offset]) {
75         case '^':
76         case '+':
77             *offset = *offset + AT_PARSE_STRING_FORMAT_FLAG_LEN;
78             return AT_FORMAT_ADD;
79         default:
80             return AT_FORMAT_ERROR;
81     }
82 }
83 
at_parse_del_one_remain_cmd(at_cmd_info_t * cmd_info)84 void at_parse_del_one_remain_cmd(at_cmd_info_t *cmd_info)
85 {
86     at_cmd_info_t *wait_free = cmd_info;
87     if (wait_free == NULL) {
88         return;
89     }
90 
91     if (wait_free->cmd_str != NULL) {
92         at_free(wait_free->cmd_str);
93         wait_free->cmd_str = NULL;
94     }
95 
96     at_free(wait_free);
97     wait_free = NULL;
98 }
99 
at_parse_del_all_remain_cmd(void)100 static void at_parse_del_all_remain_cmd(void)
101 {
102     at_cmd_info_t *cmd;
103 
104     cmd = at_parse_get_next_remain_cmd();
105     while (cmd != NULL) {
106         at_parse_del_one_remain_cmd(cmd);
107         cmd = at_parse_get_next_remain_cmd();
108     }
109 }
110 
at_parse_add_remain_list(const char * data,uint32_t start,uint32_t len,uint16_t channel_id)111 static at_ret_t at_parse_add_remain_list(const char *data, uint32_t start, uint32_t len, uint16_t channel_id)
112 {
113     at_cmd_info_t *tail = g_at_remain_list;
114 
115     if (len == 0) {
116         return AT_RET_OK;
117     }
118     at_cmd_info_t *new_node = at_malloc(sizeof(at_cmd_info_t));
119     if (new_node == NULL) {
120         return AT_RET_MALLOC_ERROR;
121     }
122 
123     new_node->cmd_str = at_malloc(len + AT_PARSE_STRING_END_FLAG_LEN);
124     if (new_node->cmd_str == NULL) {
125         at_free(new_node);
126         return AT_RET_MALLOC_ERROR;
127     }
128 
129     new_node->channel_id = channel_id;
130     new_node->str_len = (uint16_t)(len + AT_PARSE_STRING_END_FLAG_LEN);
131     new_node->next = NULL;
132     memset_s(new_node->cmd_str, new_node->str_len, 0, new_node->str_len);
133     memcpy_s(new_node->cmd_str, len, data + start, len);
134 
135     if (tail == NULL) {
136         g_at_remain_list = new_node;
137         return AT_RET_OK;
138     }
139 
140     while (tail->next != NULL) {
141         tail = tail->next;
142     }
143     tail->next = new_node;
144 
145     return AT_RET_OK;
146 }
147 
at_parse_split_combine_cmd_machines(at_parse_state_t state,char ch,uint16_t * index,char * out_string)148 static at_parse_state_t at_parse_split_combine_cmd_machines(at_parse_state_t state, char ch,
149                                                             uint16_t *index, char *out_string)
150 {
151     switch (state) {
152         case AT_NORMAL_STATE:
153             if (ch == '\\') {
154                 return AT_ESCAPE_STATE;
155             }
156 
157             if (ch == ';' || ch == '\0') {
158                 return AT_END_STATE;
159             }
160 
161             out_string[(*index)++] = ch;
162             break;
163 
164         case AT_ESCAPE_STATE:
165             if (ch == '\0') {
166                 return AT_END_STATE;
167             }
168             if (ch != ';') {
169                 out_string[(*index)++] = '\\';
170             }
171             out_string[(*index)++] = ch;
172 
173         default:
174             break;
175     }
176     return AT_NORMAL_STATE;
177 }
178 
at_parse_split_combine_cmd(const char * data,uint32_t len,uint16_t channel_id)179 at_ret_t at_parse_split_combine_cmd(const char *data, uint32_t len, uint16_t channel_id)
180 {
181     at_ret_t ret;
182     uint32_t cmd_start = 0;
183     uint32_t cmd_end;
184     uint16_t index = 0;
185     at_parse_state_t state = AT_NORMAL_STATE;
186     char *cmd_string = (char*)at_malloc(len + AT_PARSE_STRING_END_FLAG_LEN);
187     if (cmd_string == NULL) {
188         return AT_RET_MALLOC_ERROR;
189     }
190     memset_s(cmd_string, len + AT_PARSE_STRING_END_FLAG_LEN, 0, len + AT_PARSE_STRING_END_FLAG_LEN);
191 
192     for (cmd_end = cmd_start; cmd_end <= len; cmd_end++) {
193         state = at_parse_split_combine_cmd_machines(state, data[cmd_end], &index, cmd_string);
194         if (state != AT_END_STATE) {
195             continue;
196         }
197 
198         ret = at_parse_add_remain_list(cmd_string, 0, index, channel_id);
199         if (ret != AT_RET_OK) {
200             at_parse_del_all_remain_cmd();
201             at_free(cmd_string);
202             return ret;
203         }
204         memset_s(cmd_string, len + AT_PARSE_STRING_END_FLAG_LEN, 0, len + AT_PARSE_STRING_END_FLAG_LEN);
205         state = AT_NORMAL_STATE;
206         index = 0;
207         cmd_start = cmd_end + 1;
208     }
209 
210     at_free(cmd_string);
211     return AT_RET_OK;
212 }
213 
at_parse_cmd_type(const char * str,uint16_t * offset)214 at_cmd_type_t at_parse_cmd_type(const char *str, uint16_t *offset)
215 {
216     const char *type_start;
217     type_start = str + *offset;
218     if ((*type_start == '?') && (*(type_start + AT_PARSE_OFFSET_1) == '\0')) {
219         *offset = *offset + AT_PARSE_OFFSET_1;
220         return AT_CMD_TYPE_READ;
221 #ifdef CONFIG_AT_SUPPORT_QUERY
222     } else if ((*type_start == '?') && (*(type_start + AT_PARSE_OFFSET_1) == '=')) {
223         *offset = *offset + AT_PARSE_OFFSET_2;
224         return AT_CMD_TYPE_QUERY;
225 #endif
226     } else if ((*type_start == '=') &&
227                (*(type_start + AT_PARSE_OFFSET_1) == '?') &&
228                (*(type_start + AT_PARSE_OFFSET_2) == '\0')) {
229         *offset = *offset + AT_PARSE_OFFSET_2;
230         return AT_CMD_TYPE_TEST;
231     } else if (*type_start == '=') {
232         *offset = *offset + AT_PARSE_OFFSET_1;
233         return AT_CMD_TYPE_SET;
234     } else if (*type_start == '\0') {
235         *offset = *offset + AT_PARSE_OFFSET_1;
236         return AT_CMD_TYPE_CMD;
237     }
238     return AT_CMD_TYPE_ERROR;
239 }
240 
at_parse_update_min_index(const at_para_parse_syntax_t * syntax,uint16_t * min_index)241 static void at_parse_update_min_index(const at_para_parse_syntax_t *syntax, uint16_t *min_index)
242 {
243     if ((syntax->attribute & AT_SYNTAX_ATTR_OPTIONAL) == 0) {
244         (*min_index)++;
245     }
246 }
247 
at_parse_get_expect_para_number(const at_para_parse_syntax_t * syntax,uint16_t * para_min_num,uint16_t * para_max_num)248 static void at_parse_get_expect_para_number(const at_para_parse_syntax_t *syntax,
249                                             uint16_t *para_min_num, uint16_t *para_max_num)
250 {
251     while (syntax[*para_max_num].last != true) {
252         (void)at_parse_update_min_index(&syntax[*para_max_num], para_min_num);
253         (*para_max_num)++;
254     }
255 
256     (void)at_parse_update_min_index(&syntax[*para_max_num], para_min_num);
257     (*para_max_num)++;
258 }
259 
at_parse_split_params_machines(at_parse_state_t state,char ch)260 static at_parse_state_t at_parse_split_params_machines(at_parse_state_t state, char ch)
261 {
262     switch (state) {
263         case AT_NORMAL_STATE:
264             if (ch == '\\') {
265                 return AT_ESCAPE_STATE;
266             }
267 
268             if (ch == ',') {
269                 return AT_END_STATE;
270             }
271             break;
272 
273         case AT_ESCAPE_STATE:
274         default:
275             break;
276     }
277     return AT_NORMAL_STATE;
278 }
279 
at_parse_get_actual_para_number(const char * str)280 static uint16_t at_parse_get_actual_para_number(const char *str)
281 {
282     uint16_t num = 0;
283     uint16_t index = 0;
284     at_parse_state_t state = AT_NORMAL_STATE;
285 
286     while (str[index] != '\0') {
287         state = at_parse_split_params_machines(state, str[index]);
288         if (state == AT_END_STATE) {
289             num++;
290             state = AT_NORMAL_STATE;
291         }
292         index++;
293     }
294 
295     return ++num;
296 }
297 
at_parse_check_para_num(const char * str,const at_para_parse_syntax_t * syntax,at_parse_param_table_t * str_table)298 static at_ret_t at_parse_check_para_num(const char *str, const at_para_parse_syntax_t *syntax,
299                                         at_parse_param_table_t *str_table)
300 {
301     uint16_t para_min_num = 0;
302     uint16_t para_max_num = 0;
303     (void)at_parse_get_expect_para_number(syntax, &para_min_num, &para_max_num);
304     uint16_t para_actual_num = at_parse_get_actual_para_number(str);
305     if ((para_actual_num < para_min_num) || (para_actual_num > para_max_num)) {
306         return AT_RET_PARSE_PARA_ERROR;
307     }
308 
309     str_table->param_count = para_actual_num;
310     str_table->param_max_num = para_max_num;
311     return AT_RET_OK;
312 }
313 
at_parse_create_params_machines(at_parse_state_t state,char ch)314 static at_parse_state_t at_parse_create_params_machines(at_parse_state_t state, char ch)
315 {
316     switch (state) {
317         case AT_NORMAL_STATE:
318             if (ch == '\\') {
319                 return AT_ESCAPE_STATE;
320             }
321 
322             if (ch == ',' || ch == '\0') {
323                 return AT_END_STATE;
324             }
325             break;
326 
327         case AT_ESCAPE_STATE:
328             if (ch == '\0') {
329                 return AT_END_STATE;
330             }
331         default:
332             break;
333     }
334     return AT_NORMAL_STATE;
335 }
336 
at_parse_para_array_init(at_parse_param_table_t * str_table)337 static at_ret_t at_parse_para_array_init(at_parse_param_table_t *str_table)
338 {
339     uint16_t paras_array_size = str_table->param_max_num * sizeof(at_parse_param_t);
340     str_table->params_array = at_malloc(paras_array_size);
341     if (str_table->params_array == NULL) {
342         return AT_RET_MALLOC_ERROR;
343     }
344     memset_s(str_table->params_array, paras_array_size, 0, paras_array_size);
345     return AT_RET_OK;
346 }
347 
at_parse_create_para_array(const char * str,at_parse_param_table_t * str_table)348 static at_ret_t at_parse_create_para_array(const char *str, at_parse_param_table_t *str_table)
349 {
350     at_ret_t ret = AT_RET_OK;
351     const char *ch = str;
352     ret = at_parse_para_array_init(str_table);
353     if (ret != AT_RET_OK) {
354         return ret;
355     }
356 
357     for (uint16_t count = 0; count < str_table->param_count; count++, ch++) {
358         const char *para_start = ch;
359         uint16_t para_len = 0;
360         at_parse_state_t state = AT_NORMAL_STATE;
361 
362         while (state != AT_END_STATE) {
363             state = at_parse_create_params_machines(state, *ch);
364             if (state != AT_END_STATE) {
365                 ch++;
366                 para_len++;
367             }
368         }
369 
370         if (para_len == 0) {
371             str_table->params_array[count].str = NULL;
372         } else {
373             str_table->params_array[count].str = para_start;
374         }
375         str_table->params_array[count].str_len = para_len;
376     }
377 
378     return ret;
379 }
380 
at_parse_argument_assign_int(const at_parse_param_t * para_array,const void * args,const at_para_parse_syntax_t * syntax)381 static at_ret_t at_parse_argument_assign_int(const at_parse_param_t *para_array, const void *args,
382                                              const at_para_parse_syntax_t *syntax)
383 {
384     int64_t value;
385     char *s = NULL;
386     int32_t *val = (int32_t*)((uintptr_t)args + syntax->offset);
387 
388     if (para_array->str_len > AT_PARSE_UINT32_STRING_LENGTH) {
389         return AT_RET_PARSE_PARA_ERROR;
390     }
391 
392     /* AT_PARSE_UINT32_BASE is 0. This means that this function can convert decimal, octal, and hexadecimal. */
393     value = (int64_t)strtoull(para_array->str, &s, AT_PARSE_UINT32_BASE);
394     if (para_array->str_len != (uint32_t)(s - para_array->str)) {
395         return AT_RET_PARSE_PARA_ERROR;
396     }
397 
398     if (value > AT_PARSE_S32_MAX || value < AT_PARSE_S32_MIN) {
399         return AT_RET_PARSE_PARA_ERROR;
400     }
401 
402     *val = (int32_t)value;
403     return AT_RET_OK;
404 }
405 
at_parse_verify_argument_int(const void * args,const at_para_parse_syntax_t * syntax)406 static at_ret_t at_parse_verify_argument_int(const void *args, const at_para_parse_syntax_t *syntax)
407 {
408     int32_t val = *(int32_t*)((uintptr_t)args + syntax->offset);
409 
410     if ((syntax->attribute & AT_SYNTAX_ATTR_LIST_VALUE) != 0) {
411         for (uint32_t i = 0; i < syntax->entry.int_list.num; i++) {
412             if (val == syntax->entry.int_list.values[i]) {
413                 return AT_RET_OK;
414             }
415         }
416         return AT_RET_PARSE_PARA_ERROR;
417     }
418 
419     if ((syntax->attribute & AT_SYNTAX_ATTR_AT_MIN_VALUE) != 0) {
420         if (val < syntax->entry.int_range.min_val) {
421             return AT_RET_PARSE_PARA_ERROR;
422         }
423     }
424 
425     if ((syntax->attribute & AT_SYNTAX_ATTR_AT_MAX_VALUE) != 0) {
426         if (val > syntax->entry.int_range.max_val) {
427             return AT_RET_PARSE_PARA_ERROR;
428         }
429     }
430 
431     return AT_RET_OK;
432 }
433 
at_parse_argument_prepare_string(char * str,uint32_t index_max,const at_parse_param_t * para_array)434 static void at_parse_argument_prepare_string(char *str, uint32_t index_max, const at_parse_param_t *para_array)
435 {
436     bool escape = false;
437     for (uint16_t len = 0, index = 0; (len < para_array->str_len) && (index < index_max); len++) {
438         if (escape == true) {
439             str[index++] = para_array->str[len];
440             escape = false;
441             continue;
442         }
443         if (para_array->str[len] == '\\') {
444             escape = true;
445             continue;
446         }
447         str[index++] = para_array->str[len];
448     }
449 }
450 
at_parse_argument_assign_string(const at_parse_param_t * para_array,const void * args,const at_para_parse_syntax_t * syntax)451 static at_ret_t at_parse_argument_assign_string(const at_parse_param_t *para_array, const void *args,
452                                                 const at_para_parse_syntax_t *syntax)
453 {
454     char **val = (char**)((uintptr_t)args + syntax->offset);
455 
456     *val = (char*)at_malloc(para_array->str_len + 1);
457     if (*val == NULL) {
458         return AT_RET_MALLOC_ERROR;
459     }
460     memset_s(*val, para_array->str_len + 1, 0, para_array->str_len + 1);
461 
462     (void)at_parse_argument_prepare_string(*val, para_array->str_len + 1, para_array);
463 
464     if ((syntax->attribute & AT_SYNTAX_ATTR_FIX_CASE) == 0) {
465         at_base_toupper(*val, para_array->str_len);
466     }
467 
468     return AT_RET_OK;
469 }
470 
at_parse_verify_argument_string(const void * args,const at_para_parse_syntax_t * syntax)471 static at_ret_t at_parse_verify_argument_string(const void *args, const at_para_parse_syntax_t *syntax)
472 {
473     const char **val = (const char**)((uintptr_t)args + syntax->offset);
474     if ((syntax->attribute & AT_SYNTAX_ATTR_LIST_VALUE) != 0) {
475         for (uint32_t i = 0; i < syntax->entry.string_list.num; i++) {
476             /* It's guaranteed that both sides have a terminator('\0'). */
477             if (strcmp((const char*)syntax->entry.string_list.values[i], *val) == 0) {
478                 return AT_RET_OK;
479             }
480         }
481         return AT_RET_PARSE_PARA_ERROR;
482     }
483 
484     if ((syntax->attribute & AT_SYNTAX_ATTR_MAX_LENGTH) != 0) {
485         if (strlen(*val) > syntax->entry.string.max_length) {
486             return AT_RET_PARSE_PARA_ERROR;
487         }
488     }
489 
490     return AT_RET_OK;
491 }
492 
at_parse_char_to_hex(char ch,uint8_t * val)493 static at_ret_t at_parse_char_to_hex(char ch, uint8_t *val)
494 {
495     if ((ch >= '0') && (ch <= '9')) {
496         *val = (uint8_t)ch - (uint8_t)'0';    /* Forcible type conversion is used to eliminate alarms(G.TYP.03). */
497     } else if ((ch >= 'a') && (ch <= 'f')) {
498         *val = (uint8_t)ch - (uint8_t)'a' + AT_PARSE_NUM_OF_HEX_A;
499     } else if ((ch >= 'A') && (ch <= 'F')) {
500         *val = (uint8_t)ch - (uint8_t)'A' + AT_PARSE_NUM_OF_HEX_A;
501     } else {
502         return AT_RET_PARSE_PARA_ERROR;
503     }
504     return AT_RET_OK;
505 }
506 
at_parse_hex_string_to_uint8(const char * src,uint32_t src_len,uint8_t * dst)507 static at_ret_t at_parse_hex_string_to_uint8(const char* src, uint32_t src_len, uint8_t *dst)
508 {
509     at_ret_t ret = AT_RET_OK;
510     uint32_t index = 0;
511     uint8_t hex;
512 
513     while (index < src_len) {
514         ret = at_parse_char_to_hex(*(src + index), &hex);
515         if (ret != AT_RET_OK) {
516             return ret;
517         }
518         /* index >> AT_PARSE_OFFSET_1 is equivalent to index / 2 */
519         dst[index >> AT_PARSE_OFFSET_1] = (uint8_t)(hex << AT_PARSE_OFFSET_4);
520         index++;
521 
522         ret = at_parse_char_to_hex(*(src + index), &hex);
523         if (ret != AT_RET_OK) {
524             return ret;
525         }
526         dst[index >> AT_PARSE_OFFSET_1] |= hex;
527         index++;
528     }
529     return ret;
530 }
531 
at_parse_argument_assign_octet_string(const at_parse_param_t * para_array,const void * args,const at_para_parse_syntax_t * syntax)532 static at_ret_t at_parse_argument_assign_octet_string(const at_parse_param_t *para_array, const void *args,
533                                                       const at_para_parse_syntax_t *syntax)
534 {
535     uint8_t **val = (uint8_t**)((uintptr_t)args + syntax->offset);
536     uint32_t *len = (uint32_t*)((uintptr_t)args + syntax->entry.octet_string.length_field_offset);
537     uint32_t str_len = para_array->str_len;
538 
539     if ((syntax->attribute & AT_SYNTAX_ATTR_LENGTH_FIELD) != 0) {
540         if (str_len != *len * AT_PARSE_OCTET_BYTES) {
541             return AT_RET_PARSE_PARA_ERROR;
542         }
543     } else {
544         if ((str_len & AT_PARSE_OFFSET_1) != 0) {  /* This is equivalent to str_len % 2 */
545             return AT_RET_PARSE_PARA_ERROR;
546         }
547         *len = str_len >> AT_PARSE_OFFSET_1;  /* This is equivalent to str_len / 2 */
548     }
549 
550     *val = at_malloc(*len + 1);
551     if (*val == NULL) {
552         return AT_RET_MALLOC_ERROR;
553     }
554     (*val)[*len] = '\0';
555 
556     return at_parse_hex_string_to_uint8(para_array->str, para_array->str_len, *val);
557 }
558 
at_parse_verify_argument_octet_string(const void * args,const at_para_parse_syntax_t * syntax)559 static at_ret_t at_parse_verify_argument_octet_string(const void *args, const at_para_parse_syntax_t *syntax)
560 {
561     uint32_t len = *(uint32_t*)((uintptr_t)args + syntax->entry.octet_string.length_field_offset);
562 
563     if ((syntax->attribute & AT_SYNTAX_ATTR_MAX_LENGTH) != 0) {
564         if (len > syntax->entry.octet_string.max_length) {
565             return AT_RET_PARSE_PARA_ERROR;
566         }
567     }
568 
569     return AT_RET_OK;
570 }
571 
at_parse_argument_assign_bit_string(const at_parse_param_t * para_array,const void * args,const at_para_parse_syntax_t * syntax)572 static at_ret_t at_parse_argument_assign_bit_string(const at_parse_param_t *para_array, const void *args,
573                                                     const at_para_parse_syntax_t *syntax)
574 {
575     uint32_t *val = (uint32_t*)((uintptr_t)args + syntax->offset);
576     char ch;
577 
578     if (para_array->str_len > AT_PARSE_BIT_STRING_MAX_LEN) {
579         return AT_RET_PARSE_PARA_ERROR;
580     }
581 
582     *val = 0;
583     /* Converting a binary string to a decimal number */
584     for (uint32_t index = 0; index < para_array->str_len; index++) {
585         ch = para_array->str[index];
586         if (ch != '0' && ch != '1') {
587             return AT_RET_PARSE_PARA_ERROR;
588         }
589 
590         *val = (*val << AT_PARSE_OFFSET_1) | ((uint32_t)ch - (uint32_t)'0');
591     }
592     return AT_RET_OK;
593 }
594 
at_parse_verify_argument_bit_string(const void * args,const at_para_parse_syntax_t * syntax)595 static at_ret_t at_parse_verify_argument_bit_string(const void *args, const at_para_parse_syntax_t *syntax)
596 {
597     uint32_t val = *(uint32_t*)((uintptr_t)args + syntax->offset);
598 
599     if ((syntax->attribute & AT_SYNTAX_ATTR_LIST_VALUE) != 0) {
600         for (uint16_t index = 0; index < syntax->entry.bit_string_list.num; index++) {
601             if (val == syntax->entry.bit_string_list.values[index]) {
602                 return AT_RET_OK;
603             }
604         }
605         return AT_RET_PARSE_PARA_ERROR;
606     }
607 
608     if ((syntax->attribute & AT_SYNTAX_ATTR_AT_MAX_VALUE) != 0) {
609         if (val > syntax->entry.bit_string_range.max_value) {
610             return AT_RET_PARSE_PARA_ERROR;
611         }
612     }
613 
614     return AT_RET_OK;
615 }
616 
at_parse_one_argument(at_parse_param_t * para_array,void * args,const at_para_parse_syntax_t * syntax,uint16_t index)617 static at_ret_t at_parse_one_argument(at_parse_param_t *para_array, void *args,
618                                       const at_para_parse_syntax_t *syntax, uint16_t index)
619 {
620     at_ret_t ret;
621     at_parse_args_t parse_table[AT_SYNTAX_TYPE_NUM] = {
622         {at_parse_argument_assign_int, at_parse_verify_argument_int},
623         {at_parse_argument_assign_string, at_parse_verify_argument_string},
624         {at_parse_argument_assign_bit_string, at_parse_verify_argument_bit_string},
625         {at_parse_argument_assign_octet_string, at_parse_verify_argument_octet_string}
626     };
627 
628     if (para_array->str_len == 0) {
629         if ((syntax[index].attribute & AT_SYNTAX_ATTR_OPTIONAL) == 0) {
630             return AT_RET_PARSE_PARA_MISSING_ERROR;
631         } else {
632             return AT_RET_OK;
633         }
634     }
635 
636     /* Fill the number of parameters in the parameter structure.Its position is at the beginning of args */
637     *(uint32_t*)args |= (1 << (uint32_t)index);
638     /* The value of syntax[index].type is obtained from the command list.
639        The value of type must be smaller than that of AT_SYNTAX_TYPE_NUM. */
640     ret = parse_table[syntax[index].type].assign_func(para_array, args, &syntax[index]);
641     if (ret != AT_RET_OK) {
642         return ret;
643     }
644 
645     ret = parse_table[syntax[index].type].verify_func(args, &syntax[index]);
646     if (ret != AT_RET_OK) {
647         return ret;
648     }
649 
650     return AT_RET_OK;
651 }
652 
653 /* This is a generic interface. Args is used to store AT command parameters.Therefore, the args type is void*. */
at_parse_para_arguments(const char * str,void * args,const at_para_parse_syntax_t * syntax)654 at_ret_t at_parse_para_arguments(const char *str, void *args, const at_para_parse_syntax_t *syntax)
655 {
656     at_ret_t ret;
657     at_parse_param_table_t *str_table = NULL;
658 
659     str_table = at_malloc(sizeof(at_parse_param_table_t));
660     if (str_table == NULL) {
661         return AT_RET_MALLOC_ERROR;
662     }
663 
664     ret = at_parse_check_para_num(str, syntax, str_table);
665     if (ret != AT_RET_OK) {
666         at_free(str_table);
667         return ret;
668     }
669 
670     ret = at_parse_create_para_array(str, str_table);
671     if (ret != AT_RET_OK) {
672         at_free(str_table);
673         return ret;
674     }
675 
676     for (uint16_t count = 0; count < str_table->param_max_num; count++) {
677         ret = at_parse_one_argument(&str_table->params_array[count], args, syntax, count);
678         if (ret != AT_RET_OK) {
679             at_free(str_table->params_array);
680             at_free(str_table);
681             return ret;
682         }
683     }
684 
685     at_free(str_table->params_array);
686     at_free(str_table);
687     return AT_RET_OK;
688 }
689 
at_parse_free_one_argument(void * args,const at_para_parse_syntax_t * syntax)690 static void at_parse_free_one_argument(void *args, const at_para_parse_syntax_t *syntax)
691 {
692     switch (syntax->type) {
693         case AT_SYNTAX_TYPE_STRING: {
694                 char **val = (char**)((uintptr_t)args + syntax->offset);
695                 if (*val != NULL) {
696                     at_free(*val);
697                 }
698             }
699             break;
700 
701         case AT_SYNTAX_TYPE_OCTET_STRING: {
702                 char **val = (char**)((uintptr_t)args + syntax->offset);
703                 if (*val != NULL) {
704                     at_free(*val);
705                 }
706             }
707             break;
708 
709         default:
710             break;
711     }
712 }
713 
714 /* Args is used to store AT command parameters. */
at_parse_free_arguments(void * args,const at_para_parse_syntax_t * syntax)715 void at_parse_free_arguments(void *args, const at_para_parse_syntax_t *syntax)
716 {
717     for (uint16_t index = 0;; index++) {
718         at_parse_free_one_argument(args, &syntax[index]);
719         if (syntax[index].last == true) {
720             break;
721         }
722     }
723 }
724