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

cmd_whatis.c

/*
 * $Id: cmd_whatis.c,v 1.1 2004/12/21 23:26:19 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>

void whatis_usage(command_t *);

/*
 * single_type()
 */
int
single_type(command_t *cmd)
{
      int type_cnt = 0, hit_count, i;
      kltype_t *kltp;
      char *cp, buffer[256], *type_name;
      syment_t *sp;
      static char *types[] = {"struct", "union", "enum", NULL};

      type_name = buffer;
      if (cmd->args[0][0] == '\"') {
            strcpy(type_name, &cmd->args[0][1]);
            if ((cp = strchr(type_name, '\"'))) {
                  *cp = 0;
            }
      } else {
            strcpy(type_name, cmd->args[0]);
      }

      /* strip leading syntatic sugar */
      for (i = 0; types[i]; i++) {
            if (!strncmp(type_name, types[i], strlen(types[i]))) {
                  type_name += strlen(types[i]);
                  break;
            }
      }

      hit_count = 0;
      if ((kltp = kl_find_type(type_name, KLT_TYPE))) {
            hit_count++;

            if (cmd->flags & C_LIST) {
                  if (cmd->flags & C_NEXT) {
                        walk_ktype(kltp, cmd->flags, cmd->ofp);
                  } else {
                        ktype_banner(cmd->ofp, (BANNER|SMAJOR));
                        print_ktype(kltp, cmd->flags, cmd->ofp);
                  }
            } else {
                  kl_print_type((void *)NULL, kltp, 
                        0, cmd->flags, cmd->ofp);
            }
      }
      if ((kltp = kl_find_type(type_name, KLT_TYPEDEF))) {
            if (hit_count) {
                  fprintf(cmd->ofp, "\n");
            }
            hit_count++;
            if (cmd->flags & C_LIST) {
                  if (cmd->flags & C_NEXT) {
                        walk_ktype(kltp, cmd->flags, cmd->ofp);
                  } else {
                        ktype_banner(cmd->ofp, (BANNER|SMAJOR));
                        print_ktype(kltp, cmd->flags, cmd->ofp);
                  }
            } else {
                  kltype_t *rkltp;

                  kl_print_type((void *)NULL, kltp, 
                        0, cmd->flags, cmd->ofp);
                  rkltp = kltp->kl_realtype;
                  while (rkltp && (rkltp->kl_type == KLT_POINTER)) {
                        rkltp = rkltp->kl_realtype;
                  }
                  while (rkltp && (rkltp->kl_realtype)
                         && (rkltp != rkltp->kl_realtype)) {
                        rkltp = rkltp->kl_realtype;
                  }

                  if (rkltp && ((rkltp->kl_type == KLT_STRUCT) ||
                            (rkltp->kl_type == KLT_UNION) ||
                            (rkltp->kl_type == KLT_ENUMERATION))) { 
                              
                        kl_print_type((void *)NULL, rkltp, 0, 
                              cmd->flags, cmd->ofp);
                  } else if (!rkltp) {
                        fprintf(cmd->efp, 
                              "Type information not available\n");
                  }
            }
      }
      if ((sp = kl_lkup_symname(type_name))) {
            if (hit_count) {
                  fprintf(cmd->ofp, "\n");
            }
            hit_count++;
            symbol_banner(cmd->ofp, BANNER|SMAJOR);
            kl_print_symbol(0, sp, cmd->flags);
      }

      if (hit_count) {
            type_cnt += hit_count;
      } else {
            fprintf(KL_ERRORFP, "could not find type information for %s\n",
            type_name);
      } 
      return(type_cnt);
}

/*
 * whatis_cmd() -- Run the 'whatis' command.
 */
