2 * Small utility functions for winebuild
4 * Copyright 2000 Alexandre Julliard
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.
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.
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
22 #include "wine/port.h"
36 #define MAX_TMP_FILES 8
37 static const char *tmp_files
[MAX_TMP_FILES
];
38 static unsigned int nb_tmp_files
;
40 /* atexit handler to clean tmp files */
41 static void cleanup_tmp_files(void)
44 for (i
= 0; i
< MAX_TMP_FILES
; i
++) if (tmp_files
[i
]) unlink( tmp_files
[i
] );
48 void *xmalloc (size_t size
)
52 res
= malloc (size
? size
: 1);
55 fprintf (stderr
, "Virtual memory exhausted.\n");
61 void *xrealloc (void *ptr
, size_t size
)
63 void *res
= realloc (ptr
, size
);
64 if (size
&& res
== NULL
)
66 fprintf (stderr
, "Virtual memory exhausted.\n");
72 char *xstrdup( const char *str
)
74 char *res
= strdup( str
);
77 fprintf (stderr
, "Virtual memory exhausted.\n");
83 char *strupper(char *s
)
86 for (p
= s
; *p
; p
++) *p
= toupper(*p
);
90 int strendswith(const char* str
, const char* end
)
94 return l
>= m
&& strcmp(str
+ l
- m
, end
) == 0;
97 void fatal_error( const char *msg
, ... )
100 va_start( valist
, msg
);
103 fprintf( stderr
, "%s:", input_file_name
);
105 fprintf( stderr
, "%d:", current_line
);
106 fputc( ' ', stderr
);
108 else fprintf( stderr
, "winebuild: " );
109 vfprintf( stderr
, msg
, valist
);
114 void fatal_perror( const char *msg
, ... )
117 va_start( valist
, msg
);
120 fprintf( stderr
, "%s:", input_file_name
);
122 fprintf( stderr
, "%d:", current_line
);
123 fputc( ' ', stderr
);
125 vfprintf( stderr
, msg
, valist
);
131 void error( const char *msg
, ... )
134 va_start( valist
, msg
);
137 fprintf( stderr
, "%s:", input_file_name
);
139 fprintf( stderr
, "%d:", current_line
);
140 fputc( ' ', stderr
);
142 vfprintf( stderr
, msg
, valist
);
147 void warning( const char *msg
, ... )
151 if (!display_warnings
) return;
152 va_start( valist
, msg
);
155 fprintf( stderr
, "%s:", input_file_name
);
157 fprintf( stderr
, "%d:", current_line
);
158 fputc( ' ', stderr
);
160 fprintf( stderr
, "warning: " );
161 vfprintf( stderr
, msg
, valist
);
165 /* get a name for a temp file, automatically cleaned up on exit */
166 char *get_temp_file_name( const char *prefix
, const char *suffix
)
172 assert( nb_tmp_files
< MAX_TMP_FILES
);
173 if (!nb_tmp_files
&& !save_temps
) atexit( cleanup_tmp_files
);
175 if (!prefix
|| !prefix
[0]) prefix
= "winebuild";
176 if (!suffix
) suffix
= "";
177 if (!(ext
= strchr( prefix
, '.' ))) ext
= prefix
+ strlen(prefix
);
178 name
= xmalloc( sizeof("/tmp/") + (ext
- prefix
) + sizeof(".XXXXXX") + strlen(suffix
) );
179 strcpy( name
, "/tmp/" );
180 memcpy( name
+ 5, prefix
, ext
- prefix
);
181 strcpy( name
+ 5 + (ext
- prefix
), ".XXXXXX" );
182 strcat( name
, suffix
);
184 /* first try without the /tmp/ prefix */
185 if ((fd
= mkstemps( name
+ 5, strlen(suffix
) )) != -1)
187 else if ((fd
= mkstemps( name
, strlen(suffix
) )) == -1)
188 fatal_error( "could not generate a temp file\n" );
191 tmp_files
[nb_tmp_files
++] = name
;
195 /* output a standard header for generated files */
196 void output_standard_file_header( FILE *outfile
)
199 fprintf( outfile
, "/* File generated automatically from %s; do not edit! */\n",
202 fprintf( outfile
, "/* File generated automatically; do not edit! */\n" );
204 "/* This file can be copied, modified and distributed without restriction. */\n\n" );
207 /* dump a byte stream into the assembly code */
208 void dump_bytes( FILE *outfile
, const void *buffer
, unsigned int size
)
211 const unsigned char *ptr
= buffer
;
214 fprintf( outfile
, "\t.byte " );
215 for (i
= 0; i
< size
- 1; i
++, ptr
++)
217 if ((i
% 16) == 15) fprintf( outfile
, "0x%02x\n\t.byte ", *ptr
);
218 else fprintf( outfile
, "0x%02x,", *ptr
);
220 fprintf( outfile
, "0x%02x\n", *ptr
);
224 /*******************************************************************
227 * Open a file in the given srcdir and set the input_file_name global variable.
229 FILE *open_input_file( const char *srcdir
, const char *name
)
232 FILE *file
= fopen( name
, "r" );
236 fullname
= xmalloc( strlen(srcdir
) + strlen(name
) + 2 );
237 strcpy( fullname
, srcdir
);
238 strcat( fullname
, "/" );
239 strcat( fullname
, name
);
240 file
= fopen( fullname
, "r" );
242 else fullname
= xstrdup( name
);
244 if (!file
) fatal_error( "Cannot open file '%s'\n", fullname
);
245 input_file_name
= fullname
;
251 /*******************************************************************
254 * Close the current input file (must have been opened with open_input_file).
256 void close_input_file( FILE *file
)
259 free( input_file_name
);
260 input_file_name
= NULL
;
265 /*******************************************************************
266 * remove_stdcall_decoration
268 * Remove a possible @xx suffix from a function name.
269 * Return the numerical value of the suffix, or -1 if none.
271 int remove_stdcall_decoration( char *name
)
273 char *p
, *end
= strrchr( name
, '@' );
274 if (!end
|| !end
[1] || end
== name
) return -1;
275 /* make sure all the rest is digits */
276 for (p
= end
+ 1; *p
; p
++) if (!isdigit(*p
)) return -1;
278 return atoi( end
+ 1 );
282 /*******************************************************************
285 * Run a file through the assembler.
287 void assemble_file( const char *src_file
, const char *obj_file
)
292 if (!as_command
) as_command
= xstrdup("as");
293 cmd
= xmalloc( strlen(as_command
) + strlen(obj_file
) + strlen(src_file
) + 6 );
294 sprintf( cmd
, "%s -o %s %s", as_command
, obj_file
, src_file
);
295 if (verbose
) fprintf( stderr
, "%s\n", cmd
);
297 if (err
) fatal_error( "%s failed with status %d\n", as_command
, err
);
302 /*******************************************************************
305 * Create a new dll spec file descriptor
307 DLLSPEC
*alloc_dll_spec(void)
311 spec
= xmalloc( sizeof(*spec
) );
312 spec
->file_name
= NULL
;
313 spec
->dll_name
= NULL
;
314 spec
->init_func
= NULL
;
315 spec
->type
= SPEC_WIN32
;
316 spec
->base
= MAX_ORDINALS
;
318 spec
->stack_size
= 0;
320 spec
->nb_entry_points
= 0;
321 spec
->alloc_entry_points
= 0;
323 spec
->nb_resources
= 0;
324 spec
->characteristics
= 0;
326 spec
->subsystem_major
= 4;
327 spec
->subsystem_minor
= 0;
328 spec
->entry_points
= NULL
;
330 spec
->ordinals
= NULL
;
331 spec
->resources
= NULL
;
336 /*******************************************************************
339 * Free dll spec file descriptor
341 void free_dll_spec( DLLSPEC
*spec
)
345 for (i
= 0; i
< spec
->nb_entry_points
; i
++)
347 ORDDEF
*odp
= &spec
->entry_points
[i
];
349 free( odp
->export_name
);
350 free( odp
->link_name
);
352 free( spec
->file_name
);
353 free( spec
->dll_name
);
354 free( spec
->init_func
);
355 free( spec
->entry_points
);
357 free( spec
->ordinals
);
358 free( spec
->resources
);
363 /*******************************************************************
366 * Map a string to a valid C identifier.
368 const char *make_c_identifier( const char *str
)
370 static char buffer
[256];
373 for (p
= buffer
; *str
&& p
< buffer
+sizeof(buffer
)-1; p
++, str
++)
375 if (isalnum(*str
)) *p
= *str
;
383 /*******************************************************************
386 * Generate an internal name for a stub entry point.
388 const char *get_stub_name( const ORDDEF
*odp
, const DLLSPEC
*spec
)
390 static char buffer
[256];
391 if (odp
->name
|| odp
->export_name
)
394 sprintf( buffer
, "__wine_stub_%s", odp
->name
? odp
->name
: odp
->export_name
);
395 /* make sure name is a legal C identifier */
396 for (p
= buffer
; *p
; p
++) if (!isalnum(*p
) && *p
!= '_') break;
397 if (!*p
) return buffer
;
399 sprintf( buffer
, "__wine_stub_%s_%d", make_c_identifier(spec
->file_name
), odp
->ordinal
);
404 /*****************************************************************
405 * Function: get_alignment
408 * According to the info page for gas, the .align directive behaves
409 * differently on different systems. On some architectures, the
410 * argument of a .align directive is the number of bytes to pad to, so
411 * to align on an 8-byte boundary you'd say
413 * On other systems, the argument is "the number of low-order zero bits
414 * that the location counter must have after advancement." So to
415 * align on an 8-byte boundary you'd say
418 * The reason gas is written this way is that it's trying to mimick
419 * native assemblers for the various architectures it runs on. gas
420 * provides other directives that work consistently across
421 * architectures, but of course we want to work on all arches with or
422 * without gas. Hence this function.
426 * align -- the number of bytes to align to. Must be a power of 2.
428 unsigned int get_alignment(unsigned int align
)
432 assert( !(align
& (align
- 1)) );
439 if (target_platform
!= PLATFORM_APPLE
) return align
;
444 while ((1 << n
) != align
) n
++;
452 /* return the page size for the target CPU */
453 unsigned int get_page_size(void)
457 case CPU_x86
: return 4096;
458 case CPU_x86_64
: return 4096;
459 case CPU_POWERPC
: return 4096;
460 case CPU_SPARC
: return 8192;
461 case CPU_ALPHA
: return 8192;
468 /* return the size of a pointer on the target CPU */
469 unsigned int get_ptr_size(void)
486 /* return the assembly name for a C symbol */
487 const char *asm_name( const char *sym
)
489 static char buffer
[256];
491 switch (target_platform
)
494 case PLATFORM_WINDOWS
:
496 strcpy( buffer
+ 1, sym
);
503 /* return an assembly function declaration for a C function name */
504 const char *func_declaration( const char *func
)
506 static char buffer
[256];
508 switch (target_platform
)
512 case PLATFORM_WINDOWS
:
513 sprintf( buffer
, ".def _%s; .scl 2; .type 32; .endef", func
);
516 sprintf( buffer
, ".type %s,@function", func
);
522 /* output a size declaration for an assembly function */
523 void output_function_size( FILE *outfile
, const char *name
)
525 switch (target_platform
)
528 case PLATFORM_WINDOWS
:
531 fprintf( outfile
, "\t.size %s, .-%s\n", name
, name
);
536 /* output the GNU note for non-exec stack */
537 void output_gnu_stack_note( FILE *outfile
)
539 switch (target_platform
)
541 case PLATFORM_WINDOWS
:
545 fprintf( outfile
, "\t.section .note.GNU-stack,\"\",@progbits\n" );
550 /* return a global symbol declaration for an assembly symbol */
551 const char *asm_globl( const char *func
)
553 static char buffer
[256];
555 switch (target_platform
)
558 sprintf( buffer
, "\t.globl _%s\n\t.private_extern _%s\n_%s:", func
, func
, func
);
560 case PLATFORM_WINDOWS
:
561 sprintf( buffer
, "\t.globl _%s\n_%s:", func
, func
);
564 sprintf( buffer
, "\t.globl %s\n\t.hidden %s\n%s:", func
, func
, func
);
569 const char *get_asm_ptr_keyword(void)
571 switch(get_ptr_size())
573 case 4: return ".long";
574 case 8: return ".quad";
580 const char *get_asm_string_keyword(void)
582 switch (target_platform
)
591 const char *get_asm_short_keyword(void)
593 switch (target_platform
)
595 default: return ".short";
599 const char *get_asm_rodata_section(void)
601 switch (target_platform
)
603 case PLATFORM_APPLE
: return ".const";
604 default: return ".section .rodata";
608 const char *get_asm_string_section(void)
610 switch (target_platform
)
612 case PLATFORM_APPLE
: return ".cstring";
613 default: return ".section .rodata";