xref: /OK3568_Linux_fs/external/rk_pcba_test/pcba_minui/script_parser.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 
2 #include <sys/types.h>
3 #include <ctype.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 
9 #include "script_parser.h"
10 #include "debug.h"
11 
12 
13 #define ITEM_NAME_MAX_LEN               32
14 
15 #define KEY_MAX_LEN                     32
16 #define VALUE_MAX_LEN                   128
17 
18 #define ITEM_MAX_COUNT                  128
19 
20 #define LINE_MAX_LEN                    512
21 
22 #define LINE_ERROR                      -1
23 #define LINE_COMMENT                    0
24 #define LINE_NULL                       1
25 #define LINE_MAINKEY                    2
26 #define LINE_SUBKEY                     3
27 
28 #define DATA_TYPE_SINGLE_WORD           1
29 #define DATA_TYPE_STRING                2
30 #define DATA_TYPE_MULTI_WORD            3
31 #define DATA_TYPE_GPIO                  4
32 
33 struct script_head
34 {
35     int mainkey_cnt;
36     int version[3];
37 };
38 
39 struct script_item
40 {
41     char name[32];
42     int length;
43     int offset;
44 };
45 
46 /*
47  * get value data type.
48  */
__get_str2int(char * buf,int value[])49 static int __get_str2int(char *buf, int value[])
50 {
51     char *src;
52     char ch;
53     unsigned int temp;
54     int sign;
55     int i;
56     int idx;
57     char str[128];
58 
59     src = buf;
60 
61     if (strncasecmp(src, "port:p", 6) == 0) {
62         /* handle gpio */
63         src += 6;
64         if (strncasecmp(src, "ower", 4) == 0) {
65             value[0] = 0xffff;
66             src += 4;
67         }
68         else {
69             ch = *src++;
70             if (islower(ch))
71                 value[0] = ch - 'a' + 1;
72             else if (isupper(ch))
73                 value[0] = ch - 'A' + 1;
74             else
75                 return -1;
76         }
77 
78         temp = 0;
79         ch = *src++;
80         while (ch != '<') {
81             if (isdigit(ch)) {
82                 temp = temp * 10 + (ch - '0');
83                 ch = *src++;
84             }
85             else if (ch == '\0') {
86                 src--;
87                 break;
88             }
89             else {
90                 return -1;
91             }
92         }
93         value[1] = temp;
94 
95         idx = 2;
96         ch = *src++;
97         while (ch != '\0') {
98             i = 0;
99             memset(str, 0, sizeof(str));
100             while (ch != '>') {
101                 if (isupper(ch))
102                     ch = tolower(ch);
103                 str[i++] = ch;
104                 ch = *src++;
105             }
106 
107             if (strcmp(str, "default") == 0 ||
108                 strcmp(str, "none") == 0 ||
109                 strcmp(str, "null") == 0 ||
110                 strcmp(str, "-1") == 0) {
111                 value[idx] = -1;
112             }
113             else {
114                 i = 0;
115                 ch = str[i++];
116                 temp = 0;
117                 if (ch == '-') {
118                     sign = -1;
119                     ch = str[i++];
120                 }
121                 else {
122                     sign = 1;
123                 }
124 
125                 while (ch != '\0') {
126                     if (isdigit(ch))
127                         temp = temp * 10 + (ch - '0');
128                     else
129                         return -1;
130 
131                     ch = str[i++];
132                 }
133 
134                 value[idx] = temp * sign;
135             }
136 
137             idx++;
138             ch = *src++;
139             if (ch == '<') {
140                 ch = *src++;
141             }
142             else if (ch == '\0') {
143                 ;
144             }
145             else {
146                 return -1;
147             }
148         }
149 
150         switch (idx) {
151             case 3:
152                 value[3] = -1;
153             case 4:
154                 value[4] = -1;
155             case 5:
156                 value[5] = -1;
157             case 6:
158                 break;
159             default:
160                 return -1;
161         }
162 
163         return DATA_TYPE_GPIO;
164     }
165     else if (strncasecmp(src, "string:", 7) == 0) {
166         src += 7;
167         idx = 0;
168         while (src[idx] != '\0') {
169             idx++;
170             if (idx > 127)
171                 break;
172         }
173 
174         if (idx & 0x03)
175             idx = (idx & (~0x03)) + 4;
176 
177         value[0] = idx >> 2;
178         value[1] = 1;
179 
180         return DATA_TYPE_STRING;
181     }
182     else if (src[0] == '"') {
183         src += 1;
184         idx = 0;
185         while (src[idx] != '"') {
186             idx++;
187             if (idx > 127)
188                 break;
189         }
190 
191         src[idx] = '\0';
192         if (idx & 0x03)
193             idx = (idx & (~0x03)) + 4;
194 
195         value[0] = idx >> 2;
196         value[1] = 2;
197 
198         return DATA_TYPE_STRING;
199     }
200     else if (isdigit(src[0]) && (src[1] == 'x' || src[2] == 'X')) {
201         temp = 0;
202         ch = *src++;
203         while (ch != '\0') {
204             if (isdigit(ch)) {
205                 temp = temp * 16 + (ch - '0');
206                 ch = *src++;
207             }
208             else if (isupper(ch)) {
209                 temp = temp * 16 + (ch - 'A' + 10);
210                 ch = *src++;
211             }
212             else if (islower(ch)) {
213                 temp = temp * 16 + (ch - 'a' + 10);
214                 ch = *src++;
215             }
216             else {
217                 break;
218             }
219         }
220         value[0] = temp;
221 
222         return DATA_TYPE_SINGLE_WORD;
223     }
224     else if (isdigit(src[0]) ||
225             (isdigit(src[1]) && src[0] == '-')) {
226         if (src[0] == '-') {
227             sign = -1;
228             ch = *src++;
229         }
230         else {
231             sign = 1;
232         }
233 
234         temp = 0;
235         ch = *src++;
236         while (ch != '\0') {
237             if (isdigit(ch)) {
238                 temp = temp * 10 + (ch - '0');
239                 ch = *src++;
240             }
241             else {
242                 break;
243             }
244         }
245         value[0] = temp * sign;
246 
247         return DATA_TYPE_SINGLE_WORD;
248     }
249     else {
250         idx = 0;
251         while (src[idx] != '\0') {
252             idx++;
253             if (idx > 127)
254                 break;
255         }
256 
257         if (idx & 0x03)
258             idx = (idx & (~0x03)) + 4;
259 
260         value[0] = idx >> 2;
261 
262         return DATA_TYPE_STRING;
263     }
264 }
265 
266 /*
267  * get key[32] and value[128], end with '\0'.
268  * \retval -1 empty line.
269  * \retval 0 OK
270  */
__get_key_value(char * buf,char * key,char * value)271 static int __get_key_value(char *buf, char *key, char *value)
272 {
273     char *src;
274     int key_idx;
275     int value_idx;
276 
277     /* check line */
278     src = buf;
279     key_idx = value_idx = 0;
280     while (1) {
281         if (*src == ' ' || *src == '\t') {
282             src++;
283         }
284         else if (*src == 0x0a || *src == 0x0d) {
285             key[key_idx] = '\0';
286             value[value_idx] = '\0';
287             return -1;
288         }
289         else {
290             break;
291         }
292     }
293 
294     /* get key */
295     while (*src != '=') {
296         key[key_idx++] = *src++;
297         if (key_idx >= 31) {
298             key[key_idx] = '\0';
299             break;
300         }
301     }
302 
303     for (key_idx--; key_idx > 0; key_idx--) {
304         if (key[key_idx] == ' ' || key[key_idx] == '\t') {
305             key[key_idx] = '\0';
306         }
307         else {
308             key[key_idx + 1] = '\0';
309             break;
310         }
311     }
312 
313     for (; *src != '='; src++);
314 
315     /* check line */
316     src++;
317     while (1) {
318         if (*src == ' ' || *src == '\t') {
319             src++;
320         }
321         else if (*src == 0x0a || *src == 0x0d) {
322             value[value_idx] = '\0';
323             return 0;
324         }
325         else {
326             break;
327         }
328     }
329 
330     /* get value */
331     while (*src != 0x0a && *src != 0x0d) {
332         value[value_idx++] = *src++;
333         if (value_idx >= 127) {
334             value[value_idx] = '\0';
335             break;
336         }
337     }
338 
339     for (value_idx--; value_idx > 0; value_idx--) {
340         if (value[value_idx] == ' ' || value[value_idx] == '\t') {
341             value[value_idx] = '\0';
342         }
343         else {
344             value[value_idx + 1] = '\0';
345             break;
346         }
347     }
348 
349     return 0;
350 }
351 
__fill_mainkey(char * buf,struct script_item * item)352 static int __fill_mainkey(char *buf, struct script_item *item)
353 {
354     char *src;
355     char ch;
356     int i;
357 
358     src = buf + 1;
359     for (ch = *src++, i = 0; ch != ']'; i++, ch = *src++) {
360         item->name[i] = ch;
361         if (i + 1 >= ITEM_NAME_MAX_LEN) {
362             item->name[i] = '\0';
363             break;
364         }
365     }
366 
367     if (item->name[0] == '\0')
368         return -1;
369 
370     return 0;
371 }
372 
__getline(char * buf,int len,int * flag)373 static int __getline(char *buf, int len, int *flag)
374 {
375     char *src;
376     char ch;
377     char prev_ch;
378     int line_len;
379 
380     /* get line flag */
381     src = buf;
382     ch = *src++;
383     switch (ch) {
384         case ';':
385             *flag = LINE_COMMENT;
386             break;
387 
388         case 0x0a:
389         case 0x0d:
390             *flag = LINE_NULL;
391             break;
392 
393         case '[':
394             *flag = LINE_MAINKEY;
395             break;
396 
397         default:
398             *flag = LINE_SUBKEY;
399             break;
400     }
401 
402     /* get line length */
403     if (*flag == LINE_NULL) {
404         ch = *src++;
405         if (ch == 0x0a)
406             return 2;
407         else
408             return 1;
409     }
410 
411     ch = *src++;
412     line_len = 1;
413     while (line_len < len) {
414         if (ch == 0x0a || ch == 0x0d)
415             break;
416 
417         ch = *src++;
418         line_len++;
419         if (line_len >= LINE_MAX_LEN) {
420             *flag = LINE_ERROR;
421             return 0;
422         }
423     }
424     line_len++;
425 
426     prev_ch = ch;
427     ch = *src++;
428     if (prev_ch == 0x0d) {
429         if (ch == 0x0a)
430             line_len++;
431     }
432 
433     return line_len;
434 }
435 
__parse_script(char * buf,int len)436 static char*  __parse_script(char *buf, int len)
437 {
438     char *src;
439     int rest_len, line_num;
440     struct script_item *item_table = NULL;
441     struct script_head head;
442     unsigned int mainkey_idx, subkey_idx;
443     int new_mainkey;
444     char key[KEY_MAX_LEN];
445     char value[VALUE_MAX_LEN];
446     char *key_data = NULL, *key_addr;
447     int *value_data = NULL, *value_addr;
448     int value_idx;
449     int fmt_value[8];
450     unsigned int i;
451     int ret;
452     int shmid;
453     char *script_buf, *pos;
454 
455     db_debug("the length of script is %d\n", len);
456 
457     /* allocate memory for key and value */
458     item_table = malloc(sizeof(struct script_item) * ITEM_MAX_COUNT);
459     if (item_table == NULL) {
460         db_debug("allocate memory for main key failed(%s)\n", strerror(errno));
461         ret = -1;
462         goto out;
463     }
464     memset(item_table, 0, sizeof(struct script_item) * ITEM_MAX_COUNT);
465 
466     key_data = malloc(512 * 1024);
467     if (key_data == NULL) {
468         db_debug("allocate memory for key data failed(%s)\n", strerror(errno));
469         ret = -1;
470         goto out;
471     }
472     memset(key_data, 0, 512 * 1024);
473     key_addr = key_data;
474 
475     value_data = malloc(512 * 1024);
476     if (value_data == NULL) {
477         db_debug("allocate memory for value data failed(%s)\n",
478                 strerror(errno));
479         ret = -1;
480         goto out;
481     }
482     memset(value_data, 0, 512 * 1024);
483     value_addr = value_data;
484 
485     /* parse script main loop */
486     src = buf;
487     rest_len = len;
488     mainkey_idx = subkey_idx = value_idx = 0;
489     new_mainkey = 0;
490     line_num = 0;
491     while (rest_len) {
492         int line_len;
493         int flag;
494 
495         /* get current line */
496         line_len = __getline(src, rest_len, &flag);
497         rest_len -= line_len;
498         line_num++;
499         switch (flag) {
500             case LINE_COMMENT:
501             case LINE_NULL:
502                 break;
503 
504             case LINE_MAINKEY:
505                 /* get main key */
506                 if (__fill_mainkey(src, &item_table[mainkey_idx])) {
507                     ret = -1;
508                     goto out;
509                 }
510 
511                 if (new_mainkey) {
512                     item_table[mainkey_idx].offset =
513                         item_table[mainkey_idx-1].offset +
514                         item_table[mainkey_idx-1].length * 10;
515                 }
516                 else {
517                     /* first main key */
518                     new_mainkey = 1;
519                     item_table[mainkey_idx].offset = 0;
520                 }
521 
522                 mainkey_idx++;
523                 break;
524 
525             case LINE_SUBKEY:
526                 /* get key[32] and value[128] */
527                 memset(key, 0, KEY_MAX_LEN);
528                 memset(value, 0, VALUE_MAX_LEN);
529                 ret = __get_key_value(src, key, value);
530                 if (ret == -1)
531                     continue;
532 
533                 /* stores key[32], stores value's offset in the next 4 bytes,
534                  * stores value's length[31;16] and type[0:15] in the next
535                  * next 4 bytes. there are total 40 bytes for one key data.
536                  *
537                  * the unit of value data length is int
538                  */
539                 strcpy(key_addr, key);
540                 key_addr += KEY_MAX_LEN;
541 
542                 /* get value data type */
543                 memset(fmt_value, 0, sizeof(int) * 8);
544                 ret = __get_str2int(value, fmt_value);
545                 switch (ret) {
546                     case DATA_TYPE_SINGLE_WORD:
547                         *value_addr = fmt_value[0];
548                         *(unsigned int *)key_addr = value_idx;
549                         key_addr += 4;
550                         *(unsigned int *)key_addr = (1 << 0) |
551                             (DATA_TYPE_SINGLE_WORD << 16);
552                         value_addr++;
553                         value_idx++;
554                         break;
555 
556                     case DATA_TYPE_STRING:
557                         if (fmt_value[0]) {
558                             if (fmt_value[1] == 1) {
559                                 strncpy((char *)value_addr, value +
560                                         sizeof("string:") - 1, fmt_value[0] << 2);
561                             }
562                             else if (fmt_value[1] == 2) {
563                                 strncpy((char *)value_addr, value + 1,
564                                         fmt_value[0] << 2);
565                             }
566                             else{
567                                 strncpy((char *)value_addr, value,
568                                         fmt_value[0] << 2);
569                             }
570                         }
571 
572                         *(unsigned int *)key_addr = value_idx;
573                         key_addr += 4;
574                         *(unsigned int *)key_addr = (fmt_value[0] << 0) |
575                             (DATA_TYPE_STRING << 16);
576                         value_addr += fmt_value[0];
577                         value_idx += fmt_value[0];
578                         break;
579 
580                     case DATA_TYPE_GPIO:
581                         for (i = 0; i < 6; i++)
582                             *value_addr++ = fmt_value[i];
583                         *(unsigned int *)key_addr = value_idx;
584                         key_addr += 4;
585                         *(unsigned int *)key_addr = (6 << 0) |
586                             (DATA_TYPE_GPIO << 16);
587                         value_idx += 6;
588                         break;
589 
590                     default:
591                         db_debug("%s: L%d: fix me\n", __func__, __LINE__);
592                 }
593 
594                 subkey_idx++;
595                 key_addr += 4;
596                 item_table[mainkey_idx - 1].length++;
597                 break;
598 
599             default:
600                 db_debug("script format error at line %d\n", line_num);
601                 ret = -1;
602                 goto out;
603         }
604 
605         src += line_len;
606     }
607 
608     if (mainkey_idx <= 0) {
609         db_debug("mainkey_idx = %d\n", mainkey_idx);
610         ret = -1;
611         goto out;
612     }
613 
614     /* recalc first subkey offset */
615     for (i = 0; i < mainkey_idx; i++) {
616         item_table[i].offset += (sizeof(struct script_head) >> 2) +
617             ((sizeof(struct script_item) * mainkey_idx) >> 2);
618     }
619 
620     /* recalc every subkey offset */
621     key_addr = key_data;
622     i = 0;
623     while (i < subkey_idx * 10 * sizeof(int)) {
624         key_addr += ITEM_NAME_MAX_LEN;
625         *(unsigned int *)key_addr += (sizeof(struct script_head) >> 2) +
626             ((sizeof(struct script_item) * mainkey_idx) >> 2) +
627             (subkey_idx * 10);
628         i += 10 * sizeof(int); /* the sizeof each subkey data */
629         key_addr += 8;
630     }
631 
632     /* init script head */
633     head.mainkey_cnt = mainkey_idx;
634     head.version[0] = SCRIPT_VERSION0;
635     head.version[1] = SCRIPT_VERSION1;
636     head.version[2] = SCRIPT_VERSION2;
637 
638     /* allocate share memory segment for script buffer */
639     i = sizeof(struct script_head) + sizeof(struct script_item) *
640         mainkey_idx + 10 * sizeof(int) * subkey_idx + sizeof(int) * value_idx;
641     #if 0
642     shmid = shmget(IPC_PRIVATE, i, IPC_CREAT | 0666);
643     if (shmid == -1) {
644         db_debug("allocate share memory segment for script buffer "
645                 "failed(%s)\n", strerror(errno));
646         ret = -1;
647         goto out;
648     }
649     db_debug("script shmid = %d\n", shmid);
650 
651     script_buf = pos = shmat(shmid, 0, 0);
652     if (script_buf == (void *)-1) {
653         db_debug("attach the share memory segment failed(%s)\n",
654                 strerror(errno));
655         shmctl(shmid, IPC_RMID, 0);
656         ret = -1;
657         goto out;
658     }
659 #else
660 	script_buf = pos =  malloc(i);
661 #endif
662     /* stores script buffer */
663     memcpy(pos, &head, sizeof(struct script_head));
664     pos += sizeof(struct script_head);
665     memcpy(pos, item_table, sizeof(struct script_item) * mainkey_idx);
666     pos += sizeof(struct script_item) * mainkey_idx;
667     memcpy(pos, key_data, 10 * sizeof(int) * subkey_idx);
668     pos += 10 * sizeof(int) * subkey_idx;
669     memcpy(pos, value_data, sizeof(int) * value_idx);
670 
671     //shmdt(script_buf);
672   //  ret = shmid;
673   return script_buf;
674 
675 out:
676     /* free memory */
677     if (item_table)
678         free(item_table);
679     if (key_data)
680         free(key_data);
681     if (value_data)
682         free(value_data);
683 
684     return NULL;
685 }
686 
parse_script(const char * name)687 char * parse_script(const char *name)
688 {
689     FILE *fscript;
690     int len;
691     char *buf;
692     int read_len;
693     int shmid;
694     char *script_buf;
695 
696     if (name == NULL) {
697         db_error("script: invalid file name(null)\n");
698         return NULL;
699     }
700 
701     /* read script data */
702     fscript = fopen(name, "rb");
703     if (fscript == NULL) {
704         db_error("script: can't open %s(%s)\n", name, strerror(errno));
705         return NULL;
706     }
707 
708     fseek(fscript, 0, SEEK_END);
709     len = ftell(fscript);
710     fseek(fscript, 0, SEEK_SET);
711 
712     buf = malloc(len);
713     if (buf == NULL) {
714         db_error("script: allocate memory for script data failed(%s)\n",
715                 strerror(errno));
716         fclose(fscript);
717         return NULL;
718     }
719 
720     read_len = fread(buf, 1, len, fscript);
721     if (read_len < len) {
722         db_debug("len = %d, read_len = %d, fix me\n", len, read_len);
723     }
724     fclose(fscript);
725 
726     /* parse script */
727     script_buf = __parse_script(buf, len);
728     free(buf);
729 
730     return script_buf;
731 }
732 
deparse_script(int shmid)733 void deparse_script(int shmid)
734 {
735     //shmctl(shmid, IPC_RMID, 0);
736 }
737