#ident "$Header: /proj/irix6.5.7m/isms/irix/cmd/icrash_old/lib/libeval/RCS/eval.c,v 1.1 1999/05/25 19:19:20 tjm Exp $" #define _KERNEL 1 #include #include #include #include #include #include #include #include #include #include #include "icrash.h" #include "extern.h" #include "eval.h" #include "variable.h" #include "dwarflib.h" /* Global variables */ static int logical_flag; /* The base_type[] array is necessary because base types are not * directly accessible from the Dwarf database. Three of the entries * have to be modified at startup if the vmcore image is from a * 32-bit system. They are the entries for "long", "signed long", * and "unsigned long". On a 32-bit core dump, these types take up * four bytes. On a 64-bit system, they take up eight bytes. */ base_t base_type[] = { /*---------------------------------------------------------*/ /* NAME ACTUAL_NAME BYTE_SIZE ENCODING */ /*---------------------------------------------------------*/ { "char", (char *)0, 1, 6 }, { "signed char", "char", 1, 6 }, { "unsigned char", (char *)0, 1, 8 }, { "short", (char *)0, 2, 5 }, { "signed short", "short", 2, 5 }, { "unsigned short", (char *)0, 2, 7 }, { "int", (char *)0, 4, 5 }, { "signed int", "int", 4, 5 }, { "signed", "int", 4, 5 }, { "unsigned int", (char *)0, 4, 7 }, { "unsigned", "unsigned int", 4, 7 }, { "long", (char *)0, 8, 5 }, { "signed long", "long", 8, 5 }, { "unsigned long", (char *)0, 8, 7 }, { "long long", (char *)0, 8, 5 }, { "signed long long", "long long", 8, 5 }, { "unsigned long long", (char *)0, 8, 7 }, { (char *)0, (char *)0, 0, 0 } }; /* * get_base_type() */ base_t * get_base_type(char *s) { int i, count, blank_count = 0, len, gap = 0; char *ptr, *first, *last, *gapp = 0, *cp, typename[128] = ""; strcat (typename, s); ptr = typename; len = strlen(typename); /* Strip off any leading "white space" (spaces and tabs) */ while ((*ptr == ' ') || (*ptr == '\t')) { blank_count++; ptr++; } len -= blank_count; bcopy (ptr, typename, len); typename[len] = 0; /* Compress any "white space" between words. */ ptr = typename; blank_count = 0; while (*ptr && (*ptr != '*')) { if ((*ptr == ' ') || (*ptr == '\t')) { cp = ptr + 1; blank_count = 0; while ((*cp == ' ') || (*cp == '\t')) { blank_count++; cp++; } if ((cp - ptr) > 1) { bcopy(cp, ptr + 1, len - (cp - typename)); len -= blank_count; } } ptr++; } *ptr = 0; for (i = 0; base_type[i].name; i++) { if (!strcmp(typename, base_type[i].name)) { break; } } if (base_type[i].name) { return(&base_type[i]); } else { return((base_t*)NULL); } } /* * base_typestr() */ char * base_typestr(type_t *tp, int flags) { int i, len = 0, ptrcnt = 0; type_t *t; base_t *btp; char *tsp, *c; t = tp; while (t->flag == POINTER_FLAG) { ptrcnt++; t = t->t_next; } btp = (base_t *)t->t_ptr; if (btp->actual_name) { len = strlen(btp->actual_name) + ptrcnt + 3; } else { len = strlen(btp->name) + ptrcnt + 3; } tsp = (char *)ALLOC_BLOCK(len, flags); c = tsp; *c++ = '('; if (btp->actual_name) { strcat(c, btp->actual_name); c += strlen(btp->actual_name); } else { strcat(c, btp->name); c += strlen(btp->name); } for (i = 0; i < ptrcnt; i++) { *c++ = '*'; } *c++ = ')'; *c = 0; return(tsp); } /* * get_type() -- Convert a typecast string into a type. * * Returns a pointer to a struct containing type information (dwarf, * base, etc.) The type of struct returned is indicated by the * contents of type. If the typecast contains an asterisk, set * ptr_type equal to one, otherwise set it equal to zero. */ type_t * get_type(char *s, int flags) { static int symtable_type = -1; int len, type = 0; char *cp, typename[128]; base_t *bp; type_t *t, *head, *last; dw_type_t *dtp; dw_type_info_t *dti; head = last = (type_t *)NULL; if (symtable_type < 0) { symtable_type = DWARF_TYPE_FLAG; } if (!strncmp(s, "struct", 6)) { if (cp = strpbrk(s + 7, " \t*")) { len = cp - (s + 7); } else { len = strlen(s + 7); } bcopy (s + 7, typename, len); typename[len] = 0; if (symtable_type == DWARF_TYPE_FLAG) { if (!(dtp = dw_lkup(stp, typename, DW_TAG_structure_type))) { return ((type_t *)NULL); } type = DWARF_TYPE_FLAG; } } else if (!strncmp(s, "union", 5)) { if (cp = strpbrk(s + 6, " \t*")) { len = cp - (s + 6); } else { len = strlen(s + 6); } bcopy (s + 6, typename, len); typename[len] = 0; if (symtable_type == DWARF_TYPE_FLAG) { if (!(dtp = dw_lkup(stp, typename, DW_TAG_union_type))) { return ((type_t *)NULL); } type = DWARF_TYPE_FLAG; } } else if (bp = get_base_type(s)) { type = BASE_TYPE_FLAG; } else { /* Check to see if this is a typedef */ if (cp = strpbrk(s, " \t*)")) { len = cp - s; } else { len = strlen(s); } bcopy (s, typename, len); typename[len] = 0; if (symtable_type == DWARF_TYPE_FLAG) { if (!(dtp = dw_lkup(stp, typename, DW_TAG_typedef))) { return ((type_t *)NULL); } type = DWARF_TYPE_FLAG; } } /* check to see if this cast is a pointer to a type (or a pointer * to a pointer to a type, etc.) */ cp = s; while (cp = strpbrk(cp, "*")) { t = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); t->flag = POINTER_FLAG; if (last) { last->t_next = t; last = t; } else { head = last = t; } cp++; } /* Allocate a type block that will point to the type specific * (BASE or DWARF) record */ t = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); t->flag = type; switch (t->flag) { case BASE_TYPE_FLAG : t->t_ptr = (void *)bp; break; case DWARF_TYPE_FLAG : dti = (dw_type_info_t *)ALLOC_BLOCK(sizeof(*dti), flags); if (!dw_type_info(dtp->dt_off, dti, flags)) { return((type_t*)NULL); } t->t_ptr = (void *)dti; break; default : free_type(head); return((type_t*)NULL); } if (last) { last->t_next = t; } else { head = t; } return(head); } /* * free_type() */ void free_type(type_t *head) { type_t *t0, *t1; t0 = head; while(t0) { if (t0->flag == POINTER_FLAG) { t1 = t0->t_next; free_block((k_ptr_t)t0); t0 = t1; } else { if (is_temp_block(t0->t_ptr)) { if (t0->flag == DWARF_TYPE_FLAG) { dw_free_type_info((dw_type_info_t*)t0->t_ptr); } else { free_block((k_ptr_t)t0->t_ptr); } } free_block((k_ptr_t)t0); t0 = (type_t *)NULL; } } } /* * member_to_type() -- Converts a struct/union member to a type * * With dwarf members, all DW_TAG_pointer dies are converted to * type_t structs with POINTER_FLAG set. The original dw_type_info_t * struct pointer is linked to the t_link field -- since it contains * information necessary for the dowhatis() command. */ type_t * member_to_type(void *x, int ntype, int flags) { dw_die_t *dp; dw_type_info_t *t, *dti; type_t *tp, *head = (type_t *)NULL, *last = (type_t *)NULL; if (ntype == DWARF_TYPE_FLAG) { t = (dw_type_info_t *)x; /* Make sure this is a DW_TAG_member */ if (t->t_tag != DW_TAG_member) { return((type_t *)NULL); } dp = t->t_actual_type; while (dp && dp->d_tag == DW_TAG_pointer_type) { tp = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); tp->flag = POINTER_FLAG; if (last) { last->t_next = tp; last = tp; } else { head = last = tp; } dp = dp->d_next; } /* If We step past all the pointer dies and don't point at anything, * this must be a void pointer. Setup a VOID type struct so that we * can maintain a pointer to the type info in dw_type_info_t struct. */ if (!dp) { tp = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); tp->flag = VOID_FLAG; tp->t_ptr = t; if (last) { last->t_next = tp; last = tp; } else { head = last = tp; } return(head); } dti = (dw_type_info_t *)ALLOC_BLOCK(sizeof(*dti), flags); switch (dp->d_tag) { case DW_TAG_structure_type : /* Check to see if this die points to the struct * members. If not, we need to search for the actual * struct definition. */ if (!dp->d_sibling_off) { dw_type_t *dtp; if (!(dtp = dw_lkup(stp, dp->d_name, DW_TAG_structure_type))) { /* Information is not available for this * struct. Make the actual type be dp. It's * better to have something rather than * nothing. */ t->t_actual_type = t->t_type; tp = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); tp->flag = DWARF_TYPE_FLAG; tp->t_ptr = (void *)t; if (last) { last->t_next = tp; } else { head = tp; } return(head); } if (!dw_type_info(dtp->dt_off, dti, flags)) { return((type_t *)NULL); } } else { if (!dw_type_info(dp->d_off, dti, flags)) { return((type_t *)NULL); } } break; case DW_TAG_union_type : /* Check to see if this die points to the union * members. If not, we need to search for the actual * union definition. */ if (!dp->d_sibling_off) { dw_type_t *dtp; if (!(dtp = dw_lkup(stp, dp->d_name, DW_TAG_union_type))) { /* Information is not available for this * union. Make the actual type be dp. It's * better to have something rather than * nothing. */ t->t_actual_type = t->t_type; tp = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); tp->flag = DWARF_TYPE_FLAG; tp->t_ptr = (void *)t; if (last) { last->t_next = tp; } else { head = tp; } return(head); } if (!dw_type_info(dtp->dt_off, dti, flags)) { return((type_t *)NULL); } } else { if (!dw_type_info(dp->d_off, dti, flags)) { return((type_t *)NULL); } } break; default : if (!dw_type_info(dp->d_off, dti, flags)) { return((type_t *)NULL); } break; } /* Check to see if the real type is a DW_TAG_base_type. If it is, * then check to see if t_bit_offset and/or t_bit_size are set in * the original dw_type_info_s struct. If they are, copy the values * over to dti. */ if (dti->t_tag == DW_TAG_base_type) { if (t->t_bit_offset) { dti->t_bit_offset = t->t_bit_offset; } if (t->t_bit_size) { dti->t_bit_size = t->t_bit_size; } dti->t_byte_size = t->t_byte_size; } /* Save the pointer to the info about the actual member (for * use by dowhatis() ) */ dti->t_link = t; tp = (type_t *)ALLOC_BLOCK(sizeof(type_t), flags); tp->flag = DWARF_TYPE_FLAG; tp->t_ptr = (void *)dti; if (last) { last->t_next = tp; } else { head = tp; } return(head); } return((type_t *)NULL); } /* * is_keyword() */ int is_keyword(char *c, int len) { /* This is temporary. Really need to lookup string to see if * it is a type or typedef. */ if (!strncmp(c, "struct", len)) { return(1); } else if (!strncmp(c, "union", len)) { return(1); } else if (!strncmp(c, "char", len)) { return(1); } else if (!strncmp(c, "short", len)) { return(1); } else if (!strncmp(c, "int", len)) { return(1); } else if (!strncmp(c, "long", len)) { return(1); } else if (!strncmp(c, "unsigned", len)) { return(1); } else if (!strncmp(c, "signed", len)) { return(1); } else { char *c1; c1 = (char*)alloc_block(len+1, B_TEMP); strncat(c1, c, len); c1[len] = 0; switch (symbol_table) { case DWARF_TYPE_FLAG: if (dw_lkup(stp, c1, DW_TAG_typedef)) { free_block((k_ptr_t)c1); return(1); } break; } free_block((k_ptr_t)c1); } return(0); } /* * expand_variables() */ char * expand_variables(char *exp, int flags) { int len; char vname[64], *s, *e, *v, *newexp; variable_t *vp; newexp = (char *)ALLOC_BLOCK(256, flags); e = exp; v = strchr(e, '$'); while (v) { vname[0] = 0; strncat(newexp, e, (v - e)); if (s = strpbrk((v + 1), " .\t+-*/()[]|~!$&%^<>?:&=^\"\'")) { len = (uint)s - (uint)v + 1; } else { len = strlen(v) + 1; } strncpy(vname, v, len); vname[len -1] = 0; vp = find_variable(vtab, vname, V_TYPEDEF|V_STRING); if (!vp) { return((char *)NULL); } /* If this is a typedef, then make sure the typestr is between * an open and close parenthesis. Otherwise, just include the * string. */ if (vp->v_flags & V_TYPEDEF) { strcat(newexp, "("); strcat(newexp, vp->v_typestr); strcat(newexp, ")"); } else { strcat(newexp, vp->v_exp); } if (e = s) { v = strchr(e, '$');; } else { v = (char *)NULL; } } if (e) { strcat(newexp, e); } return(newexp); } /* * get_token_list() */ token_t * get_token_list(char *str, int *error) { int i, paren_count = 0; char *cp; token_t *tok, *tok_head = (token_t*)NULL, *tok_last = (token_t*)NULL; cp = str; *error = 0; while (*cp) { /* Skip past any "white space" (spaces and tabs). */ switch (*cp) { case ' ' : case '\t' : case '`' : cp++; continue; case '\'' : break; case '\"' : break; default : break; } /* Allocate space for the next token */ tok = (token_t *)alloc_block(sizeof(token_t), B_TEMP); tok->ptr = cp; switch(*cp) { /* Check for operators */ case '+' : if (*((char*)cp + 1) == '+') { /* We aren't doing asignment here, so the ++ operator * is not considered valid. */ *error = E_BAD_OPERATOR; return (tok_last); } else if (!tok_last || (tok_last->operator && (tok_last->operator != CLOSE_PAREN))) { tok->operator = UNARY_PLUS; } else { tok->operator = ADD; } break; case '-' : if (*((char*)cp + 1) == '-') { /* We aren't doing asignment here, so the -- operator * is not considered valid. */ *error = E_BAD_OPERATOR; return (tok_last); } else if (*((char*)cp + 1) == '>') { tok->operator = RIGHT_ARROW; cp++; } else if (!tok_last || (tok_last->operator && (tok_last->operator != CLOSE_PAREN))) { tok->operator = UNARY_MINUS; } else { tok->operator = SUBTRACT; } break; case '.' : /* XXX - need to check to see if this is a decimal point * in the middle fo a floating point value. */ tok->operator = DOT; break; case '*' : /* XXX - need a better way to tell if this is an INDIRECTION. * perhaps check the next token? */ if (!tok_last || (tok_last->operator && ((tok_last->operator != CLOSE_PAREN) && (tok_last->operator != CAST)))) { tok->operator = INDIRECTION; } else { tok->operator = MULTIPLY; } break; case '/' : tok->operator = DIVIDE; break; case '%' : tok->operator = MODULUS; break; case '(' : { char *s; int len; /* Make sure the previous token is an operator */ if (tok_last && !tok_last->operator) { *error = E_SYNTAX_ERROR; return (tok_last); } if (tok_last && ((tok_last->operator == RIGHT_ARROW) || (tok_last->operator == DOT))) { *error = E_SYNTAX_ERROR; return (tok_last); } /* Check here to see if following tokens constitute a cast. */ /* Skip past any "white space" (spaces and tabs) */ while ((*(cp+1) == ' ') || (*(cp+1) == '\t')) { cp++; } if ((*(cp+1) == '(') || (*(cp+1) == '*') || (*(cp+1) == ')')){ tok->operator = OPEN_PAREN; paren_count++; break; } if (s = strpbrk(cp+1, " *)")) { len = (uint)s - (uint)(cp+1); if (is_keyword((char*)((uint)(cp+1)), len)) { if (!(s = strpbrk((cp+1), ")"))) { *error = E_OPEN_PAREN; return (tok); } len = (uint)s - (uint)(cp+1); tok->string = (char *)alloc_block(len + 1, B_TEMP); bcopy((cp+1), tok->string, len); tok->string[len] = 0; tok->operator = CAST; cp = (char *)((uint)(cp+1) + len); break; } } tok->operator = OPEN_PAREN; paren_count++; break; } case ')' : if (tok_last && ((tok_last->operator == RIGHT_ARROW) || (tok_last->operator == DOT))) { *error = E_SYNTAX_ERROR; return (tok_last); } tok->operator = CLOSE_PAREN; paren_count--; break; case '&' : if (*((char*)cp + 1) == '&') { tok->operator = LOGICAL_AND; cp++; } else if (!tok_last || (tok_last && (tok_last->operator && tok_last->operator != CLOSE_PAREN))) { tok->operator = ADDRESS; } else { tok->operator = BITWISE_AND; } break; case '|' : if (*((char*)cp + 1) == '|') { tok->operator = LOGICAL_OR; cp++; } else { tok->operator = BITWISE_OR; } break; case '=' : if (*((char*)cp + 1) == '=') { tok->operator = EQUAL; cp++; } else { /* ASIGNMENT -- NOT IMPLEMENTED */ tok->operator = NOT_YET; } break; case '<' : if (*((char*)cp + 1) == '<') { tok->operator = LEFT_SHIFT; cp++; } else if (*((char*)cp + 1) == '=') { tok->operator = LESS_THAN_OR_EQUAL; cp++; } else { tok->operator = LESS_THAN; } break; case '>' : if (*((char*)(cp + 1)) == '>') { tok->operator = RIGHT_SHIFT; cp++; } else if (*((char*)cp + 1) == '=') { tok->operator = GREATER_THAN_OR_EQUAL; cp++; } else { tok->operator = GREATER_THAN; } break; case '!' : if (*((char*)cp + 1) == '=') { tok->operator = NOT_EQUAL; cp++; } else { tok->operator = LOGICAL_NEGATION; } break; case '$' : { int e, len; char *s, *vname; variable_t *vp; token_t *t; if (s = strpbrk((cp + 1), " .\t+-*/()[]|~!$&%^<>?:&=^\"\'")) { len = (uint)s - (uint)cp + 1; } else { len = strlen(cp) + 1; } vname = (char *)alloc_block(len, B_TEMP); memcpy(vname, cp, (len -1)); vname[len - 1] = 0; vp = find_variable(vtab, vname, 0); if (!vp || (vp->v_flags & V_COMMAND)) { *error = E_BAD_EVAR; free_block((k_ptr_t)vname); return(tok); } if (vp->v_flags & V_TYPEDEF) { free_block((k_ptr_t)vname); free_tokens(tok); t = get_token_list(vp->v_typestr, &e); if (!tok_head) { tok_head = tok_last = t; } else { tok_last->next = t; while (t->next) { t = t->next; } tok_last = t; } if (cp = s) { continue; } else { return(tok_head); } } else if (vp->v_flags & V_STRING) { if (tok_head) { *error = E_END_EXPECTED; return(tok); } /* Skip ahead to the first non-blank character */ while (s && (*s == ' ')) { s++; } if (s && (*s != 0)) { *error = E_END_EXPECTED; tok->ptr = s; return(tok); } tok->string = (char *)alloc_block(strlen(vp->v_exp) + 1, B_TEMP); /* We have to copy the string so that it doesn't * get freed when the token is freed. */ strcpy(tok->string, vp->v_exp); tok->type = TEXT; return(tok); } } case '~' : tok->operator = ONES_COMPLEMENT; break; case '^' : tok->operator = BITWISE_EXCLUSIVE_OR; break; case '?' : tok->operator = CONDITIONAL; break; case ':' : tok->operator = CONDITIONAL_ELSE; break; case '[' : tok->operator = OPEN_SQUARE_BRACKET;; break; case ']' : tok->operator = CLOSE_SQUARE_BRACKET;; break; default: { char *s; int len; /* Check and see if this token is a STRING or CHARACTER * type (begins with a single or double quote). */ if ((*cp == '\'') || (*cp == '\"')) { /* Make sure we don't already have any tokens. */ if (tok_head) { *error = E_END_EXPECTED; return(tok); } switch (*cp) { case '\'' : s = strpbrk((cp + 1), "\'"); if (!s) { *error = E_BAD_STRING; return(tok); } len = (uint)s - (uint)cp; if (len == 2) { tok->type = CHARACTER; } else { tok->type = TEXT; } break; case '\"' : s = strpbrk((cp + 1), "\""); if (!s) { *error = E_BAD_STRING; return(tok); } len = (uint)s - (uint)cp; tok->type = TEXT; break; } if (strlen(cp) > (len + 1)) { /* Check to see if there is a colon or * semi-colon directly following the * string. If there is, then the string * is OK (the following characters are part * of the next expression). Also, it's OK * to have trailing blanks as long as that's * all threre is. */ char *c; c = s + 1; while (*c) { if ((*c == ',') || (*c == ';')) { break; } else if (*c != ' ') { *error = E_END_EXPECTED; tok->ptr = c; return(tok); } c++; } /* Truncate the trailing blanks (they are not part * of the string). */ if (c != (s + 1)) { *(s + 1) = 0; } } tok->string = (char *)alloc_block(len, B_TEMP); bcopy((cp + 1), tok->string, len - 1); tok->string[len - 1] = 0; return(tok); } if (s = strpbrk(cp, " .\t+-*/()[]|~!$&%^<>?:&=^\"\'")) { len = (uint)s - (uint)cp + 1; } else { len = strlen(cp) + 1; } tok->string = (char *)alloc_block(len, B_TEMP); bcopy(cp, tok->string, len - 1); tok->string[len - 1] = 0; cp = (char *)((uint)cp + len - 2); /* Check to see if this is the keyword "sizeof." If not, * then check to see if the string is a member name. */ if (!strcmp(tok->string, "sizeof")) { tok->operator = SIZEOF; free_block((k_ptr_t)tok->string); tok->string = 0; } else if (tok_last && ((tok_last->operator == RIGHT_ARROW) || (tok_last->operator == DOT))) { tok->type = MEMBER; } else { tok->type = STRING; } break; } } if (!(tok->type)) { tok->type = OPERATOR; } if (!tok_head) { tok_head = tok_last = tok; } else { tok_last->next = tok; tok_last = tok; } cp++; } if (paren_count < 0) { *error = E_CLOSE_PAREN; return(tok); } else if (paren_count > 0) { *error = E_OPEN_PAREN; return(tok); } if (DEBUG(DC_EVAL, 1)) { token_t *t; fprintf(KL_ERRORFP, " TOKEN OPERATOR PTR " "STRING NEXT\n"); fprintf(KL_ERRORFP, "--------------------------------------------------" "----------------\n"); t = tok_head; while(t) { fprintf(KL_ERRORFP, "%8x %8d %8x %26s %8x\n", t, t->operator, t->ptr, t->string, t->next); t = t->next; } fprintf(KL_ERRORFP, "--------------------------------------------------" "----------------\n"); } return(tok_head); } /* * is_unary() */ int is_unary(int op) { switch (op) { case LOGICAL_NEGATION : case ADDRESS : case INDIRECTION : case UNARY_MINUS : case UNARY_PLUS : case ONES_COMPLEMENT : case CAST : return(1); default : return(0); } } /* * is_binary() */ int is_binary(int op) { switch (op) { case BITWISE_OR : case BITWISE_EXCLUSIVE_OR : case BITWISE_AND : case RIGHT_SHIFT : case LEFT_SHIFT : case ADD : case SUBTRACT : case MULTIPLY : case DIVIDE : case MODULUS : case LOGICAL_OR : case LOGICAL_AND : case EQUAL : case NOT_EQUAL : case LESS_THAN : case GREATER_THAN : case LESS_THAN_OR_EQUAL : case GREATER_THAN_OR_EQUAL : case RIGHT_ARROW : case DOT : return(1); default : return(0); } } /* * precedence() */ int precedence(int a) { if ((a >= CONDITIONAL) && (a <= CONDITIONAL_ELSE)) { return(1); } else if (a == LOGICAL_OR) { return(2); } else if (a == LOGICAL_AND) { return(3); } else if (a == BITWISE_OR) { return(4); } else if (a == BITWISE_EXCLUSIVE_OR) { return(5); } else if (a == BITWISE_AND) { return(6); } else if ((a >= EQUAL) && (a <= NOT_EQUAL)) { return(7); } else if ((a >= LESS_THAN) && (a <= GREATER_THAN_OR_EQUAL)) { return(8); } else if ((a >= RIGHT_SHIFT) && (a <= LEFT_SHIFT)) { return(9); } else if ((a >= ADD) && (a <= SUBTRACT)) { return(10); } else if ((a >= MULTIPLY) && (a <= MODULUS)) { return(11); } else if ((a >= LOGICAL_NEGATION) && (a <= SIZEOF)) { return(12); } else if ((a >= RIGHT_ARROW) && (a <= DOT)) { return(13); } else { return(0); } } /* * make_node() */ node_t * make_node(token_t *t, int flags) { node_t *np; struct syment *sp; symdef_t *sdp; np = (node_t*)ALLOC_BLOCK(sizeof(*np), flags); if (t->type == OPERATOR) { /* Check to see if this token represents a typecast */ if (t->operator == CAST) { type_t *tp; if (!(np->type = get_type(t->string, flags))) { free_nodes(np); return((node_t*)NULL); } np->node_type = OPERATOR; np->operator = CAST; /* Determin whether or not this is a pointer to a type * and the type class (base or dwarf). */ tp = np->type; if (tp->flag == POINTER_FLAG) { np->flags = POINTER_FLAG; tp = tp->t_next; while (tp->flag == POINTER_FLAG) { tp = tp->t_next; } } switch(tp->flag) { case BASE_TYPE_FLAG: np->flags |= BASE_TYPE_FLAG; break; case DWARF_TYPE_FLAG: np->flags |= DWARF_TYPE_FLAG; break; default: free_nodes(np); return((node_t*)NULL); } } else { np->node_type = OPERATOR; np->operator = t->operator; } } else if (t->type == MEMBER) { np->name = (char *)dup_block((k_ptr_t)t->string, B_TEMP); np->node_type = MEMBER; } else if (t->type == STRING) { if ((sp = get_sym(t->string, B_TEMP)) && !(flags & C_NOVARS)) { np->address = sp->n_value; np->flags |= ADDRESS_FLAG; np->name = t->string; t->string = (char*)NULL; np->node_type = VARIABLE; /* Need to make a call to sym_lkup() to see if there * is type information available for this variable. * * XXX - The symdef_s struct actually overlays dw_type_s * struct. In that struct is the die offset of the variable. * If type information is available for this variable, then * we need to follow this path (check the variable die, then * the type, etc.) Not sure if there are any functions that * will do this right now (get_type() takes a type name -- * something that we don't have yet). */ sdp = sym_lkup(stp, np->name); free_sym(sp); /* XXX - For now, addtach a type struct for type long (it will * be the size of a kernel pointer). That will at least let us * do something and will prevent the scenario where we have a * type node with out a pointer to a type struct! This needs * to be replaced with code to handle actual variable types. */ np->type = alloc_block(sizeof(type_t), flags); np->type->flag = POINTER_FLAG; np->type->t_ptr = get_type("long", flags); np->node_type = TYPE_DEF; np->flags |= POINTER_FLAG; kl_get_block(K, np->address, K_NBPW(K), &np->value, "pointer value"); if (!PTRSZ64(K)) { np->value >>= 32; } } else if (flags & (C_WHATIS|C_SIZEOF)) { switch (symbol_table) { case DWARF_TYPE_FLAG : { dw_type_t *dtp; /* Check and see if this is a struct name */ dtp = dw_lkup(stp, t->string, DW_TAG_structure_type); if (!dtp) { /* Check to see if this is a union name */ dtp = dw_lkup(stp, t->string, DW_TAG_union_type); } if (!dtp) { /* Check to see if this is a typedef name */ dtp = dw_lkup(stp, t->string, DW_TAG_typedef); } if (dtp) { /* If struct, union or typedef */ dw_type_info_t *dti; dti = (dw_type_info_t*)ALLOC_BLOCK(sizeof(*dti), flags); dw_type_info(dtp->dt_off, dti, flags); np->node_type = TYPE_DEF; np->flags = DWARF_TYPE_FLAG; np->type = (type_t*)alloc_block(sizeof(type_t), B_TEMP); np->type->flag = DWARF_TYPE_FLAG; np->type->t_ptr = dti; } else if (sp) { np->address = sp->n_value; np->flags |= ADDRESS_FLAG; np->name = t->string; t->string = (char*)NULL; np->node_type = VARIABLE; free_sym(sp); } else { if (GET_VALUE(t->string, &np->value)) { free_nodes(np); return((node_t*)NULL); } np->node_type = NUMBER; } return(np); } } } else { if (GET_VALUE(t->string, &np->value)) { free_nodes(np); return((node_t*)NULL); } np->node_type = NUMBER; } } else if ((t->type == TEXT) || (t->type == CHARACTER)) { np->node_type = t->type; np->name = t->string; t->string = (char*)NULL; /* So the block doesn't get freed twice */ } else { /* ERROR! */ } np->tok_ptr = t->ptr; return(np); } /* * get_node() */ node_t * get_node(token_t **tpp, int flags) { node_t *n; n = make_node(*tpp, flags); *tpp = (*tpp)->next; return(n); } /* * add_node() */ int add_node(node_t *root, node_t *new_node) { node_t *n = root; /* Find the most lower-right node */ while (n->right) { n = n->right; } /* If the node we found is a leaf node, return an error (we will * have to insert the node instead). */ if (n->node_type == NUMBER) { return(-1); } else { n->right = new_node; } return(0); } /* * add_rchild() */ int add_rchild(node_t *root, node_t *new_node) { if (add_node(root, new_node) == -1) { return(-1); } return(0); } /* * add_lchild() */ int add_lchild(node_t *root, node_t *new_node) { node_t *n = root; /* Find the most lower-left node and make sure it is not a leaf * (child) node. */ while (n->left) { n = n->left; } /* If the node we found is a leaf node, return an error. */ if (n->node_type == NUMBER) { return(-1); } else { n->left = new_node; } return(0); } /* * node_to_typestr() * * Return a type string based on contents of node. The string is * allocated as B_TEMP or B_PERM depending on the contents of flags. * */ char * node_to_typestr(node_t *np, int flags) { char *tsp = (char *)NULL; type_t *t; /* Determine if this is a Dwarf type or base type. Determine this * by walking pointer chain until we get to the type-specific struct. * However, pass a pointer to the entire chain on to the typestr * routine. */ if (np->flags & DWARF_TYPE_FLAG) { tsp = dw_typestr(np->type, flags); } else if (np->flags & BASE_TYPE_FLAG) { tsp = base_typestr(np->type, flags); } else { /* Assume the value is an int. */ tsp = (char *)ALLOC_BLOCK(6, flags); strcpy(tsp, "(int)"); } return(tsp); } /* * free_tokens() */ void free_tokens(token_t *tp) { token_t *t, *tnext; t = tp; while (t) { tnext = t->next; if (t->string) { free_block((k_ptr_t)t->string); } free_block((k_ptr_t)t); t = tnext; } } /* * free_nodes() */ void free_nodes(node_t *np) { type_t *tp, *tnext; node_t *q; /* If there is nothing to free, just return. */ if (!np) { return; } if (q = np->left) { free_nodes(q); } if (q = np->right) { free_nodes(q); } if (np->name) { free_block((k_ptr_t)np->name); } free_type(np->type); free_block((k_ptr_t)np); } /* * get_sizeof() */ node_t * get_sizeof(token_t **tpp, int *error) { int size; node_t *n0; /* The next token should be either a CAST or an OPEN_PAREN. If it's * something else, then return with an error. */ if ((*tpp)->type == OPERATOR) { if ((*tpp)->operator == OPEN_PAREN) { n0 = do_eval(tpp, C_SIZEOF, error); if (*error) { return(n0); } } else if ((*tpp)->operator == CAST) { if (!(n0 = get_node(tpp, C_SIZEOF))) { *error = E_SYNTAX_ERROR; return((node_t*)NULL); } } else { *error = E_BAD_TYPE; return(n0); } if (!n0->type) { *error = E_NOTYPE; return(n0); } if (n0->type->flag & POINTER_TYPE) { n0->value = K_NBPW(K); } else if (n0->type->flag & DWARF_TYPE_FLAG) { dw_type_info_t *dp = n0->type->t_ptr; n0->value = dp->t_byte_size; } else if (n0->type->flag & BASE_TYPE_FLAG) { base_t *bp = n0->type->t_ptr; n0->value = bp->byte_size; } else { *error = E_BAD_TYPE; return(n0); } n0->node_type = NUMBER; n0->flags = 0; n0->operator = 0; n0->byte_size = 0; n0->address = 0; if (n0->type) { free_type(n0->type); n0->type = 0; } } return(n0); } /* * do_eval() -- Reduces an equation to a single value. * * Any parenthesis (and nested parenthesis) within the equation will * be solved first via a recursive call to do_eval(). */ node_t * do_eval(token_t **tpp, int flags, int *error) { node_t *root = (node_t*)NULL, *n0, *n1; /* Loop through the tokens until we run out of tokens or we hit * a CLOSE_PAREN. If we hit an OPEN_PAREN, make a recursive call * to do_eval(). */ while (*tpp) { n0 = n1 = (node_t *)NULL; /* Check for an OPEN_PAREN token */ if ((*tpp)->operator == OPEN_PAREN) { /* skip over the OPEN_PAREN token */ *tpp = (*tpp)->next; /* Get the value contained within the parenthesis. If there * was an error, just return. */ n0 = do_eval(tpp, flags, error); if (*error) { free_nodes(root); return(n0); } /* If CLOSE_PAREN was the last token, we are at the end of * the token list. In that case, just return n0 (which should * contain the result). Otherwise, just fall through and see * what the next operator is (so that we can determine the * proper location for this operand in the parse tree). * * Or, if do_eval() was called from get_sizeof(), then we * need to return also (even if there are aditional tokens. */ if (!*tpp || (flags & C_SIZEOF)) { if (root) { add_rchild(root, n0); } else { root = n0; } return(root); } } else if ((*tpp)->operator == SIZEOF) { /* skip over the SIZEOF token */ *tpp = (*tpp)->next; n0 = get_sizeof(tpp, error); if (*error) { free_nodes(root); return(n0); } } else if (((*tpp)->operator == CLOSE_PAREN) || ((*tpp)->operator == CLOSE_SQUARE_BRACKET)) { /* Reduce the resulting tree to a single value */ replace(root, error, flags); /* Advance the token pointer past the CLOSE_PAREN or * CLOSE_SQUARE_BRACKET and then return. */ *tpp = (*tpp)->next; return(root); } /* If we don't already have a token loaded into n0, get one * now. */ if (!n0) { if (!(n0 = get_node(tpp, flags))) { *error = E_SYNTAX_ERROR; return((node_t*)NULL); } } if (n0->node_type == OPERATOR) { if (is_unary(n0->operator)) { int do_eval_call = 0; if (n0->operator == INDIRECTION) { /* Make a recursive call to do_eval() and then * take the resulting value and link it in as * the right child node (after making sure that * no error occurred). */ do_eval_call++; n1 = do_eval(tpp, flags, error); if (*error) { /* Free nodes, if there are any */ free_nodes(root); free_nodes(n0); return(n1); } } else if (n0->operator == CAST) { if (!*tpp) { *error = E_SYNTAX_ERROR; } else if (((*tpp)->type == TYPE_DEF) || ((*tpp)->type == OPERATOR) || ((*tpp)->type == VARIABLE)) { if ((*tpp)->operator == CLOSE_PAREN) { /* Step over the CLOSE_PAREN and return */ *tpp = (*tpp)->next; return(n0); } do_eval_call++; n1 = do_eval(tpp, flags, error); } else if (!(n1 = get_node(tpp, flags))) { *error = E_SYNTAX_ERROR; } if (*error) { free_nodes(root); return(n0); } } else if (n0->operator == ADDRESS) { if (!*tpp) { *error = E_SYNTAX_ERROR; } else if (((*tpp)->operator == OPEN_PAREN) || ((*tpp)->next && (((*tpp)->next->operator == RIGHT_ARROW) || ((*tpp)->next->operator == DOT)))) { do_eval_call++; n1 = do_eval(tpp, flags, error); } else if (!(n1 = get_node(tpp, flags))) { *error = E_SYNTAX_ERROR; } if (*error) { free_nodes(root); return(n0); } } else if (*tpp && ((*tpp)->operator == OPEN_PAREN)) { /* skip over the OPEN_PAREN token */ *tpp = (*tpp)->next; /* Get the value contained within the parenthesis. If * there was an error, just return. */ n1 = do_eval(tpp, flags, error); if (*error) { free_nodes(root); free_nodes(n0); return(n1); } } else { if ((*tpp == (token_t*)NULL) || !(n1 = get_node(tpp, flags))){ *error = E_SYNTAX_ERROR; free_nodes(root); return(n0); } } n0->right = n1; /* Check for nested unary operators */ while (is_unary(n1->operator)) { node_t *n2 = (node_t *)NULL; /* If there aren't any more tokens, return an * error (there are none to match up with the * unary operator). */ if (!(*tpp) || !(n2 = get_node(tpp, flags))) { *error = E_SYNTAX_ERROR; return(n1); } n1->right = n2; n1 = n2; } if (replace_unary(n0, error, flags) == -1) { if (n0->right) { free_block((k_ptr_t)n0->right); n0->right = (node_t *)NULL; } if (*error == 0) { *error = E_SYNTAX_ERROR; } return(n0); } if (do_eval_call) { if (!root) { root = n0; } else { add_rchild(root, n0); } if (!replace(root, error, flags)) { if (!(*error)) { *error = E_SYNTAX_ERROR; } } return(root); } } else { /* ERROR? */ } } /* n0 should now contain a non-operator node. Check to see if * there is a next token. If there isn't, just add the last * rchild and return. */ if (!*tpp) { if (!root) { root = n0; } else { add_rchild(root, n0); } if (!replace(root, error, flags)) { if (!(*error)) { *error = E_SYNTAX_ERROR; } } return(root); } /* Make sure the next token is an operator. */ if (!(*tpp)->operator) { free_nodes(root); free_nodes(n0); n1 = get_node(tpp, flags); *error = E_SYNTAX_ERROR; return(n1); } else if (((*tpp)->operator == CLOSE_PAREN) || ((*tpp)->operator == CLOSE_SQUARE_BRACKET)) { if (root) { add_rchild(root, n0); } else { root = n0; } /* Reduce the resulting tree to a single value */ if (!replace(root, error, flags)) { if (!(*error)) { *error = E_SYNTAX_ERROR; } return(root); } /* Advance the token pointer past the CLOSE_PAREN and then * return. */ *tpp = (*tpp)->next; return(root); } else if ((*tpp)->operator == OPEN_SQUARE_BRACKET) { /* skip over the OPEN_SQUARE_BRACKET token */ *tpp = (*tpp)->next; /* Get the value contained within the brackets. This * value must represent an array index. */ n1 = get_array_index(tpp, error); if (*error) { free_nodes(root); free_nodes(n0); return(n1); } /* Convert the array (or pointer type) to an element type * using the index value obtained above. Make sure that * n0 contains some sort of type definition first, however. */ if (n0->node_type != TYPE_DEF) { *error = E_BAD_TYPE; free_nodes(n1); return(n0); } array_to_element(n0, n1, error); if (*error) { free_nodes(n0); return(n1); } free_nodes(n1); /* If there aren't any more tokens, just * return. */ if (!(*tpp)) { return(n0); } } else if (!is_binary((*tpp)->operator)) { free_nodes(root); n1 = get_node(tpp, flags); *error = E_SYNTAX_ERROR; return(n1); } /* Now get the operator node */ if (!(n1 = get_node(tpp, flags))) { *error = E_SYNTAX_ERROR; return((node_t*)NULL); } /* Check to see if this binary operator is RIGHT_ARROW or DOT. * If it is, we need to reduce it to a single value node now. */ while ((n1->operator == RIGHT_ARROW) || (n1->operator == DOT)) { /* The next node must contain the name of the struct|union * member. */ if (!*tpp || ((*tpp)->type != MEMBER)) { if (root) { free_nodes(root); } free_nodes(n0); *error = E_BAD_MEMBER; return(n1); } n1->left = n0; /* Now get the next node and link it as the right child. */ if (!(n0 = get_node(tpp, flags))) { *error = E_SYNTAX_ERROR; return((node_t*)NULL); } n1->right = n0; if (!(n0 = replace(n1, error, flags))) { if (!(*error)) { *error = E_SYNTAX_ERROR; } return(n1); }; /* Check to see if there is a next token. If there is, check * to see if it is the operator CLOSE_PAREN. If it is, then * return (skipping over the CLOSE_PAREN first). */ if ((*tpp && (*tpp)->operator == CLOSE_PAREN) || (*tpp && (*tpp)->operator == CLOSE_SQUARE_BRACKET)) { if (root) { add_rchild(root, n0); } else { root = n0; } /* Reduce the resulting tree to a single value */ replace(root, error, flags); /* Advance the token pointer past the CLOSE_PAREN and then * return. */ *tpp = (*tpp)->next; return(root); } /* Check to see if the next node is an OPEN_SQUARE_BRACKET. * If it is, then we have to reduce the contents of the square * brackets to an index array. */ if (*tpp && (*tpp)->operator == OPEN_SQUARE_BRACKET) { /* Advance the token pointer and call do_eval() again. */ *tpp = (*tpp)->next; n1 = get_array_index(tpp, error); if (*error) { free_nodes(root); free_nodes(n0); return(n1); } /* Convert the array (or pointer type) to an element type * using the index value obtained above. Make sure that * n0 contains some sort of type definition first, however. */ if (n0->node_type != TYPE_DEF) { *error = E_BAD_TYPE; free_nodes(n1); return(n0); } array_to_element(n0, n1, error); if (*error) { free_nodes(n0); return(n1); } free_nodes(n1); } /* Now get the next operator node (if there is one). */ if (!*tpp || !(n1 = get_node(tpp, flags))) { if (root) { add_rchild(root, n0); } else { root = n0; } return(root); } } if (!root) { root = n1; n1->left = n0; } else if (precedence(root->operator) >= precedence(n1->operator)) { add_rchild(root, n0); n1->left = root; root = n1; } else { if (!root->right) { n1->left = n0; root->right = n1; } else { add_rchild(root, n0); n1->left = root->right; root->right = n1; } } } /* while(*tpp) */ return(root); } /* * get_array_index() * */ node_t * get_array_index(token_t **tpp, int *error) { int size, shft; k_uint_t index; node_t *n0; dw_type_info_t *dp; n0 = do_eval(tpp, 0, error); if (*error) { return(n0); } if (n0->node_type != NUMBER) { if (n0->node_type == TYPE_DEF) { if (n0->type->flag != DWARF_TYPE_FLAG) { *error = E_BAD_INDEX; } else { dp = n0->type->t_ptr; if (dp->t_tag == DW_TAG_base_type) { size = dp->t_byte_size; kl_get_block(K, n0->address, size, &index, "index"); if (shft = (8 - size)) { index = index >> (shft * 8); } n0->value = index; n0->address = 0; free_type(n0->type); n0->type = 0; n0->flags = 0; } else { *error = E_BAD_INDEX; } } } else { *error = E_BAD_INDEX; } } n0->node_type = INDEX; return(n0); } /* * replace_cast() */ int replace_cast(node_t *n, int *error, int flags) { int type; k_uint_t value; type_t *t; if (!n || !n->right) { *error = E_SYNTAX_ERROR; return(-1); } if (n->flags & POINTER_FLAG) { if (n->right->node_type == VADDR) { if (n->right->flags & ADDRESS_FLAG) { n->value = n->right->address; } else { *error = E_SYNTAX_ERROR; return(-1); } } else if (n->right->node_type == VARIABLE) { /* Replace a VARIABLE node with a TYPE_DEF node if possible. * Return if there was an error. */ replace_variable(n->right, error, flags); if (*error) { return(-1); } /* Check and see if the attempt to determine this variable's * type failed. We know that's the case when the NOTYPE_FLAG * is set. If the ADDRESS_FLAG is also set, we can continue * (using the address value in the cast). Otherwise, we have * to return an error. */ if (n->right->flags & NOTYPE_FLAG) { if (n->right->flags & ADDRESS_FLAG) { n->value = n->right->address; } else { *error = E_SYNTAX_ERROR; return(-1); } } else { n->value = n->right->value; } } else { n->value = n->right->value; } n->node_type = TYPE_DEF; n->operator = 0; free_nodes(n->right); n->right = (node_t *)NULL; return(0); } if (!(t = eval_type(n))) { *error = E_BAD_TYPE; return(-1); } /* If we don't have a pointer and we're a dwarf type AND * we don't point to a base type, return error. */ if (!(n->flags & POINTER_FLAG)) { if (n->flags & DWARF_TYPE_FLAG) { dw_type_info_t *atp = (dw_type_info_t*)n->type->t_ptr; if (atp->t_actual_type->d_tag != DW_TAG_base_type) { *error = E_BAD_TYPE; return(-1); } } else if (!(n->flags & BASE_TYPE_FLAG)) { *error = E_BAD_TYPE; return(-1); } } if (t->flag & DWARF_TYPE_FLAG) { if (n->right->node_type == TYPE_DEF) { n->value = n->right->value; } else if (n->right->node_type == VARIABLE) { /* XXX not working... */ n->value = n->right->address; } else if (n->right->node_type == NUMBER) { n->value = n->right->value; } else { *error = E_BAD_TYPE; return(-1); } } else if (t->flag & BASE_TYPE_FLAG) { n->byte_size = ((base_t*)t->t_ptr)->byte_size; value = n->right->value; switch (((base_t*)t->t_ptr)->byte_size) { case 1 : if (((base_t*)(t->t_ptr))->encoding == 8) { n->value = (unsigned char)value; n->flags |= UNSIGNED_FLAG; } else { n->value = (char)value; } break; case 2 : if (((base_t*)(t->t_ptr))->encoding == 7) { n->value = (unsigned short)value; n->flags |= UNSIGNED_FLAG; } else { n->value = (short)value; } break; case 4 : if (((base_t*)(t->t_ptr))->encoding == 7) { n->value = (unsigned int)value; n->flags |= UNSIGNED_FLAG; } else { n->value = (int)value; } break; case 8 : if (((base_t*)(t->t_ptr))->encoding == 7) { n->value = (unsigned long long)value; n->flags |= UNSIGNED_FLAG; } else { n->value = (long long)value; } break; default : *error = E_BAD_TYPE; return(-1); } } n->node_type = TYPE_DEF; n->operator = 0; n->type = t; free_block((k_ptr_t)n->right); n->right = (node_t *)NULL; return(0); } /* * apply_unary() */ int apply_unary(node_t *n, k_uint_t *value, int *error) { if (!n || !n->right) { return(-1); } switch (n->operator) { case UNARY_MINUS : *value = (0 - n->right->value); break; case UNARY_PLUS : *value = (n->right->value); break; case ONES_COMPLEMENT : *value = ~(n->right->value); break; case LOGICAL_NEGATION : if (n->right->value) { *value = 0; } else { *value = 1; } logical_flag++; break; default : break; } return(0); } /* * replace_unary() -- * * Convert a unary operator node that contains a pointer to a value * with a node containing the numerical result. Free the node that * originally contained the value. */ int replace_unary(node_t *n, int *error, int flags) { kaddr_t addr; k_uint_t value; if (!n->right) { *error = E_SYNTAX_ERROR; return(-1); } if (is_unary(n->right->operator)) { replace_unary(n->right, error, flags); } if (n->operator == CAST) { return(replace_cast(n, error, flags)); } else if (n->operator == INDIRECTION) { type_t *tp; dw_die_t *d; dw_type_info_t *dtp; /* Replace a VARIABLE node with a TYPE_DEF node if possible. * If it's not possible, return an error. */ if (n->right->node_type == VARIABLE) { if (replace_variable(n->right, error, flags)) { if (!(*error)) { *error = E_NOTYPE; } return(-1); } } /* Make sure we have a pointer */ if (!(n->right->flags & POINTER_FLAG)) { *error = E_BAD_POINTER; return(-1); } /* Get the pointer to the type_s struct */ if (!(tp = n->right->type)) { *error = E_BAD_TYPE; return(-1); } /* Make sure the right child is a TYPE_DEF. */ if (n->right->node_type != TYPE_DEF) { *error = E_BAD_TYPE; return(-1); } /* Make sure we have a pointer to a base or dwarf type * structure. */ if (n->right->flags & BASE_TYPE_FLAG) { n->flags = BASE_TYPE_FLAG; } else if (n->right->flags & DWARF_TYPE_FLAG) { n->flags = DWARF_TYPE_FLAG; } else { *error = E_BAD_TYPE; return(-1); } n->node_type = TYPE_DEF; n->operator = 0; /* The first type_t struct MUST be a pointer to a type (BASE or * DWARF). If it points to a DWARF type, strip off the * pointer block and procede. If it points to a BASE type, we need * to check if it points to type char. If it does, we have to set * the STRING_FLAG before stripping off the pointer block. */ if (tp->flag == POINTER_FLAG) { type_t *t; if (!(t = eval_type(n->right))) { *error = E_BAD_TYPE; return(-1); } /* Zero out the type field in the right child so it wont * accidently be freed when the right child is freed * (upon success). */ n->right->type = (type_t*)NULL; if (!strcmp(((base_t*)t->t_ptr)->name, "char")) { n->flags |= STRING_FLAG; } n->type = tp->t_next; /* Free the pointer block */ free_block((k_ptr_t)tp); /* Get the pointer address */ addr = n->address = n->right->value; n->flags |= (INDIRECTION_FLAG|ADDRESS_FLAG); /* If this is a pointer to a pointer, just get the next * pointer value and return. */ if (n->type->flag == POINTER_FLAG) { kl_get_block(K, addr, K_NBPW(K), &n->value, "pointer value"); if (!PTRSZ64(K)) { n->value >>= 32; } /* Set the appropriate node flag values */ n->flags |= POINTER_FLAG; free_nodes(n->right); n->left = n->right = (node_t *)NULL; return(0); } n->value = addr; /* Turn off the pointer flag */ n->flags &= (~POINTER_FLAG); } else { *error = E_SYNTAX_ERROR; return(-1); } /* Zero out the type field in the right child so it wont * accidently be freed when the right child is freed * (upon success). */ n->right->type = (type_t*)NULL; free_nodes(n->right); n->left = n->right = (node_t *)NULL; return(0); } else if (n->operator == ADDRESS) { type_t *t; if (n->right->node_type == TYPE_DEF) { t = n->right->type; } else if (n->right->node_type == VARIABLE) { int ret; ret = replace_variable(n->right, error, flags); if (*error) { return(-1); } /* If we can't find type information for this variable, we * should convert the node to a VADDR node (with no type * reference). That way pointer math will still work. */ if (ret == 1) { n->node_type = VADDR; n->flags = ADDRESS_FLAG; n->operator = 0; n->address = n->right->address; n->name = n->right->name = 0; n->type = n->right->type = 0; n->value = 0; free_nodes(n->right); n->left = n->right = (node_t *)NULL; return(0); } t = n->right->type; } else { *error = E_BAD_TYPE; return(-1); } n->type = (type_t*)ALLOC_BLOCK(sizeof(type_t), flags); n->type->flag = POINTER_FLAG; n->type->t_next = t; n->node_type = TYPE_DEF; n->operator = 0; n->value = n->right->address; n->flags = POINTER_FLAG; if (!(t = eval_type(n))) { *error = E_BAD_TYPE; return(-1); } n->flags |= t->flag; n->right->type = 0; free_nodes(n->right); n->left = n->right = (node_t *)NULL; return(0); } else if (apply_unary(n, &value, error) == -1) { return(-1); } free_nodes(n->right); n->node_type = NUMBER; n->operator = 0; n->left = n->right = (node_t *)NULL; bcopy(&value, &n->value, sizeof(k_uint_t)); return(0); } /* * apply() */ int apply(node_t *np, k_uint_t *value, int *error, int flags) { int do_signed = 0; /* Each operator node must have two operands */ if (!np->right || !np->left) { *error = E_SYNTAX_ERROR; return(-1); } if (np->right->node_type == OPERATOR) { replace(np->right, error, flags); } if (!(np->flags & UNSIGNED_FLAG)) { do_signed++; } if ((np->left->node_type == TYPE_DEF) || (np->left->node_type == VARIABLE) || (np->left->node_type == VADDR)) { int size; k_uint_t lvalue; /* If the left or right nodes are base types (either Dwarf or * BAES_TYPE), convert them to proper numeric values. Otherwise, * use the address/pointer value to perform pointer math. */ if (!type_to_number(np->left, error)) { if (np->left->flags & ADDRESS_FLAG) { size = K_NBPW(K); lvalue = np->left->address; } else { type_t *tp; /* Since we only allow pointer math, anything other than * a pointer causes failure. */ tp = (type_t*)np->left->type; if (tp->flag != POINTER_FLAG) { *error = E_SYNTAX_ERROR; return(-1); } tp = tp->t_next; switch (tp->flag) { case POINTER_FLAG : size = K_NBPW(K); break; case DWARF_TYPE_FLAG : size = ((dw_type_info_t*)tp->t_ptr)->t_byte_size; break; default : *error = E_SYNTAX_ERROR; return(-1); } lvalue = np->left->value; } switch (np->operator) { case ADD : *value = lvalue + (np->right->value * size); break; case SUBTRACT : *value = lvalue - (np->right->value * size); break; default : *error = E_BAD_OPERATOR; return(-1); } return(0); } } if (do_signed) { switch (np->operator) { case ADD : *value = (k_int_t)np->left->value + (k_int_t)np->right->value; break; case SUBTRACT : *value = (k_int_t)np->left->value - (k_int_t)np->right->value; break; case MULTIPLY : *value = (k_int_t)np->left->value * (k_int_t)np->right->value; break; case DIVIDE : *value = (k_int_t)np->left->value / (k_int_t)np->right->value; break; case BITWISE_OR : *value = (k_int_t)np->left->value | (k_int_t)np->right->value; break; case BITWISE_AND : *value = (k_int_t)np->left->value & (k_int_t)np->right->value; break; case MODULUS : *value = (k_int_t)np->left->value % (k_int_t)np->right->value; break; case RIGHT_SHIFT : *value = (k_int_t)np->left->value >> (k_int_t)np->right->value; break; case LEFT_SHIFT : *value = (k_int_t)np->left->value << (k_int_t)np->right->value; break; case LOGICAL_OR : if ((k_int_t)np->left->value || (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case LOGICAL_AND : if ((k_int_t)np->left->value && (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case EQUAL : if ((k_int_t)np->left->value == (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case NOT_EQUAL : if ((k_int_t)np->left->value != (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case LESS_THAN : if ((k_int_t)np->left->value < (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case GREATER_THAN : if ((k_int_t)np->left->value > (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case LESS_THAN_OR_EQUAL : if ((k_int_t)np->left->value <= (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case GREATER_THAN_OR_EQUAL : if ((k_int_t)np->left->value >= (k_int_t)np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; default : break; } } else { switch (np->operator) { case ADD : *value = np->left->value + np->right->value; break; case SUBTRACT : *value = np->left->value - np->right->value; break; case MULTIPLY : *value = np->left->value * np->right->value; break; case DIVIDE : *value = np->left->value / np->right->value; break; case BITWISE_OR : *value = np->left->value | np->right->value; break; case BITWISE_AND : *value = np->left->value & np->right->value; break; case MODULUS : *value = np->left->value % np->right->value; break; case RIGHT_SHIFT : *value = np->left->value >> np->right->value; break; case LEFT_SHIFT : *value = np->left->value << np->right->value; break; case LOGICAL_OR : if (np->left->value || np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case LOGICAL_AND : if (np->left->value && np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case EQUAL : if (np->left->value == np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case NOT_EQUAL : if (np->left->value != np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case LESS_THAN : if (np->left->value < np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case GREATER_THAN : if (np->left->value > np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case LESS_THAN_OR_EQUAL : if (np->left->value <= np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; case GREATER_THAN_OR_EQUAL : if (np->left->value >= np->right->value) { *value = 1; } else { *value = 0; } logical_flag++; break; default : break; } } if ((np->flags & UNSIGNED_FLAG) && (np->byte_size < sizeof(k_uint_t))) { k_uint_t mask; mask = ((k_uint_t)1 << (np->byte_size * 8)) - 1; *value &= mask; } return(0); } /* * replace() -- * * Replace the tree with a node containing the numerical result of * the equation. */ node_t * replace(node_t *np, int *error, int flags) { k_uint_t value; node_t *q, *r; if (!np) { return((node_t *)NULL); } if (np->node_type == OPERATOR) { if (!(q = np->left)) { return((node_t *)NULL); } while (q) { if (!replace(q, error, flags)) { return((node_t *)NULL); } q = q->right; } /* If the left node is a VARIABLE, convert it to TYPE_DEF here. */ if (np->left->node_type == VARIABLE) { /* Replace the VARIABLE node with a TYPE_DEF node. If * there was an error, or if there wasn't any dwarf type * info available, return an error. */ if (replace_variable(np->left, error, flags)) { if (*error == 0) { *error = E_NOTYPE; } return((node_t *)NULL); } } if ((np->operator == RIGHT_ARROW) || (np->operator == DOT)) { int i; kaddr_t addr = 0; type_t *tp, *mp; /* The left node must point to a TYPE_DEF */ if (np->left->node_type != TYPE_DEF) { if (np->left->flags & NOTYPE_FLAG) { *error = E_NOTYPE; } else { *error = E_BAD_TYPE; } return((node_t *)NULL); } /* Get the type information. Check to see if we have a * pointer to a type. If we do, we need to strip off the * pointer and get the type info. */ if (np->left->type->flag == POINTER_FLAG) { tp = np->left->type->t_next; free_block((k_ptr_t)np->left->type); } else { tp = np->left->type; } /* We need to zero out the left child's type pointer * to prevent the type structs from being prematurely * freed (upon success). We have to remember, however, to * the free the type information before we return. */ np->left->type = (type_t*)NULL; /* tp should now point at a dwarf type_t struct. If it * points to anything else, return failure. */ if (tp->flag != DWARF_TYPE_FLAG) { *error = E_BAD_TYPE; free_type(tp); return((node_t *)NULL); } switch (tp->flag) { case DWARF_TYPE_FLAG: { dw_die_t *dp; dw_type_info_t *dti; /* Get the type die information entry. It should be * one of the following: * * DW_TAG_structure_type * DW_TAG_union_type * DW_TAG_pointer_type * * If it's a DW_TAG_pointer_type, it must reference a * DW_TAG_structure_type or DW_TAG_union_type. Otherwise * return failure. */ dti = (dw_type_info_t *)tp->t_ptr; /* * XXX: Hack for the curnmlist musical * chairs. Do a lookup on the name again. */ if(dti && dti->t_name) dw_lkup(stp,dti->t_name,dti->t_tag); dp = dti->t_actual_type; /* If dp points to a DW_TAG_pointer_type, get the next * die record (which should contain struct/union * information). */ if (dp->d_tag == DW_TAG_pointer_type) { dp = dp->d_next; } /* Make sure dp points to a DW_TAG_structure_type or * DW_TAG_union_type. If it doesn't, return failure. */ if ((dp->d_tag != DW_TAG_structure_type) && (dp->d_tag != DW_TAG_union_type)) { *error = E_BAD_TYPE; free_type(tp); return((node_t *)NULL); } /* Get type information for member. If member is a * pointer to a type, get the pointer address and load * it into value. Otherwise, load the struct/union * address plus loc offset into address. */ if (!(mp = dw_lkup_member(stp, tp->t_ptr, np->right->name, flags))) { *error = E_BAD_MEMBER; free_type(tp); return((node_t *)NULL); } /* Now free the struct type information */ free_type(tp); np->node_type = TYPE_DEF; np->operator = 0; addr = np->left->value + ((dw_type_info_t *)mp->t_ptr)->t_loc; np->address = addr; np->flags |= (DWARF_TYPE_FLAG|ADDRESS_FLAG); if (!(np->type = member_to_type(mp->t_ptr, DWARF_TYPE_FLAG, flags))) { free_type(mp); *error = E_BAD_MEMBER; return((node_t *)NULL); } /* We have to free up the memory block that mp points * to. We can't call free_type(), since it will free * up the type information that np->type points to. So, * we have to free the block manually... */ free_block((k_ptr_t)mp); if (np->type->flag == POINTER_FLAG) { np->flags |= POINTER_FLAG; kl_get_block(K, addr, K_NBPW(K), &np->value, "pointer value"); if (!PTRSZ64(K)) { np->value >>= 32; } } else { np->value = addr; } break; } } free_nodes(np->left); free_nodes(np->right); np->left = np->right = (node_t*)NULL; return(np); } else { if (np->left->byte_size && np->right->byte_size) { if (np->left->byte_size > np->right->byte_size) { /* Left byte_size is greater than right */ np->byte_size = np->left->byte_size; np->type = np->left->type; np->flags = np->left->flags; free_type(np->right->type); } else if (np->left->byte_size < np->right->byte_size) { /* Right byte_size is greater than left */ np->byte_size = np->right->byte_size; np->type = np->right->type; np->flags = np->right->flags; free_type(np->left->type); } else { /* Left and right byte_size is equal */ if (np->left->flags & UNSIGNED_FLAG) { np->byte_size = np->left->byte_size; np->type = np->left->type; np->flags = np->left->flags; free_type(np->right->type); } else if (np->right->flags & UNSIGNED_FLAG) { np->byte_size = np->right->byte_size; np->type = np->right->type; np->flags = np->right->flags; free_type(np->left->type); } else { np->byte_size = np->left->byte_size; np->type = np->left->type; np->flags = np->left->flags; free_type(np->right->type); } } } else if (np->left->byte_size) { np->byte_size = np->left->byte_size; np->type = np->left->type; np->flags = np->left->flags; free_type(np->right->type); } else if (np->right->byte_size) { np->byte_size = np->right->byte_size; np->type = np->right->type; np->flags = np->right->flags; } else { /* XXX - No byte sizes */ } if (apply(np, &value, error, flags)) { return((node_t *)NULL); } } np->right->type = np->left->type = (type_t*)NULL; /* Flesh out the rest of the node struct. */ np->node_type = NUMBER; np->flags &= ~(DWARF_TYPE_FLAG|BASE_TYPE_FLAG); np->operator = 0; np->value = value; free_block((k_ptr_t)np->left); free_block((k_ptr_t)np->right); np->left = np->right = (node_t*)NULL; } return(np); } /* * replace_variable() */ int replace_variable(node_t *n, int *error, int flags) { dw_type_t *dtp; type_t *t; dw_type_info_t *dti; /* Check to see if this is a dwarf kernel */ if (!stp) { /* Lookup the variable type by name */ if (!(dtp = dw_lkup(stp, n->name, DW_TAG_variable))) { *error = E_BAD_VARIABLE; return(-1); } /* Allocate some space for the dw_type_info_s struct and then * get the struct referenced by d_off. */ dti = (dw_type_info_t*)ALLOC_BLOCK(sizeof(*dti), flags); if (!dw_type_info(dtp->dt_off, dti, flags)) { dw_free_type_info(dti); *error = E_BAD_TYPE; return(-1); } if (!(n->type = dw_var_to_type(dti, flags))) { /* If we can't find type information for this variable, we * set a flag (NOTYPE_FLAG) and return one (1). We don't, * set *error, however. We may be able to get by with just * the address of the variable. */ n->flags |= NOTYPE_FLAG; dw_free_type_info(dti); return(1); } n->node_type = TYPE_DEF; n->operator = 0; if (n->type->flag == POINTER_FLAG) { n->flags = POINTER_FLAG; kl_get_block(K, n->address, 8, &n->value, "pointer value (DWARF)"); } else { n->value = n->address; } if (!(t = eval_type(n))) { *error = E_BAD_TYPE; return(-1); } n->flags |= t->flag; } return(0); } /* * array_to_element() */ void array_to_element(node_t *n0, node_t *n1, int *error) { int size; type_t *t; base_t *btp; dw_type_info_t *dtp; dw_die_t *dp; /* Take the array index and determine the proper pointer * value for the type pointer or array data type. */ t = n0->type; if (n0->node_type == TYPE_DEF) { if (t->flag == POINTER_FLAG) { if (t->t_next->flag == DWARF_TYPE_FLAG) { dtp = (dw_type_info_t*)t->t_next->t_ptr; t = t->t_next; free_block((k_ptr_t)n0->type); n0->type = t; size = dtp->t_byte_size; } else if (t->t_next->flag == BASE_TYPE_FLAG) { btp = (base_t*)t->t_next->t_ptr; t = t->t_next; free_block((k_ptr_t)n0->type); n0->type = t; size = btp->byte_size; } else { *error = E_BAD_INDEX; } } else if (t->flag == DWARF_TYPE_FLAG) { dtp = (dw_type_info_t*)t->t_ptr; if (dtp->t_tag == DW_TAG_array_type) { dtp->t_tag = dtp->t_type->d_next->d_tag; dtp->t_off = dtp->t_type->d_next->d_off; dtp->t_name = dtp->t_type->d_next->d_name; dp = dtp->t_type; while (dp->d_next) { dp = dp->d_next; } size = dp->d_byte_size; dtp->t_type = dtp->t_type->d_next; dtp->t_actual_type = dp; dtp->t_byte_size = size; } else { *error = E_BAD_INDEX; } } else { *error = E_BAD_INDEX; } if (!(*error)) { n0->address = n0->value + (n1->value * size); n0->value = n0->address; n0->flags &= (~POINTER_FLAG); n0->flags |= (ADDRESS_FLAG|INDIRECTION_FLAG); } } else { *error = E_BAD_INDEX; } } /* * type_to_number() * * Convert a base type (Dwarf or BASE_TYPE) to a numeric value. Return * 1 on successful conversion, 0 if nothing was done. */ int type_to_number(node_t *np, int *error) { int byte_size, bit_offset, bit_size, encoding, j, k; k_uint_t value, value1; dw_type_info_t *dti; /* Make sure we point to a type */ if (!np->type) { return(0); } if (np->type->flag == POINTER_FLAG) { return(0); } dti = (dw_type_info_t*)np->type->t_ptr; if (np->flags & BASE_TYPE_FLAG) { /* Nothing needs to be done. It's already a base value * (we still need to return a 1). */ return(1); } else if (np->flags & DWARF_TYPE_FLAG) { if (dti->t_tag == DW_TAG_base_type) { byte_size = dti->t_byte_size; bit_offset = dti->t_bit_offset; if (!(bit_size = dti->t_bit_size)) { bit_size = (byte_size * 8); } encoding = dti->t_encoding; } else { return(0); } } kl_get_block(K, np->address, byte_size, &value1, "value"); value = kl_get_bit_value(&value1, byte_size, bit_size, bit_offset); switch (byte_size) { case 1 : if (encoding == 8) { np->value = (unsigned char)value; np->flags |= UNSIGNED_FLAG; } else { np->value = (char)value; } break; case 2 : if (encoding == 7) { np->value = (unsigned short)value; np->flags |= UNSIGNED_FLAG; } else { np->value = (short)value; } break; case 4 : if (encoding == 7) { np->value = (unsigned int)value; np->flags |= UNSIGNED_FLAG; } else { np->value = (int)value; } break; case 8 : if (encoding == 7) { np->value = (unsigned long long)value; np->flags |= UNSIGNED_FLAG; } else { np->value = (long long)value; } break; default : *error = E_BAD_TYPE; return(0); } np->node_type = NUMBER; return(1); } /* * eval_type() */ type_t * eval_type(node_t *n) { type_t *t; t = n->type; while (t->flag == POINTER_FLAG) { t = t->t_next; /* If for some reason, there is no type pointer (this shouldn't * happen but...), we have to make sure that we don't try to * reference a NULL pointer and get a SEGV. Return an error if * 't' is NULL. */ if (!t) { return((type_t*)NULL); } } if ((t->flag == BASE_TYPE_FLAG) || (t->flag == DWARF_TYPE_FLAG)) { return (t); } return((type_t*)NULL); } /* * eval() */ node_t * eval(char **exp, int flags, int *error) { int i; token_t *tok, *t; node_t *n; char *e, *s; *error = 0; logical_flag = 0; /* Make sure we actually have a command line to evaluate */ if (!(*exp)) { return ((node_t*)NULL); } /* Expand any variables that are in the expression string. Free * the original string and change s so that it points to the new * expression string (so that the new string will be freed up when * we are done). */ if (e = expand_variables(*exp, 0)) { free_block((k_ptr_t)*exp); *exp = e; s = *exp; } else { *error = E_BAD_VARIABLE; tok = (token_t *)alloc_block(sizeof(token_t), B_TEMP); tok->ptr = *exp; } if (!(*error)) { tok = get_token_list(s, error); } if (*error) { n = (node_t *)ALLOC_BLOCK(sizeof(node_t), flags); n->tok_ptr = tok->ptr; } else { t = tok; n = do_eval(&t, flags, error); if (!*error) { if (!(n = replace(n, error, flags))) { n = (node_t *)ALLOC_BLOCK(sizeof (node_t), flags); n->tok_ptr = s + strlen(s) -1; *error = E_SYNTAX_ERROR; } else { /* Check to see if the the result should be interpreted * as 'true' or 'false' */ if (logical_flag && ((n->value == 0) || (n->value == 1))) { n->flags |= BOOLIAN_FLAG; } } } } if (!(*error) && (n->node_type == VARIABLE)) { if (n->flags & NOTYPE_FLAG) { if (!(n->flags & ADDRESS_FLAG)) { *error = E_NOTYPE; } } else { if (replace_variable(n, error, flags) == 1) { *error = E_NOTYPE; } } } free_tokens(tok); return(n); } /* * print_number() * * If we get here it means the type is BASE_TYPE. If there isn't * a type_s struct linked in, then make type the default (int). * Then, depending on the contents of flags, display the value * in HEX, OCTAL, or DECIMAL form. There is a special case for * type char (display as a character). */ void print_number(node_t *np, FILE *ofp, int flags) { base_t *bt; k_uint_t value; /* Check to make sure we have a base_type pointer. This is kind * of a hack since we can get to this routine from a number of * different ways and it's not always clear that a type will have * been designated along the way. Check the upper word and see if * any bits are set. If they are, treat the value as a "long long" * type (64-bit) value. Otherwise, treat it as an "int" value. */ if (!np->type) { if (np->value & 0xffffffff00000000) { np->type = get_type("long long", 0); } else { np->type = get_type("int", 0); } np->byte_size = ((base_t *)np->type->t_ptr)->byte_size; } if (flags & C_HEX) { if (np->byte_size && (np->byte_size != sizeof(k_uint_t))) { np->value = np->value & (((k_uint_t)1<<(k_uint_t)(np->byte_size*8))-1); } fprintf(ofp, "0x%llx", np->value); } else if (flags & C_OCTAL) { fprintf(ofp, "0%llo", np->value); } else { if (np->flags & UNSIGNED_FLAG) { fprintf(ofp, "%llu", np->value); } else { bt = (base_t *)np->type->t_ptr; value = np->value << ((8 - np->byte_size) * 8); print_base(&value, bt->byte_size, bt->encoding, flags, ofp); } } } /* * print_eval_results() */ int print_eval_results(node_t *np, FILE *ofp, int flags) { int size; kaddr_t addr; dw_type_info_t *t; dw_die_t *d; /* Print the results */ switch (np->node_type) { case NUMBER: print_number(np, ofp, flags); break; case TYPE_DEF: { type_t *tp; k_ptr_t ptr; /* If this is a pointer just print out the address. */ if (np->flags & POINTER_FLAG) { fprintf(ofp, "0x%llx", np->value); break; } if (np->flags & DWARF_TYPE_FLAG) { /* Get the type information */ t = (dw_type_info_t *)np->type->t_ptr; /* * XXX: Hack for the curnmlist musical chairs. * Do a lookup on that name again. */ if(t && t->t_name) dw_lkup(stp,t->t_name,t->t_tag); if (t->t_type->d_tag == DW_TAG_typedef) { d = t->t_actual_type; } else { d = t->t_type; } size = t->t_byte_size; ptr = alloc_block(size, B_TEMP); if ((d->d_tag == DW_TAG_base_type) && !(np->flags & ADDRESS_FLAG)) { switch (size) { case 1: *(unsigned char *)ptr = np->value; break; case 2: *(unsigned short *)ptr = np->value; break; case 4: *(unsigned int *)ptr = np->value; break; case 8: *(unsigned long long *)ptr = np->value; break; } dw_print_type(ptr, t, 0, flags|SUPPRESS_NAME, ofp); free_block(ptr); return(1);; } addr = np->value; kl_get_block(K, addr, size, ptr, "type"); if (KL_ERROR) { kl_print_error(K); free_block(ptr); return(1); } /* Print out the actual type */ switch (d->d_tag) { case DW_TAG_structure_type: case DW_TAG_union_type: dw_print_type(ptr, t, 0, flags, ofp); break; default: dw_print_type(ptr, t, 0, (flags|SUPPRESS_NAME|SUPPRESS_NL), ofp); break; } free_block(ptr); } else if (np->flags & BASE_TYPE_FLAG) { base_t *b; if (!(flags & ADDRESS_FLAG)) { print_number(np, ofp, flags); } else { /* Get the type information */ b = (base_t *)np->type->t_ptr; size = b->byte_size; ptr = alloc_block(size, B_TEMP); addr = np->value; kl_get_block(K, addr, size, ptr, "type"); if (KL_ERROR) { free_block(ptr); return(1); } print_base(ptr, size, b->encoding, flags, ofp); } } break; } case VADDR: case VARIABLE: /* If we get here, there was no type info available. * The ADDRESS_FLAG should be set (otherwise we would have * returned an error). So, print out the address. */ fprintf(ofp, "0x%llx", np->address); break; default: if (np->node_type == TEXT) { print_string(np->name, ofp); if (KL_ERROR) { kl_print_error(K); return(1); } } else if (np->node_type == CHARACTER) { fprintf(ofp, "\'%c\'", np->name[0]); } break; } return(0); } /* * print_eval_error() */ void print_eval_error(char *cmdname, char *s, char *bad_ptr, int error, int flags) { int i, cmd_len; if ((cmdname[0] == 'p') || !strcmp(cmdname, "eval")) { fprintf(KL_ERRORFP, "print"); if ((cmdname[1] == 'x') || (cmdname[1] == 'o')) { fprintf(KL_ERRORFP, "%c %s\n", cmdname[1], s); cmd_len = 6; } else { fprintf(KL_ERRORFP, " %s\n", s); cmd_len = 5; } } else { if (flags & CMD_STRING) { fprintf(KL_ERRORFP, "%s%s\n", cmdname, s); } else { fprintf(KL_ERRORFP, "%s %s\n", cmdname, s); } cmd_len = strlen(cmdname); } if (!bad_ptr) { for (i = 0; i < (strlen(s) + cmd_len); i++) { fprintf(KL_ERRORFP, " "); } } else { for (i = 0; i < (bad_ptr - s + 1 + cmd_len); i++) { fprintf(KL_ERRORFP, " "); } } fprintf(KL_ERRORFP, "^ "); switch (error) { case E_OPEN_PAREN : fprintf(KL_ERRORFP, "Too many open parenthesis\n"); break; case E_CLOSE_PAREN : fprintf(KL_ERRORFP, "Too many close parenthesis\n"); break; case E_BAD_MEMBER : fprintf(KL_ERRORFP, "No such member\n"); break; case E_BAD_OPERATOR : fprintf(KL_ERRORFP, "Bad operator\n"); break; case E_BAD_TYPE : fprintf(KL_ERRORFP, "Bad type\n"); break; case E_NOTYPE : fprintf(KL_ERRORFP, "Could not find type information\n"); break; case E_BAD_POINTER : fprintf(KL_ERRORFP, "Bad pointer\n"); break; case E_BAD_VARIABLE : fprintf(KL_ERRORFP, "Not a variable\n"); break; case E_BAD_INDEX : fprintf(KL_ERRORFP, "Bad array index\n"); break; case E_BAD_STRING : fprintf(KL_ERRORFP, "Non-termining string\n"); break; case E_END_EXPECTED : fprintf(KL_ERRORFP, "Expected end of print statement\n"); break; case E_BAD_EVAR : fprintf(KL_ERRORFP, "Bad eval variable\n"); break; default : fprintf(KL_ERRORFP, "Syntax error\n"); break; } }