USING_NAMESPACE_ACADO // --------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------- // SIMPLE AUXILIARY FUNCTION: Expression symmetricDoubleProduct( const Expression& expr, const Expression& arg ) { uint dim = arg.getNumCols(); uint dim2 = arg.getNumRows(); IntermediateState inter_res = zeros<double>(dim2,dim); for( uint i = 0; i < dim; i++ ) { for( uint k1 = 0; k1 < dim2; k1++ ) { for( uint k2 = 0; k2 <= k1; k2++ ) { inter_res(k1,i) += expr(k1,k2)*arg(k2,i); } for( uint k2 = k1+1; k2 < dim2; k2++ ) { inter_res(k1,i) += expr(k2,k1)*arg(k2,i); } } } Expression new_expr( "", dim, dim ); for( uint i = 0; i < dim; i++ ) { for( uint j = 0; j <= i; j++ ) { Expression new_tmp = 0; for( uint k1 = 0; k1 < dim2; k1++ ) { new_tmp = new_tmp+arg(k1,i)*inter_res(k1,j); } new_expr(i,j) = new_tmp; new_expr(j,i) = new_tmp; } } return new_expr; }
struct expr * cdr(struct expr * e, struct context * ctx) { struct list *nl; struct expr *a, *re; if (!e) return empty_list(); if (list_len(e) < 2) { free_expr(e); return empty_list(); } a = eval(e->v.list->next->v, ctx); if (a->t != LLIST || a->v.list == NULL) { full_free_expr(a); free_expr(e); return empty_list(); } nl = list_dup(a->v.list->next); if (!nl) { re = empty_list(); } else { re = new_expr(LLIST); re->v.list = nl; } full_free_expr(a); free_expr(e); return re; }
struct expr * cons(struct expr * e, struct context * ctx) { struct expr *ne, *a, *b, *re; struct list *l; if (!e || list_len(e) < 3) { dbgprintf("invalid cons expr\n"); free_expr(e); return empty_list(); } a = eval(e->v.list->next->v, ctx); b = eval(e->v.list->next->next->v, ctx); if (b->t != LLIST) { full_free_expr(a); re = empty_list(); } else { re = new_expr(LLIST); list_add(re, a); for (l = b->v.list; l != NULL; l = l->next) list_add(re, exprs_dup(l->v)); free_list(l); } full_free_expr(b); free_expr(e); return re; }
static expression_t *gnu_get_oplist(asm86_t * a, int *pn, int deref) /* Get a comma (or colon for jmpf and callf) separated list of instruction * operands. */ { expression_t *e, *o1, *o2; token_t *t; int sreg; if ((e= gnu_get_operand(a, pn, deref)) == nil) return nil; t = get_token(*pn); if (t->symbol == ':' && IS_REGSEG(sreg = isregister(e->name))) { a->seg = segreg2seg(sreg); del_expr(e); (*pn)++; e = gnu_get_oplist(a, pn, deref); } else if (t->symbol == ',' || t->symbol == ':') { o1= e; (*pn)++; if ((o2= gnu_get_oplist(a, pn, deref)) == nil) { del_expr(o1); return nil; } e= new_expr(); e->operator= ','; e->left= o2; e->right= o1; } return e; }
static te_expr *base(state *s) { /* <base> = <constant> | <variable> | <function> <power> | "(" <expr> ")" */ te_expr *ret; switch (s->type) { case TOK_NUMBER: ret = new_expr(0, 0); ret->value = s->value; next_token(s); break; case TOK_VARIABLE: ret = new_expr(0, 0); ret->bound = s->var; next_token(s); break; case TOK_FUNCTION1: ret = new_expr(0, 0); ret->f1 = s->f1; next_token(s); ret->left = power(s); break; case TOK_OPEN: next_token(s); ret = expr(s); if (s->type != TOK_CLOSE) { s->type = TOK_ERROR; } else { next_token(s); } break; default: ret = new_expr(0, 0); s->type = TOK_ERROR; ret->value = NAN; break; } return ret; }
struct expr * atom_t(void) { struct expr *e; e = new_expr(LATOM); e->v.atom = new_atom("t"); return e; }
exprt concatenate_array_id( const exprt &array, const mp_integer &index, const typet &type) { std::string a, identifier; a = array.get_string(ID_identifier); identifier=a+"["+integer2string(index)+"]"; symbol_exprt new_expr(identifier, type); return new_expr; }
static te_expr *term(state *s) { /* <term> = <factor> {("*" | "/" | "%") <factor>} */ te_expr *ret = factor(s); while (s->type == TOK_FUNCTION2 && (s->f2 == mul || s->f2 == divide || s->f2 == fmod)) { te_fun2 t = s->f2; next_token(s); ret = new_expr(ret, factor(s)); ret->f2 = t; } return ret; }
static te_expr *expr(state *s) { /* <expr> = <term> {("+" | "-") <term>} */ te_expr *ret = term(s); while (s->type == TOK_FUNCTION2 && (s->f2 == add || s->f2 == sub)) { te_fun2 t = s->f2; next_token(s); ret = new_expr(ret, term(s)); ret->f2 = t; } return ret; }
static te_expr *factor(state *s) { /* <factor> = <power> {"^" <power>} */ te_expr *ret = power(s); while (s->type == TOK_FUNCTION2 && (s->f2 == pow)) { te_fun2 t = s->f2; next_token(s); ret = new_expr(ret, power(s)); ret->f2 = t; } return ret; }
void goto_symext::replace_nondet(exprt &expr) { if(expr.id()==ID_side_effect && expr.get(ID_statement)==ID_nondet) { exprt new_expr(ID_nondet_symbol, expr.type()); new_expr.set(ID_identifier, "symex::nondet"+std::to_string(nondet_count++)); new_expr.add_source_location()=expr.source_location(); expr.swap(new_expr); } else Forall_operands(it, expr) replace_nondet(*it); }
struct expr * defun(struct expr * e, struct context * ctx) { struct expr *pe, *pl; struct list *l; if (!e || list_len(e) < 4) { free_expr(e); return empty_list(); } if (!e->v.list->next || !e->v.list->next->v || e->v.list->next->v->t != LATOM || !e->v.list->next->v->v.atom || !e->v.list->next->v->v.atom->v) { free_expr(e); return empty_list(); } if (!e->v.list->next->next || !is_valid_p_expr(e->v.list->next->next->v)) { free_expr(e); return empty_list(); } if (!e->v.list->next->next->next || !e->v.list->next->next->next->v) { free_expr(e); return empty_list(); } pl = new_expr(LLIST); pl->v.list = new_list(); pl->v.list->v = new_expr(LATOM); pl->v.list->v->v.atom = new_atom("lambda"); pl->v.list->next = new_list(); pl->v.list->next->v = exprs_dup(e->v.list->next->next->v); pl->v.list->next->next = new_list(); pl->v.list->next->next->v = exprs_dup(e->v.list->next->next->next->v); pe = add_to_context(ctx, strdup(e->v.list->next->v->v.atom->v), pl); full_free_expr(pe); free_expr(e); return empty_list(); }
exprt concatenate_array_id( const exprt &array, const exprt &index, const typet &type) { std::string a, idx, identifier; a = array.get_string(ID_identifier); if (index.id()==ID_typecast) idx = index.op0().get_string(ID_value); else idx = index.get_string(ID_value); mp_integer i=string2integer(idx); identifier=a+"["+integer2string(i)+"]"; symbol_exprt new_expr(identifier, type); return new_expr; }
static te_expr *power(state *s) { /* <power> = {("-" | "+")} <base> */ int sign = 1; while (s->type == TOK_FUNCTION2 && (s->f2 == add || s->f2 == sub)) { if (s->f2 == sub) sign = -sign; next_token(s); } te_expr *ret; if (sign == 1) { ret = base(s); } else { ret = new_expr(base(s), 0); ret->f1 = negate; } return ret; }
struct expr * list(struct expr * e, struct context * ctx) { struct expr *pe, *re; const struct list *l; int i; if (!e) return empty_list(); if (list_len(e) < 2) { free_expr(e); return empty_list(); } re = new_expr(LLIST); for (i = 1; (l = get_list_el(e, i)) != NULL; ++i) { pe = eval(l->v, ctx); list_add(re, pe); } free_expr(e); return re; }
static expression_t *ack_get_oplist(int *pn, int deref) /* Get a comma (or colon for jmpf and callf) separated list of instruction * operands. */ { expression_t *e, *o1, *o2; token_t *t; if ((e= ack_get_operand(pn, deref)) == nil) return nil; if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') { o1= e; (*pn)++; if ((o2= ack_get_oplist(pn, deref)) == nil) { del_expr(o1); return nil; } e= new_expr(); e->operator= ','; e->left= o1; e->right= o2; } return e; }
struct expr * empty_list(void) { return new_expr(LLIST); }
asm86_t *gnu_get_instruction(void) { asm86_t *a= nil; expression_t *e; token_t *t; while ((t= get_token(0))->symbol == ';' || t->symbol == '/') { zap(); /* if a comment started by a '/' */ skip_token(1); } if (t->type == T_EOF) return nil; if (t->type == T_COMMENT || t->type == T_C_PREPROCESSOR) { a = new_asm86(); if (t->type == T_COMMENT) a->opcode = COMMENT; else a->opcode = C_PREPROCESSOR; a->raw_string = malloc(t->len + 1); if (!a->raw_string) return NULL; strcpy(a->raw_string, t->name); skip_token(1); return a; } if (t->symbol == '#') { /* Preprocessor line and file change. */ if ((t= get_token(1))->type != T_WORD || !isanumber(t->name) || get_token(2)->type != T_STRING ) { parse_err(1, t, "file not preprocessed?\n"); zap(); } else { set_file(get_token(2)->name, strtol(get_token(1)->name, nil, 0) - 1); /* GNU CPP adds extra cruft, simply zap the line. */ zap(); } a= gnu_get_instruction(); } else if (t->type == T_WORD && get_token(1)->symbol == ':') { /* A label definition. */ a= new_asm86(); a->line= t->line; a->opcode= DOT_LABEL; a->optype= PSEUDO; a->args= e= new_expr(); e->operator= ':'; e->name= copystr(t->name); syms_add(t->name); skip_token(2); } else if (t->type == T_WORD && get_token(1)->symbol == '=') { int n= 2; if ((e= gnu_get_C_expression(&n)) == nil) { zap(); a= gnu_get_instruction(); } else if (get_token(n)->type != T_COMMENT && get_token(n)->symbol != ';') { parse_err(1, t, "garbage after assignment\n"); zap(); a= gnu_get_instruction(); } else { a= new_asm86(); if (get_token(n)->type == T_COMMENT) { token_t *c = get_token(n); a->raw_string = malloc(c->len + 1); if (!a->raw_string) return NULL; strcpy(a->raw_string, c->name); } a->line= t->line; a->opcode= DOT_EQU; a->optype= PSEUDO; a->args= new_expr(); a->args->operator= '='; a->args->name= copystr(t->name); syms_add(t->name); a->args->middle= e; skip_token(n+1); } } else if (t->type == T_WORD) { if ((a= gnu_get_statement()) == nil) { zap(); a= gnu_get_instruction(); } } else { parse_err(1, t, "syntax error\n"); zap(); a= gnu_get_instruction(); } return a; }
token_t primary(void) { expr_t *expr; entry_t *entry; token_t token; int ch, lineno, column; if (ahead) { token = ahead->token; push_expr(ahead); ahead = NULL; return (token); } ch = skipws(); lineno = parser.lineno; column = parser.column - 1; switch (ch) { case EOF: token = tok_eof; break; case '(': token = tok_oparen; break; case ')': token = tok_cparen; break; case '[': token = tok_obrack; break; case ']': token = tok_cbrack; break; case '{': token = tok_obrace; break; case '}': token = tok_cbrace; break; case ';': token = tok_semicollon; break; case ':': token = tok_collon; break; case ',': token = tok_comma; break; case '.': if ((ch = getch()) != '.') { ungetch(ch); token = tok_dot; } else if (getch() != '.') error(NULL, "error near '..'"); else token = tok_ellipsis; break; case '=': if ((ch = getch()) == '=') token = tok_eq; else { ungetch(ch); token = tok_set; } break; case '&': if ((ch = getch()) == '&') token = tok_andand; else if (ch == '=') token = tok_andset; else { ungetch(ch); token = tok_and; } break; case '|': if ((ch = getch()) == '|') token = tok_oror; else if (ch == '=') token = tok_orset; else { ungetch(ch); token = tok_or; } break; case '^': if ((ch = getch()) == '=') token = tok_xorset; else { ungetch(ch); token = tok_xor; } break; case '<': if ((ch = getch()) == '=') token = tok_le; else if (ch == '<') { if ((ch = getch()) == '=') token = tok_lshset; else { ungetch(ch); token = tok_lsh; } } else { ungetch(ch); token = tok_lt; } break; case '>': if ((ch = getch()) == '=') token = tok_ge; else if (ch == '>') { if ((ch = getch()) == '=') token = tok_rshset; else { ungetch(ch); token = tok_rsh; } } else { ungetch(ch); token = tok_gt; } break; case '+': if ((ch = getch()) == '+') token = tok_inc; else if (ch == '=') token = tok_addset; else { ungetch(ch); token = tok_add; } break; case '-': if ((ch = getch()) == '-') token = tok_dec; else if (ch == '=') token = tok_subset; else if (ch == '>') token = tok_arrow; else { ungetch(ch); token = tok_sub; } break; case '*': if ((ch = getch()) == '=') token = tok_mulset; else { ungetch(ch); token = tok_mul; } break; case '/': if ((ch = getch()) == '=') token = tok_divset; else { ungetch(ch); token = tok_div; } break; case '%': if ((ch = getch()) == '=') token = tok_remset; else { ungetch(ch); token = tok_rem; } break; case '!': if ((ch = getch()) == '=') token = tok_ne; else { ungetch(ch); token = tok_not; } break; case '~': token = tok_com; break; case '?': token = tok_question; break; case 'a' ... 'z': case 'A' ... 'Z': case '_': token = identifier(ch); break; case '0' ... '9': token = number(ch); break; case '"': token = string(); break; case '\'': token = character(); break; default: error(NULL, "syntax error"); } parser.token = token; expr = new_expr(token, lineno, column); if (token == tok_string) { if ((entry = get_hash(strings, parser.string)) == NULL) { entry = (entry_t *)xmalloc(sizeof(entry_t)); entry->name.string = xstrdup(parser.string); entry->value = entry->name.string; put_hash(strings, entry); } expr->data._unary.cp = entry->value; } else expr->data._unary = parser.value; push_expr(expr); return (token); }
static expression_t *ack_get_C_expression(int *pn) /* Read a "C-like" expression. Note that we don't worry about precedence, * the expression is printed later like it is read. If the target language * does not have all the operators (like ~) then this has to be repaired by * changing the source file. (No problem, you still have one source file * to maintain, not two.) */ { expression_t *e, *a1, *a2; token_t *t; if ((t= get_token(*pn))->symbol == '[') { /* [ expr ]: grouping. */ (*pn)++; if ((a1= ack_get_C_expression(pn)) == nil) return nil; if (get_token(*pn)->symbol != ']') { parse_err(1, t, "missing ]\n"); del_expr(a1); return nil; } (*pn)++; e= new_expr(); e->operator= '['; e->middle= a1; } else if (t->type == T_WORD || t->type == T_STRING) { /* Label, number, or string. */ e= new_expr(); e->operator= t->type == T_WORD ? 'W' : 'S'; e->name= allocate(nil, (t->len+1) * sizeof(e->name[0])); memcpy(e->name, t->name, t->len+1); e->len= t->len; (*pn)++; } else if (t->symbol == '+' || t->symbol == '-' || t->symbol == '~') { /* Unary operator. */ (*pn)++; if ((a1= ack_get_C_expression(pn)) == nil) return nil; e= new_expr(); e->operator= t->symbol; e->middle= a1; } else { parse_err(1, t, "expression syntax error\n"); return nil; } switch ((t= get_token(*pn))->symbol) { case '+': case '-': case '*': case '/': case '%': case '&': case '|': case '^': case S_LEFTSHIFT: case S_RIGHTSHIFT: (*pn)++; a1= e; if ((a2= ack_get_C_expression(pn)) == nil) { del_expr(a1); return nil; } e= new_expr(); e->operator= t->symbol; e->left= a1; e->right= a2; } return e; }
asm86_t *ack_get_instruction(void) { asm86_t *a= nil; expression_t *e; token_t *t; while ((t= get_token(0))->symbol == ';') skip_token(1); if (t->type == T_EOF) return nil; if (t->symbol == '#') { /* Preprocessor line and file change. */ if ((t= get_token(1))->type != T_WORD || !isanumber(t->name) || get_token(2)->type != T_STRING ) { parse_err(1, t, "file not preprocessed?\n"); zap(); } else { set_file(get_token(2)->name, strtol(get_token(1)->name, nil, 0) - 1); /* GNU CPP adds extra cruft, simply zap the line. */ zap(); } a= ack_get_instruction(); } else if (t->type == T_WORD && get_token(1)->symbol == ':') { /* A label definition. */ a= new_asm86(); a->line= t->line; a->opcode= DOT_LABEL; a->optype= PSEUDO; a->args= e= new_expr(); e->operator= ':'; e->name= copystr(t->name); skip_token(2); } else if (t->type == T_WORD && get_token(1)->symbol == '=') { int n= 2; if ((e= ack_get_C_expression(&n)) == nil) { zap(); a= ack_get_instruction(); } else if (get_token(n)->symbol != ';') { parse_err(1, t, "garbage after assignment\n"); zap(); a= ack_get_instruction(); } else { a= new_asm86(); a->line= t->line; a->opcode= DOT_EQU; a->optype= PSEUDO; a->args= new_expr(); a->args->operator= '='; a->args->name= copystr(t->name); a->args->middle= e; skip_token(n+1); } } else if (t->type == T_WORD) { if ((a= ack_get_statement()) == nil) { zap(); a= ack_get_instruction(); } } else { parse_err(1, t, "syntax error\n"); zap(); a= ack_get_instruction(); } return a; }
static expression_t *ack_get_operand(int *pn, int deref) /* Get something like: (memory), offset(base)(index*scale), or simpler. */ { expression_t *e, *offset, *base, *index; token_t *t; int c; /* Is it (memory)? */ if (get_token(*pn)->symbol == '(' && ((t= get_token(*pn + 1))->type != T_WORD || !isregister(t->name)) ) { /* A memory dereference. */ (*pn)++; if ((offset= ack_get_C_expression(pn)) == nil) return nil; if (get_token(*pn)->symbol != ')') { parse_err(1, t, "operand syntax error\n"); del_expr(offset); return nil; } (*pn)++; e= new_expr(); e->operator= '('; e->middle= offset; return e; } /* #constant? */ if (dialect == NCC && deref && ((c= get_token(*pn)->symbol) == '#' || c == '*')) { /* NCC: mov ax,#constant -> ACK: mov ax,constant */ (*pn)++; return ack_get_C_expression(pn); } /* @address? */ if (dialect == NCC && get_token(*pn)->symbol == '@') { /* NCC: jmp @address -> ACK: jmp (address) */ (*pn)++; if ((offset= ack_get_operand(pn, deref)) == nil) return nil; e= new_expr(); e->operator= '('; e->middle= offset; return e; } /* Offset? */ if (get_token(*pn)->symbol != '(') { /* There is an offset. */ if ((offset= ack_get_C_expression(pn)) == nil) return nil; } else { /* No offset. */ offset= nil; } /* (base)? */ if (get_token(*pn)->symbol == '(' && (t= get_token(*pn + 1))->type == T_WORD && isregister(t->name) && get_token(*pn + 2)->symbol == ')' ) { /* A base register expression. */ base= new_expr(); base->operator= 'B'; base->name= copystr(t->name); (*pn)+= 3; } else { /* No base register expression. */ base= nil; } /* (index*scale)? */ if (get_token(*pn)->symbol == '(') { /* An index most likely. */ token_t *m= nil; if (!( /* This must be true: */ (t= get_token(*pn + 1))->type == T_WORD && isregister(t->name) && (get_token(*pn + 2)->symbol == ')' || ( get_token(*pn + 2)->symbol == '*' && (m= get_token(*pn + 3))->type == T_WORD && strchr("1248", m->name[0]) != nil && m->name[1] == 0 && get_token(*pn + 4)->symbol == ')' )) )) { /* Alas it isn't */ parse_err(1, t, "operand syntax error\n"); del_expr(offset); del_expr(base); return nil; } /* Found an index. */ index= new_expr(); index->operator= m == nil ? '1' : m->name[0]; index->name= copystr(t->name); (*pn)+= (m == nil ? 3 : 5); } else { /* No index. */ index= nil; } if (dialect == NCC && deref && base == nil && index == nil && !(offset != nil && offset->operator == 'W' && isregister(offset->name)) ) { /* NCC: mov ax,thing -> ACK mov ax,(thing) */ e= new_expr(); e->operator= '('; e->middle= offset; return e; } if (base == nil && index == nil) { /* Return a lone offset as is. */ e= offset; } else { e= new_expr(); e->operator= 'O'; e->left= offset; e->middle= base; e->right= index; } return e; }
static te_expr *base(state *s) { /* <base> = <constant> | <variable> | <function-0> {"(" ")"} | <function-1> <power> | <function-X> "(" <expr> {"," <expr>} ")" | "(" <list> ")" */ te_expr *ret; int arity; switch (TYPE_MASK(s->type)) { case TOK_NUMBER: ret = new_expr(TE_CONSTANT, 0); ret->value = s->value; next_token(s); break; case TOK_VARIABLE: ret = new_expr(TE_VARIABLE, 0); ret->bound = s->bound; next_token(s); break; case TE_FUNCTION0: case TE_CLOSURE0: ret = new_expr(s->type, 0); ret->function = s->function; if (IS_CLOSURE(s->type)) ret->parameters[0] = s->context; next_token(s); if (s->type == TOK_OPEN) { next_token(s); if (s->type != TOK_CLOSE) { s->type = TOK_ERROR; } else { next_token(s); } } break; case TE_FUNCTION1: case TE_CLOSURE1: ret = new_expr(s->type, 0); ret->function = s->function; if (IS_CLOSURE(s->type)) ret->parameters[1] = s->context; next_token(s); ret->parameters[0] = power(s); break; case TE_FUNCTION2: case TE_FUNCTION3: case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: case TE_CLOSURE2: case TE_CLOSURE3: case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: arity = ARITY(s->type); ret = new_expr(s->type, 0); ret->function = s->function; if (IS_CLOSURE(s->type)) ret->parameters[arity] = s->context; next_token(s); if (s->type != TOK_OPEN) { s->type = TOK_ERROR; } else { int i; for(i = 0; i < arity; i++) { next_token(s); ret->parameters[i] = expr(s); if(s->type != TOK_SEP) { break; } } if(s->type != TOK_CLOSE || i != arity - 1) { s->type = TOK_ERROR; } else { next_token(s); } } break; case TOK_OPEN: next_token(s); ret = list(s); if (s->type != TOK_CLOSE) { s->type = TOK_ERROR; } else { next_token(s); } break; default: ret = new_expr(0, 0); s->type = TOK_ERROR; ret->value = NAN; break; } return ret; }
static expression_t *gnu_get_operand(asm86_t * a, int *pn, int deref) /* Get something like: $immed, memory, offset(%base,%index,scale), or simpler. */ { expression_t *e, *offset, *base, *index; token_t *t; int c; if (get_token(*pn)->symbol == '$') { /* An immediate value. */ (*pn)++; return gnu_get_C_expression(pn); } if (get_token(*pn)->symbol == '*') { (*pn)++; deref = 1; #if 0 if ((offset= gnu_get_operand(a, pn, deref)) == nil) return nil; #if 0 e= new_expr(); e->operator= '('; e->middle= offset; return e; #endif return offset; #endif } if ((get_token(*pn)->symbol == '%') && (t= get_token(*pn + 1))->type == T_WORD && isregister(t->name) ) { /* A register operand. */ (*pn)+= 2; e= new_expr(); e->operator= 'W'; e->name= copystr(t->name); return e; } /* Offset? */ if (get_token(*pn)->symbol != '(' || get_token(*pn + 1)->symbol != '%') { /* There is an offset. */ if ((offset= gnu_get_C_expression(pn)) == nil) return nil; } else { /* No offset. */ offset= nil; } /* (%base,%index,scale) ? */ base= index= nil; if (get_token(*pn)->symbol == '(') { (*pn)++; /* %base ? */ if (get_token(*pn)->symbol == '%' && (t= get_token(*pn + 1))->type == T_WORD && isregister(t->name) ) { /* A base register expression. */ base= new_expr(); base->operator= 'B'; base->name= copystr(t->name); (*pn)+= 2; } if (get_token(*pn)->symbol == ',') (*pn)++; /* %index ? */ if (get_token(*pn)->symbol == '%' && (t= get_token(*pn + 1))->type == T_WORD && isregister(t->name) ) { /* A index register expression. */ index= new_expr(); index->operator= '1'; /* for now */ index->name= copystr(t->name); (*pn)+= 2; } if (get_token(*pn)->symbol == ',') (*pn)++; /* scale ? */ if ((base != nil || index != nil) && (t= get_token(*pn))->type == T_WORD && strchr("1248", t->name[0]) != nil && t->name[1] == 0 ) { if (index == nil) { /* Base is really an index register. */ index= base; base= nil; } index->operator= t->name[0]; (*pn)++; } if (get_token(*pn)->symbol == ')') { /* Ending paren. */ (*pn)++; } else { /* Alas. */ parse_err(1, t, "operand syntax error\n"); del_expr(offset); del_expr(base); del_expr(index); return nil; } } if (base == nil && index == nil) { if (deref) { /* Return a lone offset as (offset). */ e= new_expr(); e->operator= '('; e->middle= offset; } else { /* Return a lone offset as is. */ e= offset; } } else { e= new_expr(); e->operator= 'O'; e->left= offset; e->middle= base; e->right= index; } return e; }