Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

eval.c

/*
 * $Id: eval.c,v 1.1 2004/12/21 23:26:17 tjm Exp $
 *
 * This file is part of lcrash, an analysis tool for Linux memory dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, and others
 *
 * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <lcrash.h>
#include <lc_eval.h>
#include <string.h>

/* Forward declarations
 */
static void free_node(node_t *);
static node_t *make_node(token_t *, int);
static node_t *get_node_list(token_t *, int);
static node_t *do_eval(int);
static int is_unary(int);
static int is_binary(int);
static int precedence(int);
static node_t *get_sizeof(void);
static int replace_cast(node_t *, int);
static int replace_unary(node_t *, int);
static node_t *replace(node_t *, int);
static void array_to_element(node_t*, node_t*);
static int type_to_number(node_t *);
kltype_t *number_to_type(node_t *);
static type_t *eval_type(node_t *);
static type_t *get_type(char *, int);
static int add_rchild(node_t *, node_t *);
static void free_nodelist(node_t *);

/* Global variables
 */
static int logical_flag;
static node_t *node_list = (node_t *)NULL;
uint64_t eval_error;
char *error_token;

/*
 * set_eval_error()
 */
static void
set_eval_error(uint64_t ecode)
{
      eval_error = ecode;
}

/*
 * is_typestr()
 * 
 * We check for "struct", "union", etc. separately because they
 * would not be an actual part of the type name. We also assume
 * that the string passed in 
 *
 * - does not have any leading blanks or tabs 
 * - is NULL terminated
 * - contains only one type name to check
 * - does not contain any '*' characters
 */
static int
is_typestr(char *str)
{
      int len;

      len = strlen(str);
      if ((len >= 6) && !strncmp(str, "struct", 6)) {
            return(1);
      } else if ((len >= 5) &&!strncmp(str, "union", 5)) {
            return(1);
      } else if ((len >= 5) &&!strncmp(str, "short", 5)) {
            return(1);
      } else if ((len >= 8) &&!strncmp(str, "unsigned", 8)) {
            return(1);
      } else if ((len >= 6) &&!strncmp(str, "signed", 6)) {
            return(1);
      } else if ((len >= 4) &&!strncmp(str, "long", 4)) {
            return(1);
      } 
      /* Strip off any trailing blanks 
       */
      while(*str && ((str[strlen(str) - 1] == ' ') 
                  || (str[strlen(str) - 1] == '\t'))) {
            str[strlen(str) - 1] = 0;
      }
      if (kl_find_type(str, KLT_TYPES)) {
            return (1);
      }
      return(0);
}

/* 
 * free_tokens()
 */
static void
free_tokens(token_t *tp)
{
      token_t *t, *tnext;

      t = tp;
      while (t) {
            tnext = t->next;
            if (t->string) {
                  kl_free_block((void *)t->string);
            }
            kl_free_block((void *)t);
            t = tnext;
      }
}

#ifdef NOTYET
/*
 * process_variable()
 */
static int
process_variable(char **str, token_t *tok)
{
      int len;
      char *s, *vname;
      variable_t *vp;
      token_t *t;

      if (s = strpbrk((cp + 1), " .\t+-*/()[]|~!$&%^<>?:&=^\"\'")) {
            len = (uaddr_t)s - (uaddr_t)cp + 1;
      } else {
            len = strlen(cp) + 1;
      }
      vname = (char *)kl_alloc_block(len, K_TEMP);
      memcpy(vname, cp, (len -1));
      vname[len - 1] = 0;
      vp = find_variable(vtab, vname, 0);
      if (!vp || (vp->v_flags & V_COMMAND)) {
            set_eval_error(E_BAD_EVAR);
            error_token = tok->ptr;
            kl_free_block((void *)vname);
            return(1);
      }
      if (vp->v_flags & V_TYPEDEF) {
            kl_free_block((void *)vname);
            free_tokens(tok);
            t = get_token_list(vp->v_typestr);
            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) {
                  set_eval_error(E_END_EXPECTED);
                  error_token = tok->ptr;
                  return(1);
            }

            /* Skip ahead to the first non-blank character
             */
            while (s && (*s == ' ')) {
                  s++;
            }
            if (s && (*s != 0)) {
                  set_eval_error(E_END_EXPECTED);
                  tok->ptr = s;
                  error_token = tok->ptr;
                  return(1);
            }

            tok->string = (char *)
                  kl_alloc_block(strlen(vp->v_exp) + 1, K_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(0);
      }
      return(1);
}
#endif

/*
 * process_text()
 */
static int
process_text(char **str, token_t *tok)
{
      char *cp = *str;
      char *s;
      int len;

      /* Check and see if this token is a STRING or CHARACTER 
       * type (beginning with a single or double quote).
       */
      if (*cp == '\'') {
            /* make sure that only a single character is between 
             * the single quotes (it can be an escaped character 
             * too).
             */
            s = strpbrk((cp + 1), "\'");
            if (!s) {
                  set_eval_error(E_SINGLE_QUOTE);
                  error_token = tok->ptr;
                  return(1);
            }
            len = (uaddr_t)s - (uaddr_t)cp;
            if ((*(cp+1) == '\\')) {
                  if (*(cp+2) == '0') {
                        long int val;
                        char *ep;

                        val = strtol((char*)(cp+2), 
                              (char **)&ep, 8);
                        if ((val > 255) || (*ep != '\'')) {
                              set_eval_error(E_BAD_CHAR);
                              error_token = tok->ptr;
                              return(1);
                        }
                  } else if (*(cp+3) != '\'') {
                        set_eval_error(E_BAD_CHAR);
                        error_token = tok->ptr;
                        return(1);
                  }
                  tok->type = CHARACTER;
            } else if (len == 2) {
                  tok->type = CHARACTER;
            } else { 

                  /* Treat as a single token entry. It's possible 
                   * that what's between the single quotes is a 
                   * type name. That will be determined later on.
                   */
                  tok->type = STRING;
            }
            *str = cp + len;
      } else if (*cp == '\"') {
            s = strpbrk((cp + 1), "\"");
            if (!s) {
                  set_eval_error(E_BAD_STRING);
                  error_token = tok->ptr;
                  return(1);
            }
            len = (uaddr_t)s - (uaddr_t)cp;
            tok->type = TEXT;
            *str = cp + len;
      }
      if ((tok->type == STRING) || (tok->type == TEXT)) {

            if ((tok->type == TEXT) && (strlen(cp) > (len + 1))) {

                  /* Check to see if there is a comma 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 != ' ') {
                              set_eval_error(E_END_EXPECTED);
                              tok->ptr = c;
                              error_token = tok->ptr;
                              return(1);
                        }
                        c++;
                  }
                  /* Truncate the trailing blanks (they are not 
                   * part of the string).
                   */
                  if (c != (s + 1)) {
                        *(s + 1) = 0;
                  }
            }
            tok->string = (char *)kl_alloc_block(len, K_TEMP);
            memcpy(tok->string, (cp + 1), len - 1);
            tok->string[len - 1] = 0;
      }
      return(0);
}

/*
 * get_token_list()
 */
