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

kl_typeinfo.c

/*
 * $Id: kl_typeinfo.c,v 1.1 2004/12/21 23:26:20 tjm Exp $
 *
 * This file is part of libklib.
 * A library which provides access to Linux system kernel dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, NEC, and others
 *
 * Copyright (C) 1999 - 2004 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <klib.h>

/*
 * kl_find_type() -- find a KLT type by name.
 */
kltype_t *
kl_find_type(char *name, int tnum)
{
      dbg_sym_t *stp;
      kltype_t *kltp = (kltype_t *)NULL;

      if (!tnum || IS_TYPE(tnum)) {
            if ((stp = dbg_find_sym(name, DBG_TYPE, 0))) {
                  kltp = (kltype_t *)stp->sym_kltype;
                  if (tnum && !(kltp->kl_type & tnum)) {
                        /* We have found a type by this name
                         * but it does not have the right 
                         * type number (e.g., we're looking
                         * for a struct and we don't find
                         * a KLT_STRUCT type by this name).
                         */
                        return((kltype_t *)NULL);
                  }
            }
      }
      if (!tnum || IS_TYPEDEF(tnum)) {
            if ((stp = dbg_find_sym(name, DBG_TYPEDEF, 0))) {
                  kltp = (kltype_t *)stp->sym_kltype;
            }
      }
      return(kltp);
}

/*
 * kl_find_next_type() -- find next KLT type 
 */
kltype_t *
kl_find_next_type(kltype_t *kltp, int type)
{
      kltype_t *nkltp = NULL;
      dbg_sym_t *nstp;

      if (kltp && kltp->kl_ptr) {
            nstp = (dbg_sym_t *)kltp->kl_ptr;
            nkltp = (kltype_t *)nstp->sym_kltype;
            if (type) {
                  while(nkltp && !(nkltp->kl_type & type)) {
                        if ((nstp = dbg_next_sym(nstp))) {
                              nkltp = (kltype_t *)nstp->sym_kltype;
                        } else {
                              nkltp = (kltype_t *)NULL;
                        }
                  }
            }
      }
      return(nkltp);
}

/*
 * kl_first_type()
 */
kltype_t *
kl_first_type(int tnum)
{
      kltype_t *kltp = NULL;
      dbg_sym_t *stp;

      if (IS_TYPE(tnum)) {
            /* If (tnum == KLT_TYPE), then return the first type
             * record, regardless of the type. Otherwise, search
             * for the frst type that mapps into tnum.
             */
            if ((stp = dbg_first_sym(DBG_TYPE))) {
                  kltp = (kltype_t *)stp->sym_kltype;
                  if (tnum != KLT_TYPE) {
                        while (kltp && !(kltp->kl_type & tnum)) {
                              if ((stp = dbg_next_sym(stp))) {
                                    kltp = (kltype_t *)stp->sym_kltype;
                              } else {
                                    kltp = (kltype_t *)NULL;
                              }
                        }
                  }
            }
      } else if (IS_TYPEDEF(tnum)) {
            if ((stp = dbg_first_sym(DBG_TYPEDEF))) {
                  kltp = (kltype_t *)stp->sym_kltype;
            }
      }
      return(kltp);
}

/*
 * kl_next_type()
 */
kltype_t *
kl_next_type(kltype_t *kltp)
{
      dbg_sym_t *stp, *nstp;
      kltype_t *nkltp = (kltype_t *)NULL;

      if (!kltp) {
            return((kltype_t *)NULL);
      }
      stp = (dbg_sym_t *)kltp->kl_ptr;
      if ((nstp = dbg_next_sym(stp))) {
            nkltp = (kltype_t *)nstp->sym_kltype;
      }
      return(nkltp);
}

/*
 * kl_prev_type()
 */
kltype_t *
kl_prev_type(kltype_t *kltp)
{
      dbg_sym_t *stp, *pstp;
      kltype_t *pkltp = (kltype_t *)NULL;

      if (!kltp) {
            return((kltype_t *)NULL);
      }
      stp = (dbg_sym_t *)kltp->kl_ptr;
      if ((pstp = dbg_prev_sym(stp))) {
            pkltp = (kltype_t *)pstp->sym_kltype;
      }
      return(pkltp);
}

