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