int
whatis_cmd(command_t *cmd)
{
      int i, j = 0, ptr_cnt = 0, type_cnt = 0, flags;
      kltype_t *kltp, *rkltp;
      char *buf;
      node_t *np;
      type_t *tp;

      if (cmd->nargs == 0) {
            if (cmd->flags & C_ALL) {
                  type_cnt = list_ktypes(cmd->flags, cmd->ofp);
            } else {
                  fprintf(KL_ERRORFP, "Invalid commandline.\n");
                  whatis_usage(cmd);
                  return(1);
            }
      } else if ((cmd->nargs == 1) && !strpbrk(cmd->args[0], 
            "\'.-()*&0123456789")) {
            type_cnt = single_type(cmd);
      } else {
            /* Count the number of bytes necessary to hold the 
             * entire expression string.
             */
            for (i = 0; i < cmd->nargs; i++) {
                  j += (strlen(cmd->args[i]) + 1);
            }

            /* Allocate space for the expression string and copy 
             * the individual arguments into it.
             */
            buf = (char *)kl_alloc_block(j, K_TEMP);
            for (i = 0; i < cmd->nargs; i++) {
                  strcat(buf, cmd->args[i]);
                  if ((i + 1) < cmd->nargs) {
                        strcat(buf, " ");
                  }
            }

            /* Evaluate the expression
             */
            np = eval(&buf, C_WHATIS|C_NOVARS);
            if (!np || eval_error) {
                  print_eval_error(cmd->command, buf,
                        (error_token ? error_token : (char*)NULL), 
                        eval_error, CMD_NAME_FLG);
                  kl_free_block((void *)buf);
                  free_nodes(np);
                  free_eval_memory();
                  return(1);
            }

            /* Print the results
             */
            if ((tp = np->type)) {
                  while (tp && (tp->flag == POINTER_FLAG)) {
                        ptr_cnt++;
                        tp = tp->t_next;
                  }
            }
            if (!tp || (tp->flag != KLTYPE_FLAG)) {
                  if (!(kltp = number_to_type(np))) {
                        fprintf(cmd->efp, 
                              "Type information not available\n");
                        free_eval_memory();
                        free_nodes(np);
                        return(1);
                  }
            } else {
                  kltp = tp->t_kltp;
            }
            if (cmd->flags & C_LIST) {
                  rkltp = kl_realtype(kltp, 0);
                  if (!rkltp) {
                        rkltp = kltp;
                  }
                  if (cmd->flags & C_NEXT) {
                        walk_ktype(rkltp, cmd->flags, cmd->ofp);
                  } else {
                        ktype_banner(cmd->ofp, (BANNER|SMAJOR));
                        print_ktype(rkltp, cmd->flags, cmd->ofp);
                  }
            } else {
                  if (!(rkltp = kl_realtype(kltp, KLT_FUNCTION))) {
                        fprintf(cmd->efp, "Could not find real "
                              "type information\n");
                        free_eval_memory();
                        free_nodes(np);
                        return(1);
                  } 
                  if (rkltp->kl_type == KLT_FUNCTION) {
                        kl_print_type((void *)NULL, kltp, 0, 
                              flags|SUPPRESS_NAME, cmd->ofp);
                  } else if (ptr_cnt) {
                        switch(rkltp->kl_type) {
                              case KLT_STRUCT:
                                    fprintf(cmd->ofp, "struct ");
                                    break;

                              case KLT_UNION:
                                    fprintf(cmd->ofp, "union ");
                                    break;

                              case KLT_ENUMERATION:
                                    break;
                        }
                        fprintf(cmd->ofp, "%s ", rkltp->kl_name); 
                        while(ptr_cnt) {
                              fprintf(cmd->ofp, "*"); 
                              ptr_cnt--;
                        }
                        fprintf(cmd->ofp, "\n");
                  } else if ((rkltp->kl_type == KLT_STRUCT) ||
                              (rkltp->kl_type == KLT_UNION) ||
                              (rkltp->kl_type == KLT_ENUMERATION)) {
                        kl_print_type((void *)NULL, rkltp, 0, 
                              cmd->flags, cmd->ofp);
                  } else {
                        kl_print_type((void *)NULL, kltp, 0, 
                              cmd->flags|SUPPRESS_NAME, cmd->ofp);
                  }
#ifdef NOT
                  } else if (kltp->kl_realtype && 
                        (kltp->kl_realtype->kl_type == KLT_TYPEDEF)) { 

                        kl_print_type((void *)NULL, kltp, 0, 
                              cmd->flags|SUPPRESS_NAME, cmd->ofp);
                  } else {
                        kl_print_type((void *)NULL, rkltp, 0, 
                              flags, cmd->ofp);
                  } 
#endif
            }
            type_cnt++;
            if (buf) {
                  kl_free_block(buf);
            }
            free_nodes(np);
      }

      if (cmd->flags & C_LIST) {
            ktype_banner(cmd->ofp, SMAJOR);
            PLURAL("type", type_cnt, cmd->ofp);
      }
      free_eval_memory();
      return(0);
}

#define _WHATIS_USAGE "[-a] [-f] [-l] [-n] [-w outfile] expression"

/*
 * whatis_usage() -- Print the usage string for the 'whatis' command.
 */
void
whatis_usage(command_t *cmd)
{
      CMD_USAGE(cmd, _WHATIS_USAGE);
}

/*
 * whatis_help() -- Print the help information for the 'whatis' command.
 */
void
whatis_help(command_t *cmd)
{
      CMD_HELP(cmd, _WHATIS_USAGE,
      "Display, in C-like fashion, detailed information about kernel "
      "types (structs, unions, typedefs, base types, etc.) If the "
      "-a option is specified, display a list of all types. If the -l " 
      "option is specified, display type information in tabular form. "
      "When the -f option is specified, along with the -l option, "
      "display additional information about the type. If the -n option "
      "is specified for a struct or union, along with the -l option, "
      "display information about each member.");
}

/*
 * whatis_parse() -- Parse the command line arguments for 'whatis'.
 */
int
whatis_parse(command_t *cmd)
{
      if (set_cmd_flags(cmd, (C_ALL|C_LIST|C_FULL|C_NEXT|
                        C_WRITE|C_NO_OPCHECK), 0)) {
            return(1);
      }
      return(0);
}

/*
 * whatis_complete() -- Complete arguments of 'whatis' command.
 */
char *
whatis_complete(command_t *cmd)
{
      char *ret;

      /* complete standard options (for example, -w option) arguments
       */
      if ((ret = complete_standard_options(cmd)) != NOT_COMPLETED) {
            return(ret);
      }
      fprintf(cmd->ofp, "\n");
      whatis_usage(cmd);
      return(DRAW_NEW_ENTIRE_LINE);
}

Generated by  Doxygen 1.6.0   Back to index