]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/eval_arg.c
Enable expression evaluation for numeric command line args
[z180-stamp.git] / avr / eval_arg.c
CommitLineData
fcd2239e
L
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
15static jmp_buf eval_jbuf;
16static char ch;
17static char *start_p;
18static char *bp;
19
20
21static long expr(void);
22
23static 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
31static void error (void)
32{
33 --bp;
34 longjmp (eval_jbuf, 1);
35}
36
37static void next(void)
38{
39 do
40 ch = *bp++;
41 while (ch == ' ' || ch == '\n');
42}
43
44static 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
67static 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
86static 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
110static 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
134long 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}