8 char *Expression::eval_math(
char *expr,
char op_char) {
12 char *brk = strpbrk(expr, sep);
24 case '+': r = i1+i2;
break;
25 case '*': r = i1*i2;
break;
34 char *Expression::evalPart(
int start,
int end,
int& resLen) {
40 char c = ebuffer[end+1];
42 char *part = ebuffer+
start;
49 else if (part[0] ==
'+' || part[0] ==
'*') {
50 res = eval_math(part+1, part[0]);
52 else if (part[0] ==
'#') {
53 if (strncmp(part,
"#FILE", 5) == 0) {
63 const char *sourcename = loc.
get_path();
67 int buflen = fileLen+strlen(path)+strlen(sourcename)+100;
68 res = (
char *)malloc(buflen+1);
71 int printed = sprintf(res,
"@SETSOURCE %s,%i@%s@SETSOURCE %s,%i@",
74 sourcename, sourceline);
75 if (printed >= buflen) {
76 fprintf(stderr,
"%s:%i: Error: buffer overflow\n", __FILE__, __LINE__);
91 if (resLen == -1 && res) resLen = strlen(res);
95 bool Expression::evalRest(
const int offset) {
100 aisc_assert(strncmp(ebuffer+offset,
"$(", 2) == 0);
103 const char *more_to_eval = strstr(ebuffer+offset+2,
"$(");
105 if (!evalRest(more_to_eval-ebuffer))
return false;
111 const char *paren = strchr(ebuffer+offset+2,
')');
113 print_error(&loc,
"unbalanced parens; missing ')'");
116 closing_paren = paren-ebuffer;
122 if (offset>0 && ebuffer[offset-1] ==
'$') {
123 eval_len = closing_paren-
offset;
124 evaluated =
strduplen(ebuffer+offset+1, eval_len);
127 evaluated = evalPart(offset+2, closing_paren-1, eval_len);
134 int org_len = closing_paren-offset+1;
136 char *rest = ebuffer+closing_paren+1;
137 int restlen = used-closing_paren;
139 if (eval_len <= org_len) {
140 if (eval_len < org_len) {
142 memmove(ebuffer+offset+eval_len, rest, restlen);
143 used -= (org_len-eval_len);
145 memcpy(ebuffer+offset, evaluated, eval_len);
148 int growth = eval_len-org_len;
149 if ((used+growth+1)>bufsize) {
150 int new_bufsize = (used+growth+1)*3/2;
151 char *new_linebuf = (
char*)malloc(new_bufsize);
153 memcpy(new_linebuf, ebuffer, offset);
154 memcpy(new_linebuf+offset, evaluated, eval_len);
156 memcpy(new_linebuf+offset+eval_len, rest, restlen);
159 ebuffer = new_linebuf;
160 bufsize = new_bufsize;
164 memmove(ebuffer+offset+eval_len, rest, restlen);
165 memcpy(ebuffer+offset, evaluated, eval_len);
175 char *ld = strstr(ebuffer+offset,
"$(");
177 int next_offset = ld-ebuffer;
178 if (next_offset == offset) {
179 static int deadlock_offset;
180 static int deadlock_count;
182 if (next_offset == deadlock_offset) {
184 if (deadlock_count > 50) {
185 printf_error(&loc,
"detected (endless?) recursive evaluation in expression '%s'", ld);
190 deadlock_offset = next_offset;
194 return evalRest(next_offset);
CONSTEXPR_INLINE bool is_SPACE_LF_EOS(char c)
const char * get_path() const
char * read_aisc_file(const char *path, const Location *loc)
const char * formatted(const char *format,...)
char * strduplen(const char *s, int len)
char * get_var_string(const Data &data, char *var, bool allow_missing_var)
static HelixNrInfo * start
#define print_error(code_or_loc, err)
#define printf_error(code_or_loc, format, arg)
static long fileLen[GB_MAX_MAPPED_FILES]
#define aisc_assert(cond)
void SKIP_SPACE_LF(const char *&var)