/*
 * kl_realtype()
 */
kltype_t *
kl_realtype(kltype_t *kltp, int tnum)
{
      kltype_t *rkltp = kltp;

      while (rkltp) {
            if (tnum && (rkltp->kl_type == tnum)) {
                  break;
            }
            if (!rkltp->kl_realtype) {
                  break;
            }
            if (rkltp->kl_realtype == rkltp) {
                  break;
            }
            rkltp = rkltp->kl_realtype;
            if (rkltp == kltp) {
                  break;
            }
      }
      return(rkltp);
}

/*
 * find type by typenum
 */
kltype_t *
kl_find_typenum(uint64_t typenum)
{
      kltype_t *kltp;

      kltp = (kltype_t *)dbg_find_typenum(typenum);
      return(kltp);
}

/*
 * kl_get_similar_typedef()
 */
int
kl_get_first_similar_typedef(char *name, char *fullname)
{
      btnode_t* stp;

      if(!name) {
            return(-1);
      }
      stp = _kl_find_btnode((btnode_t *)typedef_tree, 
                  name, NULL, strlen(name));
      if(stp){
            strcpy(fullname, stp->bt_key);
            return(0);
      } else {
            return(-1);
      }
}

/*
 * kl_type_size()
 */
int
kl_type_size(kltype_t *kltp)
{
      kltype_t *rkltp;

      if (!kltp) {
            return(0);
      }
      if (!(rkltp = kl_realtype(kltp, 0))) {
            return(0);
      }
      return(rkltp->kl_size);
}

/*      
 * kl_struct_len()
 */      
int     
kl_struct_len(char *s)
{               
      kltype_t *kltp;

      if ((kltp = kl_find_type(s, (KLT_STRUCT|KLT_UNION)))) {
            return(kltp->kl_size);
      }
      return(0);
}       

/*
 * kl_get_member()
 */
kltype_t *
kl_get_member(kltype_t *kltp, char *f)
{
      kltype_t *mp;

      if ((mp = kltp->kl_member)) {
            while (mp) {
                  if (!strcmp(mp->kl_name, f)) {
                        break;
                  }
                  mp = mp->kl_member;
            }
      }
      return(mp);
}

/*
 * kl_find_member()
 */
kltype_t *
kl_find_member(char *s, char *f)
{
      kltype_t *kltp, *mp = NULL;
      
      if (!(kltp = kl_find_type(s, (KLT_STRUCT|KLT_UNION)))) {
            if ((kltp = kl_find_type(s, KLT_TYPEDEF))) {
                  kltp = kl_realtype(kltp, 0);
            }
      }
      if (kltp) {
            mp = kl_get_member(kltp, f);
      }
      return(mp);
}

/*
 * kl_member_offset()
 */
int
kl_member_offset(char *s, char *f)
{       
      kltype_t *mp;

      if ((mp = kl_find_member(s, f))) {
            return(mp->kl_offset);
      }     
      return(-1);
}

/*
 * kl_is_member()
 */
int
kl_is_member(char *s, char *f)
{
      kltype_t *mp;

      if ((mp = kl_find_member(s, f))) {
            return(1);
      }
      return(0);
}

/*
 * kl_member_size()
 */
int
kl_member_size(char *s, char *f)
{
      kltype_t *mp;
      
      if ((mp = kl_find_member(s, f))) {
            return(mp->kl_size);
      }
      return(0);
}

#define TAB_SPACES                 8
#define LEVEL_INDENT(level, flags) {\
      int i, j; \
      if (!(flags & NO_INDENT)) { \
            for (i = 0; i < level; i++) { \
                  for (j = 0; j < TAB_SPACES; j++) { \
                        fprintf(ofp, " "); \
                  } \
            }\
      } \
}
#define PRINT_NL(flags, ofp) \
      if (!(flags & SUPPRESS_NL)) { \
            fprintf(ofp, "\n"); \
      }

/* 
 * kl_print_typedef_type()
 */
