/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2007 Dave Chapman
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <libgen.h>

#ifndef O_BINARY
#define O_BINARY 0
#endif

static off_t filesize(int fd)
{
    struct stat buf;

    fstat(fd,&buf);
    return buf.st_size;
}

static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name)
{
    int i;

    fprintf(fp,"unsigned char %s[%ld] = {",name,len);

    for (i=0;i<len;i++) {
        if ((i % 16) == 0) {
           fprintf(fp,"\n    ");
        }
        if (i == (len-1)) {
            fprintf(fp,"0x%02x",buf[i]);
        } else if ((i % 16) == 15) {
            fprintf(fp,"0x%02x,",buf[i]);
        } else {
            fprintf(fp,"0x%02x, ",buf[i]);
        }
    }
    fprintf(fp,"\n};\n");
}

int main (int argc, char* argv[])
{
    char* cname;
    int i;
    FILE *cfile, *hfile;
    char cfilename[256], hfilename[256];

    if (argc < 3) {
        fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n");
        return 1;
    }

    cname=argv[1];

    snprintf(cfilename,256,"%s.c",cname);
    cfile = fopen(cfilename,"w+");
    if (cfile == NULL) {
        fprintf(stderr,"Couldn't open %s\n",cfilename);
        return 2;
    }

    snprintf(hfilename,256,"%s.h",cname);
    hfile = fopen(hfilename,"w+");
    if (hfile == NULL) {
        fprintf(stderr,"Couldn't open %s\n",hfilename);
        fclose(cfile);
        return 3;
    }

    fprintf(cfile,"/* Generated by bin2c */\n\n");
    fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename));
    fprintf(hfile,"/* Generated by bin2c */\n\n");

    for(i=0; i < argc - 2; i++) {
        unsigned char* buf;
        off_t len;
        off_t orig_len;
        char *ext;
        char *array = argv[2+i];

        int fd = open(array,O_RDONLY|O_BINARY);
        if (fd < 0) {
            fprintf(stderr,"Can not open %s\n",argv[2+i]);
            fclose(cfile);
            fclose(hfile);
            return 4;
        }

        orig_len = filesize(fd);
        /* pad to 32bit */
        len = (orig_len + 3) & ~3;

        buf = malloc(len);
        if (read(fd,buf,orig_len) < orig_len) {
            fprintf(stderr,"Short read, aborting\n");
            return 5;
        }

        /* pad to 32bit with zeros */
        if (len > orig_len)
            memset(buf+orig_len, 0, len-orig_len);
        
        /* remove file extension */
        ext = strchr (array, '.');
        if (ext != NULL)
            *ext = '\0';
        write_cfile (buf, len, cfile, array);
        fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len);

        close(fd);
    }

    fclose(cfile);
    fclose(hfile);

    return 0;
}
