]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/eval_arg.c
Enable expression evaluation for numeric command line args
[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 (ch == ' ' || ch == '\n');
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 }
80 else
81 f = number ();
82
83 return f;
84 }
85
86 static long term (void)
87 {
88 long t = factor();
89
90 for (;;)
91 switch (ch) {
92 case '*':
93 next();
94 t *= factor();
95 break;
96 case '/':
97 next();
98 t /= factor();
99 break;
100 case '%':
101 next();
102 t %= factor();
103 break;
104 default:
105 return t;
106 }
107 }
108
109
110 static long expr(void)
111 {
112 long e;
113
114 if (ch == '+') {
115 next();
116 e = term ();
117 } else if (ch == '-') {
118 next();
119 e = - term ();
120 } else
121 e = term ();
122
123 while (ch == '+' || ch == '-') {
124 char op = ch;
125 next();
126 if (op == '-')
127 e -= term ();
128 else
129 e += term ();
130 }
131 return e;
132 }
133
134 long eval_arg(char *arg, char **end_ptr)
135 {
136 long val;
137
138 start_p = arg;
139 bp = arg;
140 next();
141 if (setjmp (eval_jbuf) != 0) {
142 if (!end_ptr) {
143 print_error_pos();
144 longjmp(cmd_jbuf, 1);
145 }
146 val = -1;
147 } else {
148 val = expr ();
149 --bp;
150 }
151
152 if (!end_ptr) {
153 if (*bp != '\0') {
154 print_error_pos();
155 longjmp(cmd_jbuf, 1);
156 }
157 } else
158 *end_ptr = bp;
159
160 return val;
161 }