void
kl_print_typedef_type(
      void *ptr, 
      kltype_t *kltp, 
      int level, 
      int flags, 
      FILE *ofp)
{
      kltype_t *rkltp;

      if (ptr) {
            rkltp = kltp->kl_realtype;
            while (rkltp->kl_type == KLT_TYPEDEF) {
                  if (rkltp->kl_realtype) {
                        rkltp = rkltp->kl_realtype;
                  }
            }
            if (rkltp->kl_type == KLT_POINTER) {
                  kl_print_pointer_type(ptr, kltp, level, flags, ofp);
                  return;
            } 
            switch (rkltp->kl_type) {
                  case KLT_BASE:
                        kl_print_base_type(ptr, kltp, 
                              level, flags, ofp);
                        break;

                  case KLT_UNION:
                  case KLT_STRUCT:
                        kl_print_struct_type(ptr, kltp, 
                              level, flags, ofp);
                        break;

                  case KLT_ARRAY:
                        kl_print_array_type(ptr, kltp, 
                              level, flags, ofp);
                        break;

                  case KLT_ENUMERATION:
                        kl_print_enumeration_type(ptr, 
                              kltp, level, flags, ofp);
                        break;

                  default:
                        kl_print_base_type(ptr, kltp, 
                              level, flags, ofp);
                        break;
            }
      } else {
            LEVEL_INDENT(level, flags);
            rkltp = kltp->kl_realtype;
            while (rkltp && rkltp->kl_type == KLT_POINTER) {
                  rkltp = rkltp->kl_realtype;
            }
            if (rkltp && rkltp->kl_type == KLT_FUNCTION) {
                  if (kltp->kl_realtype->kl_type == KLT_POINTER) {
                        fprintf(ofp, "typedef %s(*%s)();", 
                              kltp->kl_typestr, kltp->kl_name);
                  } else {
                        fprintf(ofp, "typedef %s(%s)();", 
                              kltp->kl_typestr, kltp->kl_name);
                  }
            } else {
                  if (SUPPRESS_NAME) {
                        fprintf(ofp, "%s", kltp->kl_typestr);
                  } else {
                        fprintf(ofp, "typedef %s%s;", 
                              kltp->kl_typestr, kltp->kl_name);
                  }
            } 
            PRINT_NL(flags, ofp);
      }
}

/*
 * kl_print_pointer_type()
 */
void
kl_print_pointer_type(
      void *ptr, 
      kltype_t *kltp, 
      int level, 
      int flags, 
      FILE *ofp)
{
      kltype_t *itp;

      if (kltp->kl_type == KLT_MEMBER) {
            itp = kltp->kl_realtype;
      } else {
            itp = kltp;
      }

      /* See if this is a pointer to a function. If it is, then it
       * has to be handled differently...
       */ 
      while (itp->kl_type == KLT_POINTER) {
            if ((itp = itp->kl_realtype)) {
                  if (itp->kl_type == KLT_FUNCTION) {
                        kl_print_function_type(ptr, 
                              kltp, level, flags, ofp);
                        return;
                  }
            } else {
                  LEVEL_INDENT(level, flags);
                  fprintf(ofp, "%s%s;\n", 
                        kltp->kl_typestr, kltp->kl_name);
                  return;
            }
      }

      LEVEL_INDENT(level, flags);
      if (ptr) {
            kaddr_t tmp = KL_GET_PTR(ptr);
            if(kltp->kl_name){
            if (*(kaddr_t *)ptr) {
                  fprintf(ofp, "%s = 0x%"FMTPTR"x", 
                        kltp->kl_name, tmp); 
            } else {
                  fprintf(ofp, "%s = (nil)", kltp->kl_name); 
            }
      } else {
                  if (tmp != 0) {
                        fprintf(ofp, "0x%"FMTPTR"x", tmp); 
                  } else {
                        fprintf(ofp, "(nil)"); 
                  }
            }
      } else {
            if (kltp->kl_typestr) {
                  if (kltp->kl_name) {
                        fprintf(ofp, "%s%s;", 
                              kltp->kl_typestr, kltp->kl_name);
                  } else {
                        fprintf(ofp, "%s;", kltp->kl_typestr);
                  }
            } else {
                  fprintf(ofp, "<UNKNOWN>;");
            }
      }
      PRINT_NL(flags, ofp);
}

/*
 * kl_print_function_type()
 */
