https://bitbucket.org/daniel_fort/magic-lantern
Raw File
Tip revision: 128459811ce1ff28aea3f9f20971b3d059e76738 authored by alex@thinkpad on 13 October 2012, 17:05:35 UTC
5DC: Added a small joke on "don't click me" :)
Tip revision: 1284598
stdio.c
/** \file
 * Re-implementation of <stdio.h> functions that we don't have in the
 * Canon firmware.
 *
 * These are decidedly non-optimal.
 *
 * Portions copied from uClibc 0.9.30 under the GPL.
 * Those portions are: Copyright (C) 2002 Manuel Novoa III
 */

#include "dryos.h"
//#include <errno.h>

// sometimes gcc likes very much the default fprintf and uses that one
// => renamed to my_fprintf to force it to use this one
int
my_fprintf(
    FILE *          file,
    const char *        fmt,
    ...
)
{
    va_list         ap;

    char* buf = alloc_dma_memory(256);

    va_start( ap, fmt );
    int len = vsnprintf( buf, 256, fmt, ap );
    va_end( ap );

    FIO_WriteFile( file, buf, len );
    free_dma_memory(buf);
    return len;
}


int
snprintf(
    char *          buf,
    size_t          max_len,
    const char *        fmt,
    ...
)
{
    va_list         ap;

    va_start( ap, fmt );
    int len = vsnprintf( buf, max_len, fmt, ap );
    va_end( ap );
    return len;
}




static inline int
ISSPACE( char c )
{
    return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}


int __errno;

//#define SET_ERRNO(x) __errno = (x)
#define SET_ERRNO(x) /* NOP */
#define _STRTO_ENDPTR           1

unsigned long long strto_ll(
    const char* str,
    char ** endptr,
    int base,
    int sflag)
{
    unsigned long long number;
#if _STRTO_ENDPTR
    const char *fail_char;
#define SET_FAIL(X) fail_char = (X)
#else
#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
#endif
    unsigned int n1;
    unsigned char negative, digit;

    SET_FAIL(str);

    while (ISSPACE(*str)) {        /* Skip leading whitespace. */
        ++str;
    }

    /* Handle optional sign. */
    negative = 0;
    switch (*str) {
        case '-': negative = 1;    /* Fall through to increment str. */
        case '+': ++str;
    }

    if (!(base & ~0x10)) {        /* Either dynamic (base = 0) or base 16. */
        base += 10;                /* Default is 10 (26). */
        if (*str == '0') {
            SET_FAIL(++str);
            base -= 2;            /* Now base is 8 or 16 (24). */
            if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
                ++str;
                base += base;    /* Base is 16 (16 or 48). */
            }
        }

        if (base > 16) {        /* Adjust in case base wasn't dynamic. */
            base = 16;
        }
    }

    number = 0;

    if (((unsigned)(base - 2)) < 35) { /* Legal base. */
        do {
            digit = ((unsigned char)(*str - '0') <= 9)
                ? /* 0..9 */ (*str - '0')
                : /* else */ (((unsigned char)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
                   ? /* >= A/a */ ((unsigned char)(0x20 | *str) - ('a' - 10))
                   : /* else   */ 40 /* bad value */);

            if (digit >= base) {
                break;
            }

            SET_FAIL(++str);

#if 1
            /* Optional, but speeds things up in the usual case. */
            if (number <= (ULLONG_MAX >> 6)) {
                number = number * base + digit;
            } else
#endif
            {
                n1 = ((unsigned char) number) * base + digit;
                number = (number >> CHAR_BIT) * base;

                if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) {
                    number = (number << CHAR_BIT) + n1;
                } else {        /* Overflow. */
                    number = ULLONG_MAX;
                    negative &= sflag;
                    SET_ERRNO(ERANGE);
                }
            }

        } while (1);
    }

#if _STRTO_ENDPTR
    if (endptr) {
        *endptr = (char *) fail_char;
    }
