/*
 * Useful functions for winegcc/winewrap
 *
 * Copyright 2000 Francois Gouget
 * Copyright 2002 Dimitrie O. Paun
 * Copyright 2003 Richard Cohen
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "config.h"
#include "wine/port.h"

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>

#include "utils.h"

#if !defined(min)
# define min(x,y) (((x) < (y)) ? (x) : (y))
#endif

int verbose = 0;

void error(const char* s, ...)
{
    va_list ap;
    
    va_start(ap, s);
    fprintf(stderr, "winegcc: ");
    vfprintf(stderr, s, ap);
    fprintf(stderr, "\n");
    va_end(ap);
    exit(2);
}

void* xmalloc(size_t size)
{
    void* p;

    if ((p = malloc (size)) == NULL)
	error("Can not malloc %d bytes.", size);

    return p;
}

void *xrealloc(void* p, size_t size)
{
    void* p2 = realloc (p, size);
    if (size && !p2)
	error("Can not realloc %d bytes.", size);

    return p2;
}

int strendswith(const char* str, const char* end)
{
    int l = strlen(str);
    int m = strlen(end);
   
    return l >= m && strcmp(str + l - m, end) == 0; 
}

char* strmake(const char* fmt, ...)
{
    int n;
    size_t size = 100;
    char* p;
    va_list ap;

    p = xmalloc (size);
    while (1)
    {
        va_start(ap, fmt);
	n = vsnprintf (p, size, fmt, ap);
	va_end(ap);
        if (n > -1 && (size_t)n < size) return p;
	size = min( size*2, (size_t)n+1 );
	p = xrealloc (p, size);
    }
}

strarray* strarray_alloc(void)
{
    strarray* arr = xmalloc(sizeof(*arr));
    arr->maximum = arr->size = 0;
    arr->base = NULL;
    return arr;
}

void strarray_free(strarray* arr)
{
    free(arr->base);
    free(arr);
}

void strarray_add(strarray* arr, const char* str)
{
    if (arr->size == arr->maximum)
    {
	arr->maximum += 10;
	arr->base = xrealloc(arr->base, sizeof(*(arr->base)) * arr->maximum);
    }
    arr->base[arr->size++] = str;
}

void strarray_del(strarray* arr, int i)
{
    if (i < 0 || i >= arr->size) error("Invalid index i=%d", i);
    memmove(&arr->base[i], &arr->base[i + 1], (arr->size - i - 1) * sizeof(arr->base[0]));
    arr->size--;
}

void strarray_addall(strarray* arr, const strarray* from)
{
    int i;

    for (i = 0; i < from->size; i++)
	strarray_add(arr, from->base[i]);
}

strarray* strarray_dup(const strarray* arr)
{
    strarray* dup = strarray_alloc();
    int i;

    for (i = 0; i < arr->size; i++)
	strarray_add(dup, arr->base[i]);

    return dup;
}

strarray* strarray_fromstring(const char* str, const char* delim)
{
    strarray* arr = strarray_alloc();
    char* buf = strdup(str);
    const char* tok;

    for(tok = strtok(buf, delim); tok; tok = strtok(0, delim))
	strarray_add(arr, strdup(tok));

    free(buf);
    return arr;
}

char* strarray_tostring(const strarray* arr, const char* sep)
{
    char *str, *newstr;
    int i;

    str = strmake("%s", arr->base[0]);
    for (i = 1; i < arr->size; i++)
    {
	newstr = strmake("%s%s%s", str, sep, arr->base[i]);
	free(str);
	str = newstr;
    }

    return str;
}

char* get_basename(const char* file)
{
    const char* name;
    char *base_name, *p;

    if ((name = strrchr(file, '/'))) name++;
    else name = file;

    base_name = strdup(name);
    if ((p = strrchr(base_name, '.'))) *p = 0;

    return base_name;
}

void create_file(const char* name, int mode, const char* fmt, ...)
{
    va_list ap;
    FILE *file;

    if (verbose) printf("Creating file %s\n", name);
    va_start(ap, fmt);
    if ( !(file = fopen(name, "w")) )
	error ("Can not create %s.", name);
    vfprintf(file, fmt, ap);
    va_end(ap);
    fclose(file);
    chmod(name, mode);
}

file_type get_file_type(const char* filename)
{
    /* see tools/winebuild/res32.c: check_header for details */
    static const char res_sig[] = { 0,0,0,0, 32,0,0,0, 0xff,0xff, 0,0, 0xff,0xff, 0,0, 0,0,0,0, 0,0, 0,0, 0,0,0,0, 0,0,0,0 };
    char buf[sizeof(res_sig)];
    int fd, cnt;

    fd = open( filename, O_RDONLY );
    if (fd == -1) return file_na;
    cnt = read(fd, buf, sizeof(buf));
    close( fd );
    if (cnt == -1) return file_na;

    if (cnt == sizeof(res_sig) && !memcmp(buf, res_sig, sizeof(res_sig))) return file_res;
    if (strendswith(filename, ".o")) return file_obj;
    if (strendswith(filename, ".a")) return file_arh;
    if (strendswith(filename, ".res")) return file_res;
    if (strendswith(filename, ".so")) return file_so;
    if (strendswith(filename, ".dylib")) return file_so;
    if (strendswith(filename, ".def")) return file_def;
    if (strendswith(filename, ".spec")) return file_spec;
    if (strendswith(filename, ".rc")) return file_rc;

    return file_other;
}

