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