wine/tools/winegcc/utils.c
Alexandre Julliard 2d52cfa958 Allow multiple -B options.
Do not pass the -Btools/winebuild magic option to the compiler to
avoid warnings.
Pass to the linker even the libraries we didn't find in the lib search
path, in case we are not using the standard paths.
2004-03-09 04:49:42 +00:00

323 lines
7.4 KiB
C

/*
* 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;
if ((p2 = realloc (p, size)) == NULL)
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);
fchmod(fileno(file), mode);
fclose(file);
}
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, ".def")) return file_dll;
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;
/* Windows DLL */
if ((*file = try_lib_path(dir, "lib", library, ".def", file_dll)))
return file_dll;
if ((*file = try_lib_path(dir, "", library, ".def", file_dll)))
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);
}