void
kl_print_function_type(
      void *ptr, 
      kltype_t *kltp, 
      int level, 
      int flags, 
      FILE *ofp)
{
      LEVEL_INDENT(level, flags);
      if (ptr) {
            kaddr_t a;
            a = KL_GET_PTR(ptr);
            fprintf(ofp, "%s = 0x%"FMTPTR"x", 
                  kltp->kl_name, a); 
      } else { 
            if (flags & SUPPRESS_NAME) {
                  fprintf(ofp, "%s(*)()", kltp->kl_typestr);
            } else {
                  fprintf(ofp, "%s(*%s)();", 
                        kltp->kl_typestr, kltp->kl_name);
            }
      }
      PRINT_NL(flags, ofp);
}

/*
 * kl_print_array_type()
 */
void
kl_print_array_type(void *ptr, kltype_t *kltp, int level, int flags, FILE *ofp)
{
      int i, count = 0, size, low, high;
      char *typestr, *name, *p;
      kltype_t *rkltp, *etp;

      if (kltp->kl_type != KLT_ARRAY) {
            rkltp = kltp->kl_realtype;
            while (rkltp->kl_type != KLT_ARRAY) {
                  if (!(rkltp = rkltp->kl_realtype)) {
                        break;
                  }
            }
            if (!rkltp) {
                  LEVEL_INDENT(level, flags);
                  fprintf(ofp, "<ARRAY_TYPE>;");
                  PRINT_NL(flags, ofp);
                  return;
            }
      } else {
            rkltp = kltp;
      }

      etp = rkltp->kl_elementtype;
      while (etp && (etp->kl_type == KLT_TYPEDEF)) {
            etp = etp->kl_realtype;
      }
      if (!etp) {
            LEVEL_INDENT(level, flags);
            fprintf(ofp, "<BAD_ELEMENT_TYPE> %s;\n", rkltp->kl_name);
            PRINT_NL(flags, ofp);
            return;
      }
      low = rkltp->kl_low_bounds;
      high = rkltp->kl_high_bounds;

      if (ptr) {

            p = ptr;

            if ((etp->kl_size == 1) && (etp->kl_encoding == ENC_CHAR)) {
                  LEVEL_INDENT(level, flags);
                  if (flags & SUPPRESS_NAME) {
                        fprintf(ofp, "\"");
                        flags &= ~SUPPRESS_NAME;
                  } else {
                        fprintf(ofp, "%s = \"", kltp->kl_name);
                  }
                  for (i = 0; i < high; i++) {
                        if (*(char*)p == 0) {
                              break;
                        }
                        fprintf(ofp, "%c", *(char *)p);
                        p++;
                  }
                  fprintf(ofp, "\"");
                  PRINT_NL(flags, ofp);
            } else {
                  LEVEL_INDENT(level, flags);
                  if (flags & SUPPRESS_NAME) {
                        fprintf(ofp, "{\n");
                        flags &= ~SUPPRESS_NAME;
                  } else {
                        fprintf(ofp, "%s = {\n", kltp->kl_name);
                  }

                  if (etp->kl_type == KLT_POINTER) {
                        size = KL_NBPW;
                  } else {
                        size = etp->kl_size;
                  }
                  for (i = low; i <= high; i++) {

                        LEVEL_INDENT(level + 1, flags);
                        fprintf(ofp, "[%d] ", i);

                        switch (etp->kl_type) {
                              case KLT_POINTER :
                                    kl_print_pointer_type(p, etp, 
                                          level, flags, ofp);
                                    break;

                              case KLT_TYPEDEF:
                                    kl_print_typedef_type(p, etp, 
                                          level, flags, ofp);
                                    break;

                              case KLT_BASE:
                                    kl_print_base_value(p, 
                                          etp, flags, ofp);
                                    fprintf(ofp, "\n");
                                    break;

                              case KLT_STRUCT:
                              case KLT_UNION:
                                    kl_print_struct_type(p, 
                                          etp, level + 1, 
                                          flags|NO_INDENT, ofp);
                                    break;

                              default:
                                    kl_print_base_value(p, 
                                          etp, flags, ofp);
                                    fprintf(ofp, "\n");
                                    break;
                        }
                        p = (void *)((uaddr_t)p + size);
                  }
                  LEVEL_INDENT(level, flags);
                  fprintf(ofp, "}");
                  PRINT_NL(flags, ofp);
            }
      } else {
            if (rkltp) {
                  count = (rkltp->kl_high_bounds - 
                              rkltp->kl_low_bounds) + 1;
            } else {
                  count = 1;
            }
            LEVEL_INDENT(level, flags);
            if (flags & SUPPRESS_NAME) {
                  typestr = etp->kl_typestr;
                  fprintf(ofp, "%s[%d]", typestr, count);
            } else {
                  typestr = kltp->kl_typestr;
                  name = kltp->kl_name;
                  fprintf(ofp, "%s%s[%d];", typestr, name, count);
            }
            PRINT_NL(flags, ofp);
      }
}