#endif

    {
        unsigned long long tmp = ((negative)
                                  ? ((unsigned long long)(-(1+LLONG_MIN)))+1
                                  : LLONG_MAX);
        if (sflag && (number > tmp)) {
            number = tmp;
            SET_ERRNO(ERANGE);
        }
    }

    return negative ? (unsigned long long)(-((long long)number)) : number;
}

long
strtol(
    const char *        str,
    char **         endptr,
    int         base
)
{
    return (long)strto_ll( str, endptr, base, 1 );
}


/*double
strtod(
    const char *        str,
    char **         endptr
)
{
    return 0;
#if 0
    double val;
    int len;
    int rc = sscanf( str, "%lf%n", &val, &len );
    if( rc != 2 )
        return HUGE_VAL;
    if( endptr )
        *endptr = str + len;
    return val;
#endif
}
*/

unsigned long
strtoul(
    const char *        str,
    char **         endptr,
    int         base
)
{
    return (long)strto_ll( str, endptr, base, 0 );
}


// Don't use strcmp since we don't have it
int
streq( const char * a, const char * b )
{
    while( *a && *b )
        if( *a++ != *b++ )
            return 0;
    return *a == *b;
}


/** Exit is tough; we want to kill the current thread, but how? */
#include "bmp.h"

/*void
exit( int rc )
{
    bmp_printf( FONT_SMALL, 0, 50, "Exit %d", rc );
    while(1)
        ;
}*/


/** realloc is implemented via malloc/free */
void *
realloc(
    void *          buf,
    size_t          new_size
)
{
    // If buf is NULL, this is a normal malloc()
    if (!buf)
    {
        void * rc = AllocateMemory( new_size );
        struct dryos_meminfo * mem = rc;
        mem--;
        DebugMsg( DM_MAGIC, 3,
            "realloc(%08x,%d) = %08x (%08x,%08x,%d)",
            (uintptr_t) buf,
            new_size,
            (uintptr_t) rc,
            mem->next,
            mem->prev,
            mem->size
        );
        return rc;
    }

    // If new_size is zero, then this is a normal free()
    if( new_size == 0 )
    {
        if( buf )
            FreeMemory(buf);
        return NULL;
    }


    struct dryos_meminfo * mem = buf;
    mem--;

    // If bit 1, 2 or 3 in mem->size is set then it is not valid
    if( mem->size & 3 )
        return NULL;

    // If the new size is less than the current size do nothing
    if( new_size < mem->size )
        return buf;

    // Allocate a new buffer and copy the old data into it
    void * new_buf = AllocateMemory( new_size );
    if (!new_buf)
        return NULL;

    unsigned i;
    for( i=0 ; i < mem->size/4 ; i++ )
    {
        ((uint32_t*) new_buf)[i] = ((uint32_t*) buf)[i];
        asm("nop; nop; nop; nop;" );
    }

    //free( buf );

    // Return a pointer to the new buffer
    return new_buf;
}

int abs(int num) {
    return (num >= 0) ? num : -num;
}

char *strstr(const char *haystack, const char *needle)
{
    size_t needlelen;
    /* Check for the null needle case.  */
    if (*needle == '\0')
        return (char *) haystack;
    needlelen = strlen(needle);
    for (; (haystack = strchr(haystack, *needle)) != NULL; haystack++)
        if (memcmp(haystack, needle, needlelen) == 0)
            return (char *) haystack;
    return NULL;
}

char* strchr(const char* s, int c) {
    while (*s != '\0' && *s != (char)c)
        s++;
    return ( (*s == c) ? (char *) s : NULL );
}

char* strpbrk(const char* s1, const char* s2)
{
    const char *sc1;
    for (sc1 = s1; *sc1 != '\0'; sc1++)
        if (strchr(s2, *sc1) != NULL)
            return (char *)sc1;
    return NULL;
}

#define MAX_VSNPRINTF_SIZE 4096

int sprintf(char* str, const char* fmt, ...)
{
    int num;
    va_list            ap;

    va_start( ap, fmt );
    num = vsnprintf( str, MAX_VSNPRINTF_SIZE, fmt, ap );
    va_end( ap );
    return num;
}

