bankdump.c 5.78 KB
/*====================================================================
 * bankdump.c
 *
 * Copyright 1995, Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
 * Inc.; the contents of this file may not be disclosed to third
 * parties, copied or duplicated in any form, in whole or in part,
 * without the prior written permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to
 * restrictions as set forth in subdivision (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS
 * 252.227-7013, and/or in similar or successor clauses in the FAR,
 * DOD or NASA FAR Supplement. Unpublished - rights reserved under the
 * Copyright Laws of the United States.
 *====================================================================*/

#include <libaudio.h>
#include <stdio.h>
#include <stdlib.h>
#include <bstring.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <ultratypes.h>
#include <audiotools.h>

#define	TABLESIZE	8192		/* must be a power of 2 */
#define M1		71
#define M2		578393
#define M3		358723

ALSymFileObj *hashtable[TABLESIZE];

static char usage[] = "<symbol file>";

static int              name2offset(char *name);
static char             *offset2name(int offset);
static char             *readFile(char *name);
static int              hash(char *str);
static int              rehash(int h);
static int              enter(char *str, ALSymFileObj *obj);
static ALSymFileObj     *lookup(char *name);

ALSymFile           *symFile;
ALSymFileObj        *symFileObj;

char *class[] = {
    "",
    "Bank      ",
    "Instrument",
    "Sound     ",
    "Key Map   ",
    "Wave Table",
    "Loop      ",
    "Bank File ",
    "Envelope  ",
    "ADPCM Book",
    "Sound File"
};

main(int argc, char **argv)
{
    char                *ofile = NULL;

    extern char         *optarg;
    extern int          optind;
    int                 errflg=0;
    int                 c;
    int                 verbose;
    char                *ptr;
    int                 i;
    ALSymFileObj        *obj;
    
    while ((c = getopt(argc, argv, "v")) != EOF) {        
        switch (c) {
            case 'v':
                verbose = 1;
            case '?':
                errflg++;
                break;
        }
    }

    if (errflg || optind == argc) {
        (void)fprintf(stderr, "%s %s\n", argv[0], usage);
        exit (2);
    }

    symFile    = (ALSymFile *)readFile(argv[optind]);
    symFileObj = (ALSymFileObj *)((char *)symFile + sizeof(ALSymFile));
    
    if(symFile->revision != AL_SYM_FILE_VERSION)
    {
        fprintf(stderr,"File %s is not a supported symbol file\n",argv[optind]);
        exit(-1);
    }
    
    /*
     * Enter all the strings in the hash table.  Assume that there is
     * one string for every object.
     */
    ptr = (char *)&symFileObj[symFile->objectCount];
    printf("Id\tClass\t\tOffset\tRef Count\tName\n");
    
    /*
     * Enter the strings in the hash table for later reference
     */
    for (i = 0; i < symFile->objectCount; i++) {
        obj = &symFileObj[i];
        
        printf("[%4d]\t%s\t0x%x\t\t%d\t%s\n", obj->objectId,
               class[obj->objectClass], obj->bankFileOffset, obj->refCount,
               ptr);

        enter(ptr, &symFileObj[i]);
        ptr += (strlen(ptr) + 1);
    }
}

/*
 * A simple and mediocre hash table implementation.  This will go into
 * an infinite loop when the hash table fills up.
 */

/* This returns an integer hash value for a string. */
static int hash(char *str)
{
    char c;
    int h = 0;
    while ((c = *str++) != '\0')
        h = (h * M1 + (int) c);
    return(h);
}

/*
 * If hash location is already full, this computes a new hash address
 * to try.
 */
static int rehash(int h)
{
    return(h +1);
}

static int enter(char *str, ALSymFileObj *obj)
{
    int h = hash(str);

    while (1) {
        int i = (h & TABLESIZE-1);
        if (!hashtable[i]) {
            hashtable[i] = obj;
            return(i);
        } else {
            /* try again */
            h = rehash(h);
        }
    }
}

static ALSymFileObj *lookup(char *name)
{
    char *str;
    
    int h = hash(name);
    while (1) {
        int i = (h & TABLESIZE-1);
        ALSymFileObj *entry = hashtable[i];
        str = (char *)symFile + entry->stringOffset;
        
        if (entry == NULL) {
            return 0;
        } else if (strcmp(name, str) == 0) {
            return(entry);
        } else {
            /* try again */
            h = rehash(h);
        }
    }
}

/*
 * matches bank object name to bank file object offset
 */
static int name2offset(char *name)
{
    ALSymFileObj *symFileObj = lookup(name);

    if (symFileObj)
        return symFileObj->bankFileOffset;
    else
        return 0;
}

/*
 * matches bank object offset to bank file object name
 */
static char *offset2name(int offset)
{
    int i;
    
    /*
     * could use a quicker search algorithm here
     */
    for (i = 0; i < symFile->objectCount; i++) {
        if (symFileObj[i].bankFileOffset = offset)
            return (char *)symFile + symFileObj[i].stringOffset;
    }
    
    return 0;
}

static char *readFile(char *name)
{
    FILE *file;
    char *ptr;
    int   len;
    int   rv;
    
    file = fopen(name, "r");
    if (!file) {
        fprintf(stderr, "error: couldn't open file %s\n", name);
        exit(1);
    }
    
    fseek(file, 0, SEEK_END);
    len = ftell(file);
    rewind(file);
    
    ptr = malloc(len);
    if (!ptr) {
        fprintf(stderr, "error: couldn't allocate memory for file %s\n", name);
        exit(1);
    }

    rv= fread(ptr, len, 1, file);
    if (rv != 1) {
        fprintf(stderr, "error reading file %s\n", name);
        exit(1);
    }
    
    return ptr;
}