fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/lib/cmd.c *
7 * Created: 2003-11-08 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2003-2009 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "console.h"
28#include "cmd.h"
29
30
31typedef struct {
32 char *name;
33 unsigned long val;
34} cmd_sym_t;
35
36
37static void *cmd_get_sym_ext = NULL;
38static int (*cmd_get_sym_fct) (void *ext, const char *sym, unsigned long *val);
39
40static void *cmd_set_sym_ext = NULL;
41static int (*cmd_set_sym_fct) (void *ext, const char *sym, unsigned long val);
42
43static unsigned cmd_sym_cnt = 0;
44static cmd_sym_t *cmd_sym = NULL;
45
46
47static
48int str_is_space (char c)
49{
50 if ((c == ' ') || (c == '\t')) {
51 return (1);
52 }
53
54 if ((c == '\n') || (c == '\r')) {
55 return (1);
56 }
57
58 return (0);
59}
60
61static
62char *str_ltrim (char *str)
63{
64 unsigned i, j;
65
66 i = 0;
67 j = 0;
68
69 while ((str[i] != 0) && str_is_space (str[i])) {
70 i += 1;
71 }
72
73 if (i == 0) {
74 return (str);
75 }
76
77 while (str[i] != 0) {
78 str[j] = str[i];
79 i += 1;
80 j += 1;
81 }
82
83 str[j] = 0;
84
85 return (str);
86}
87
88static
89char *str_rtrim (char *str)
90{
91 unsigned i, j;
92
93 i = 0; j = 0;
94
95 while (str[i] != 0) {
96 if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n')) {
97 j = i + 1;
98 }
99 i++;
100 }
101
102 str[j] = 0;
103
104 return (str);
105}
106
107void cmd_get (cmd_t *cmd, const char *prompt)
108{
109 if (prompt == NULL) {
110 prompt = "-";
111 }
112
113 pce_gets (prompt, cmd->str, PCE_CMD_MAX);
114
115 str_ltrim (cmd->str);
116 str_rtrim (cmd->str);
117
118 cmd->i = 0;
119}
120
121void cmd_set_str (cmd_t *cmd, const char *str)
122{
123 unsigned i;
124
125 cmd->i = 0;
126
127 for (i = 0; i < PCE_CMD_MAX; i++) {
128 cmd->str[i] = str[i];
129
130 if (str[i] == 0) {
131 return;
132 }
133 }
134
135 cmd->str[PCE_CMD_MAX - 1] = 0;
136}
137
138void cmd_rewind (cmd_t *cmd)
139{
140 cmd->i = 0;
141}
142
143const char *cmd_get_str (cmd_t *cmd)
144{
145 return (cmd->str + cmd->i);
146}
147
148int cmd_get_sym (cmd_t *cmd, const char *sym, unsigned long *val)
149{
150 unsigned i;
151 const char *str;
152
153 str = sym;
154
155 if ((str[0] == '%') || (str[0] == '$')) {
156 str += 1;
157 }
158
159 if (sym[0] != '$') {
160 if (cmd_get_sym_fct != NULL) {
161 if (cmd_get_sym_fct (cmd_get_sym_ext, str, val) == 0) {
162 return (0);
163 }
164 }
165
166 if (sym[0] == '%') {
167 return (1);
168 }
169 }
170
171 for (i = 0; i < cmd_sym_cnt; i++) {
172 if (strcmp (cmd_sym[i].name, str) == 0) {
173 *val = cmd_sym[i].val;
174 return (0);
175 }
176 }
177
178 return (1);
179}
180
181int cmd_set_sym (cmd_t *cmd, const char *sym, unsigned long val)
182{
183 unsigned i;
184 const char *str;
185 cmd_sym_t *tmp;
186
187 str = sym;
188
189 if ((str[0] == '%') || (str[0] == '$')) {
190 str += 1;
191 }
192
193 if (sym[0] != '$') {
194 if (cmd_set_sym_fct != NULL) {
195 if (cmd_set_sym_fct (cmd_set_sym_ext, str, val) == 0) {
196 return (0);
197 }
198 }
199
200 if (sym[0] == '%') {
201 return (1);
202 }
203 }
204
205 for (i = 0; i < cmd_sym_cnt; i++) {
206 if (strcmp (cmd_sym[i].name, str) == 0) {
207 cmd_sym[i].val = val;
208 return (0);
209 }
210 }
211
212 tmp = realloc (cmd_sym, (cmd_sym_cnt + 1) * sizeof (cmd_sym_t));
213 if (tmp == NULL) {
214 return (1);
215 }
216
217 i = cmd_sym_cnt;
218 while (i > 0) {
219 if (strcmp (tmp[i - 1].name, str) < 0) {
220 break;
221 }
222
223 tmp[i] = tmp[i - 1];
224
225 i -= 1;
226 }
227
228 tmp[i].name = strdup (str);
229 tmp[i].val = val;
230
231 cmd_sym = tmp;
232 cmd_sym_cnt += 1;
233
234 return (0);
235}
236
237void cmd_del_sym (cmd_t *cmd, const char *sym, unsigned long *val)
238{
239 unsigned i, j;
240
241 if (sym[0] == '%') {
242 return;
243 }
244
245 if (sym[0] == '$') {
246 sym += 1;
247 }
248
249 *val = 0;
250
251 j = 0;
252
253 for (i = 0; i < cmd_sym_cnt; i++) {
254 if (strcmp (cmd_sym[i].name, sym) == 0) {
255 *val = cmd_sym[i].val;
256 free (cmd_sym[i].name);
257 }
258 else {
259 cmd_sym[j] = cmd_sym[i];
260 j += 1;
261 }
262 }
263
264 cmd_sym_cnt = j;
265}
266
267void cmd_list_syms (cmd_t *cmd)
268{
269 unsigned i, k, n;
270
271 n = 0;
272 for (i = 0; i < cmd_sym_cnt; i++) {
273 k = strlen (cmd_sym[i].name);
274 if (k > n) {
275 n = k;
276 }
277 }
278
279 n += 1;
280
281 for (i = 0; i < cmd_sym_cnt; i++) {
282 k = strlen (cmd_sym[i].name);
283
284 pce_printf ("$%s", cmd_sym[i].name);
285
286 while (k < n) {
287 pce_puts (" ");
288 k += 1;
289 }
290
291 pce_printf ("= %08lX\n", cmd_sym[i].val);
292 }
293}
294
295void cmd_error (cmd_t *cmd, const char *str)
296{
297 pce_printf ("*** %s [%s]\n", str, cmd->str + cmd->i);
298}
299
300int cmd_match_space (cmd_t *cmd)
301{
302 int r;
303 unsigned i;
304
305 i = cmd->i;
306
307 while (cmd->str[i] != 0) {
308 if (str_is_space (cmd->str[i])) {
309 i += 1;
310 }
311 else if (cmd->str[i] == '#') {
312 while (cmd->str[i] != 0) {
313 i += 1;
314 }
315 }
316 else {
317 break;
318 }
319 }
320
321 r = (i > cmd->i);
322
323 cmd->i = i;
324
325 return (r);
326}
327
328static
329int str_is_ident (char c)
330{
331 if ((c >= '0') && (c <= '9')) {
332 return (1);
333 }
334
335 if ((c >= 'a') && (c <= 'z')) {
336 return (1);
337 }
338
339 if ((c >= 'A') && (c <= 'Z')) {
340 return (1);
341 }
342
343 if (c == '_') {
344 return (1);
345 }
346
347 return (0);
348}
349
350int cmd_match_ident (cmd_t *cmd, char *str, unsigned max)
351{
352 unsigned i, n;
353
354 cmd_match_space (cmd);
355
356 i = cmd->i;
357 n = 0;
358
359 switch (cmd->str[cmd->i]) {
360 case '%':
361 case '$':
362 *(str++) = cmd->str[cmd->i];
363 i += 1;
364 n += 1;
365 break;
366 }
367
368 while (cmd->str[i] != 0) {
369 if (str_is_ident (cmd->str[i]) == 0) {
370 break;
371 }
372
373 *(str++) = cmd->str[i];
374 i += 1;
375 n += 1;
376
377 if (n >= max) {
378 cmd_error (cmd, "identifier too long");
379 return (0);
380 }
381 }
382
383 *str = 0;
384
385 cmd->i = i;
386
387 return (n > 0);
388}
389
390int cmd_match_str (cmd_t *cmd, char *str, unsigned max)
391{
392 unsigned i, n;
393 int quote;
394
395 cmd_match_space (cmd);
396
397 i = cmd->i;
398 n = 0;
399
400 if (cmd->str[i] == '"') {
401 quote = 1;
402 i += 1;
403 }
404 else {
405 quote = 0;
406 }
407
408 while (cmd->str[i] != 0) {
409 if (quote) {
410 if (cmd->str[i] == '"') {
411 i += 1;
412 break;
413 }
414 }
415 else {
416 if (str_is_space (cmd->str[i])) {
417 break;
418 }
419 }
420
421 *(str++) = cmd->str[i];
422 i += 1;
423 n += 1;
424
425 if (n >= max) {
426 cmd_error (cmd, "string too long");
427 return (0);
428 }
429 }
430
431 *str = 0;
432
433 cmd->i = i;
434
435 return (n > 0);
436}
437
438int cmd_match_eol (cmd_t *cmd)
439{
440 cmd_match_space (cmd);
441
442 if (cmd->str[cmd->i] == 0) {
443 return (1);
444 }
445
446 return (0);
447}
448
449int cmd_match_end (cmd_t *cmd)
450{
451 if (cmd_match_eol (cmd)) {
452 return (1);
453 }
454
455 cmd_error (cmd, "syntax error");
456
457 return (0);
458}
459
460int cmd_match (cmd_t *cmd, const char *str)
461{
462 unsigned i;
463
464 cmd_match_space (cmd);
465
466 i = cmd->i;
467
468 while ((*str != 0) && (cmd->str[i] == *str)) {
469 i += 1;
470 str += 1;
471 }
472
473 if (*str != 0) {
474 return (0);
475 }
476
477 cmd->i = i;
478
479 return (1);
480}
481
482static
483int cmd_peek (cmd_t *cmd, const char *str)
484{
485 unsigned i, s;
486
487 s = cmd->i;
488
489 cmd_match_space (cmd);
490
491 i = cmd->i;
492
493 while ((*str != 0) && (cmd->str[i] == *str)) {
494 i += 1;
495 str += 1;
496 }
497
498 if (*str != 0) {
499 return (0);
500 }
501
502 cmd->i = s;
503
504 return (1);
505}
506
507static
508int cmd_match_expr_const (cmd_t *cmd, unsigned long *val, unsigned base)
509{
510 unsigned i;
511 unsigned cnt;
512 unsigned long ret;
513
514 cmd_match_space (cmd);
515
516 i = cmd->i;
517
518 ret = 0;
519 cnt = 0;
520
521 while (cmd->str[i] != 0) {
522 unsigned dig;
523
524 if ((cmd->str[i] >= '0') && (cmd->str[i] <= '9')) {
525 dig = cmd->str[i] - '0';
526 }
527 else if ((cmd->str[i] >= 'a') && (cmd->str[i] <= 'f')) {
528 dig = cmd->str[i] - 'a' + 10;
529 }
530 else if ((cmd->str[i] >= 'A') && (cmd->str[i] <= 'F')) {
531 dig = cmd->str[i] - 'A' + 10;
532 }
533 else {
534 break;
535 }
536
537 if (dig >= base) {
538 break;
539 }
540
541 ret = (base * ret + dig) & 0xffffffff;
542
543 cnt += 1;
544 i += 1;
545 }
546
547 if (cnt == 0) {
548 return (0);
549 }
550
551 cmd->i = i;
552 *val = ret;
553
554 return (1);
555}
556
557static
558int cmd_match_expr_literal (cmd_t *cmd, unsigned long *val, unsigned base)
559{
560 unsigned i;
561 char str[256];
562
563 cmd_match_space (cmd);
564
565 i = cmd->i;
566
567 if (cmd_match_ident (cmd, str, 256)) {
568 /*
569 * If the identifier does not start with '%' or '$', check
570 * if it could be a constant.
571 */
572 if ((str[0] != '%') && (str[0] != '$')) {
573 unsigned t;
574
575 t = cmd->i;
576 cmd->i = i;
577
578 if (cmd_match_expr_const (cmd, val, base)) {
579 /* check if the constant is at least as long
580 as the identifier. */
581 if (cmd->i >= t) {
582 return (1);
583 }
584 }
585
586 cmd->i = t;
587 }
588
589 if (cmd_get_sym (cmd, str, val) == 0) {
590 return (1);
591 }
592
593 cmd->i = i;
594 }
595
596 if (cmd_match (cmd, "(")) {
597 if (cmd_match_expr (cmd, val, base)) {
598 if (cmd_match (cmd, ")")) {
599 return (1);
600 }
601 }
602
603 cmd->i = i;
604
605 return (0);
606 }
607
608 if (cmd_match_expr_const (cmd, val, base)) {
609 return (1);
610 }
611
612 return (0);
613}
614
615static
616int cmd_match_expr_neg (cmd_t *cmd, unsigned long *val, unsigned base)
617{
618 unsigned i;
619 unsigned op;
620
621 i = cmd->i;
622
623 if (cmd_match (cmd, "!")) {
624 op = 1;
625 }
626 else if (cmd_match (cmd, "~")) {
627 op = 2;
628 }
629 else if (cmd_match (cmd, "+")) {
630 op = 3;
631 }
632 else if (cmd_match (cmd, "-")) {
633 op = 4;
634 }
635 else {
636 op = 0;
637 }
638
639 if (cmd_match_expr_literal (cmd, val, base) == 0) {
640 cmd->i = i;
641 return (0);
642 }
643
644 if (op == 1) {
645 *val = !*val;
646 }
647 else if (op == 2) {
648 *val = ~*val & 0xffffffff;
649 }
650 else if (op == 3) {
651 ;
652 }
653 else if (op == 4) {
654 *val = -*val & 0xffffffff;
655 }
656
657 return (1);
658}
659
660static
661int cmd_match_expr_product (cmd_t *cmd, unsigned long *val, unsigned base)
662{
663 unsigned i;
664 unsigned op;
665 unsigned long val2;
666
667 i = cmd->i;
668
669 if (cmd_match_expr_neg (cmd, val, base) == 0) {
670 return (0);
671 }
672
673 while (1) {
674 if (cmd_match (cmd, "*")) {
675 op = 1;
676 }
677 else if (cmd_match (cmd, "/")) {
678 op = 2;
679 }
680 else if (cmd_match (cmd, "%")) {
681 op = 3;
682 }
683 else {
684 return (1);
685 }
686
687 if (cmd_match_expr_neg (cmd, &val2, base) == 0) {
688 cmd->i = i;
689 return (0);
690 }
691
692 if (op == 1) {
693 *val = (*val * val2) & 0xffffffff;
694 }
695 else if (op == 2) {
696 if (val2 != 0) {
697 *val = *val / val2;
698 }
699 else {
700 *val = 0xffffffff;
701 }
702 }
703 else {
704 if (val2 != 0) {
705 *val = *val % val2;
706 }
707 else {
708 *val = 0;
709 }
710 }
711 }
712
713 return (0);
714}
715
716static
717int cmd_match_expr_sum (cmd_t *cmd, unsigned long *val, unsigned base)
718{
719 unsigned i;
720 unsigned op;
721 unsigned long val2;
722
723 i = cmd->i;
724
725 if (cmd_match_expr_product (cmd, val, base) == 0) {
726 return (0);
727 }
728
729 while (1) {
730 if (cmd_match (cmd, "+")) {
731 op = 1;
732 }
733 else if (cmd_match (cmd, "-")) {
734 op = 2;
735 }
736 else {
737 return (1);
738 }
739
740 if (cmd_match_expr_product (cmd, &val2, base) == 0) {
741 cmd->i = i;
742 return (0);
743 }
744
745 if (op == 1) {
746 *val = (*val + val2) & 0xffffffff;
747 }
748 else {
749 *val = (*val - val2) & 0xffffffff;
750 }
751 }
752
753 return (0);
754}
755
756static
757int cmd_match_expr_shift (cmd_t *cmd, unsigned long *val, unsigned base)
758{
759 unsigned i;
760 unsigned op;
761 unsigned long val2;
762
763 i = cmd->i;
764
765 if (cmd_match_expr_sum (cmd, val, base) == 0) {
766 return (0);
767 }
768
769 while (1) {
770 if (cmd_match (cmd, "<<<")) {
771 op = 1;
772 }
773 else if (cmd_match (cmd, ">>>")) {
774 op = 2;
775 }
776 else if (cmd_match (cmd, "<<")) {
777 op = 3;
778 }
779 else if (cmd_match (cmd, ">>")) {
780 op = 4;
781 }
782 else {
783 return (1);
784 }
785
786 if (cmd_match_expr_sum (cmd, &val2, base) == 0) {
787 cmd->i = i;
788 return (0);
789 }
790
791 val2 &= 0x1f;
792
793 if (op == 1) {
794 *val = (*val << val2) | (*val >> (32 - val2));
795 }
796 else if (op == 2) {
797 *val = (*val >> val2) | (*val << (32 - val2));
798 }
799 else if (op == 3) {
800 *val = *val << val2;
801 }
802 else if (op == 4) {
803 *val = *val >> val2;
804 }
805
806 *val &= 0xffffffff;
807 }
808
809 return (0);
810}
811
812static
813int cmd_match_expr_cmp (cmd_t *cmd, unsigned long *val, unsigned base)
814{
815 unsigned i;
816 unsigned op;
817 unsigned long val2;
818
819 i = cmd->i;
820
821 if (cmd_match_expr_shift (cmd, val, base) == 0) {
822 return (0);
823 }
824
825 while (1) {
826 if (cmd_match (cmd, "<=")) {
827 op = 1;
828 }
829 else if (cmd_match (cmd, "<")) {
830 op = 2;
831 }
832 else if (cmd_match (cmd, ">=")) {
833 op = 3;
834 }
835 else if (cmd_match (cmd, ">")) {
836 op = 4;
837 }
838 else {
839 return (1);
840 }
841
842 if (cmd_match_expr_shift (cmd, &val2, base) == 0) {
843 cmd->i = i;
844 return (0);
845 }
846
847 if (op == 1) {
848 *val = *val <= val2;
849 }
850 else if (op == 2) {
851 *val = *val < val2;
852 }
853 else if (op == 3) {
854 *val = *val >= val2;
855 }
856 else if (op == 4) {
857 *val = *val > val2;
858 }
859 }
860
861 return (0);
862}
863
864static
865int cmd_match_expr_equ (cmd_t *cmd, unsigned long *val, unsigned base)
866{
867 unsigned i;
868 unsigned op;
869 unsigned long val2;
870
871 i = cmd->i;
872
873 if (cmd_match_expr_cmp (cmd, val, base) == 0) {
874 return (0);
875 }
876
877 while (1) {
878 if (cmd_match (cmd, "==")) {
879 op = 1;
880 }
881 else if (cmd_match (cmd, "!=")) {
882 op = 2;
883 }
884 else {
885 return (1);
886 }
887
888 if (cmd_match_expr_cmp (cmd, &val2, base) == 0) {
889 cmd->i = i;
890 return (0);
891 }
892
893 if (op == 1) {
894 *val = *val == val2;
895 }
896 else if (op == 2) {
897 *val = *val != val2;
898 }
899 }
900
901 return (0);
902}
903
904static
905int cmd_match_expr_band (cmd_t *cmd, unsigned long *val, unsigned base)
906{
907 unsigned i;
908 unsigned op;
909 unsigned long val2;
910
911 i = cmd->i;
912
913 if (cmd_match_expr_equ (cmd, val, base) == 0) {
914 return (0);
915 }
916
917 while (1) {
918 if (cmd_peek (cmd, "&&")) {
919 return (1);
920 }
921
922 if (cmd_match (cmd, "&")) {
923 op = 1;
924 }
925 else {
926 return (1);
927 }
928
929 if (cmd_match_expr_equ (cmd, &val2, base) == 0) {
930 cmd->i = i;
931 return (0);
932 }
933
934 if (op == 1) {
935 *val = *val & val2;
936 }
937 }
938
939 return (0);
940}
941
942static
943int cmd_match_expr_bxor (cmd_t *cmd, unsigned long *val, unsigned base)
944{
945 unsigned i;
946 unsigned op;
947 unsigned long val2;
948
949 i = cmd->i;
950
951 if (cmd_match_expr_band (cmd, val, base) == 0) {
952 return (0);
953 }
954
955 while (1) {
956 if (cmd_match (cmd, "^")) {
957 op = 1;
958 }
959 else {
960 return (1);
961 }
962
963 if (cmd_match_expr_band (cmd, &val2, base) == 0) {
964 cmd->i = i;
965 return (0);
966 }
967
968 if (op == 1) {
969 *val = *val ^ val2;
970 }
971 }
972
973 return (0);
974}
975
976static
977int cmd_match_expr_bor (cmd_t *cmd, unsigned long *val, unsigned base)
978{
979 unsigned i;
980 unsigned op;
981 unsigned long val2;
982
983 i = cmd->i;
984
985 if (cmd_match_expr_bxor (cmd, val, base) == 0) {
986 return (0);
987 }
988
989 while (1) {
990 if (cmd_peek (cmd, "||")) {
991 return (1);
992 }
993
994 if (cmd_match (cmd, "|")) {
995 op = 1;
996 }
997 else {
998 return (1);
999 }
1000
1001 if (cmd_match_expr_bxor (cmd, &val2, base) == 0) {
1002 cmd->i = i;
1003 return (0);
1004 }
1005
1006 if (op == 1) {
1007 *val = *val | val2;
1008 }
1009 }
1010
1011 return (0);
1012}
1013
1014static
1015int cmd_match_expr_land (cmd_t *cmd, unsigned long *val, unsigned base)
1016{
1017 unsigned i;
1018 unsigned op;
1019 unsigned long val2;
1020
1021 i = cmd->i;
1022
1023 if (cmd_match_expr_bor (cmd, val, base) == 0) {
1024 return (0);
1025 }
1026
1027 while (1) {
1028 if (cmd_match (cmd, "&&")) {
1029 op = 1;
1030 }
1031 else {
1032 return (1);
1033 }
1034
1035 if (cmd_match_expr_bor (cmd, &val2, base) == 0) {
1036 cmd->i = i;
1037 return (0);
1038 }
1039
1040 if (op == 1) {
1041 *val = *val && val2;
1042 }
1043 }
1044
1045 return (0);
1046}
1047
1048static
1049int cmd_match_expr_lor (cmd_t *cmd, unsigned long *val, unsigned base)
1050{
1051 unsigned i;
1052 unsigned op;
1053 unsigned long val2;
1054
1055 i = cmd->i;
1056
1057 if (cmd_match_expr_land (cmd, val, base) == 0) {
1058 return (0);
1059 }
1060
1061 while (1) {
1062 if (cmd_match (cmd, "||")) {
1063 op = 1;
1064 }
1065 else {
1066 return (1);
1067 }
1068
1069 if (cmd_match_expr_land (cmd, &val2, base) == 0) {
1070 cmd->i = i;
1071 return (0);
1072 }
1073
1074 if (op == 1) {
1075 *val = *val || val2;
1076 }
1077 }
1078
1079 return (0);
1080}
1081
1082static
1083int cmd_match_expr_cond (cmd_t *cmd, unsigned long *val, unsigned base)
1084{
1085 unsigned i;
1086 unsigned long val2, val3;
1087
1088 i = cmd->i;
1089
1090 if (cmd_match_expr_lor (cmd, val, base) == 0) {
1091 return (0);
1092 }
1093
1094 if (cmd_match (cmd, "?") == 0) {
1095 return (1);
1096 }
1097
1098 if (cmd_match_expr_lor (cmd, &val2, base) == 0) {
1099 cmd->i = i;
1100 return (0);
1101 }
1102
1103 if (cmd_match (cmd, ":") == 0) {
1104 cmd->i = i;
1105 return (0);
1106 }
1107
1108 if (cmd_match_expr_lor (cmd, &val3, base) == 0) {
1109 cmd->i = i;
1110 return (0);
1111 }
1112
1113 *val = *val ? val2 : val3;
1114
1115 return (1);
1116}
1117
1118static
1119int cmd_match_expr_assign (cmd_t *cmd, unsigned long *val, unsigned base)
1120{
1121 unsigned i, j;
1122 unsigned op;
1123 char str[256];
1124
1125 cmd_match_space (cmd);
1126
1127 i = cmd->i;
1128
1129 if (cmd_match_ident (cmd, str, 256)) {
1130 j = 0;
1131 while (str[j] == '%') {
1132 j += 1;
1133 }
1134
1135 if (cmd_match (cmd, "=")) {
1136 op = 1;
1137 }
1138 else if (cmd_match (cmd, "+=")) {
1139 op = 2;
1140 }
1141 else if (cmd_match (cmd, "-=")) {
1142 op = 3;
1143 }
1144 else if (cmd_match (cmd, "*=")) {
1145 op = 4;
1146 }
1147 else if (cmd_match (cmd, "/=")) {
1148 op = 5;
1149 }
1150 else if (cmd_match (cmd, "<<=")) {
1151 op = 6;
1152 }
1153 else if (cmd_match (cmd, ">>=")) {
1154 op = 7;
1155 }
1156 else if (cmd_match (cmd, "|=")) {
1157 op = 8;
1158 }
1159 else if (cmd_match (cmd, "&=")) {
1160 op = 9;
1161 }
1162 else if (cmd_match (cmd, "^=")) {
1163 op = 10;
1164 }
1165 else {
1166 op = 0;
1167 }
1168
1169 if (op != 0) {
1170 unsigned long tmp;
1171
1172 if (cmd_match (cmd, ";")) {
1173 cmd_del_sym (cmd, str + j, val);
1174 return (1);
1175 }
1176
1177 if (cmd_get_sym (cmd, str + j, val)) {
1178 *val = 0;
1179 }
1180
1181 if (cmd_match_expr_cond (cmd, &tmp, base)) {
1182 switch (op) {
1183 case 1:
1184 *val = tmp;
1185 break;
1186 case 2:
1187 *val += tmp;
1188 break;
1189 case 3:
1190 *val -= tmp;
1191 break;
1192 case 4:
1193 *val *= tmp;
1194 break;
1195 case 5:
1196 if (tmp != 0) {
1197 *val /= tmp;
1198 }
1199 else {
1200 *val = 0xffffffff;
1201 }
1202 break;
1203 case 6:
1204 *val <<= tmp;
1205 break;
1206 case 7:
1207 *val >>= tmp;
1208 break;
1209 case 8:
1210 *val |= tmp;
1211 break;
1212 case 9:
1213 *val &= tmp;
1214 break;
1215 case 10:
1216 *val ^= tmp;
1217 break;
1218 default:
1219 *val = tmp;
1220 break;
1221 }
1222
1223 *val &= 0xffffffff;
1224
1225 cmd_set_sym (cmd, str + j, *val);
1226
1227 return (1);
1228 }
1229 }
1230 }
1231
1232 cmd->i = i;
1233
1234 return (cmd_match_expr_cond (cmd, val, base));
1235}
1236
1237int cmd_match_expr (cmd_t *cmd, unsigned long *val, unsigned base)
1238{
1239 while (1) {
1240 if (cmd_match_expr_assign (cmd, val, base) == 0) {
1241 return (0);
1242 }
1243
1244 if (cmd_match (cmd, ",") == 0) {
1245 return (1);
1246 }
1247 }
1248
1249 return (0);
1250}
1251
1252int cmd_match_ulng (cmd_t *cmd, unsigned long *val, unsigned base)
1253{
1254 if (cmd_match_expr_const (cmd, val, base)) {
1255 return (1);
1256 }
1257
1258 return (0);
1259}
1260
1261int cmd_match_uint (cmd_t *cmd, unsigned *val, unsigned base)
1262{
1263 unsigned long tmp;
1264
1265 if (cmd_match_expr_const (cmd, &tmp, base)) {
1266 *val = tmp;
1267 return (1);
1268 }
1269
1270 return (0);
1271}
1272
1273int cmd_match_uint16b (cmd_t *cmd, unsigned short *val, unsigned base)
1274{
1275 unsigned long tmp;
1276
1277 if (cmd_match_expr (cmd, &tmp, base)) {
1278 *val = tmp & 0xffff;
1279 return (1);
1280 }
1281
1282 return (0);
1283}
1284
1285int cmd_match_uint16 (cmd_t *cmd, unsigned short *val)
1286{
1287 return (cmd_match_uint16b (cmd, val, 16));
1288}
1289
1290int cmd_match_uint32b (cmd_t *cmd, unsigned long *val, unsigned base)
1291{
1292 return (cmd_match_expr (cmd, val, base));
1293}
1294
1295int cmd_match_uint32 (cmd_t *cmd, unsigned long *val)
1296{
1297 return (cmd_match_uint32b (cmd, val, 16));
1298}
1299
1300int cmd_match_uint16_16 (cmd_t *cmd, unsigned short *seg, unsigned short *ofs)
1301{
1302 unsigned short val;
1303
1304 if (!cmd_match_uint16 (cmd, &val)) {
1305 return (0);
1306 }
1307
1308 if (!cmd_match (cmd, ":")) {
1309 *ofs = val;
1310 return (1);
1311 }
1312
1313 *seg = val;
1314
1315 cmd_match_uint16 (cmd, ofs);
1316
1317 return (1);
1318}
1319
1320void cmd_init (void *ext, void *getsym, void *setsym)
1321{
1322 cmd_get_sym_ext = ext;
1323 cmd_get_sym_fct = getsym;
1324
1325 cmd_set_sym_ext = ext;
1326 cmd_set_sym_fct = setsym;
1327}