/* db.c : part of The Bastard disassembly environment =========================
 *
 * Contains routines for interfacing with the Typhoon database module. Typhoon
 * is pretty self-sufficient, so there will not be much here. 
 */
#include <cli/bastard_main.h>
#include <cli/parser.h>
#include <db/typhoon.h>


struct DB_CMD_TBL {
   char *cmd;
   int  id;
} db_cmd_tbl[] = {
   {"HELP", DB_HELP},
   {"DESC", DB_DESC}, 
   {"DUMP", DB_DUMP}, 
   {"MIN", DB_MIN},
   {"MAX", DB_MAX}, 
   {"COUNT", DB_COUNT},
   {"FIND", DB_FIND}, 
   {"PRINT", DB_PRINT}, 
   {NULL, 0}
};

struct dbPrintFuncTable {
        char *name;
        int table;
        dbPrintFunc func;
} static dbPrintFuncs[] = {
     { "SECTION", SECTION, dbPrintSection },
     { "ADDRESS", ADDRESS, dbPrintAddress },
     { "CODE", CODE, dbPrintCode },
     { "ADDR_EXP", ADDR_EXP, dbPrintAddrExp },
     { "CODE_EFFECT", CODE_EFFECT, dbPrintCodeEffect },
     { "INT_CODE", INT_CODE, dbPrintIntCode },
     { "FIN_CODE", FIN_CODE, dbPrintFinCode },
     { "NAME", NAME, dbPrintName },
     { "COMMENT", COMMENT, dbPrintComment },
     { "XREF", XREF, dbPrintXref },
     { "IMPORT_ADDR", IMPORT_ADDR, dbPrintImport },
     { "LIB", LIB, dbPrintLib },
     { "EXPORT_ADDR", EXPORT_ADDR, dbPrintExport },
     { "STRING", STRING, dbPrintString },
     { "FUNCTION", FUNCTION, dbPrintFunction },
     { "FUNC_PARAM", FUNC_PARAM, dbPrintFuncParam },
     { "FUNC_LOCAL", FUNC_LOCAL, dbPrintFuncLocal },
     { "FUNC_EFFECT", FUNC_EFFECT, dbPrintFuncEffect },
     { "F_INLINE", F_INLINE, dbPrintInline },
     { "STRUCTURE", STRUCTURE, dbPrintStructure },
     { "STRUCT_MEMBER", STRUCT_MEMBER, dbPrintStructMember },
    { "DATA_TYPE", DATA_TYPE, dbPrintDataType },
    { "CONSTANT", CONSTANT, dbPrintConstant },
    { "BC_MACRO", BC_MACRO, dbPrintMacro},
   { NULL, 0, NULL}
};

int TranslateDBTable( char *table ){
   int x;

   strtoupper( table, strlen(table) + 1 );
   for (x = 0; dbPrintFuncs[x].name; x++){
      if (! strcmp(dbPrintFuncs[x].name, table))
         return(x);
   }
   return(-1);
}

int TranslateDBCmd( char *cmd ){
   int x;

   strtoupper( cmd, strlen(cmd) + 1 );
   for (x = 0; db_cmd_tbl[x].cmd; x++){
      if (! strcmp(db_cmd_tbl[x].cmd, cmd))
         return(x);
   }
   return( DB_HELP );
}

/* DB interpeter commands */
void db_cmd(int argc, char **argv, struct COMMAND *c){
   int tbl, cmd;
   
   if (!argc) {
      Message("Seek HELP\n");
       return ; 
   }

   tbl = TranslateDBTable( argv[0]);   
   cmd = TranslateDBCmd(c->subcmd);
   if ( tbl != -1)
      (*dbPrintFuncs[tbl].func)(db_cmd_tbl[cmd].id);
   return;
};

/* utils */
int dbCount( int idx ){
   int n;
   d_recfrst(idx);
   while( db_status == S_OKAY){
      n++;
      d_recnext(idx);
   }
   return(n);
}