/*
 * kl_print_enumeration_type()
 */
void
kl_print_enumeration_type(
      void *ptr, 
      kltype_t *kltp, 
      int level, 
      int flags, 
      FILE *ofp)
{
      uint64_t val;
      kltype_t *mp, *rkltp;

      rkltp = kl_realtype(kltp, KLT_ENUMERATION);
      if (ptr) {
            switch (kltp->kl_size) {
                  case 1:
                        val = KL_GET_UINT8(ptr);
                        break;

                  case 2:
                        val = KL_GET_UINT16(ptr);
                        break;

                  case 4:
                        val = KL_GET_UINT32(ptr);
                        break;

                  case 8:
                        val = KL_GET_UINT64(ptr);
                        break;
            }
            mp = rkltp->kl_member;
            while (mp) {
                  if (mp->kl_value == val) {
                        break;
                  }
                  mp = mp->kl_member;
            }
            LEVEL_INDENT(level, flags);
            if (mp) {
                  fprintf(ofp, "%s = (%s=%"FMT64"d)", 
                        kltp->kl_name, mp->kl_name, val);
            } else {
                  fprintf(ofp, "%s = %"FMT64"d", kltp->kl_name, val);
            }
            PRINT_NL(flags, ofp);
      } else {
            LEVEL_INDENT(level, flags);
            fprintf (ofp, "%s {", kltp->kl_typestr);
            mp = rkltp->kl_member;
            while (mp) {
                  fprintf(ofp, "%s = %d", mp->kl_name, mp->kl_value);
                  if ((mp = mp->kl_member)) {
                        fprintf(ofp, ", ");
                  }
            }
            mp = kltp;
            if (level) {
                  fprintf(ofp, "} %s;", mp->kl_name);
            } else {
                  fprintf(ofp, "};");
            }
            PRINT_NL(flags, ofp);
      }
}

/*
 * kl_print_base_value()
 */
void
kl_print_base_value(void *ptr, kltype_t *kltp, int flags, FILE *ofp)
{
      kltype_t *rkltp;

      if (kltp->kl_type != KLT_BASE) {
            if (!(rkltp = kltp->kl_realtype)) {
                  return;
            }
            if (rkltp->kl_type != KLT_BASE) {
                  return;
            }
      } else {
            rkltp = kltp;
      }
      kl_print_base(ptr, rkltp->kl_size, rkltp->kl_encoding, flags, ofp); 
}

/*
 * kl_print_base_type()
 */
void
kl_print_base_type(void *ptr, kltype_t *kltp, int level, int flags, FILE *ofp)
{
      LEVEL_INDENT(level, flags);
      if (ptr) {
            if (!(flags & SUPPRESS_NAME))  {
                  fprintf (ofp, "%s = ", kltp->kl_name);
            }
      }
      if (kltp->kl_type == KLT_MEMBER) {
            if (kltp->kl_bit_size < (kltp->kl_size * 8)) {
                  if (ptr) {
                        kl_print_bit_value(ptr, kltp->kl_size, 
                              kltp->kl_bit_size, 
                              kltp->kl_bit_offset, flags, ofp);
                  } else {
                        if (kltp->kl_name) {
                              fprintf (ofp, "%s%s :%d;",
                                    kltp->kl_typestr, 
                                    kltp->kl_name, 
                                    kltp->kl_bit_size);
                        } else {
                              fprintf (ofp, "%s :%d;", 
                                    kltp->kl_typestr, 
                                    kltp->kl_bit_size);
                        }
                  }
                  PRINT_NL(flags, ofp);
                  return;
            }
      } 
      if (ptr) {
            kltype_t *rkltp;

            rkltp = kl_realtype(kltp, 0);
            if (rkltp->kl_encoding == ENC_UNDEFINED) {
                  /* This is a void value
                   */
                  fprintf(ofp, "<VOID>");
            } else {
                  kl_print_base(ptr, kltp->kl_size, 
                        rkltp->kl_encoding, flags, ofp); 
            }
      } else {
            if (kltp->kl_type == KLT_MEMBER) {
                  if (flags & SUPPRESS_NAME) {
                        fprintf (ofp, "%s", kltp->kl_typestr);
                  } else {
                        if (kltp->kl_name) {
                              fprintf(ofp, "%s%s;", kltp->kl_typestr, 
                                    kltp->kl_name);
                        } else {
                              fprintf (ofp, "%s :%d;", 
                                    kltp->kl_typestr, 
                                    kltp->kl_bit_size);
                        }
                  }
            } else {
                  if (SUPPRESS_NAME) {
                        fprintf(ofp, "%s", kltp->kl_name);
                  } else { 
                        fprintf(ofp, "%s;", kltp->kl_name);
                  }
            }
      }
      PRINT_NL(flags, ofp);
}

