view fluid-mnf/misc.c @ 311:9cecc930d78f

fluid-mnf: original source from TI, defenestrated line endings and rearranged directory structure, but no *.[ch] source file content changes yet
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 29 Feb 2020 05:36:07 +0000
parents
children 1cd24530c0ae
line wrap: on
line source

/******************************************************************************
 * FLUID (Flash Loader Utility Independent of Device)
 *
 * Copyright Texas Instruments, 2001.
 * Mads Meisner-Jensen, mmj@ti.com.
 *
 * Miscellaneous Utility Functions
 *
 * $Id: misc.c 1.14 Fri, 11 Oct 2002 08:40:21 +0200 mmj $
 *
 ******************************************************************************/

#include "misc.h"
#include "fluid.h"
#include "trace.h"

#include <stdio.h>
#include <time.h>

#if defined(MSC) || defined(BCC)
#include "windows.h"
#endif


/******************************************************************************
 * File And Path Name Functions
 ******************************************************************************/

// Return the length of the directory name preceding the leafname. The
// terminating slash is included in the length. Length can be zero, if there
// is no dirname.
int dirname_len(const char *pathname)
{
    char *p;
    int len;

    tr(TrUtility, "dirname_len('%s')\n", pathname);

    if ((len = strlen(pathname)) == 0)
        return 0;
    
    p = (char *) (pathname + len - 1);

    tr(TrUtility, "{ %d }\n", len);

    while (*p != '/' && *p != '\\' && len-- > 1)
        p--;

    return len;
}

// Construct a full pathname from <dirname> and <leafname>. The full
// pathname is copied in the buffer <buf> of size <size>. On success, the
// full length of the pathname is returned. Otherwise, if the buffer is too
// small, -1 is returned. NOTE: The <dirname> is supposed to end with a
// slash. If not, the leafname part (if present) of the <dirname> will be
// removed.
int pathname_make(char *buf, int size, const char *dirname, const char *leafname)
{
    int dir_len, leaf_len, result;

    tr(TrBegin|TrUtility, "pathname_make(*, %d, '%s', '%s') {\n",
       size, dirname, leafname);

    dir_len = dirname_len(dirname);
    leaf_len = strlen(leafname);

    if (dir_len > size - leaf_len - 1)
        result = E_BUFFER;
    else {
        memcpy(buf, dirname, dir_len);
        strcpy(buf + dir_len, leafname);
        result = dir_len + leaf_len;
    }

    tr(TrEnd|TrUtility, "} %d\n", result);

    return result;
}


/******************************************************************************
 * Utility Funcions
 ******************************************************************************/

// Return the base 2 logarithm of <number>. Return -1 if <number> is zero.
unsigned int log2(unsigned int number)
{
    int result = -1;

    while (number > 0) {
        number >>= 1;
        result++;
    }
    return result;
}


/******************************************************************************
 * Progress and Timer Functions
 ******************************************************************************/

static int  progress_mul;
static int  progress_index;
static char progress_string[35] = "(---------------------------------)";
static char progress_backup[33] =
"\b\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b" "\b\b\b\b\b\b\b\b";

void progress_begin(int n)
{
    tr(TrUtility, "progress_begin(%d)\n", n); 

    progress_index = 0;

    switch (arg_progress) {
    case 'a':
        // We select a progress multiplier that is a power of two. Then we
        // generate a progress indicator that is in the range [16..32[ chars
        // in length.
        progress_mul = n / 32;
        progress_mul = 1 << (log2(progress_mul) + 1);
        n = (n + progress_mul - 1) / progress_mul;

        progress_string[1 + n]     = ')';
        progress_string[1 + n + 1] = 0;
        
        flowf(NORMAL, "%s\b%s",
                     progress_string, &progress_backup[32 - n]);
        break;
    case 'c':
        break;
    case 'd':
        break;
    }
}

void progress_update_simple(int n)
{
    tr(TrUtility, "progress_update_simple(%d)\n", n);

    switch (arg_progress) {
    case 'c':
        flowf(NORMAL, "%c", n);
        break;
    }
}

void progress_update(int n)
{
    char ch;

    tr(TrUtility, "progress_update(%d)\n", n);

    switch (arg_progress) {
    case 'a':
        if (n / progress_mul > progress_index) {
            progress_index++;
            flowf(NORMAL, "*");
        }

        n = n % progress_mul;
        ch = n + (n <= 9 ? '0' : 'A' - 10);
        flowf(NORMAL, "%c\b", ch);
        break;
    case 'c':
        break;
    case 'd':
        flowf(NORMAL, ".");
        break;
    }
}

void progress_end(int n)
{
    switch (arg_progress) {
    case 'a':
        if (n % progress_mul)
            flowf(NORMAL, "*) ");
        else
            flowf(NORMAL, ") ");
        break;
    case 'c':
    case 'd':
        flowf(NORMAL, " ");
        break;
    }
}

int stopwatch_start(void)
{
#if defined(MSC) || defined(BCC)
    return GetTickCount();
#else
    return 1000 * time(NULL);
#endif
}

int stopwatch_stop(int time_start)
{
#if defined(MSC) || defined(BCC)
    return GetTickCount() - time_start;
#else
    return 1000 * (time(NULL) - time_start);
#endif
}


/******************************************************************************
 * Hexdumping
 ******************************************************************************/

void hexdump(unsigned char *buf, int size, unsigned int addr, int unitsize)
{
    int n, i;
    char string[(8+1+1) + (1+16+1+1) + (3*16) + 1];
    char *s;

    while (size > 0)
    {
        s = string;
        s += sprintf(s, "%8x ", addr); // print offset

        n = (size > 16 ? 16 : size);

        // print the textual representation
        for (i = 0; i < n; i++) {
            if (buf[i] >= ' ' && buf[i] < 127)
                *s++ = buf[i];
            else
                *s++ = '.';
        }
        // pad textual representation with spaces
        for (i = 0; i < 16 - n; i++) {
            *s++ = ' ';
        }
        *s++ = ' ';

        // print hexedecimal representation
        for (i = 0; i < n; i += unitsize) {
            switch (unitsize) {
            case 1: s += sprintf(s, "%02x ", *(uint8  *) (buf+i)); break;
            case 2: s += sprintf(s, "%04x ", *(uint16 *) (buf+i)); break;
            case 4:
                s += sprintf(s, "%08x ", (int) (*(uint32 *) (buf+i)));
                break;
            }
        }
        buf += 16;
        addr += 16;
        size -= 16;
        puts(string);
    }
}