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, ¶_min_num, ¶_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