static token_t *
get_token_list(char *str)
{
      int paren_count = 0;
      char *cp;
      token_t *tok, *tok_head = (token_t*)NULL, *tok_last = (token_t*)NULL;

      cp = str;
      eval_error = 0;

      while (*cp) {

            /* Skip past any "white space" (spaces and tabs).
             */
            switch (*cp) {
                  case ' ' :
                  case '\t' :
                  case '`' :
                        cp++;
                        continue;
                  default :
                        break;
            }

            /* Allocate space for the next token
             */
            tok = (token_t *)kl_alloc_block(sizeof(token_t), K_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.
                               */
                              set_eval_error(E_BAD_OPERATOR);
                              error_token = tok_last->ptr;
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return ((token_t*)NULL);
                        } 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.
                               */
                              set_eval_error(E_BAD_OPERATOR);
                              error_token = tok_last->ptr;
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return ((token_t*)NULL);
                        } 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) {
                              set_eval_error(E_SYNTAX_ERROR);
                              error_token = tok_last->ptr;
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return ((token_t*)NULL);
                        }

                        if (tok_last && 
                              ((tok_last->operator == RIGHT_ARROW) || 
                                    (tok_last->operator == DOT))) {
                              set_eval_error(E_SYNTAX_ERROR);
                              error_token = tok_last->ptr;
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return ((token_t*)NULL);
                        }

                        /* 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) == '(') || isdigit(*(cp+1)) ||
                              (*(cp+1) == '+') || (*(cp+1) == '-') ||
                              (*(cp+1) == '*') || (*(cp+1) == '&') || 
                                    (*(cp+1) == ')')){
                              tok->operator = OPEN_PAREN;
                              paren_count++;
                              break;
                        }
                        
                        if ((s = strpbrk(cp+1, "*)"))) {
                              char str[128];

                              len = (uaddr_t)s - (uaddr_t)(cp+1);
                              strncpy(str, cp+1, len);      
                              str[len] = 0;
                              if (!is_typestr(str)) {
                                    set_eval_error(E_BAD_TYPE);
                                    error_token = tok->ptr;
                                    free_tokens(tok_head);
                                    free_tokens(tok);
                                    return ((token_t*)NULL);
                              }
                              if (!(s = strpbrk((cp+1), ")"))) {
                                    set_eval_error(E_OPEN_PAREN);
                                    error_token = tok->ptr;
                                    free_tokens(tok_head);
                                    free_tokens(tok);
                                    return ((token_t*)NULL);
                              }
                              len = (uaddr_t)s - (uaddr_t)(cp+1);
                              tok->string = (char *) kl_alloc_block(
                                    len + 1, K_TEMP);
                              memcpy(tok->string, (cp+1), len);
                              tok->string[len] = 0;
                              tok->operator = CAST;
                              cp = (char *)((uaddr_t)(cp+1) + len);
                              break;
                        }
                        tok->operator = OPEN_PAREN;
                        paren_count++;
                        break;
                  }

                  case ')' :
                        if (tok_last && ((tok_last->operator == 
                                    RIGHT_ARROW) || 
                                    (tok_last->operator == DOT))) {
                              set_eval_error(E_SYNTAX_ERROR);
                              error_token = tok_last->ptr;
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return ((token_t*)NULL);
                        }
                        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 '$' :
#ifdef NOT_IMPLEMENTED
                        if (process_variable(&cp, tok)) {
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return((token_t*)NULL);
                        }
                        break;
#else 
                        set_eval_error(E_NOT_IMPLEMENTED);
                        error_token = tok->ptr;
                        free_tokens(tok_head);
                        free_tokens(tok);
                        return((token_t*)NULL);
#endif
                  case '~' :
                        tok->operator = ONES_COMPLEMENT;
                        break;
                  
                  case '^' :
                        tok->operator = BITWISE_EXCLUSIVE_OR;
                        break;

                  case '?' :
#ifdef NOT_IMPLEMENTED
                        tok->operator = CONDITIONAL;
                        break;
#else
                        set_eval_error(E_NOT_IMPLEMENTED);
                        error_token = tok->ptr;
                        free_tokens(tok_head);
                        free_tokens(tok);
                        return((token_t*)NULL);
#endif
                  case ':' :
#ifdef NOT_IMPLEMENTED
                        tok->operator = CONDITIONAL_ELSE;
                        break;
#else
                        set_eval_error(E_NOT_IMPLEMENTED);
                        error_token = tok->ptr;
                        free_tokens(tok_head);
                        free_tokens(tok);
                        return((token_t*)NULL);
#endif
                  case '[' :
                        tok->operator = OPEN_SQUARE_BRACKET;;
                        break;

                  case ']' :
                        tok->operator = CLOSE_SQUARE_BRACKET;;
                        break;

                  default: {

                        char *s;
                        int len;

                        /* See if the last token is a RIGHT_ARROW
                         * or a DOT. If it is, then this token must 
                         * be the name of a struct/union member.
                         */
                        if (tok_last && 
                              ((tok_last->operator == RIGHT_ARROW) ||
                                     (tok_last->operator == DOT))) {
                              tok->type = MEMBER;
                        } else if (process_text(&cp, tok)) {
                              free_tokens(tok_head);
                              free_tokens(tok);
                              return((token_t*)NULL);
                        }
                        if (tok->type == TEXT) {
                              return(tok);
                        } else if (tok->type == STRING) {
                              if (is_typestr(tok->string)) {
                                    tok->type = TYPE_DEF;
                              } else {
                                    tok->operator = TEXT;
                                    return(tok);
                              }
                              break;
                        } else if (tok->type == CHARACTER) {
                              break;
                        }

                        /* Check and See if the entire string is 
                         * a typename (valid only for whatis case).
                         */
                        s = strpbrk(cp, 
                              ".\t+-*/()[]|~!$&%^<>?:&=^\"\'");
                        if (!s && !tok->type && is_typestr(cp)) {
                              tok->type = TYPE_DEF;
                              len = strlen(cp) + 1;
                              tok->string = (char *)
                                    kl_alloc_block(len, K_TEMP);
                              memcpy(tok->string, cp, len - 1);
                              tok->string[len - 1] = 0;
                              cp = (char *)((uaddr_t)cp + len - 2);
                              break;
                        }

                        /* Now check for everything else
                         */
                        if ((s = strpbrk(cp, 
                              " .\t+-*/()[]|~!$&%^<>?:&=^\"\'"))) {
                              len = (uaddr_t)s - (uaddr_t)cp + 1;
                        } else {
                              len = strlen(cp) + 1;
                        }

                        tok->string = 
                              (char *)kl_alloc_block(len, K_TEMP);
                        memcpy(tok->string, cp, len - 1);
                        tok->string[len - 1] = 0;

                        cp = (char *)((uaddr_t)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;
                              kl_free_block((void *)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) {
            set_eval_error(E_CLOSE_PAREN);
            error_token = tok->ptr;
            free_tokens(tok_head);
            return((token_t*)NULL);
      } else if (paren_count > 0) {
            set_eval_error(E_OPEN_PAREN);
            error_token = tok->ptr;
            free_tokens(tok_head);
            return((token_t*)NULL);
      }
      return(tok_head);
}

/*
 * valid_binary_args()
 */
int
valid_binary_args(node_t *np, node_t *left, node_t *right)
{
      int op = np->operator;

      if ((op == RIGHT_ARROW) || (op == DOT)) {
            if (!left) {
                  set_eval_error(E_MISSING_STRUCTURE);
                  error_token = np->tok_ptr;
                  return(0);
            } else if (!(left->node_type == TYPE_DEF) &&
                        !(left->node_type == MEMBER) &&
                        !(left->operator == CLOSE_PAREN)) {
                  set_eval_error(E_BAD_STRUCTURE);
                  error_token = left->tok_ptr;
                  return(0);
            }
            if (!right || (!(right->node_type == MEMBER))) {
                  set_eval_error(E_BAD_MEMBER);
                  error_token = right->tok_ptr;
                  return(0);
            }
            return(1);
      }
      if (!left || !right) {
            set_eval_error(E_MISSING_OPERAND);
            error_token = np->tok_ptr;
            return(0);
      }
      switch (left->operator) {
            case CLOSE_PAREN:
            case CLOSE_SQUARE_BRACKET:
                  break;
            default:
                  switch(left->node_type) {
                        case NUMBER:      
                        case STRING:
                        case TEXT:
                        case CHARACTER:
                        case EVAL_VAR:
                        case MEMBER:
                              break;
                        default:
                              set_eval_error(E_BAD_OPERAND);
                              error_token = np->tok_ptr;
                              return(0);
                  }
      }
      switch (right->operator) {
            case OPEN_PAREN:
                  break;
            default:
                  switch(right->node_type) {
                        case NUMBER:      
                        case STRING:
                        case TEXT:
                        case CHARACTER:
                        case EVAL_VAR:
                        case MEMBER:
                              break;
                        default:
                              set_eval_error(E_BAD_OPERAND);
                              error_token = np->tok_ptr;
                              return(0);
                  }
      }
      return(1);
}

/*
 * get_node_list()
 */
static node_t *
get_node_list(token_t *tp, int flags)
{
      node_t *root = (node_t *)NULL; 
      node_t *np = (node_t *)NULL;
      node_t *last = (node_t *)NULL;

      /* Loop through the tokens and convert them to nodes. 
       */
      while (tp) {
            np = make_node(tp, flags);
            if (eval_error) {
                  return((node_t *)NULL);
            }
            if (root) {
                  last->next = np;
                  last = np;
            } else {
                  root = last = np;
            }
            tp = tp->next;
      }
      last = (node_t *)NULL;
      for (np = root; np; np = np->next) {
            if (is_binary(np->operator)) {
                  if (!valid_binary_args(np, last, np->next)) {
                        free_nodelist(root);
                        return((node_t *)NULL);
                  }     
            }
            last = np;
      }
      return(root);
}

/*
 * next_node()
 */
static node_t *
next_node(void)
{
      node_t *np;
      if ((np = node_list)) {
            node_list = node_list->next;
            np->next = (node_t*)NULL;
      }
      return(np);
}

/*
 * eval_unary()
 */
static node_t *
eval_unary(node_t *curnp, int flags)
{
      node_t *n0, *n1;

      n0 = curnp;

      /* Peek ahead and make sure there is a next node.
       * Also check to see if the next node requires
       * a recursive call to do_eval(). If it does, we'll 
       * let the do_eval() call take care of pulling it
       * off the list.
       */
      if (!node_list) {
            set_eval_error(E_SYNTAX_ERROR);
            error_token = n0->tok_ptr;
            free_nodes(n0);
            return((node_t*)NULL);
      } 
      if (n0->operator == CAST) { 
            if (node_list->operator == CLOSE_PAREN) {

                  /* Free the CLOSE_PAREN and return
                   */
                  free_node(next_node());
                  return(n0);
            }
            if (!(node_list->node_type == NUMBER) &&
                        !(node_list->node_type == VADDR) &&
                        !((node_list->operator == ADDRESS) ||
                        (node_list->operator == CAST) || 
                        (node_list->operator == UNARY_MINUS) || 
                        (node_list->operator == UNARY_PLUS) || 
                        (node_list->operator == INDIRECTION) || 
                        (node_list->operator == OPEN_PAREN))) {
                  set_eval_error(E_SYNTAX_ERROR);
                  error_token = node_list->tok_ptr;
                  free_nodes(n0);
                  return((node_t*)NULL);
            }
      } 
      if ((n0->operator == INDIRECTION) ||
                  (n0->operator == ADDRESS) ||
                  (n0->operator == OPEN_PAREN) ||
                  is_unary(node_list->operator)) {
            n1 = do_eval(flags);
            if (eval_error) {
                  free_nodes(n0);
                  free_nodes(n1);
                  return((node_t*)NULL);
            }
      } else {
            n1 = next_node();
      }

      if (n1->operator == OPEN_PAREN) {
            /* Get the value contained within the parenthesis. 
             * If there was an error, just return.
             */
            free_node(n1);
            n1 = do_eval(flags);
            if (eval_error) {
                  free_nodes(n1);
                  free_nodes(n0);
                  return((node_t*)NULL);
            }
      }

      n0->right = n1;
      if (replace_unary(n0, flags) == -1) {
            if (!eval_error) {
                  set_eval_error(E_SYNTAX_ERROR);
                  error_token = n0->tok_ptr;
            }
            free_nodes(n0);
            return((node_t*)NULL);
      }
      return(n0);
}

/* 
 * do_eval() -- Reduces an equation to a single value. 
 * 
 *   Any parenthesis (and nested parenthesis) within the equation will
 *   be solved first via recursive calls to do_eval().
 */