int memcmp(const void* s1, const void* s2,size_t n)
{
    const unsigned char *us1 = (const unsigned char *) s1;
    const unsigned char *us2 = (const unsigned char *) s2;
    while (n-- != 0) {
        if (*us1 != *us2)
            return (*us1 < *us2) ? -1 : +1;
        us1++;
        us2++;
    }
    return 0;
}

int toupper(int c)
{
    if(('a' <= c) && (c <= 'z'))
        return 'A' + c - 'a';
    return c;
}

int tolower(int c)
{
    if(('A' <= c) && (c <= 'Z'))
        return 'a' + c - 'A';
    return c;
}

void *memchr(const void *s, int c, size_t n)
{
    const unsigned char *src = s;
    unsigned char uc = c;
    while (n-- != 0) {
        if (*src == uc)
            return (void *) src;
        src++;
    }
    return NULL;
}

size_t strspn(const char *s1, const char *s2)
{
    const char *sc1;
    for (sc1 = s1; *sc1 != '\0'; sc1++)
        if (strchr(s2, *sc1) == NULL)
            return (sc1 - s1);
    return sc1 - s1;
}

int islower(int x) { return ((x)>='a') && ((x)<='z'); }
int isupper(int x) { return ((x)>='A') && ((x)<='Z'); }
int isalpha(int x) { return islower(x) || isupper(x); }
int isdigit(int x) { return ((x)>='0') && ((x)<='9'); }
int isxdigit(int x) { return isdigit(x) || (((x)>='A') && ((x)<='F')) || (((x)>='a') && ((x)<='f')); }
int isalnum(int x) { return isalpha(x) || isdigit(x); }
int ispunct(int x) { return strchr("!\"#%&'();<=>?[\\]*+,-./:^_{|}~",x)!=0; }
int isgraph(int x) { return ispunct(x) || isalnum(x); }
int isspace(int x) { return strchr(" \r\n\t",x)!=0; }
int iscntrl(int x) { return strchr("\x07\x08\r\n\x0C\x0B\x09",x)!=0; }

int is_dir(char* path)
{
    struct fio_file file;
    struct fio_dirent * dirent = FIO_FindFirstEx( path, &file );
    if( IS_ERROR(dirent) )
    {
        return 0; // this dir does not exist
    }
    else 
    {
        FIO_CleanupAfterFindNext_maybe(dirent);
        return 1; // dir found
    }
}
void FIO_CreateDir_recursive(char* path)
{
    //~ NotifyBox(2000, "create dir: %s ", path); msleep(2000);
    // B:/ML/something
    
    if (is_dir(path)) return;
    
    int n = strlen(path);
    for (int i = n-1; i > 2; i--)
    {
         if (path[i] == '/')
         {
             path[i] = '\0';
             if (!is_dir(path))
                FIO_CreateDir_recursive(path);
             path[i] = '/';
         }
    }

        FIO_CreateDirectory(path);
}

// a wrapper that also creates missing dirs and removes existing file
FILE* FIO_CreateFileEx(const char* name)
{
    //~ NotifyBox(2000, "create file: %s ", name); msleep(2000);
    // first assume the path is alright
    FIO_RemoveFile(name);
    FILE* f = FIO_CreateFile(name);
    if (f != INVALID_PTR)
    {
        //~ NotifyBox(2000, "create file: %s => success :) ", name); msleep(2000);
        return f;
    }
    
    //~ info_led_blink(5,50,50);

    // if we are here, the path may be inexistent => create it
    int n = strlen(name);
    char* namae = (char*) name; // trick to ignore the const declaration and split the path easily
    for (int i = n-1; i > 2; i--)
    {
         if (namae[i] == '/')
         {
             namae[i] = '\0';
             FIO_CreateDir_recursive(namae);
             namae[i] = '/';
         }
    }

    f = FIO_CreateFile(name);

    //~ if (f != INVALID_PTR) NotifyBox(2000, "create file: %s => success", name); msleep(2000);
        
    return f;
}
back to top