dinput: Move SetEventNotification and associated event into base class.
[wine] / tools / winebuild / utils.c
1 /*
2  * Small utility functions for winebuild
3  *
4  * Copyright 2000 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <ctype.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #include "build.h"
35
36 #define MAX_TMP_FILES 8
37 static const char *tmp_files[MAX_TMP_FILES];
38 static unsigned int nb_tmp_files;
39
40 /* atexit handler to clean tmp files */
41 static void cleanup_tmp_files(void)
42 {
43     unsigned int i;
44     for (i = 0; i < MAX_TMP_FILES; i++) if (tmp_files[i]) unlink( tmp_files[i] );
45 }
46
47
48 void *xmalloc (size_t size)
49 {
50     void *res;
51
52     res = malloc (size ? size : 1);
53     if (res == NULL)
54     {
55         fprintf (stderr, "Virtual memory exhausted.\n");
56         exit (1);
57     }
58     return res;
59 }
60
61 void *xrealloc (void *ptr, size_t size)
62 {
63     void *res = realloc (ptr, size);
64     if (size && res == NULL)
65     {
66         fprintf (stderr, "Virtual memory exhausted.\n");
67         exit (1);
68     }
69     return res;
70 }
71
72 char *xstrdup( const char *str )
73 {
74     char *res = strdup( str );
75     if (!res)
76     {
77         fprintf (stderr, "Virtual memory exhausted.\n");
78         exit (1);
79     }
80     return res;
81 }
82
83 char *strupper(char *s)
84 {
85     char *p;
86     for (p = s; *p; p++) *p = toupper(*p);
87     return s;
88 }
89
90 int strendswith(const char* str, const char* end)
91 {
92     int l = strlen(str);
93     int m = strlen(end);
94     return l >= m && strcmp(str + l - m, end) == 0;
95 }
96
97 void fatal_error( const char *msg, ... )
98 {
99     va_list valist;
100     va_start( valist, msg );
101     if (input_file_name)
102     {
103         fprintf( stderr, "%s:", input_file_name );
104         if (current_line)
105             fprintf( stderr, "%d:", current_line );
106         fputc( ' ', stderr );
107     }
108     else fprintf( stderr, "winebuild: " );
109     vfprintf( stderr, msg, valist );
110     va_end( valist );
111     exit(1);
112 }
113
114 void fatal_perror( const char *msg, ... )
115 {
116     va_list valist;
117     va_start( valist, msg );
118     if (input_file_name)
119     {
120         fprintf( stderr, "%s:", input_file_name );
121         if (current_line)
122             fprintf( stderr, "%d:", current_line );
123         fputc( ' ', stderr );
124     }
125     vfprintf( stderr, msg, valist );
126     perror( " " );
127     va_end( valist );
128     exit(1);
129 }
130
131 void error( const char *msg, ... )
132 {
133     va_list valist;
134     va_start( valist, msg );
135     if (input_file_name)
136     {
137         fprintf( stderr, "%s:", input_file_name );
138         if (current_line)
139             fprintf( stderr, "%d:", current_line );
140         fputc( ' ', stderr );
141     }
142     vfprintf( stderr, msg, valist );
143     va_end( valist );
144     nb_errors++;
145 }
146
147 void warning( const char *msg, ... )
148 {
149     va_list valist;
150
151     if (!display_warnings) return;
152     va_start( valist, msg );
153     if (input_file_name)
154     {
155         fprintf( stderr, "%s:", input_file_name );
156         if (current_line)
157             fprintf( stderr, "%d:", current_line );
158         fputc( ' ', stderr );
159     }
160     fprintf( stderr, "warning: " );
161     vfprintf( stderr, msg, valist );
162     va_end( valist );
163 }
164
165 int output( const char *format, ... )
166 {
167     int ret;
168     va_list valist;
169
170     va_start( valist, format );
171     ret = vfprintf( output_file, format, valist );
172     va_end( valist );
173     if (ret < 0) fatal_perror( "Output error" );
174     return ret;
175 }
176
177 /* get a name for a temp file, automatically cleaned up on exit */
178 char *get_temp_file_name( const char *prefix, const char *suffix )
179 {
180     char *name;
181     const char *ext;
182     int fd;
183
184     assert( nb_tmp_files < MAX_TMP_FILES );
185     if (!nb_tmp_files && !save_temps) atexit( cleanup_tmp_files );
186
187     if (!prefix || !prefix[0]) prefix = "winebuild";
188     if (!suffix) suffix = "";
189     if (!(ext = strchr( prefix, '.' ))) ext = prefix + strlen(prefix);
190     name = xmalloc( sizeof("/tmp/") + (ext - prefix) + sizeof(".XXXXXX") + strlen(suffix) );
191     strcpy( name, "/tmp/" );
192     memcpy( name + 5, prefix, ext - prefix );
193     strcpy( name + 5 + (ext - prefix), ".XXXXXX" );
194     strcat( name, suffix );
195
196     /* first try without the /tmp/ prefix */
197     if ((fd = mkstemps( name + 5, strlen(suffix) )) != -1)
198         name += 5;
199     else if ((fd = mkstemps( name, strlen(suffix) )) == -1)
200         fatal_error( "could not generate a temp file\n" );
201
202     close( fd );
203     tmp_files[nb_tmp_files++] = name;
204     return name;
205 }
206
207 /* output a standard header for generated files */
208 void output_standard_file_header(void)
209 {
210     if (spec_file_name)
211         output( "/* File generated automatically from %s; do not edit! */\n", spec_file_name );
212     else
213         output( "/* File generated automatically; do not edit! */\n" );
214     output( "/* This file can be copied, modified and distributed without restriction. */\n\n" );
215 }
216
217 /* dump a byte stream into the assembly code */
218 void dump_bytes( const void *buffer, unsigned int size )
219 {
220     unsigned int i;
221     const unsigned char *ptr = buffer;
222
223     if (!size) return;
224     output( "\t.byte " );
225     for (i = 0; i < size - 1; i++, ptr++)
226     {
227         if ((i % 16) == 15) output( "0x%02x\n\t.byte ", *ptr );
228         else output( "0x%02x,", *ptr );
229     }
230     output( "0x%02x\n", *ptr );
231 }
232
233
234 /*******************************************************************
235  *         open_input_file
236  *
237  * Open a file in the given srcdir and set the input_file_name global variable.
238  */
239 FILE *open_input_file( const char *srcdir, const char *name )
240 {
241     char *fullname;
242     FILE *file = fopen( name, "r" );
243
244     if (!file && srcdir)
245     {
246         fullname = xmalloc( strlen(srcdir) + strlen(name) + 2 );
247         strcpy( fullname, srcdir );
248         strcat( fullname, "/" );
249         strcat( fullname, name );
250         file = fopen( fullname, "r" );
251     }
252     else fullname = xstrdup( name );
253
254     if (!file) fatal_error( "Cannot open file '%s'\n", fullname );
255     input_file_name = fullname;
256     current_line = 1;
257     return file;
258 }
259
260
261 /*******************************************************************
262  *         close_input_file
263  *
264  * Close the current input file (must have been opened with open_input_file).
265  */
266 void close_input_file( FILE *file )
267 {
268     fclose( file );
269     free( input_file_name );
270     input_file_name = NULL;
271     current_line = 0;
272 }
273
274
275 /*******************************************************************
276  *         remove_stdcall_decoration
277  *
278  * Remove a possible @xx suffix from a function name.
279  * Return the numerical value of the suffix, or -1 if none.
280  */
281 int remove_stdcall_decoration( char *name )
282 {
283     char *p, *end = strrchr( name, '@' );
284     if (!end || !end[1] || end == name) return -1;
285     /* make sure all the rest is digits */
286     for (p = end + 1; *p; p++) if (!isdigit(*p)) return -1;
287     *end = 0;
288     return atoi( end + 1 );
289 }
290
291
292 /*******************************************************************
293  *         assemble_file
294  *
295  * Run a file through the assembler.
296  */
297 void assemble_file( const char *src_file, const char *obj_file )
298 {
299     char *cmd;
300     int err;
301
302     if (!as_command) as_command = xstrdup("as");
303     cmd = xmalloc( strlen(as_command) + strlen(obj_file) + strlen(src_file) + 6 );
304     sprintf( cmd, "%s -o %s %s", as_command, obj_file, src_file );
305     if (verbose) fprintf( stderr, "%s\n", cmd );
306     err = system( cmd );
307     if (err) fatal_error( "%s failed with status %d\n", as_command, err );
308     free( cmd );
309 }
310
311
312 /*******************************************************************
313  *         alloc_dll_spec
314  *
315  * Create a new dll spec file descriptor
316  */
317 DLLSPEC *alloc_dll_spec(void)
318 {
319     DLLSPEC *spec;
320
321     spec = xmalloc( sizeof(*spec) );
322     spec->file_name          = NULL;
323     spec->dll_name           = NULL;
324     spec->init_func          = NULL;
325     spec->type               = SPEC_WIN32;
326     spec->base               = MAX_ORDINALS;
327     spec->limit              = 0;
328     spec->stack_size         = 0;
329     spec->heap_size          = 0;
330     spec->nb_entry_points    = 0;
331     spec->alloc_entry_points = 0;
332     spec->nb_names           = 0;
333     spec->nb_resources       = 0;
334     spec->characteristics    = 0;
335     spec->subsystem          = 0;
336     spec->subsystem_major    = 4;
337     spec->subsystem_minor    = 0;
338     spec->entry_points       = NULL;
339     spec->names              = NULL;
340     spec->ordinals           = NULL;
341     spec->resources          = NULL;
342     return spec;
343 }
344
345
346 /*******************************************************************
347  *         free_dll_spec
348  *
349  * Free dll spec file descriptor
350  */
351 void free_dll_spec( DLLSPEC *spec )
352 {
353     int i;
354
355     for (i = 0; i < spec->nb_entry_points; i++)
356     {
357         ORDDEF *odp = &spec->entry_points[i];
358         free( odp->name );
359         free( odp->export_name );
360         free( odp->link_name );
361     }
362     free( spec->file_name );
363     free( spec->dll_name );
364     free( spec->init_func );
365     free( spec->entry_points );
366     free( spec->names );
367     free( spec->ordinals );
368     free( spec->resources );
369     free( spec );
370 }
371
372
373 /*******************************************************************
374  *         make_c_identifier
375  *
376  * Map a string to a valid C identifier.
377  */
378 const char *make_c_identifier( const char *str )
379 {
380     static char buffer[256];
381     char *p;
382
383     for (p = buffer; *str && p < buffer+sizeof(buffer)-1; p++, str++)
384     {
385         if (isalnum(*str)) *p = *str;
386         else *p = '_';
387     }
388     *p = 0;
389     return buffer;
390 }
391
392
393 /*******************************************************************
394  *         get_stub_name
395  *
396  * Generate an internal name for a stub entry point.
397  */
398 const char *get_stub_name( const ORDDEF *odp, const DLLSPEC *spec )
399 {
400     static char buffer[256];
401     if (odp->name || odp->export_name)
402     {
403         char *p;
404         sprintf( buffer, "__wine_stub_%s", odp->name ? odp->name : odp->export_name );
405         /* make sure name is a legal C identifier */
406         for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
407         if (!*p) return buffer;
408     }
409     sprintf( buffer, "__wine_stub_%s_%d", make_c_identifier(spec->file_name), odp->ordinal );
410     return buffer;
411 }
412
413
414 /*****************************************************************
415  *  Function:    get_alignment
416  *
417  *  Description:
418  *    According to the info page for gas, the .align directive behaves
419  * differently on different systems.  On some architectures, the
420  * argument of a .align directive is the number of bytes to pad to, so
421  * to align on an 8-byte boundary you'd say
422  *     .align 8
423  * On other systems, the argument is "the number of low-order zero bits
424  * that the location counter must have after advancement."  So to
425  * align on an 8-byte boundary you'd say
426  *     .align 3
427  *
428  * The reason gas is written this way is that it's trying to mimick
429  * native assemblers for the various architectures it runs on.  gas
430  * provides other directives that work consistently across
431  * architectures, but of course we want to work on all arches with or
432  * without gas.  Hence this function.
433  *
434  *
435  *  Parameters:
436  *    align  --  the number of bytes to align to. Must be a power of 2.
437  */
438 unsigned int get_alignment(unsigned int align)
439 {
440     unsigned int n;
441
442     assert( !(align & (align - 1)) );
443
444     switch(target_cpu)
445     {
446     case CPU_x86:
447     case CPU_x86_64:
448     case CPU_SPARC:
449         if (target_platform != PLATFORM_APPLE) return align;
450         /* fall through */
451     case CPU_POWERPC:
452     case CPU_ALPHA:
453         n = 0;
454         while ((1 << n) != align) n++;
455         return n;
456     }
457     /* unreached */
458     assert(0);
459     return 0;
460 }
461
462 /* return the page size for the target CPU */
463 unsigned int get_page_size(void)
464 {
465     switch(target_cpu)
466     {
467     case CPU_x86:     return 4096;
468     case CPU_x86_64:  return 4096;
469     case CPU_POWERPC: return 4096;
470     case CPU_SPARC:   return 8192;
471     case CPU_ALPHA:   return 8192;
472     }
473     /* unreached */
474     assert(0);
475     return 0;
476 }
477
478 /* return the size of a pointer on the target CPU */
479 unsigned int get_ptr_size(void)
480 {
481     switch(target_cpu)
482     {
483     case CPU_x86:
484     case CPU_POWERPC:
485     case CPU_SPARC:
486     case CPU_ALPHA:
487         return 4;
488     case CPU_x86_64:
489         return 8;
490     }
491     /* unreached */
492     assert(0);
493     return 0;
494 }
495
496 /* return the assembly name for a C symbol */
497 const char *asm_name( const char *sym )
498 {
499     static char buffer[256];
500
501     switch (target_platform)
502     {
503     case PLATFORM_APPLE:
504     case PLATFORM_WINDOWS:
505         buffer[0] = '_';
506         strcpy( buffer + 1, sym );
507         return buffer;
508     default:
509         return sym;
510     }
511 }
512
513 /* return an assembly function declaration for a C function name */
514 const char *func_declaration( const char *func )
515 {
516     static char buffer[256];
517
518     switch (target_platform)
519     {
520     case PLATFORM_APPLE:
521         return "";
522     case PLATFORM_WINDOWS:
523         sprintf( buffer, ".def _%s; .scl 2; .type 32; .endef", func );
524         break;
525     default:
526         sprintf( buffer, ".type %s,@function", func );
527         break;
528     }
529     return buffer;
530 }
531
532 /* output a size declaration for an assembly function */
533 void output_function_size( const char *name )
534 {
535     switch (target_platform)
536     {
537     case PLATFORM_APPLE:
538     case PLATFORM_WINDOWS:
539         break;
540     default:
541         output( "\t.size %s, .-%s\n", name, name );
542         break;
543     }
544 }
545
546 /* output the GNU note for non-exec stack */
547 void output_gnu_stack_note(void)
548 {
549     switch (target_platform)
550     {
551     case PLATFORM_WINDOWS:
552     case PLATFORM_APPLE:
553         break;
554     default:
555         output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
556         break;
557     }
558 }
559
560 /* return a global symbol declaration for an assembly symbol */
561 const char *asm_globl( const char *func )
562 {
563     static char buffer[256];
564
565     switch (target_platform)
566     {
567     case PLATFORM_APPLE:
568         sprintf( buffer, "\t.globl _%s\n\t.private_extern _%s\n_%s:", func, func, func );
569         return buffer;
570     case PLATFORM_WINDOWS:
571         sprintf( buffer, "\t.globl _%s\n_%s:", func, func );
572         return buffer;
573     default:
574         sprintf( buffer, "\t.globl %s\n\t.hidden %s\n%s:", func, func, func );
575         return buffer;
576     }
577 }
578
579 const char *get_asm_ptr_keyword(void)
580 {
581     switch(get_ptr_size())
582     {
583     case 4: return ".long";
584     case 8: return ".quad";
585     }
586     assert(0);
587     return NULL;
588 }
589
590 const char *get_asm_string_keyword(void)
591 {
592     switch (target_platform)
593     {
594     case PLATFORM_APPLE:
595         return ".asciz";
596     default:
597         return ".string";
598     }
599 }
600
601 const char *get_asm_short_keyword(void)
602 {
603     switch (target_platform)
604     {
605     default:            return ".short";
606     }
607 }
608
609 const char *get_asm_rodata_section(void)
610 {
611     switch (target_platform)
612     {
613     case PLATFORM_APPLE: return ".const";
614     default:             return ".section .rodata";
615     }
616 }
617
618 const char *get_asm_string_section(void)
619 {
620     switch (target_platform)
621     {
622     case PLATFORM_APPLE: return ".cstring";
623     default:             return ".section .rodata";
624     }
625 }