static node_t *
do_eval(int flags)
{
      node_t *root = (node_t*)NULL, *curnp, *n0, *n1;

      /* Loop through the list of nodes until we run out of nodes
       * or we hit a CLOSE_PAREN. If we hit an OPEN_PAREN, make a 
       * recursive call to do_eval().
       */
      curnp = next_node();
      while (curnp) {
            n0 = n1 = (node_t *)NULL;

            if (curnp->operator == OPEN_PAREN) {
                  /* Get the value contained within the parenthesis. 
                   * If there was an error, just return.
                   */
                  free_node(curnp);
                  n0 = do_eval(flags);
                  if (eval_error) {
                        free_nodes(n0);
                        free_nodes(root);
                        return((node_t *)NULL);
                  }

            } else if (curnp->operator == SIZEOF) {
                  /* Free the SIZEOF node and then make a call 
                   * to the get_sizeof() function (which will 
                   * get the next node off the list).
                   */
                  n0 = get_sizeof();
                  if (eval_error) {
                        if (!error_token) {
                              error_token = curnp->tok_ptr;
                        }
                        free_node(curnp);
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  free_node(curnp);
                  curnp = (node_t *)NULL;
            } else if (is_unary(curnp->operator)) {
                  n0 = eval_unary(curnp, flags);
            } else {
                  n0 = curnp;
                  curnp = (node_t *)NULL;
            }
            if (eval_error) {
                  free_nodes(n0);
                  free_nodes(root);
                  return((node_t *)NULL);
            }

            /* 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 (!node_list) {
                  if (root) {
                        add_rchild(root, n0);
                  } else {
                        root = n0;
                  }
                  replace(root, flags);
                  if (eval_error) {
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  return(root);
            }

            /* Make sure the next token is an operator.
             */
            if (!node_list->operator) {
                  free_nodes(root);
                  free_node(n0);
                  set_eval_error(E_SYNTAX_ERROR);
                  error_token = node_list->tok_ptr;
                  return((node_t *)NULL);
            } else if ((node_list->operator == CLOSE_PAREN) ||
                  (node_list->operator == CLOSE_SQUARE_BRACKET)) {

                  if (root) {
                        add_rchild(root, n0);
                  } else {
                        root = n0;
                  }

                  /* Reduce the resulting tree to a single value
                   */
                  replace(root, flags);
                  if (eval_error) {
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  
                  /* Step over the CLOSE_PAREN or CLOSE_SQUARE_BRACKET
                   * and then return.
                   */
                  free_node(next_node());
                  return(root);
            } else if (node_list->operator == OPEN_SQUARE_BRACKET) {

                  /* skip over the OPEN_SQUARE_BRACKET token
                   */
                  free_node(next_node());

                  /* Get the value contained within the brackets. This 
                   * value must represent an array index (value or
                   * equation).
                   */
                  n1 = do_eval(0);
                  if (eval_error) {
                        free_nodes(root);
                        free_node(n0);
                        free_node(n1);
                        return((node_t *)NULL);
                  }

                  /* 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) {
                        set_eval_error(E_BAD_TYPE);
                        error_token = n0->tok_ptr;
                        free_nodes(n0);
                        free_nodes(n1);
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  array_to_element(n0, n1);
                  free_node(n1);
                  if (eval_error) {
                        free_nodes(root);
                        free_nodes(n0);
                        return((node_t *)NULL);
                  }

                  /* If there aren't any more nodes, just
                   * return.
                   */
                  if (!node_list) {
                        return(n0);
                  }
            } else if (!is_binary(node_list->operator)) {
                  set_eval_error(E_BAD_OPERATOR);
                  error_token = node_list->tok_ptr;
                  free_nodes(root);
                  free_nodes(n0);
                  return((node_t *)NULL);
            }

            /* Now get the operator node
             */
            if (!(n1 = next_node())) {
                  set_eval_error(E_SYNTAX_ERROR);
                  error_token = n0->tok_ptr;
                  free_nodes(n0);
                  free_nodes(root);
                  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 (!node_list || (node_list->node_type != MEMBER)) {
                        set_eval_error(E_BAD_MEMBER);
                        error_token = n1->tok_ptr;
                        free_nodes(n0);
                        free_nodes(n1);
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  n1->left = n0;

                  /* Now get the next node and link it as the 
                   * right child.
                   */
                  if (!(n0 = next_node())) {
                        set_eval_error(E_SYNTAX_ERROR);
                        error_token = n1->tok_ptr;
                        free_nodes(n1);
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  n1->right = n0;
                  if (!(n0 = replace(n1, flags))) {
                        if (!(eval_error)) {
                              set_eval_error(E_SYNTAX_ERROR);
                              error_token = n1->tok_ptr;
                        }
                        free_nodes(n1);
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  n1 = (node_t *)NULL;

                  /* Check to see if there is a next node. 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 (node_list && ((node_list->operator == CLOSE_PAREN) 
                                    || (node_list->operator == 
                                    CLOSE_SQUARE_BRACKET))) {
                        if (root) {
                              add_rchild(root, n0);
                        } else {
                              root = n0;
                        }

                        /* Reduce the resulting tree to a single 
                         * value
                         */
                        replace(root, flags);
                        if (eval_error) {
                              free_nodes(root);
                              return((node_t *)NULL);
                        }
                        
                        /* Advance the token pointer past the 
                         * CLOSE_PAREN and then return.
                         */
                        free_node(next_node());
                        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 (node_list && (node_list->operator 
                                    == OPEN_SQUARE_BRACKET)) {

                        /* Advance the token pointer and call 
                         * do_eval() again.
                         */
                        free_node(next_node());
                        n1 = do_eval(0);
                        if (eval_error) {
                              free_node(n0);
                              free_node(n1);
                              free_nodes(root);
                              return((node_t *)NULL);
                        }

                        /* 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) {
                              set_eval_error(E_BAD_TYPE);
                              error_token = n0->tok_ptr;
                              free_node(n0);
                              free_node(n1);
                              free_node(root);
                              return((node_t *)NULL);
                        }
                        array_to_element(n0, n1);
                        free_node(n1);
                        if (eval_error) {
                              free_node(n0);
                              free_node(root);
                              return((node_t *)NULL);
                        }
                  }

                  /* Now get the next operator node (if there is one).
                   */
                  if (!node_list) {
                        if (root) {
                              add_rchild(root, n0);
                        } else {
                              root = n0;
                        }
                        return(root);
                  }
                  n1 = next_node();
            }

            if (n1 && ((n1->operator == CLOSE_PAREN) ||
                        (n1->operator == CLOSE_SQUARE_BRACKET))) {
                  free_node(n1);
                  if (root) {
                        add_rchild(root, n0);
                  } else {
                        root = n0;
                  }
                  replace(root, flags);
                  if (eval_error) {
                        free_nodes(root);
                        return((node_t *)NULL);
                  }
                  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;
                  }
            }
            curnp = next_node();
      } /* while(curnp) */
      return(root);
}

/*
 * is_unary()
 */
static 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()
 */
static 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()
 */
static 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);
      }
}

/* 
 * esc_char()
 */
char
esc_char(char *str)
{
      long int val;
      char ch;

      if (strlen(str) > 1) {
            val = strtol(str, (char **)NULL, 8);
            ch = (char)val; 
      } else {
            ch = str[0];
      }
      switch (ch) {
            case 'a' :
                  return((char)7);
            case 'b' :
                  return((char)8);
            case 't' :
                  return((char)9);
            case 'n' :
                  return((char)10);
            case 'f' :
                  return((char)12);
            case 'r' :
                  return((char)13);
            case 'e' :
                  return((char)27);
            default:
                  return(ch);
      }
}

/*
 * make_node()
 */
static node_t *
make_node(token_t *t, int flags)
{
      node_t *np;

      np = (node_t*)kl_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))) {
                        set_eval_error(E_BAD_CAST);
                        error_token = t->ptr;
                        free_nodes(np);
                        return((node_t*)NULL);
                  }

                  /* Determin if this is a pointer to a type
                   */
                  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 KLTYPE_FLAG:
                              np->flags |= KLTYPE_FLAG;
                              break;

                        default:
                              free_nodes(np);
                              set_eval_error(E_BAD_CAST); 
                              error_token = t->ptr;
                              return((node_t*)NULL);
                  }
                  if (!t->next) {
                        if (flags & C_WHATIS) {
                              np->node_type = TYPE_DEF;
                        } else {
                              set_eval_error(E_BAD_CAST);
                              error_token = t->ptr;
                              return((node_t*)NULL);
                        }
                  } else {
                        np->node_type = OPERATOR;
                        np->operator = CAST;
                  }
            } else {
                  np->node_type = OPERATOR;
                  np->operator = t->operator;
            }
      } else if (t->type == MEMBER) {
            np->name = (char *)kl_dup_block((void *)t->string, K_TEMP);
            np->node_type = MEMBER;
      } else if ((t->type == STRING) || (t->type == TYPE_DEF)) {
            syment_t *sp;
            dbg_sym_t *stp;
            dbg_type_t *sttp;

            if ((sp = kl_lkup_symname(t->string)) && !(flags & C_NOVARS)) {
                  int has_type = 0;

                  /* The string is a symbol name. We'll treat it as 
                   * a global kernel variable and, at least, gather in
                   * the address of the symbol and the value it points 
                   * to.
                   */
                  np->address = sp->s_addr;
                  np->flags |= ADDRESS_FLAG;
                  np->name = t->string;
                  t->string = (char*)NULL;

                  /* Need to see if there is type information available
                   * for this variable. Since this mapping is not 
                   * available yet, we will just attach a type struct 
                   * for either uint32_t or uint64_t (depending on 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! 
                   */
                  np->node_type = TYPE_DEF;
                  np->flags |= KLTYPE_FLAG;
                  np->value = KL_VREAD_PTR(np->address);
                  /* try to get the actual type info for the variable */
                  if(((stp = dbg_find_sym(sp->s_name, DBG_VAR,
                                     (uint64_t)0)) != NULL)){
                        if((sttp = (dbg_type_t *)
                              kl_find_typenum(stp->sym_typenum)) 
                                    != NULL){
                              /* kl_get_typestring(sttp); */
                              has_type = 1;
                              if(sttp->st_klt.kl_type == KLT_POINTER){
                                    np->flags ^= KLTYPE_FLAG;
                                    np->flags |= POINTER_FLAG;
                                    np->type =
                                      get_type(sttp->st_typestr,
                                             flags);
                              } else {
                                    np->type =
                                          kl_alloc_block(sizeof(type_t), K_TEMP);
                                    np->type->un.kltp =
                                          &sttp->st_klt;
                              }
                        }
                  }
                  /* no type info for the variable found */
                  if(!has_type){
                        if (PTRSZ64) {
                              np->type = get_type("uint64_t", flags);
                        } else {
                              np->type = get_type("uint32_t", flags);
                        }
                  }
            } else if (flags & (C_WHATIS|C_SIZEOF)) {

                  kltype_t *kltp;

                  if ((kltp = kl_find_type(t->string, KLT_TYPES))) {

                        np->node_type = TYPE_DEF;
                        np->flags = KLTYPE_FLAG;
                        np->type = (type_t*)
                              kl_alloc_block(sizeof(type_t), K_TEMP);
                        np->type->flag = KLTYPE_FLAG;
                        np->type->t_kltp = kltp;
                  } else {
                        if (GET_VALUE(t->string, &np->value)) {
                              set_eval_error(E_BAD_VALUE);
                              error_token = t->ptr;
                              free_nodes(np);
                              return((node_t*)NULL);
                        }
                        if (!strncmp(t->string, "0x", 2) ||
                                    !strncmp(t->string, "0X", 2)) {
                              np->flags |= UNSIGNED_FLAG;
                        }
                        np->node_type = NUMBER;
                  }
                  np->tok_ptr = t->ptr;
                  return(np);
            } else {
                  if (GET_VALUE(t->string, &np->value)) {
                        set_eval_error(E_BAD_VALUE);
                        error_token = t->ptr;
                        free_nodes(np);
                        return((node_t*)NULL);
                  }
                  if (np->value > 0xffffffff) {
                        np->byte_size = 8;
                  } else {
                        np->byte_size = 4;
                  }
                  if (!strncmp(t->string, "0x", 2) ||
                              !strncmp(t->string, "0X", 2)) {
                        np->flags |= UNSIGNED_FLAG;
                  }
                  np->node_type = NUMBER;
            }
      } else if (t->type == CHARACTER) {
            char *cp;

            /* Step over the single quote
             */
            cp = (t->ptr + 1);
            if (*cp == '\\') {
                  int i = 0;
                  char str[16];

                  /* Step over the back slash
                   */
                  cp++;
                  while (*cp != '\'') {
                        str[i++] = *cp++;
                  }
                  str[i] = 0;
                  np->value = esc_char(str);
            } else {
                  np->value = *cp;
            }
            np->type = get_type("char", flags);
            np->node_type = TYPE_DEF;
            np->flags |= KLTYPE_FLAG;
      } else if (t->type == TEXT) {
            np->node_type = TEXT;
            np->name = t->string;
            /* So the block doesn't get freed twice */
            t->string = (char*)NULL; 
      } else {
            set_eval_error(E_SYNTAX_ERROR);
            error_token = t->ptr;
            return((node_t*)NULL);
      }
      np->tok_ptr = t->ptr;
      return(np);
}

