2 * Useful functions for winegcc
4 * Copyright 2000 Francois Gouget
5 * Copyright 2002 Dimitrie O. Paun
6 * Copyright 2003 Richard Cohen
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
34 # define min(x,y) (((x) < (y)) ? (x) : (y))
39 void error(const char* s
, ...)
44 fprintf(stderr
, "winegcc: ");
45 vfprintf(stderr
, s
, ap
);
50 void* xmalloc(size_t size
)
54 if ((p
= malloc (size
)) == NULL
)
55 error("Could not malloc %d bytes\n", size
);
60 void *xrealloc(void* p
, size_t size
)
62 void* p2
= realloc (p
, size
);
64 error("Could not realloc %d bytes\n", size
);
69 char *xstrdup( const char *str
)
71 char *res
= strdup( str
);
72 if (!res
) error("Virtual memory exhausted.\n");
76 int strendswith(const char* str
, const char* end
)
81 return l
>= m
&& strcmp(str
+ l
- m
, end
) == 0;
84 char* strmake(const char* fmt
, ...)
92 char *p
= xmalloc (size
);
94 n
= vsnprintf (p
, size
, fmt
, ap
);
96 if (n
== -1) size
*= 2;
97 else if ((size_t)n
>= size
) size
= n
+ 1;
103 strarray
* strarray_alloc(void)
105 strarray
* arr
= xmalloc(sizeof(*arr
));
106 arr
->maximum
= arr
->size
= 0;
111 void strarray_free(strarray
* arr
)
117 void strarray_add(strarray
* arr
, const char* str
)
119 if (arr
->size
== arr
->maximum
)
122 arr
->base
= xrealloc(arr
->base
, sizeof(*(arr
->base
)) * arr
->maximum
);
124 arr
->base
[arr
->size
++] = str
;
127 void strarray_del(strarray
* arr
, unsigned int i
)
129 if (i
>= arr
->size
) error("Invalid index i=%d\n", i
);
130 memmove(&arr
->base
[i
], &arr
->base
[i
+ 1], (arr
->size
- i
- 1) * sizeof(arr
->base
[0]));
134 void strarray_addall(strarray
* arr
, const strarray
* from
)
138 for (i
= 0; i
< from
->size
; i
++)
139 strarray_add(arr
, from
->base
[i
]);
142 strarray
* strarray_dup(const strarray
* arr
)
144 strarray
* dup
= strarray_alloc();
147 for (i
= 0; i
< arr
->size
; i
++)
148 strarray_add(dup
, arr
->base
[i
]);
153 strarray
* strarray_fromstring(const char* str
, const char* delim
)
155 strarray
* arr
= strarray_alloc();
156 char* buf
= strdup(str
);
159 for(tok
= strtok(buf
, delim
); tok
; tok
= strtok(0, delim
))
160 strarray_add(arr
, strdup(tok
));
166 char* strarray_tostring(const strarray
* arr
, const char* sep
)
171 str
= strmake("%s", arr
->base
[0]);
172 for (i
= 1; i
< arr
->size
; i
++)
174 newstr
= strmake("%s%s%s", str
, sep
, arr
->base
[i
]);
182 char* get_basename(const char* file
)
187 if ((name
= strrchr(file
, '/'))) name
++;
190 base_name
= strdup(name
);
191 if ((p
= strrchr(base_name
, '.'))) *p
= 0;
196 void create_file(const char* name
, int mode
, const char* fmt
, ...)
201 if (verbose
) printf("Creating file %s\n", name
);
203 if ( !(file
= fopen(name
, "w")) )
204 error("Unable to open %s for writing\n", name
);
205 vfprintf(file
, fmt
, ap
);
211 file_type
get_file_type(const char* filename
)
213 /* see tools/winebuild/res32.c: check_header for details */
214 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 };
215 char buf
[sizeof(res_sig
)];
218 fd
= open( filename
, O_RDONLY
);
219 if (fd
== -1) return file_na
;
220 cnt
= read(fd
, buf
, sizeof(buf
));
222 if (cnt
== -1) return file_na
;
224 if (cnt
== sizeof(res_sig
) && !memcmp(buf
, res_sig
, sizeof(res_sig
))) return file_res
;
225 if (strendswith(filename
, ".o")) return file_obj
;
226 if (strendswith(filename
, ".a")) return file_arh
;
227 if (strendswith(filename
, ".res")) return file_res
;
228 if (strendswith(filename
, ".so")) return file_so
;
229 if (strendswith(filename
, ".dylib")) return file_so
;
230 if (strendswith(filename
, ".def")) return file_def
;
231 if (strendswith(filename
, ".spec")) return file_spec
;
232 if (strendswith(filename
, ".rc")) return file_rc
;
237 static char* try_lib_path(const char* dir
, const char* pre
,
238 const char* library
, const char* ext
,
239 file_type expected_type
)
244 /* first try a subdir named from the library we are looking for */
245 fullname
= strmake("%s/%s/%s%s%s", dir
, library
, pre
, library
, ext
);
246 if (verbose
> 1) fprintf(stderr
, "Try %s...", fullname
);
247 type
= get_file_type(fullname
);
248 if (verbose
> 1) fprintf(stderr
, type
== expected_type
? "FOUND!\n" : "no\n");
249 if (type
== expected_type
) return fullname
;
252 fullname
= strmake("%s/%s%s%s", dir
, pre
, library
, ext
);
253 if (verbose
> 1) fprintf(stderr
, "Try %s...", fullname
);
254 type
= get_file_type(fullname
);
255 if (verbose
> 1) fprintf(stderr
, type
== expected_type
? "FOUND!\n" : "no\n");
256 if (type
== expected_type
) return fullname
;
261 static file_type
guess_lib_type(enum target_platform platform
, const char* dir
,
262 const char* library
, const char *suffix
, char** file
)
264 if (platform
!= PLATFORM_WINDOWS
&& platform
!= PLATFORM_CYGWIN
)
266 /* Unix shared object */
267 if ((*file
= try_lib_path(dir
, "lib", library
, ".so", file_so
)))
270 /* Mach-O (Darwin/Mac OS X) Dynamic Library behaves mostly like .so */
271 if ((*file
= try_lib_path(dir
, "lib", library
, ".dylib", file_so
)))
275 if ((*file
= try_lib_path(dir
, "lib", library
, ".def", file_def
)))
279 /* static archives */
280 if ((*file
= try_lib_path(dir
, "lib", library
, suffix
, file_arh
)))
286 file_type
get_lib_type(enum target_platform platform
, strarray
* path
, const char *library
,
287 const char *suffix
, char** file
)
291 if (!suffix
) suffix
= ".a";
292 for (i
= 0; i
< path
->size
; i
++)
294 file_type type
= guess_lib_type(platform
, path
->base
[i
], library
, suffix
, file
);
295 if (type
!= file_na
) return type
;
300 void spawn(const strarray
* prefix
, const strarray
* args
, int ignore_errors
)
304 strarray
* arr
= strarray_dup(args
);
308 strarray_add(arr
, NULL
);
313 const char *p
= strrchr(argv
[0], '/');
317 for (i
= 0; i
< prefix
->size
; i
++)
322 prog
= strmake("%s/%s%s", prefix
->base
[i
], p
, EXEEXT
);
323 if (stat(prog
, &st
) == 0 && S_ISREG(st
.st_mode
) && (st
.st_mode
& 0111))
333 for(i
= 0; argv
[i
]; i
++) printf("%s ", argv
[i
]);
337 if ((status
= spawnvp( _P_WAIT
, argv
[0], argv
)) && !ignore_errors
)
339 if (status
> 0) error("%s failed\n", argv
[0]);
340 else perror("winegcc");