/*
 * 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("Could not malloc %d bytes.", size);

    return p;
}

void *xrealloc(void* p, size_t size)
{
    void* p2 = realloc (p, size);
    if (size && !p2)
	error("Could 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;
    va_list ap;

    while (1)
    {
        char *p = xmalloc (size);
        va_start(ap, fmt);
	n = vsnprintf (p, size, fmt, ap);
	va_end(ap);
        if (n == -1) size *= 2;
        else if ((size_t)n >= size) size = n + 1;
        else return p;
        free(p);
    }
}

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("Unable to open %s for writing.", 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 ignore_errors)
{
    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)) && !ignore_errors)
    {
	if (status > 0) error("%s failed.", argv[0]);
	else perror("winegcc");
	exit(3);
    }

    free(prog);
    strarray_free(arr);
}