void dbPrintSection(int cmd){
   struct section sec;
   int n = 0;

   switch (cmd) {
   case DB_DESC:      /* DESC */
      printf("struct section {\n\tchar name[32];\n\tunsigned long rva;\n\t"
             "unsigned short size;\n\tint flags;\n};\n");
      break;
   case DB_DUMP:      /* DUMP */
      printf("Name\t\tRVA\tSize\tFlags\n\n");
      d_keyfrst(SECTION_RVA);
      while (db_status == S_OKAY) {
              dbPrintSection( DB_PRINT );
              d_keynext(SECTION_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(SECTION_RVA);
      dbPrintSection( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(SECTION_RVA);
      dbPrintSection( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(SECTION));
      break;
   case DB_FIND:         /* FIND */
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&sec);
      printf("%s\t\t%lX\t%d\t%X\n", sec.name, sec.rva, sec.size, sec.flags);
      break;
   default:
   }
   return;
}
void dbPrintAddress(int cmd){
   struct address addr;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct address {\n\tunsigned long rva;\n\tunsigned long pa;\n\t"
             "unsigned short size;\n\tint flags;\n};\n");
      break;
   case DB_DUMP:
      printf("RVA\tPA\tSize\tFlags\n\n");
      d_keyfrst(ADDRESS_RVA);
      while (db_status == S_OKAY) {
         dbPrintAddress(DB_PRINT);
         d_keynext(ADDRESS_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(ADDRESS_RVA);
      dbPrintAddress( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(ADDRESS_RVA);
      dbPrintAddress( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(ADDRESS));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&addr);
      printf("%lX\t%lX\t%d\t%X\n", 
            addr.rva, addr.pa, addr.size, addr.flags); 
      break;
   default:
   }
   return;
}
void dbPrintCode(int cmd){
   struct code c;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct code {\n\t unsigned long rva;\n\t"
             "char mnemonic[16];\n\tlong dest;\n\tlong src;\n\t"
             "long aux;\n\tint mnemType;\n\tint destType;\n\tint srcType;"
             "\n\tint auxType;\n};\n");
      break;
   case DB_DUMP:
      printf("RVA\tMnem\tDest\tSrc\tAux\tMType\tDType\tSType\tAType\n");
      d_keyfrst(CODE_RVA);
      while (db_status == S_OKAY) {
              dbPrintCode(DB_PRINT);
              d_keynext(CODE_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(CODE_RVA);
      dbPrintCode( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(CODE_RVA);
      dbPrintCode( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(CODE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&c);
      printf("%lX\t%s\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
            c.rva, c.mnemonic, c.dest, c.src, c.aux,
             c.mnemType, c.destType, c.srcType, c.auxType); 
      break;
   default:
   }
   return;
}
void dbPrintAddrExp(int cmd){
   struct addr_exp a;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct addr_exp {\n\tunsigned long id;\n\tint scale;\n\t"
             "int index;\n\tint base;\n\tint disp;\n\tint flags;\n\t"
             "unsigned long name;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tScale\tIndex\tBase\tDisp\tFlags\tName\n");
      d_keyfrst(ADDR_EXP_ID);
      while (db_status == S_OKAY) {
         dbPrintAddrExp( DB_PRINT );
         d_keynext(ADDR_EXP_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(ADDR_EXP_ID);
      dbPrintAddrExp( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(ADDR_EXP_ID);
      dbPrintAddrExp( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(INT_CODE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&a);
      printf("%lu\t%x\t%x\t%x\t%x\t%x\t%lu\n",
               a.id, a.scale, a.index, a.base, a.disp, a.flags, a.name);
      break;
   default:
   }
   return;
}
void dbPrintCodeEffect(int cmd){
   struct code_effect e;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct code_effect {\n\tunsigned long id;\n\t"
             "unsigned long rva;\n\tint reg;\n\tint change;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tRVA\tReg\tChange\n");
      d_keyfrst(CODE_EFFECT_ID);
      while (db_status == S_OKAY) {
              dbPrintCodeEffect(DB_PRINT);
              d_keynext(CODE_EFFECT_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(CODE_EFFECT_ID);
      dbPrintCodeEffect( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(CODE_EFFECT_ID);
      dbPrintCodeEffect( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(CODE_EFFECT));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&e);
      printf("%d\t%lX\t%d\t%d\n", e.id, e.rva, e.reg, e.change);
      break;
   default:
   }
   return;
}
void dbPrintIntCode(int cmd){
   struct int_code c;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct int_code {\n\tunsigned long id;\n\tunsigned long rva;\n\t"
             "int size;\n\tchar lvalue[32];\n\tchar rvalue[64];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tRVA\tSize\tLValue\t\tRValue\n");
      d_keyfrst(INT_CODE_ID);
      while (db_status == S_OKAY) {
         dbPrintIntCode( DB_PRINT );
         d_keynext(INT_CODE_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(INT_CODE_ID);
      dbPrintIntCode( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(INT_CODE_ID);
      dbPrintIntCode( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(INT_CODE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&c);
      printf("%lu\t%d\t%d\t%s\t\t%s\n",
               c.id, c.rva, c.size, c.lvalue, c.rvalue);
      break;
   default:
   }
   return;
}
void dbPrintFinCode(int cmd){
   struct fin_code c;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct fin_code {\n\tunsigned long id;\n\tunsigned long rva;\n\t"
             "int size;\n\tchar line[256];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tRVA\tSize\tLine\n");
      d_keyfrst(FIN_CODE_ID);
      while (db_status == S_OKAY) {
         dbPrintFinCode( DB_PRINT );
         d_keynext(FIN_CODE_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(FIN_CODE_ID);
      dbPrintFinCode( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(FIN_CODE_ID);
      dbPrintFinCode( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(FIN_CODE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&c);
      printf("%lu\t%d\t%d\t%s\n", c.id, c.rva, c.size, c.line);
      break;
   default:
   }
   return;
}
void dbPrintName(int cmd){
   struct name n;
   int x = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct name {\n\tunsigned long rva;\n\tchar name[64];\n\t"
            "int type;\n};\n");
      break;
   case DB_DUMP:
      printf("Rva\tName\tType\n\n");
      d_keyfrst(NAME_RVA);
      while (db_status == S_OKAY) {
         dbPrintName( DB_PRINT );
         d_keynext(NAME_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(NAME_RVA);
      dbPrintName( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(NAME_RVA);
      dbPrintName( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(NAME));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&n);
      printf("%lX\t%s\t%lX\n", n.rva, n.name, n.type); 
      break;
   default:
   }
   return;
}
void dbPrintComment(int cmd){
   struct comment c;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct comment {\n\tunsigned long id;\n\tint type;\n\t"
             "char text[256];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tRVA\tText\tType\n");
      d_keyfrst(COMMENT_ID);
      while (db_status == S_OKAY) {
         dbPrintComment( DB_PRINT );
         d_keynext(COMMENT_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(COMMENT_ID);
      dbPrintComment( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(COMMENT_ID);
      dbPrintComment( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(COMMENT));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&c);
      printf("%lu\t%lX\t%s\n", c.id, c.type, c.text); 
      break;
   default:
   }
   return;
}
void dbPrintXref(int cmd){
   struct xref x;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct xref {\n\tint id;\n\tlong from_rva;\n\tlong to_rva;"
             "\n\tint type;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\t\tFrom\t\tTo\tType\n\n");
      d_keyfrst(XREF_ID);
      while (db_status == S_OKAY) {
         dbPrintXref( DB_PRINT );
         d_keynext(XREF_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(XREF_ID);
      dbPrintXref( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(XREF_ID);
      dbPrintXref( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(XREF));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&x);
      printf("%lu\t%08X\t%08X\t%d\n", x.id,x.from_rva,x.to_rva,x.type); 
      break;
   default:
   }
   return;
}
void dbPrintImport(int cmd){
   struct import_addr i;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct import {\n\tint lib;\n\tint type;"
             "\n\tunsigned long rva;\n};\n");
      break;
   case DB_DUMP:
      printf("Lib\t\tType\tRVA\n\n");
      d_keyfrst(IMPORT_ADDR_RVA);
      while (db_status == S_OKAY) {
         dbPrintImport( DB_PRINT);
         d_keynext(IMPORT_ADDR_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(IMPORT_ADDR_RVA);
      dbPrintImport( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(IMPORT_ADDR_RVA);
      dbPrintImport( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(IMPORT_ADDR));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&i);
      printf("%d\t\t\t%d\t%lX\n", i.library, i.type, i.rva); 
      break;
   default:
   }
   return;
}
void dbPrintLib(int cmd){
   struct lib l;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct lib {\n\tint id;\n\tchar name;\n\tint ver_hi;\n\t"
             "int ver_lo;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tname\t\tversion\n\n");
      d_keyfrst(LIB_ID);
      while (db_status == S_OKAY) {
         dbPrintLib( DB_PRINT );
         d_keynext(LIB_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(LIB_ID);
      dbPrintLib( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(LIB_ID);
      dbPrintLib( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(LIB));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&l);
      printf("%d\t%s\t\t%d.%d\n", l.id, l.name, l.ver_hi, l.ver_lo); 
      break;
   default:
   }
   return;
}
void dbPrintExport(int cmd){
   struct export_addr e;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct export {\n\tunsigned long rva;"
             "\n};\n");
      break;
   case DB_DUMP:
      printf("RVA\n\n");
      d_keyfrst(EXPORT_ADDR_RVA);
      while (db_status == S_OKAY) {
         dbPrintExport( DB_PRINT );
         d_keynext(EXPORT_ADDR_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(EXPORT_ADDR_RVA);
      dbPrintExport( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(EXPORT_ADDR_RVA);
      dbPrintExport( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(EXPORT_ADDR));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&e);
      printf("%lX\n", e.rva); 
      break;
   default:
   }
   return;
}
void dbPrintString(int cmd){
   struct string s;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct string {\n\tunsigned long rva;\n\tint length;\n\t"
             "char text[256];\n\t};\n");
      break;
   case DB_DUMP:
      printf("ID\tRVA\tText\n\n");
      d_keyfrst(STRING_RVA);
      while (db_status == S_OKAY) {
         dbPrintString( DB_PRINT);
         d_keynext(STRING_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(STRING_RVA);
      dbPrintString( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(STRING_RVA);
      dbPrintString( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(STRING));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&s);
      printf("%lX\t%s\n", s.rva, s.length, s.text); 
      break;
   default:
   }
   return;
}
void dbPrintFunction(int cmd){
   struct function f;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct function {\n\tunsigned long id;\n\t"
             "unsigned long rva;\n\tunsigned short size;\n\t"
             "unsigned long ret_type;\n\tunsigned long comment\n};\n");
      break;
   case DB_DUMP:
      printf("RVA\tSize\tReturn Type\tComment\n\n");
      d_keyfrst(FUNCTION_RVA);
      while (db_status == S_OKAY) {
         dbPrintFunction( DB_PRINT );
         d_keynext(FUNCTION_RVA);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(FUNCTION_RVA);
      dbPrintFunction( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(FUNCTION_RVA);
      dbPrintFunction( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(FUNCTION));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&f);
      printf("%lX\t%d\t%d\t%d\n", f.rva, f.size, f.ret_type, f.comment); 
      break;
   default:
   }
   return;
}

void dbPrintFuncParam(int cmd){
   struct func_param f;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct func_param {\n\tunsigned long id;\n\tunsigned long func;"
             "\n\tunsigned long type;\n\tint offset;\n\tchar name[32];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tFunc\tType\tOffset\tName\n\n");
      d_keyfrst(FUNC_PARAM_ID);
      while (db_status == S_OKAY) {
         dbPrintFuncParam( DB_PRINT );
         d_keynext(FUNC_PARAM_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(FUNC_PARAM_ID);
      dbPrintFuncParam( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(FUNC_PARAM_ID);
      dbPrintFuncParam( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(FUNC_PARAM));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&f);
      printf("%lu\t%lu\t%lu\t%d\t%s\n", f.id, f.func, f.type, f.addr_exp, 
                                       f.name); 
      break;
   default:
   }
   return;
}

void dbPrintFuncLocal(int cmd){
   struct func_local f;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct func_local {\n\tunsigned long id;\n\tunsigned long func;"
             "\n\tunsigned long type;\n\tint offset;\n\tchar name[32];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tFunc\tType\tOffset\tName\n\n");
      d_keyfrst(FUNC_LOCAL_ID);
      while (db_status == S_OKAY) {
         dbPrintFuncLocal( DB_PRINT );
         d_keynext(FUNC_LOCAL_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(FUNC_LOCAL_ID);
      dbPrintFuncLocal( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(FUNC_LOCAL_ID);
      dbPrintFuncLocal( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(FUNC_LOCAL));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&f);
      printf("%lu\t%lu\t%lu\t%d\t%s\n", f.id, f.func, f.type, f.addr_exp, 
                                       f.name); 
      break;
   default:
   }
   return;
}

void dbPrintFuncEffect(int cmd){
   struct func_effect e;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct func_effect {\n\tunsigned long id;\n\t"
             "unsigned long func;\n\tint reg;\n\tint change;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tFunc\tReg\tChange\n");
      d_keyfrst(FUNC_EFFECT_ID);
      while (db_status == S_OKAY) {
              dbPrintFuncEffect(DB_PRINT);
              d_keynext(FUNC_EFFECT_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(FUNC_EFFECT_ID);
      dbPrintFuncEffect( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(FUNC_EFFECT_ID);
      dbPrintFuncEffect( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(FUNC_EFFECT));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&e);
      printf("%d\t%d\t%d\t%d\n", e.id, e.func, e.reg, e.change);
      break;
   default:
   }
   return;
}
void dbPrintInline(int cmd){
   struct f_inline f;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct f_inline {\n\tunsigned long id;\n\tchar name[64];\n\t"
             "unsigned long rva;\n\tunsigned short size;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tName\t\tRVA\tSize\n\n");
      d_keyfrst(F_INLINE_ID);
      while (db_status == S_OKAY) {
         dbPrintInline( DB_PRINT );
         d_keynext(F_INLINE_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(F_INLINE_ID);
      dbPrintInline( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(F_INLINE_ID);
      dbPrintInline( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(F_INLINE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&f);
      printf("%lu\t%s\t\t%lX\t%d\n", f.id, f.name, f.rva, f.size); 
      break;
   default:
   }
   return;
}

void dbPrintStructure(int cmd){
   struct structure s;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct structure {\n\tunsigned long id;\n\tchar name[32];\n\t"
             "unsigned short size;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tName\t\tSize\n\n");
      d_keyfrst(STRUCTURE_ID);
      while (db_status == S_OKAY) {
         dbPrintStructure( DB_PRINT );
         d_keynext(STRUCTURE_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(STRUCTURE_ID);
      dbPrintStructure( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(STRUCTURE_ID);
      dbPrintStructure( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(STRUCTURE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&s);
      printf("%lu\t%s\t\t%d\n", s.id, s.name, s.size); 
      break;
   default:
   }
   return;
}

void dbPrintStructMember(int cmd){
   struct struct_member s;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct struct_member {\n\tunsigned long id;\n\t"
            "unsigned long type;\n\tint size;\n\tunsigned long structure\n\t"
            "int order;\n\tchar name[32];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tType\tSize\tStruct\tOrder\tName\n\n");
      d_keyfrst(STRUCT_MEMBER_ID);
      while (db_status == S_OKAY) {
         dbPrintStructMember( DB_PRINT);
         d_keynext(STRUCT_MEMBER_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(STRUCT_MEMBER_ID);
      dbPrintStructMember( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(STRUCT_MEMBER_ID);
      dbPrintStructMember( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(STRUCT_MEMBER));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&s);
      printf("%lu\t%lu\t%d\t%lu\t%d\t%s\n", s.id, s.type, s.size, s.structure, 
                                       s.order, s.name); 
      break;
   default:
   }
   return;
}

void dbPrintDataType(int cmd){
   struct data_type d;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct data_type {unsigned long id;\n\tint size\n\t"
             "char name[32];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tSize\tName\n\n");
      d_keyfrst(DATA_TYPE_ID);
      while (db_status == S_OKAY) {
         dbPrintDataType( DB_PRINT);
         d_keynext(DATA_TYPE_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(DATA_TYPE_ID);
      dbPrintDataType( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(DATA_TYPE_ID);
      dbPrintDataType( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(DATA_TYPE));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&d);
      printf("%lu\t%d\t%s\n", d.id, d.size, d.name); 
      break;
   default:
   }
   return;
}

void dbPrintConstant(int cmd){
   struct constant c;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct constant {\n\tunsigned long id\n\t"
             "char name[32];\n\tlong value;\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tName\t\tValue\n\n");
      d_keyfrst(CONSTANT_ID);
      while (db_status == S_OKAY) {
         dbPrintConstant(DB_PRINT);
         d_keynext(CONSTANT_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(CONSTANT_ID);
      dbPrintConstant( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(CONSTANT_ID);
      dbPrintConstant( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(CONSTANT));
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&c);
      printf("%lu\t%s\t\t%lX\n", c.id, c.name, c.value); 
      break;
   default:
   }
   return;
}
void dbPrintMacro(int cmd){
   struct bc_macro m;
   int n = 0;

   switch (cmd) {
   case DB_DESC:
      printf("struct bc_macro {\n\tunsigned long id\n\t"
            "char name[32];\n\tchar macro[256];\n};\n");
      break;
   case DB_DUMP:
      printf("ID\tName\t\tMacro\n\n");
      d_keyfrst(BC_MACRO_ID);
      while (db_status == S_OKAY) {
         dbPrintMacro(DB_PRINT);
         d_keynext(BC_MACRO_ID);
      }
      printf("\n");
      break;
   case DB_MIN:         /* MIN */
      d_keyfrst(BC_MACRO_ID);
      dbPrintMacro( DB_PRINT );
      break;
   case DB_MAX:         /* MAX */
      d_keylast(BC_MACRO_ID);
      dbPrintMacro( DB_PRINT );
      break;
   case DB_COUNT:         /* COUNT */
      printf("Count: %d records\n", dbCount(BC_MACRO) );
      break;
   case DB_PRINT:         /* PRINT CURRENT RECORD */
      d_recread(&m);
      printf("%lu\t%s\t\t%s\n", m.id, m.name, m.macro); 
      break;
   default:
   }
   return;
}
