Merge winewrap into winegcc. Many cleanups.
[wine] / tools / winegcc / utils.c
1 /*
2  * Useful functions for winegcc/winewrap
3  *
4  * Copyright 2000 Francois Gouget
5  * Copyright 2002 Dimitrie O. Paun
6  * Copyright 2003 Richard Cohen
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <errno.h>
30
31 #include "utils.h"
32
33 #if !defined(min)
34 # define min(x,y) (((x) < (y)) ? (x) : (y))
35 #endif
36
37 int verbose = 0;
38
39 void error(const char* s, ...)
40 {
41     va_list ap;
42     
43     va_start(ap, s);
44     fprintf(stderr, "Error: ");
45     vfprintf(stderr, s, ap);
46     fprintf(stderr, "\n");
47     va_end(ap);
48     exit(2);
49 }
50
51 void* xmalloc(size_t size)
52 {
53     void* p;
54
55     if ((p = malloc (size)) == NULL)
56         error("Can not malloc %d bytes.", size);
57
58     return p;
59 }
60
61 void *xrealloc(void* p, size_t size)
62 {
63     void* p2;
64     if ((p2 = realloc (p, size)) == NULL)
65         error("Can not realloc %d bytes.", size);
66
67     return p2;
68 }
69
70 int strendswith(const char* str, const char* end)
71 {
72     int l = strlen(str);
73     int m = strlen(end);
74    
75     return l >= m && strcmp(str + l - m, end) == 0; 
76 }
77
78 char* strmake(const char* fmt, ...)
79 {
80     int n;
81     size_t size = 100;
82     char* p;
83     va_list ap;
84
85     p = xmalloc (size);
86     while (1)
87     {
88         va_start(ap, fmt);
89         n = vsnprintf (p, size, fmt, ap);
90         va_end(ap);
91         if (n > -1 && (size_t)n < size) return p;
92         size = min( size*2, (size_t)n+1 );
93         p = xrealloc (p, size);
94     }
95 }
96
97 strarray* strarray_alloc(void)
98 {
99     strarray* arr = xmalloc(sizeof(*arr));
100     arr->maximum = arr->size = 0;
101     arr->base = NULL;
102     return arr;
103 }
104
105 void strarray_free(strarray* arr)
106 {
107     free(arr->base);
108     free(arr);
109 }
110
111 void strarray_add(strarray* arr, const char* str)
112 {
113     if (arr->size == arr->maximum)
114     {
115         arr->maximum += 10;
116         arr->base = xrealloc(arr->base, sizeof(*(arr->base)) * arr->maximum);
117     }
118     arr->base[arr->size++] = str;
119 }
120
121 strarray* strarray_dup(const strarray* arr)
122 {
123     strarray* dup = strarray_alloc();
124     int i;
125
126     for (i = 0; i < arr->size; i++)
127         strarray_add(dup, arr->base[i]);
128
129     return dup;
130 }
131
132 char* get_basename(const char* file)
133 {
134     const char* name;
135     char *base_name, *p;
136
137     if ((name = strrchr(file, '/'))) name++;
138     else name = file;
139
140     base_name = strdup(name);
141     if ((p = strrchr(base_name, '.'))) *p = 0;
142
143     return base_name;
144 }
145
146 void create_file(const char* name, const char* fmt, ...)
147 {
148     va_list ap;
149     FILE *file;
150
151     if (verbose) printf("Creating file %s\n", name);
152     va_start(ap, fmt);
153     if ( !(file = fopen(name, "w")) )
154         error ("Can not create %s.", name);
155     vfprintf(file, fmt, ap);
156     va_end(ap);
157     fclose(file);
158 }
159
160 file_type get_file_type(const char* dir, const char* filename)
161 {
162     /* see tools/winebuild/res32.c: check_header for details */
163     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 };
164     char buf[sizeof(res_sig)];
165     char *fullname;
166     int fd, cnt;
167
168     fullname = strmake("%s/%s", dir, filename);
169     fd = open( fullname, O_RDONLY );
170     cnt = read(fd, buf, sizeof(buf));
171     if (cnt == -1) error("Can't read file: %s/%s", dir, filename);
172     free( fullname );
173     close( fd );
174
175     if (fd == -1) return file_na;
176
177     if (cnt == sizeof(res_sig) && !memcmp(buf, res_sig, sizeof(res_sig))) return file_res;
178     if (strendswith(filename, ".o")) return file_obj;
179     if (strendswith(filename, ".a")) return file_arh;
180     if (strendswith(filename, ".res")) return file_res;
181     if (strendswith(filename, ".so")) return file_so;
182     if (strendswith(filename, ".def")) return file_dll;
183     if (strendswith(filename, ".rc")) return file_rc;
184
185     return file_other;
186 }
187
188 static file_type try_lib_path(const char* dir, const char* pre, 
189                               const char* library, const char* ext)
190 {
191     char *fullname;
192     file_type type;
193
194     fullname = strmake("%s%s%s", pre, library, ext);
195     if (verbose > 1) fprintf(stderr, "Try %s/%s...", dir, fullname);
196     type = get_file_type(dir, fullname);
197     free( fullname );
198     if (verbose > 1) fprintf(stderr, type == file_na ? "no\n" : "FOUND!\n");
199     return type;
200 }
201
202 static file_type guess_lib_type(const char* dir, const char* library)
203 {
204     /* Unix shared object */
205     if (try_lib_path(dir, "lib", library, ".so") == file_so)
206         return file_so;
207
208     /* Windows DLL */
209     if (try_lib_path(dir, "lib", library, ".def") == file_dll)
210         return file_dll;
211     if (try_lib_path(dir, "", library, ".def") == file_dll)
212         return file_dll;
213
214     /* Unix static archives */
215     if (try_lib_path(dir, "lib", library, ".a") == file_arh)
216         return file_arh;
217
218     return file_na;
219 }
220
221 file_type get_lib_type(strarray* path, const char* library)
222 {
223     int i;
224
225     for (i = 0; i < path->size; i++)
226     {
227         file_type type = guess_lib_type(path->base[i], library);
228         if (type != file_na) return type;
229     }
230     return file_na;
231 }
232
233 void spawn(const strarray* args)
234 {
235     int i, status;
236     strarray* arr = strarray_dup(args);
237     const char **argv = arr->base;
238
239     strarray_add(arr, NULL);
240     if (verbose)
241     {
242         for(i = 0; argv[i]; i++) printf("%s ", argv[i]);
243         printf("\n");
244     }
245
246     if ((status = spawnvp( _P_WAIT, argv[0], argv)))
247     {
248         if (status > 0) error("%s failed.", argv[0]);
249         else perror("Error:");
250         exit(3);
251     }
252
253     strarray_free(arr);
254 }