/*
 * add_node()
 */
static 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()
 */
static int
add_rchild(node_t *root, node_t *new_node)
{
      if (add_node(root, new_node) == -1) {
            return(-1);
      }
      return(0);
}

#ifdef NOT
/*
 * add_lchild()
 */
static 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);

}
#endif

/*
 * free_type()
 */
static void
free_type(type_t *head) 
{
      type_t *t0, *t1;

      t0 = head;
      while(t0) {
            if (t0->flag == POINTER_FLAG) {
                  t1 = t0->t_next;
                  kl_free_block((void *)t0);
                  t0 = t1;
            } else {
                  if (is_temp_block(t0->t_kltp)) {
                        if (t0->flag != KLTYPE_FLAG) {
                              kl_free_block((void *)t0->t_kltp);
                        }
                  }
                  kl_free_block((void *)t0);
                  t0 = (type_t *)NULL;
            }
      }
}

/*
 * get_type() -- Convert a typecast string into a type. 
 * 
 *   Returns a pointer to a struct containing type information.
 *   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.
 */
static type_t *
get_type(char *s, int flags)
{
      int len, type = 0;
      char *cp, typename[128];
      type_t *t, *head, *last;
      kltype_t *kltp;

      head = last = (type_t *)NULL;

      /* Get the type string
       */
        if (!strncmp(s, "struct", 6)) {
                if ((cp = strpbrk(s + 7, " \t*"))) {
                        len = cp - (s + 7);
                } else {
                        len = strlen(s + 7);
                }
                memcpy(typename, s + 7, len);
        } else if (!strncmp(s, "union", 5)) {
                if ((cp = strpbrk(s + 6, " \t*"))) {
                        len = cp - (s + 6);
                } else {
                        len = strlen(s + 6);
                }
                memcpy(typename, s + 6, len);
        } else {
            if ((cp = strpbrk(s, "*)"))) {
                  len = cp - s;
            } else {
                  len = strlen(s);
            }
            memcpy(typename, s, len);
      }

      /* Strip off any trailing spaces 
       */
      while (len && ((typename[len - 1] == ' ') || 
                  (typename[len - 1] == '\t'))) {
            len--;
      }
      typename[len] = 0;

      if (!(kltp = kl_find_type(typename, KLT_TYPES))) {
            return ((type_t *)NULL);
      }
      type = KLTYPE_FLAG;

      /* check to see if this cast is a pointer to a type, a pointer
       * to a pointer to a type, etc.
       */
      cp = s;
      while ((cp = strpbrk(cp, "*"))) {
            t = (type_t *)kl_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
       * record.
       */
      t = (type_t *)kl_alloc_block(sizeof(type_t), flags);
      t->flag = type;

      switch (t->flag) {

            case KLTYPE_FLAG:
                  t->t_kltp = kltp;
                  break;

            default:
                  free_type(head);
                  return((type_t*)NULL);
      }
      if (last) {
            last->t_next = t;
      } else {
            head = t;
      }
      return(head);
}

/*
 * free_node()
 */
static void
free_node(node_t *np)
{
      /* If there is nothing to free, just return.
       */
      if (!np) {
            return;
      }
      if (np->name) {
            kl_free_block((void *)np->name);
      }
      free_type(np->type);
      kl_free_block((void *)np);
}

/*
 * free_nodes()
 */
void
free_nodes(node_t *np)
{
      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) {
            kl_free_block((void *)np->name);
      }
      free_type(np->type);
      kl_free_block((void *)np);
}

/*
 * free_nodelist()
 */
static void
free_nodelist(node_t *np)
{
      node_t *nnp;

      while(np) {
            nnp = np->next;
            free_node(np);
            np = nnp;
      }
}

extern int alloc_debug;

/*
 * free_eval_memory()
 */
void
free_eval_memory(void)
{
      free_nodelist(node_list);
      node_list = (node_t*)NULL;
}

/*
 * get_sizeof()
 */
static node_t *
get_sizeof()
{
      node_t *curnp, *n0;

      if (!(curnp = next_node())) {
            set_eval_error(E_SYNTAX_ERROR);
            return((node_t*)NULL);
      }

      /* The next token should be a CAST or an open paren. 
       * If it's something else, then return an error.
       */
      if (curnp->operator == OPEN_PAREN) {
            free_nodes(curnp);
            n0 = do_eval(C_SIZEOF);
            if (eval_error) {
                  error_token = n0->tok_ptr;
                  free_nodes(n0);
                  return((node_t*)NULL);
            }
      } else if (curnp->operator == CAST) {
            n0 = curnp;
      } else {
            set_eval_error(E_BAD_TYPE);
            error_token = n0->tok_ptr;
            free_nodes(n0);
            return((node_t*)NULL);
      }

      if (!n0->type) {
            set_eval_error(E_NOTYPE);
            error_token = n0->tok_ptr;
            free_nodes(n0);
            return((node_t*)NULL);
      }

      if (n0->type->flag & POINTER_FLAG) {
            n0->value = KL_NBPW;
      } else if (n0->type->flag & KLTYPE_FLAG) {
            kltype_t *kltp;
            
            kltp = kl_realtype(n0->type->t_kltp, 0);

            if (kltp->kl_bit_size) {
                  n0->value = kltp->kl_bit_size / 8;
                  if (kltp->kl_bit_size % 8) {
                        n0->value += 1;
                  }
            } else {
                  n0->value = kltp->kl_size;
            }
      } else {
            set_eval_error(E_BAD_TYPE);
            error_token = n0->tok_ptr;
            free_nodes(n0);
            return((node_t*)NULL);
      }
      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);
}

/*
 * apply_unary()
 */
static int
apply_unary(node_t *n, uint64_t *value)
{
      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);
}

/*
 * pointer_math()
 */