/*
 * kl_print_member()
 */
void
kl_print_member(void *ptr, kltype_t *mp, int level, int flags, FILE *ofp)
{
      int kl_type = 0;
      kltype_t *rkltp;

      if ((rkltp = mp->kl_realtype)) {
            kl_type = rkltp->kl_type;
      }
      switch (kl_type) {
            case KLT_STRUCT:
            case KLT_UNION:
                  kl_print_struct_type(ptr, mp, level, flags, ofp);
                  break;
            case KLT_ARRAY:
                  kl_print_array_type(ptr, mp, level, flags, ofp);
                  break;
            case KLT_POINTER:
                  kl_print_pointer_type(ptr, mp, level, flags, ofp);
                  break;
            case KLT_FUNCTION:
                  kl_print_function_type(ptr, mp, level, flags, ofp);
                  break;
            case KLT_BASE:
                  kl_print_base_type(ptr, mp, level, flags, ofp);
                  break;
              case KLT_ENUMERATION:
                  kl_print_enumeration_type(ptr, mp, level, flags, ofp);
                  break;
            case KLT_TYPEDEF: 
                  while (rkltp && rkltp->kl_realtype) {
                        if (rkltp->kl_realtype == rkltp) {
                              break;
                        }
                        rkltp = rkltp->kl_realtype;
                  }
                  if (ptr) {
                        kl_print_typedef_type(ptr, mp, 
                              level, flags, ofp);
                        break;
                  } 
                  LEVEL_INDENT(level, flags);
                  if (flags & SUPPRESS_NAME) {
                        if (rkltp && (mp->kl_bit_size < 
                                    (rkltp->kl_size * 8))) {
                              fprintf (ofp, "%s :%d", 
                                    mp->kl_typestr, 
                                    mp->kl_bit_size);
                        } else {
                              fprintf(ofp, "%s", 
                                    mp->kl_realtype->kl_name);
                        }
                  } else {
                        if (rkltp && (mp->kl_bit_size < 
                                    (rkltp->kl_size * 8))) {
                              if (mp->kl_name) {
                                    fprintf (ofp, "%s%s :%d;",
                                          mp->kl_typestr, 
                                          mp->kl_name, 
                                          mp->kl_bit_size);
                              } else {
                                    fprintf (ofp, "%s :%d;", 
                                          mp->kl_typestr, 
                                          mp->kl_bit_size);
                              }
                        } else {
                              fprintf(ofp, "%s %s;", 
                                    mp->kl_realtype->kl_name, 
                                    mp->kl_name);
                        }
                  }
                  PRINT_NL(flags, ofp);
                  break;

            default:
                  LEVEL_INDENT(level, flags);
                  if (mp->kl_typestr) {
                        fprintf(ofp, "%s%s;", 
                              mp->kl_typestr, mp->kl_name);
                  } else {
                        fprintf(ofp, "<\?\?\?> %s;", mp->kl_name);
                  }
                  PRINT_NL(flags, ofp);
                  break;
      }
}

/*
 * kl_print_struct_type()
 */