static char* try_lib_path(const char* dir, const char* pre, 
			  const char* library, const char* ext,
			  file_type expected_type)
{
    char *fullname;
    file_type type;

    fullname = strmake("%s/%s%s%s", dir, pre, library, ext);
    if (verbose > 1) fprintf(stderr, "Try %s...", fullname);
    type = get_file_type(fullname);
    if (verbose > 1) fprintf(stderr, type == expected_type ? "FOUND!\n" : "no\n");
    if (type == expected_type) return fullname;
    free( fullname );
    return 0; 
}

static file_type guess_lib_type(const char* dir, const char* library, char** file)
{
    /* Unix shared object */
    if ((*file = try_lib_path(dir, "lib", library, ".so", file_so)))
	return file_so;
	
    /* Mach-O (Darwin/Mac OS X) Dynamic Library behaves mostly like .so */
    if ((*file = try_lib_path(dir, "lib", library, ".dylib", file_so)))
	return file_so;

    /* Windows DLL */
    if ((*file = try_lib_path(dir, "lib", library, ".def", file_def)))
	return file_dll;
    if ((*file = try_lib_path(dir, "", library, ".def", file_def)))
	return file_dll;

    /* Unix static archives */
    if ((*file = try_lib_path(dir, "lib", library, ".a", file_arh)))
	return file_arh;

    return file_na;
}

file_type get_lib_type(strarray* path, const char* library, char** file)
{
    int i;

    for (i = 0; i < path->size; i++)
    {
        file_type type = guess_lib_type(path->base[i], library, file);
	if (type != file_na) return type;
    }
    return file_na;
}

void spawn(const strarray* prefix, const strarray* args)
{
    int i, status;
    strarray* arr = strarray_dup(args);
    const char** argv;
    char* prog = 0;

    strarray_add(arr, NULL);
    argv = arr->base;

    if (prefix)
    {
        for (i = 0; i < prefix->size; i++)
        {
            const char* p;
            struct stat st;

            if (!(p = strrchr(argv[0], '/'))) p = argv[0];
            free( prog );
            prog = strmake("%s/%s", prefix->base[i], p);
            if (stat(prog, &st) == 0)
            {
                if ((st.st_mode & S_IFREG) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
                {
                    argv[0] = prog;
                    break;
                }
            }
        }
    }

    if (verbose)
    {
	for(i = 0; argv[i]; i++) printf("%s ", argv[i]);
	printf("\n");
    }

    if ((status = spawnvp( _P_WAIT, argv[0], argv)))
    {
	if (status > 0) error("%s failed.", argv[0]);
	else perror("winegcc");
	exit(3);
    }

    free(prog);
    strarray_free(arr);
}