static int
pointer_math(node_t *np, uint64_t *value, int type, int flags)
{
      int size;
      uint64_t lvalue, rvalue;
      type_t *tp, *tp1;

      if (type < 0) {
            if (np->left->flags & POINTER_FLAG) {

                  /* Since we only allow pointer math, 
                   * anything other than a pointer causes 
                   * failure.
                   */
                  tp = (type_t*)np->left->type;
                  if (tp->flag != POINTER_FLAG) {
                        set_eval_error(E_SYNTAX_ERROR);
                        error_token = np->left->tok_ptr;
                        return(-1);
                  }

                  tp = tp->t_next;

                  switch (tp->flag) {

                        case POINTER_FLAG :
                              size = KL_NBPW;
                              break;

                        case KLTYPE_FLAG : {
                              /* Get the size of the real type,
                               * not just the size of a pointer 
                               * If there isn't any type info,
                               * then just set size equal to the
                               * size of a pointer.
                               */
                              kltype_t *kltp, *rkltp;

                              kltp = tp->t_kltp;
                              rkltp = kl_realtype(kltp, 0);
                              if (!(size = rkltp->kl_size)) {
                                    if (kltp != rkltp) {
                                          size = kltp->kl_size;
                                    } else {
                                          size = KL_NBPW;
                                    }
                              }
                              break;
                        }

                        default :
                              set_eval_error(E_SYNTAX_ERROR);
                              error_token = np->left->tok_ptr;
                              return(-1);
                  }
                  lvalue = np->left->value;
            } else {
                  size = KL_NBPW;
                  lvalue = np->left->address;
            } 
            switch (np->operator) {
                  case ADD :
                        *value = lvalue + (np->right->value * size);
                        break;

                  case SUBTRACT :
                        *value = lvalue - (np->right->value * size);
                        break;

                  default :
                        set_eval_error(E_BAD_OPERATOR);
                        error_token = np->tok_ptr;
                        return(-1);
            }
      } else if (type > 0) {
            if (np->right->flags & POINTER_FLAG) {

                  /* Since we only allow pointer math, 
                   * anything other than a pointer causes 
                   * failure.
                   */
                  tp = (type_t*)np->right->type;
                  if (tp->flag != POINTER_FLAG) {
                        set_eval_error(E_SYNTAX_ERROR);
                        error_token = np->right->tok_ptr;
                        return(-1);
                  }

                  tp = tp->t_next;

                  switch (tp->flag) {

                        case POINTER_FLAG :
                              size = KL_NBPW;
                              break;

                        case KLTYPE_FLAG :
                              size = tp->t_kltp->kl_size;
                              break;

                        default :
                              set_eval_error(E_SYNTAX_ERROR);
                              error_token = np->right->tok_ptr;
                              return(-1);
                  }
                  rvalue = np->right->value;
            } else {
                  size = KL_NBPW;
                  rvalue = np->right->address;
            } 
            switch (np->operator) {
                  case ADD :
                        *value = rvalue + (np->left->value * size);
                        break;

                  case SUBTRACT :
                        *value = rvalue - (np->left->value * size);
                        break;

                  default :
                        set_eval_error(E_BAD_OPERATOR);
                        error_token = np->tok_ptr;
                        return(-1);
            }
      } else {
            return(-1);
      }
      tp1 = (type_t *)kl_alloc_block(sizeof(type_t), flags);
      tp1->flag = POINTER_FLAG;
      np->type = tp1;
      while (tp->flag == POINTER_FLAG) {
            tp1->t_next = (type_t *)kl_alloc_block(sizeof(type_t), flags);
            tp1->flag = POINTER_FLAG;
            tp1 = tp1->t_next;      
            tp = tp->t_next;  
      }
      if (tp) {
            tp1->t_next = (type_t *)kl_alloc_block(sizeof(type_t), flags);
            tp1 = tp1->t_next;
            tp1->flag = KLTYPE_FLAG;
            tp1->t_kltp = tp->t_kltp;
            if (type < 0) {
                  if (np->left->flags & POINTER_FLAG) {
                        np->flags |= POINTER_FLAG;
                  } else {
                        np->flags |= VADDR;
                  }
            } else {
                  if (np->right->flags & POINTER_FLAG) {
                        np->flags |= POINTER_FLAG;
                  } else {
                        np->flags |= VADDR;
                  }
            }
      }
      return(0);
}

/*
 * check_unsigned()
 */
int
check_unsigned(node_t *np)
{
      kltype_t *kltp, *rkltp;

      if (np->flags & UNSIGNED_FLAG) {
            return(1);
      } 
      if (!np->type) {
            return(0);
      }
      if (np->type->flag == POINTER_FLAG) {
            return(0);
      }
      kltp = np->type->t_kltp;
      if ((rkltp = kl_realtype(kltp, 0))) {
            if (rkltp->kl_encoding == ENC_UNSIGNED) {
                  np->flags |= UNSIGNED_FLAG;
                  return(1);
            }
      }
      return(0);
}

/*
 * apply()
 */