void
kl_print_struct_type(void *buf, kltype_t *kltp, int level, int flags, FILE *ofp)
{
      void *ptr = NULL;
      kltype_t *mp, *rkltp;

      LEVEL_INDENT(level, flags);
      if ((level == 0) || (flags & NO_INDENT)) {
            fprintf(ofp, "%s{\n", kltp->kl_typestr);
      } else {
            if (buf) {
                  if (level) {
                        fprintf(ofp, "%s = %s{\n", 
                              kltp->kl_name, kltp->kl_typestr);
                  } else {
                        fprintf(ofp, "%s{\n", kltp->kl_typestr);
                  }
                  flags &= (~SUPPRESS_NL);
            } else {
                  if (kltp->kl_typestr) {
                        fprintf(ofp, "%s{\n", kltp->kl_typestr);
                  } else {
                        fprintf(ofp, "<UNKNOWN> {\n");
                  }
            }
      }

      /* If the NO_INDENT is set, we need to turn it off at this
       * point -- just in case we come across a member of this struct
       * that is also a struct.
       */
      if (flags & NO_INDENT) {
            flags &= ~(NO_INDENT);
      }

      if (kltp->kl_type == KLT_MEMBER) {
            rkltp = kl_realtype(kltp, 0);
      } else {
            rkltp = kltp;
      }
      level++;
      if ((mp = rkltp->kl_member)) {
            while (mp) {
                  if (buf) {
                        ptr = buf + mp->kl_offset;
                  }
                  kl_print_member(ptr, mp, level, flags, ofp);
                  mp = mp->kl_member;
            }
      } else {
            if (kltp->kl_flags & TYP_INCOMPLETE_FLG) {
                  LEVEL_INDENT(level, flags);
                  fprintf(ofp, "<INCOMPLETE TYPE>\n");
            }
      }
      level--;
      LEVEL_INDENT(level, flags);

      /* kl_size = 0 for empty structs */
      if (ptr || ((kltp->kl_size == 0) && buf)) { 
            fprintf(ofp, "}");
      } else if (kltp->kl_type == KLT_MEMBER) {
            fprintf(ofp, "} %s;", kltp->kl_name);
      } else {
            fprintf(ofp, "};");
      }
      PRINT_NL(flags, ofp);
}

/*
 * kl_print_type()
 */
void
kl_print_type(void *buf, kltype_t *kltp, int level, int flags, FILE *ofp)
{
      void *ptr;

      if (buf) {
            if (kltp->kl_offset) {
                  ptr = (void *)((uaddr_t)buf + kltp->kl_offset);
            } else {
                  ptr = buf;
            }
      } else {
            ptr = 0;
      }

      /* Only allow binary printing for base types
       */
      if (kltp->kl_type != KLT_BASE) {
            flags &= (~K_BINARY);
      }
      switch (kltp->kl_type) {

            case KLT_TYPEDEF:
                  kl_print_typedef_type(ptr, kltp, level, flags, ofp);
                  break;

            case KLT_STRUCT:
            case KLT_UNION:
                  kl_print_struct_type(ptr, kltp, level, flags, ofp);
                  break;

            case KLT_MEMBER:
                  kl_print_member(ptr, kltp, level, flags, ofp);
                  break;

            case KLT_POINTER:
                  kl_print_pointer_type(ptr, kltp, level, flags, ofp);
                  break;

            case KLT_FUNCTION:
                  LEVEL_INDENT(level, flags);
                  kl_print_function_type(ptr, kltp, level, flags, ofp);
                  break;

            case KLT_ARRAY:
                  kl_print_array_type(ptr, kltp, level, flags, ofp);
                  break;

            case KLT_ENUMERATION:
                  kl_print_enumeration_type(ptr, 
                        kltp, level, flags, ofp);
                  break;

            case KLT_BASE:
                  kl_print_base_type(ptr, kltp, level, flags, ofp);
                  break;

            default:
                  LEVEL_INDENT(level, flags);
                  if (flags & SUPPRESS_NAME) {
                        fprintf (ofp, "%s", kltp->kl_name);
                  } else {
                        fprintf (ofp, "%s %s;", 
                              kltp->kl_name, kltp->kl_name);
                  }
                  PRINT_NL(flags, ofp);
      }
}

Generated by  Doxygen 1.6.0   Back to index