]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/eval_arg.c
Remove extern declarations from command_tbl.c, create .h files for that.
[z180-stamp.git] / avr / eval_arg.c
1 /*
2 * (C) Copyright 2016 Leo C. <erbl259-lmu@yahoo.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0
5 */
6
7 #include "eval_arg.h"
8 #include "command.h" /* jump_buf */
9 #include <ctype.h>
10 #include <setjmp.h>
11 #include "print-utils.h"
12
13 static jmp_buf eval_jbuf;
14 static char ch;
15 static char *start_p;
16 static char *bp;
17
18
19 static long expr(void);
20
21 static void print_error_pos(void)
22 {
23 printf_P(PSTR("Arg: '%s'\n"
24 " "), start_p);
25 print_blanks(bp - start_p);
26 my_puts_P(PSTR("^syntax error!\n"));
27 }
28
29 static void error (void)
30 {
31 --bp;
32 longjmp (eval_jbuf, 1);
33 }
34
35 static void next(void)
36 {
37 do
38 ch = *bp++;
39 while (isspace(ch));
40 }
41
42 static long number (void)
43 {
44 int base = 16;
45 char *end_p;
46 long n;
47
48 if (ch == '$') { /* FIXME: should be '#' */
49 next();
50 base = 10;
51 }
52 if (!isdigit(ch) && !(base == 16 && isxdigit(ch)))
53 error ();
54
55 n = strtoul(bp - 1, &end_p, base);
56
57 if (end_p == bp - 1)
58 error();
59 bp = end_p;
60 next();
61
62 return n;
63 }
64
65 static long factor (void)
66 {
67 long f;
68
69 if (ch == '(')
70 {
71 next();
72 f = expr();
73 if (ch == ')')
74 next();
75 else
76 error ();
77 } else {
78 char sign = ch;
79 if (sign == '+' || sign == '-') {
80 next();
81 }
82 f = number();
83 if (sign == '-')
84 f = -f;
85 }
86 return f;
87 }
88
89 static long term (void)
90 {
91 long t = factor();
92
93 for (;;)
94 switch (ch) {
95 case '*':
96 next();
97 t *= factor();
98 break;
99 case '/':
100 next();
101 t /= factor();
102 break;
103 case '%':
104 next();
105 t %= factor();
106 break;
107 default:
108 return t;
109 }
110 }
111
112
113 static long expr(void)
114 {
115 long e = term ();
116
117 while (ch == '+' || ch == '-') {
118 char op = ch;
119 next();
120 if (op == '-')
121 e -= term ();
122 else
123 e += term ();
124 }
125 return e;
126 }
127
128 long eval_arg(char *arg, char **end_ptr)
129 {
130 long val;
131
132 start_p = arg;
133 bp = arg;
134 next();
135 if (setjmp (eval_jbuf) != 0) {
136 if (!end_ptr) {
137 print_error_pos();
138 longjmp(cmd_jbuf, 1);
139 }
140 val = -1;
141 } else {
142 val = expr ();
143 --bp;
144 }
145
146 if (!end_ptr) {
147 if (*bp != '\0') {
148 print_error_pos();
149 longjmp(cmd_jbuf, 1);
150 }
151 } else
152 *end_ptr = bp;
153
154 return val;
155 }