static int
apply(node_t *np, uint64_t *value, int flags)
{
      int ltype, rtype, do_signed = 0;

      /* There must be two operands
       */
      if (!np->right || !np->left) {
            set_eval_error(E_MISSING_OPERAND);
            error_token = np->tok_ptr;
            return(-1);
      }

      if (np->right->node_type == OPERATOR) {
            replace(np->right, flags);
            if (eval_error) {
                  return(-1);
            }
      }

      ltype = np->left->node_type;
      rtype = np->right->node_type;
      if ((ltype == TYPE_DEF) || (ltype == VADDR)) {
            if ((rtype == TYPE_DEF) || (rtype == VADDR)) {
                  set_eval_error(E_NO_VALUE);
                  error_token = np->tok_ptr;
                  return(-1);
            }
            if (check_unsigned(np->left)) {
                  np->flags |= UNSIGNED_FLAG;
            } else {
                  do_signed++;
            }
            if (!type_to_number(np->left)) {
                  return(pointer_math(np, value, -1, flags));
            }
            np->byte_size = np->left->byte_size;
      } else if ((rtype == TYPE_DEF) || (rtype == VADDR)) {
            if ((ltype == TYPE_DEF) || (ltype == VADDR)) {
                  error_token = np->tok_ptr;
                  set_eval_error(E_NO_VALUE);
                  return(-1);
            }
            if (check_unsigned(np->right)) {
                  np->flags |= UNSIGNED_FLAG;
            } else {
                  do_signed++;
            }
            if (!type_to_number(np->right)) {
                  return(pointer_math(np, value, 1, flags));
            }
            np->byte_size = np->right->byte_size;
      } else if ((np->left->flags & UNSIGNED_FLAG) || 
                  (np->right->flags & UNSIGNED_FLAG)) {
            np->flags |= UNSIGNED_FLAG;
      } else {
            do_signed++;
      }

      if (do_signed) {
            switch (np->operator) {
                  case ADD :
                        *value = (int64_t)np->left->value + 
                              (int64_t)np->right->value;
                        break;

                  case SUBTRACT :
                        *value = (int64_t)np->left->value - 
                              (int64_t)np->right->value;
                        break;

                  case MULTIPLY :
                        *value = (int64_t)np->left->value * 
                              (int64_t)np->right->value;
                        break;

                  case DIVIDE :
                        if ((int64_t)np->right->value == 0) {
                              set_eval_error(E_DIVIDE_BY_ZERO);
                              error_token = np->right->tok_ptr;
                              return(-1);
                        }
                        *value = (int64_t)np->left->value / 
                              (int64_t)np->right->value;
                        break;

                  case BITWISE_OR :
                        *value = (int64_t)np->left->value | 
                              (int64_t)np->right->value;
                        break;

                  case BITWISE_AND :
                        *value = (int64_t)np->left->value & 
                              (int64_t)np->right->value;
                        break;

                  case MODULUS :
                        if ((int64_t)np->right->value == 0) {
                              set_eval_error(E_DIVIDE_BY_ZERO);
                              error_token = np->right->tok_ptr;
                              return(-1);
                        }
                        *value = (int64_t)np->left->value % 
                              (int64_t)np->right->value;
                        break;

                  case RIGHT_SHIFT :
                        *value = 
                              (int64_t)np->left->value >> 
                                    (int64_t)np->right->value;
                        break;

                  case LEFT_SHIFT :
                        *value = 
                              (int64_t)np->left->value << 
                                    (int64_t)np->right->value;
                        break;

                  case LOGICAL_OR :
                        if ((int64_t)np->left->value ||     
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case LOGICAL_AND :
                        if ((int64_t)np->left->value && 
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case EQUAL :
                        if ((int64_t)np->left->value == 
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case NOT_EQUAL :
                        if ((int64_t)np->left->value != 
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case LESS_THAN :
                        if ((int64_t)np->left->value < 
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case GREATER_THAN :
                        if ((int64_t)np->left->value > 
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case LESS_THAN_OR_EQUAL :
                        if ((int64_t)np->left->value <= 
                                    (int64_t)np->right->value) {
                              *value = 1;
                        } else {
                              *value = 0;
                        }
                        logical_flag++;
                        break;

                  case GREATER_THAN_OR_EQUAL :
                        if ((int64_t)np->left->value >= 
                                    (int64_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;
            }
      }
      return(0);
}

/*
 * member_to_type()
 */
static type_t *
member_to_type(kltype_t *kltp, int flags)
{
      kltype_t *rkltp;
      type_t *tp, *head = (type_t *)NULL, *last = (type_t *)NULL;

      /* Make sure this is a member
       */
      if (kltp->kl_type != KLT_MEMBER) {
            return((type_t *)NULL);
      }

      rkltp = kltp->kl_realtype;
      while (rkltp && rkltp->kl_type == KLT_POINTER) {
            tp = (type_t *)kl_alloc_block(sizeof(type_t), flags);
            tp->flag = POINTER_FLAG;
            if (last) {
                  last->t_next = tp;
                  last = tp;
            } else {
                  head = last = tp;
            }
            rkltp = rkltp->kl_realtype;
      }

      /* If We step past all the pointer records 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 some 
       * type info.
       */
      if (!rkltp) {
            tp = (type_t *)kl_alloc_block(sizeof(type_t), flags);
            tp->flag = VOID_FLAG;
            tp->t_kltp = kltp;
            if (last) {
                  last->t_next = tp;
                  last = tp;
            } else {
                  head = last = tp;
            }
            return(head);
      }

      tp = (type_t *)kl_alloc_block(sizeof(type_t), flags);
      tp->flag = KLTYPE_FLAG;
      tp->t_kltp = kltp;
      if (last) {
            last->t_next = tp;
      } else {
            head = tp;
      }
      return(head);
}

/*
 * replace() -- 
 *
 * Replace the tree with a node containing the numerical result of
 * the equation. If pointer math is performed, the result will have
 * the same type as the pointer.
 */
static node_t *
replace(node_t *np, int flags)
{
      uint64_t value;
      node_t *q;
                        
      if (!np) {
            return((node_t *)NULL);
      }

      if (np->node_type == OPERATOR) {
            if (!(q = np->left)) {
                  return((node_t *)NULL);
            }
            while (q) {
                  if (!replace(q, flags)) {
                        return((node_t *)NULL);
                  }
                  q = q->right;
            }

            if ((np->operator == RIGHT_ARROW) || (np->operator == DOT)) {
                  kaddr_t addr = 0;
                  type_t *tp;

                  /* The left node must point to a TYPE_DEF
                   */
                  if (np->left->node_type != TYPE_DEF) {
                        if (np->left->flags & NOTYPE_FLAG) {
                              set_eval_error(E_NOTYPE);
                              error_token = np->left->tok_ptr;
                        } else {
                              set_eval_error(E_BAD_TYPE);
                              error_token = np->left->tok_ptr;
                        }
                        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;
                        kl_free_block((void *)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 type_t struct that
                   * references a kltype_t struct. If it points 
                   * to anything else, return failure.
                   *
                   */
                  if (tp->flag != KLTYPE_FLAG) {
                        set_eval_error(E_BAD_TYPE);
                        error_token = np->left->tok_ptr;
                        free_type(tp);
                        return((node_t *)NULL);
                  }

                  switch (tp->flag) {
                        case KLTYPE_FLAG: {
                              /* Make sure that the type referenced
                               * is a struct, union, or pointer to
                               * a struct or union. If it isn't one
                               * of these, then return failure.
                               */
                              kltype_t *kltp, *kltmp; 
                              
                              kltp = kl_realtype(tp->t_kltp, 0);
                              if ((kltp->kl_type != KLT_STRUCT) &&
                                    (kltp->kl_type != KLT_UNION)) {
                                    error_token = 
                                          np->left->tok_ptr;
                                    set_eval_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. In any event, load 
                               * the struct/union address plus the
                               * offset of the member.
                               */
                              kltmp = kl_get_member(kltp,
                                          np->right->name);
                              if (!kltmp) {
                                    set_eval_error(E_BAD_MEMBER);
                                    error_token = 
                                          np->right->tok_ptr;
                                    free_type(tp);
                                    return((node_t *)NULL);
                              }
                              np->type = member_to_type(kltmp, flags);
                              if (!np->type) {
                                    set_eval_error(E_BAD_MEMBER);
                                    error_token = 
                                          np->right->tok_ptr;
                                    free_type(tp);
                                    return((node_t *)NULL);
                              }

                              /* Now free the struct type information
                               */
                              free_type(tp);
                              np->node_type = TYPE_DEF;
                              np->flags |= KLTYPE_FLAG;
                              np->operator = 0;
                              addr = 0;
                              if (np->left->flags & POINTER_FLAG) {
                                    addr =  np->left->value +
                                          kltmp->kl_offset;
                              } else if (np->left->flags & 
                                          ADDRESS_FLAG) {
                                    addr =  np->left->address +
                                          kltmp->kl_offset;
                              }
                              if (addr) {
                                    np->address = addr;
                                    np->flags |= ADDRESS_FLAG;
                              }

                              if (np->type->flag == POINTER_FLAG) {
                                    np->flags |= POINTER_FLAG;
                                    np->value = KL_VREAD_PTR(addr);
                              } 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 || !np->right) {
                        set_eval_error(E_MISSING_OPERAND);
                        error_token = np->tok_ptr;
                        return((node_t *)NULL);
                  }
                  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, flags)) {
                        return((node_t *)NULL);
                  }
            }
            np->right->type = np->left->type = (type_t*)NULL;

            /* Flesh out the rest of the node struct. 
             */
            if (np->type) {
                  np->node_type = TYPE_DEF;
                  np->flags |= KLTYPE_FLAG;
            } else {
                  np->node_type = NUMBER;
                  np->flags &= ~(KLTYPE_FLAG);
            }
            np->operator = 0;
            np->value = value;
            kl_free_block((void *)np->left);
            kl_free_block((void *)np->right);
            np->left = np->right = (node_t*)NULL;
      }
      return(np);
}

/*
 * replace_cast()
 */
static int
replace_cast(node_t *n, int flags)
{
      type_t *t;

      if (!n) {
            set_eval_error(E_SYNTAX_ERROR);
            return(-1);
      } else if (!n->right) {
            set_eval_error(E_SYNTAX_ERROR);
            error_token = n->tok_ptr;
            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 {
                        set_eval_error(E_SYNTAX_ERROR);
                        error_token = n->right->tok_ptr;
                        return(-1);
                  }

            } else {
                  n->value = n->right->value;
                  n->address = 0;
            }
      } else if (n->right->flags & ADDRESS_FLAG) {
            n->flags |= ADDRESS_FLAG;
            n->address = n->right->address;
            n->value = n->right->value;
      } else {
            kltype_t *kltp;

            if (!(t = eval_type(n))) {
                  set_eval_error(E_BAD_TYPE);
                  error_token = n->tok_ptr;
                  return(-1);
            }
            if (t->t_kltp->kl_type != KLT_BASE) {

                  kltp = kl_realtype(t->t_kltp, 0);
                  if (kltp->kl_type != KLT_BASE) {
                        set_eval_error(E_BAD_CAST);
                        error_token = n->tok_ptr;
                        return(-1);
                  }
            }
            n->value = n->right->value;
            n->type = t;
      }
      n->node_type = TYPE_DEF;
      n->operator = 0;
      free_node(n->right);
      n->right = (node_t *)NULL;
      return(0);
}

/*
 * replace_indirection()
 */
static int
replace_indirection(node_t *n, int flags)
{
      kaddr_t addr;
      type_t *t, *tp;

      /* Make sure there is a right child and that it is a TYPE_DEF. 
       */
      if (!n->right) {
            set_eval_error(E_BAD_TYPE);
            error_token = n->tok_ptr;
            return(-1);
      } else if (n->right->node_type != TYPE_DEF) {
            set_eval_error(E_BAD_TYPE);
            error_token = n->right->tok_ptr;
            return(-1);
      }

      if ((flags & C_WHATIS) && (!(POINTER_FLAG|ADDRESS_FLAG))) {
            set_eval_error(E_BAD_WHATIS);
            error_token = n->tok_ptr;
            return(-1);
      }

      /* Make sure the right node contains a pointer value
       */
      if (!(n->right->flags & POINTER_FLAG)) {
            set_eval_error(E_BAD_POINTER);
            error_token = n->right->tok_ptr;
            return(-1);
      }
      
      /* Get the pointer to the first type struct and make sure 
       * it's a pointer.
       */
      if (!(tp = n->right->type) || (tp->flag != POINTER_FLAG)) {
            set_eval_error(E_BAD_TYPE);
            error_token = n->right->tok_ptr;
            return(-1);
      }

      /* Make sure we have a pointer to a type structure.
       */
      if (!(n->right->flags & KLTYPE_FLAG)) {
            set_eval_error(E_BAD_TYPE);
            error_token = n->right->tok_ptr;
            return(-1);
      }

      n->node_type = TYPE_DEF;
      n->flags = KLTYPE_FLAG;
      n->operator = 0;

      if (!(t = eval_type(n->right))) {
            set_eval_error(E_BAD_TYPE);
            error_token = n->right->tok_ptr;
            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(t->t_kltp->kl_name, "char")) {
            n->flags |= STRING_FLAG;
      }
      n->type = tp->t_next;

      /* Free the pointer struct
       */
      kl_free_block((void *)tp);

      /* Get the pointer address 
       */
      addr = n->address = n->right->value;
      n->flags |= ADDRESS_FLAG;

      /* If this is a pointer to a pointer, get the next
       * pointer value.
       */
      if (n->type->flag == POINTER_FLAG) {
            n->value = KL_VREAD_PTR(addr);

            /* Set the appropriate node flag values 
             */
            n->flags |= POINTER_FLAG;
            free_node(n->right);
            n->left = n->right = (node_t *)NULL;
            return(0);
      } 

      /* Zero out the type field in the right child so it doesn't 
       * accidently get freed up when the right child is freed 
       * (upon success).
       */
      n->right->type = (type_t*)NULL;
      free_node(n->right);
      n->left = n->right = (node_t *)NULL;
      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.
 */
static int
replace_unary(node_t *n, int flags)
{
      uint64_t value;

      if (!n->right) {
            set_eval_error(E_MISSING_OPERAND);
            error_token = n->tok_ptr;
            return(-1);
      }
      if (is_unary(n->right->operator)) {
            if (replace_unary(n->right, flags) == -1) {
                  return(-1);
            }
      }
      if (n->operator == CAST) {
            return(replace_cast(n, flags));
      } else if (n->operator == INDIRECTION) {
            return(replace_indirection(n, flags));
      } else if (n->operator == ADDRESS) {
            type_t *t;

            if (n->right->node_type == TYPE_DEF) {
                  if (!(n->right->flags & ADDRESS_FLAG)) {
                        set_eval_error(E_NO_ADDRESS);
                        error_token = n->right->tok_ptr;
                        return(-1);
                  }
                  t = n->right->type;
            } else {
                  set_eval_error(E_BAD_TYPE);
                  error_token = n->right->tok_ptr;
                  return(-1);
            }
            n->type = (type_t*)kl_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))) {
                  set_eval_error(E_BAD_TYPE);
                  error_token = n->tok_ptr;
                  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) == -1) {
            return(-1);
      }
      free_nodes(n->right);
      n->node_type = NUMBER;
      n->operator = 0;
      n->left = n->right = (node_t *)NULL;
      memcpy(&n->value, &value, sizeof(uint64_t));
      return(0);
}

/*
 * pointer_to_element()
 */
static void
pointer_to_element(node_t *n0, node_t *n1)
{
      int size;
      kltype_t *kltp, *rkltp;
      type_t *tp;

      if (!(tp = n0->type)) {
            set_eval_error(E_BAD_INDEX);
            error_token = n0->tok_ptr;
            return;
      } 
      if (tp->t_next->flag == POINTER_FLAG) {
            size = KL_NBPW;
      } else {
            kltp = tp->t_next->t_kltp;
            if (!(rkltp = kl_realtype(kltp, 0))) {
                  set_eval_error(E_BAD_INDEX);
                  error_token = n0->tok_ptr;
                  return;
            }
            size = rkltp->kl_size;
      }

      /* Get the details on the array element
       */
      n0->flags |= ADDRESS_FLAG;
      n0->address = n0->value + (n1->value * size);
      n0->type = tp->t_next;
      kl_free_block(tp);
      if (tp->flag == POINTER_FLAG) {
            n0->flags |= POINTER_FLAG;
            n0->value = KL_VREAD_PTR(n0->address);
      } else {
            n0->flags &= (~POINTER_FLAG);
            n0->value = 0;
      }
}

/*
 * array_to_element()
 */
static void
array_to_element(node_t *n0, node_t *n1)
{
      kltype_t *kltp, *rkltp, *ip, *ep;
      type_t *tp, *troot = (type_t *)NULL;

      if (!(tp = n0->type)) {
            set_eval_error(E_BAD_INDEX);
            error_token = n0->tok_ptr;
            return;
      }

      /* If we are indexing a pointer, then make a call to the
       * pointer_to_element() and return.
       */
      if (tp->flag == POINTER_FLAG) {
            return(pointer_to_element(n0, n1));
      }

      if (!(kltp = n0->type->t_kltp)) {
            set_eval_error(E_BAD_INDEX);
            error_token = n0->tok_ptr;
            return;
      }
      if (!(rkltp = kl_realtype(kltp, KLT_ARRAY))) {
            set_eval_error(E_BAD_INDEX);
            error_token = n0->tok_ptr;
            return;
      }
      ip = rkltp->kl_indextype; 
      ep = rkltp->kl_elementtype;
      if (!ip || !ep) {
            set_eval_error(E_BAD_INDEX);
            error_token = n0->tok_ptr;
            return;
      }
      /* Get the details on the array element
       */
      n0->address = n0->address + (n1->value * ep->kl_size);
      if (ep->kl_flags & POINTER_FLAG) { 
            n0->flags |= POINTER_FLAG;
            n0->value = KL_VREAD_PTR(n0->address);
      }
      n0->value = 0;
      n0->flags |= ADDRESS_FLAG;
      kltp = ep;
      while (kltp->kl_type == KLT_POINTER) {
            if (troot) {
                  tp->t_next = (type_t*)kl_alloc_block(sizeof(type_t), 
                              K_TEMP);
                  tp = tp->t_next;
            } else {
                  tp = (type_t*)kl_alloc_block(sizeof(type_t), K_TEMP);
                  troot = tp;
            }
            tp->flag = POINTER_FLAG;
            kltp = kltp->kl_realtype;
      }
      if (troot) {
            tp->t_next = (type_t*)kl_alloc_block(sizeof(type_t), K_TEMP);
            tp = tp->t_next;
            n0->type = troot;
      } else {
            tp = (type_t*)kl_alloc_block(sizeof(type_t), K_TEMP);
            n0->type = tp;
      }
      tp->flag = KLTYPE_FLAG; 
      tp->t_kltp = ep;
}

/*
 * number_to_size()
 */
int
number_to_size(node_t *np)
{
      int unsigned_flag = 0;

      if (np->node_type != NUMBER) {
            set_eval_error(E_BAD_TYPE);
            error_token = np->tok_ptr;
            return(0);
      }
      if (np->flags & UNSIGNED_FLAG) {
            unsigned_flag = 1;
      } 
      if ((np->value >= 0) && (np->value <= 0xffffffff)) {
            return(4);
      } else if (((np->value >> 32) & 0xffffffff) == 0xffffffff) {
            if (unsigned_flag) {
                  return(8);
            } else if (KL_NBPW == 4) {
                  return(4);
            } else {
                  return(8);
            }
      } 
      return(8);
}

/*
 * number_to_type()
 */
kltype_t *
number_to_type(node_t *np)
{
      int unsigned_flag = 0;
      kltype_t *kltp, *rkltp = (kltype_t *)NULL;

      if (np->node_type != NUMBER) {
            set_eval_error(E_BAD_TYPE);
            error_token = np->tok_ptr;
            return((kltype_t *)NULL);
      }
      if (np->flags & UNSIGNED_FLAG) {
            unsigned_flag = 1;
      } 
      if ((np->value >= 0) && (np->value <= 0xffffffff)) {
            if (unsigned_flag) {
                  kltp = kl_find_type("uint32_t", KLT_TYPEDEF);
            } else {
                  kltp = kl_find_type("int32_t", KLT_TYPEDEF);
            }
      } else if (((np->value >> 32) & 0xffffffff) == 0xffffffff) {
            if (unsigned_flag) {
                  kltp = kl_find_type("uint64_t", KLT_TYPEDEF);
            } else if (KL_NBPW == 4) {
                  kltp = kl_find_type("int32_t", KLT_TYPEDEF);
            } else {
                  kltp = kl_find_type("int64_t", KLT_TYPEDEF);
            }
      } else {
            if (unsigned_flag) {
                  kltp = kl_find_type("uint64_t", KLT_TYPEDEF);
            } else {
                  kltp = kl_find_type("int64_t", KLT_TYPEDEF);
            }
      }
      if (kltp) {
            if (!(rkltp = kl_realtype(kltp, 0))) {
                  rkltp = kltp;
            }
      } else {
            set_eval_error(E_BAD_TYPE);
            error_token = np->tok_ptr;
      }
      return(rkltp);
}

/*
 * type_to_number() 
 *
 * Convert a base type to a numeric value. Return 1 on successful 
 * conversion, 0 if nothing was done.
 */
static int
type_to_number(node_t *np) 
{
      int byte_size, bit_offset, bit_size, encoding;
      uint64_t value, value1;
      kltype_t *kltp, *rkltp;

      /* Sanity check...
       */
      if (np->node_type != TYPE_DEF) {
            set_eval_error(E_NOTYPE);
            error_token = np->tok_ptr;
            return(0);
      }
      if (!np->type) {
            set_eval_error(E_NOTYPE);
            error_token = np->tok_ptr;
            return(0);
      }
      if (np->type->flag == POINTER_FLAG) {
            return(0);
      }

      /* Get the real type record and make sure that it is
       * for a base type.
       */
      kltp = np->type->t_kltp;
      rkltp = kl_realtype(kltp, 0);
      if (rkltp->kl_type != KLT_BASE) {
            set_eval_error(E_NOTYPE);
            error_token = np->tok_ptr;
            return(0);
      }

      byte_size = rkltp->kl_size;
      bit_offset = rkltp->kl_bit_offset;
      if (!(bit_size = rkltp->kl_bit_size)) {
            bit_size = byte_size * 8;
      }
      encoding = rkltp->kl_encoding;
      if (np->flags & ADDRESS_FLAG) {
            GET_BLOCK(np->address, byte_size, &value1);
      } else {
            value1 = np->value;
      }
      value = kl_get_bit_value(&value1, byte_size, bit_size, bit_offset);
      switch (byte_size) {

            case 1 :
                  if (encoding == ENC_UNSIGNED) {
                        np->value = (unsigned char)value;
                        np->flags |= UNSIGNED_FLAG;
                  } else if (encoding == ENC_SIGNED) {
                        np->value = (signed char)value;
                  } else {
                        np->value = (char)value;
                  }
                  break;

            case 2 :
                  if (encoding == ENC_UNSIGNED) {
                        np->value = (uint16_t)value;
                        np->flags |= UNSIGNED_FLAG;
                  } else {
                        np->value = (int16_t)value;
                  }
                  break;

            case 4 :
                  if (encoding == ENC_UNSIGNED) {
                        np->value = (uint32_t)value;
                        np->flags |= UNSIGNED_FLAG;
                  } else {
                        np->value = (int32_t)value;
                  }
                  break;

            case 8 :
                  if (encoding == ENC_UNSIGNED) {
                        np->value = (uint64_t)value;
                        np->flags |= UNSIGNED_FLAG;
                  } else {
                        np->value = (int64_t)value;
                  }
                  break;

            default :
                  set_eval_error(E_BAD_TYPE);
                  error_token = np->tok_ptr;
                  return(0);
      }
      np->byte_size = byte_size;
      np->node_type = NUMBER;
      return(1);
}

/*
 * eval_type()
 */
static 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 == KLTYPE_FLAG) {
            return (t);
      }
      return((type_t*)NULL);
}

/* 
 * expand_variables()
 */
static char *
expand_variables(char *exp, int flags)
{
#ifdef NOTYET
      int len, vcount = 0;
      char vname[64], *s, *e, *v, *newexp;
      variable_t *vp;

      eval_error = 0;

      newexp = (char *)kl_alloc_block(256, flags);
      e = exp;
      v = strchr(e, '$');
      while (v) {
            vcount++;
            vname[0] = 0;
            strncat(newexp, e, (v - e));
            if (s = strpbrk((v + 1), " .\t+-*/()[]|~!$&%^<>?:&=^\"\'")) {
                  len = (uaddr_t)s - (uaddr_t)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 (vcount) {
            if (e) {
                  strcat(newexp, e);
            }
      }
      return(newexp);
#endif
      return((char *)NULL);
}

/*
 * eval()
 */
node_t *
eval(char **exp, int flags)
{
      token_t *tok;
      node_t *n, *root;
      char *e, *s;

      eval_error = 0;
      logical_flag = 0;

      /* Make sure there is an expression to evaluate
       */
      if (!(*exp)) {
            return ((node_t*)NULL);
      }

      /* Expand any variables that are in the expression string. If
       * a new string is allocated by the expand_variables() function,
       * we need to make sure the original expression string gets 
       * freed. In any event, point s at the current expression string 
       * so that it gets freed up when we are done.
       */
      if ((e = expand_variables(*exp, 0))) {
            kl_free_block((void *)*exp);
            *exp = e;
      } else if (eval_error) {
            eval_error |= E_BAD_EVAR;
            error_token = *exp;
      } 
      s = *exp;
      tok = get_token_list(s);
      if (eval_error) { 
            return((node_t*)NULL);
      } 
      
      /* Get the node_list and evaluate the expression.
       */
      node_list = get_node_list(tok, flags);
      if (eval_error) {
            free_nodelist(node_list);
            node_list = (node_t*)NULL;
            free_tokens(tok);
            return((node_t*)NULL);
      }
      if (!(n = do_eval(flags))) {
            if (!eval_error) {
                  set_eval_error(E_SYNTAX_ERROR);
                  error_token = s + strlen(s) - 1;
            }
            free_nodes(n);
            free_tokens(tok);
            return((node_t*)NULL);
      }

      if (!(root = replace(n, flags))) {
            if (eval_error) {
                  free_nodes(n);
                  free_tokens(tok);
                  return((node_t*)NULL);
            }
            root = n;
      }

      /* Check to see if the the result should 
       * be interpreted as 'true' or 'false'
       */
      if (logical_flag && ((root->value == 0) || (root->value == 1))) {
            root->flags |= BOOLIAN_FLAG;
      }
      free_tokens(tok);
      return(root);
}

/*
 * print_number()
 */
void
print_number(node_t *np, FILE *ofp, int flags)
{
      int size;
      uint64_t value;

      if ((size = number_to_size(np)) && (size != sizeof(uint64_t))) {
            value = np->value & (((uint64_t)1 << (uint64_t)(size*8))-1);
      } else {
            value = np->value;
      }
      if (flags & K_HEX) {
            fprintf(ofp, "0x%"FMT64"x", value);
      } else if (flags & K_OCTAL) {
            fprintf(ofp, "0%"FMT64"o", value);
      } else if (flags & K_BINARY) {
            fprintf(ofp, "0b");
            kl_binary_print(value, ofp);
      } else {
            if (np->flags & UNSIGNED_FLAG) {
                  fprintf(ofp, "%"FMT64"u", value);
            } else {
                  fprintf(ofp, "%"FMT64"d", np->value);
            }
      }
}

/*
 * print_string()
 */
void
print_string(kaddr_t addr, int size, FILE *ofp)
{
      int i;
      char *str;

      if (!size) {
            size = 255;
      }
      str = (char*)kl_alloc_block(size, K_TEMP);
      GET_BLOCK(addr, size, str);
      fprintf(ofp, "\"%s", str);
      for (i = 0; i < size; i++) {
            if (!str[i]) {
                  break;
            }
      }
      if (KL_ERROR || (i == size)) {
            fprintf(ofp, "...");
      }
      fprintf(ofp, "\"");
      kl_free_block(str);
}

/*
 * print_eval_results()
 */
int
print_eval_results(node_t *np, FILE *ofp, int flags)
{
      int size;
      kaddr_t addr;

      /* Print the results
       */
      switch (np->node_type) {

            kltype_t *kltp, *rkltp;

            case NUMBER:
                  print_number(np, ofp, flags);
                  break;

            case TYPE_DEF: {

                  if (np->flags & POINTER_FLAG) {
                        /* XXX prepend the pointer type before
                           value of pointer */
                        fprintf(ofp, "(%s *) ",
                              np->type->un.next->un.kltp->kl_typestr);
                        fprintf(ofp, "0x%"FMT64"x", np->value);
                        if (np->type->t_next->flag == POINTER_FLAG) {
                              break;
                        }
                        kltp = np->type->t_next->t_kltp;
                        if (kltp->kl_encoding == ENC_CHAR) {
                              fprintf(ofp, " ");
                              print_string(np->value, 0, ofp);
                        }
                        break;
                  }
                  if (np->flags & KLTYPE_FLAG) {
                        void * ptr;

                        /* Get the type information. It's possible
                         * that the type is a member. In which case,
                         * the size may only be from this record
                         * (which would be the casse if this is an 
                         * array). We must check the original type
                         * record first, and try the realtype record
                         * if the value is zero.
                         */
                        kltp = np->type->t_kltp;

                        /* Check to see if this is a typedef. If
                         * it is, then it might be a typedef for
                         * a pointer type. Don't walk to the last
                         * type record.
                         */
                        if ((rkltp = kl_realtype(kltp, KLT_TYPEDEF))) {
                              while (rkltp->kl_realtype) {
                                    rkltp = rkltp->kl_realtype;
                                    if (rkltp->kl_type ==
                                        KLT_POINTER) {
                                          break;
                                    }
                                    if((rkltp->kl_name != 0) && 
                                       !(strcmp(rkltp->kl_name,
                                              "void"))) {
                                          /* we are about to
                                           * dereference a void*
                                           */
                                          fprintf(KL_ERRORFP,
                         "Can't dereference a generic pointer.\n");
                                          return(1);
                                    }
                              }
                              if (rkltp->kl_type == KLT_POINTER) {
                                    fprintf(ofp, "0x%"FMT64"x", 
                                          np->value);
                                    break;
                              }
                        }
                        rkltp = kl_realtype(kltp, 0);
                        size = rkltp->kl_size;
                        if (!size || (size < 0)) {
                              size = kltp->kl_size;
                        }

                        if(rkltp->kl_type==KLT_ARRAY) {
                              size = rkltp->kl_high_bounds -
                                    rkltp->kl_low_bounds + 1;
                              if(rkltp->kl_elementtype == NULL){
                                    fprintf(KL_ERRORFP,
                                          "Incomplete array"
                                          " type.\n");
                                          return(1);
                              }
                              if(rkltp->kl_elementtype->kl_type ==
                                 KLT_POINTER){
                                    size *= KL_NBPW;
                              } else {
                                    size *= rkltp->kl_elementtype->kl_size;
                              }
                        }
                        if(size){
                              ptr = kl_alloc_block(size, K_TEMP);
                        } else {
                              ptr = NULL;
                        }
                        if ((rkltp->kl_type == KLT_BASE) && 
                                    !(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;
                              }
                              kl_print_type(ptr, rkltp, 0, 
                                    flags|SUPPRESS_NAME, ofp);
                              kl_free_block(ptr);
                              return(1);
                        }

                        if(size){
                              addr = np->address;
                              GET_BLOCK(addr, size, ptr);
                              if (KL_ERROR) {
                                    kl_print_error();
                                    kl_free_block(ptr);
                                    return(1);
                              }
                        }     
                        /* Print out the actual type
                         */
                        switch (rkltp->kl_type) {
                              case KLT_STRUCT:
                              case KLT_UNION:
                                    kl_print_type(ptr, rkltp, 0, 
                                          flags, ofp);
                                    break;

                              case KLT_ARRAY:
                                    kl_print_type(ptr, rkltp, 0, 
                                          flags|
                                          SUPPRESS_NAME, ofp);
                                    break;

                              default:
                                    kl_print_type(ptr, rkltp, 0, 
                                          (flags|
                                          SUPPRESS_NAME|
                                          SUPPRESS_NL), ofp);
                                    break;
                        }
                        if(ptr){
                              kl_free_block(ptr);
                        }
                  }
                  break;
            }

            case VADDR:
                  /* 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%"FMT64"x", np->address);
                  break;

            default:
                  if (np->node_type == TEXT) {
                        kl_print_string(np->name, ofp);
                        if (KL_ERROR) {
                              kl_print_error();
                              return(1);
                        }
                  } else if (np->node_type == CHARACTER) {
                        fprintf(ofp, "\'%c\'", (char)np->value);
                  }
                  break;
      }
      return(0);
}

/*
 * print_eval_error()
 */
void
print_eval_error(
      char *cmdname, 
      char *s, 
      char *bad_ptr, 
      uint64_t error, 
      int flags)
{
      int i, cmd_len;

      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_STRUCTURE :
                  fprintf(KL_ERRORFP, "Invalid structure\n");
                  break;

            case E_MISSING_STRUCTURE :
                  fprintf(KL_ERRORFP, "Missing structure\n");
                  break;

            case E_BAD_MEMBER :
                  fprintf(KL_ERRORFP, "No such member\n");
                  break;

            case E_BAD_OPERATOR :
                  fprintf(KL_ERRORFP, "Invalid operator\n");
                  break;

            case E_MISSING_OPERAND :
                  fprintf(KL_ERRORFP, "Missing operand\n");
                  break;

            case E_BAD_OPERAND :
                  fprintf(KL_ERRORFP, "Invalid operand\n");
                  break;

            case E_BAD_TYPE :
                  fprintf(KL_ERRORFP, "Invalid type\n");
                  break;

            case E_NOTYPE :
                  fprintf(KL_ERRORFP, 
                        "Could not find type information\n");
                  break;

            case E_BAD_POINTER :
                  fprintf(KL_ERRORFP, "Invalid pointer\n");
                  break;

            case E_BAD_INDEX :
                  fprintf(KL_ERRORFP, "Invalid array index\n");
                  break;

            case E_BAD_CHAR :
                  fprintf(KL_ERRORFP, "Invalid character value\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, "Invalid eval variable\n");
                  break;

            case E_BAD_VALUE :
                  fprintf(KL_ERRORFP, "Invalid value\n");
                  break;

            case E_NO_VALUE :
                  fprintf(KL_ERRORFP, "No value supplied\n");
                  break;

            case E_DIVIDE_BY_ZERO :
                  fprintf(KL_ERRORFP, "Divide by zero\n");
                  break;

            case E_BAD_CAST :
                  fprintf(KL_ERRORFP, "Invalid cast\n");
                  break;

            case E_NO_ADDRESS :
                  fprintf(KL_ERRORFP, "Not an address\n");
                  break;

            case E_SINGLE_QUOTE :
                  fprintf(KL_ERRORFP, "Missing single quote\n");
                  break;

            case E_BAD_WHATIS :
                  fprintf(KL_ERRORFP, "Invalid whatis Operation\n");
                  break;

            case E_NOT_IMPLEMENTED :
                  fprintf(KL_ERRORFP, "Not implemented\n");
                  break;

            default :
                  fprintf(KL_ERRORFP, "Syntax error\n");
                  break;
      }
}


Generated by  Doxygen 1.6.0   Back to index