~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/tools/winebuild/utils.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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 #ifdef HAVE_SYS_STAT_H
 34 # include <sys/stat.h>
 35 #endif
 36 #ifdef HAVE_SYS_MMAN_H
 37 #include <sys/mman.h>
 38 #endif
 39 
 40 #include "build.h"
 41 
 42 #define MAX_TMP_FILES 8
 43 static const char *tmp_files[MAX_TMP_FILES];
 44 static unsigned int nb_tmp_files;
 45 
 46 static const struct
 47 {
 48     const char *name;
 49     enum target_cpu cpu;
 50 } cpu_names[] =
 51 {
 52     { "i386",    CPU_x86 },
 53     { "i486",    CPU_x86 },
 54     { "i586",    CPU_x86 },
 55     { "i686",    CPU_x86 },
 56     { "i786",    CPU_x86 },
 57     { "x86_64",  CPU_x86_64 },
 58     { "sparc",   CPU_SPARC },
 59     { "alpha",   CPU_ALPHA },
 60     { "powerpc", CPU_POWERPC }
 61 };
 62 
 63 /* atexit handler to clean tmp files */
 64 static void cleanup_tmp_files(void)
 65 {
 66     unsigned int i;
 67     for (i = 0; i < MAX_TMP_FILES; i++) if (tmp_files[i]) unlink( tmp_files[i] );
 68 }
 69 
 70 
 71 void *xmalloc (size_t size)
 72 {
 73     void *res;
 74 
 75     res = malloc (size ? size : 1);
 76     if (res == NULL)
 77     {
 78         fprintf (stderr, "Virtual memory exhausted.\n");
 79         exit (1);
 80     }
 81     return res;
 82 }
 83 
 84 void *xrealloc (void *ptr, size_t size)
 85 {
 86     void *res = realloc (ptr, size);
 87     if (size && res == NULL)
 88     {
 89         fprintf (stderr, "Virtual memory exhausted.\n");
 90         exit (1);
 91     }
 92     return res;
 93 }
 94 
 95 char *xstrdup( const char *str )
 96 {
 97     char *res = strdup( str );
 98     if (!res)
 99     {
100         fprintf (stderr, "Virtual memory exhausted.\n");
101         exit (1);
102     }
103     return res;
104 }
105 
106 char *strupper(char *s)
107 {
108     char *p;
109     for (p = s; *p; p++) *p = toupper(*p);
110     return s;
111 }
112 
113 int strendswith(const char* str, const char* end)
114 {
115     int l = strlen(str);
116     int m = strlen(end);
117     return l >= m && strcmp(str + l - m, end) == 0;
118 }
119 
120 void fatal_error( const char *msg, ... )
121 {
122     va_list valist;
123     va_start( valist, msg );
124     if (input_file_name)
125     {
126         fprintf( stderr, "%s:", input_file_name );
127         if (current_line)
128             fprintf( stderr, "%d:", current_line );
129         fputc( ' ', stderr );
130     }
131     else fprintf( stderr, "winebuild: " );
132     vfprintf( stderr, msg, valist );
133     va_end( valist );
134     exit(1);
135 }
136 
137 void fatal_perror( const char *msg, ... )
138 {
139     va_list valist;
140     va_start( valist, msg );
141     if (input_file_name)
142     {
143         fprintf( stderr, "%s:", input_file_name );
144         if (current_line)
145             fprintf( stderr, "%d:", current_line );
146         fputc( ' ', stderr );
147     }
148     vfprintf( stderr, msg, valist );
149     perror( " " );
150     va_end( valist );
151     exit(1);
152 }
153 
154 void error( const char *msg, ... )
155 {
156     va_list valist;
157     va_start( valist, msg );
158     if (input_file_name)
159     {
160         fprintf( stderr, "%s:", input_file_name );
161         if (current_line)
162             fprintf( stderr, "%d:", current_line );
163         fputc( ' ', stderr );
164     }
165     vfprintf( stderr, msg, valist );
166     va_end( valist );
167     nb_errors++;
168 }
169 
170 void warning( const char *msg, ... )
171 {
172     va_list valist;
173 
174     if (!display_warnings) return;
175     va_start( valist, msg );
176     if (input_file_name)
177     {
178         fprintf( stderr, "%s:", input_file_name );
179         if (current_line)
180             fprintf( stderr, "%d:", current_line );
181         fputc( ' ', stderr );
182     }
183     fprintf( stderr, "warning: " );
184     vfprintf( stderr, msg, valist );
185     va_end( valist );
186 }
187 
188 int output( const char *format, ... )
189 {
190     int ret;
191     va_list valist;
192 
193     va_start( valist, format );
194     ret = vfprintf( output_file, format, valist );
195     va_end( valist );
196     if (ret < 0) fatal_perror( "Output error" );
197     return ret;
198 }
199 
200 /* find a build tool in the path, trying the various names */
201 static char *find_tool( const char * const *names )
202 {
203     static char **dirs;
204     static unsigned int count, maxlen;
205 
206     char *p, *file;
207     unsigned int i, len;
208     struct stat st;
209 
210     if (!dirs)
211     {
212         char *path;
213 
214         /* split the path in directories */
215 
216         if (!getenv( "PATH" )) return NULL;
217         path = xstrdup( getenv( "PATH" ));
218         for (p = path, count = 2; *p; p++) if (*p == ':') count++;
219         dirs = xmalloc( count * sizeof(*dirs) );
220         count = 0;
221         dirs[count++] = p = path;
222         while (*p)
223         {
224             while (*p && *p != ':') p++;
225             if (!*p) break;
226             *p++ = 0;
227             dirs[count++] = p;
228         }
229         for (i = 0; i < count; i++) maxlen = max( maxlen, strlen(dirs[i])+2 );
230     }
231 
232     while (*names)
233     {
234         len = strlen(*names) + sizeof(EXEEXT) + 1;
235         file = xmalloc( maxlen + len );
236 
237         for (i = 0; i < count; i++)
238         {
239             strcpy( file, dirs[i] );
240             p = file + strlen(file);
241             if (p == file) *p++ = '.';
242             if (p[-1] != '/') *p++ = '/';
243             strcpy( p, *names );
244             strcat( p, EXEEXT );
245 
246             if (!stat( file, &st ) && S_ISREG(st.st_mode) && (st.st_mode & 0111)) return file;
247         }
248         free( file );
249         names++;
250     }
251     return NULL;
252 }
253 
254 const char *get_as_command(void)
255 {
256     if (!as_command)
257     {
258         if (target_alias)
259         {
260             as_command = xmalloc( strlen(target_alias) + sizeof("-as") );
261             strcpy( as_command, target_alias );
262             strcat( as_command, "-as" );
263         }
264         else
265         {
266             static const char * const commands[] = { "gas", "as", NULL };
267             if (!(as_command = find_tool( commands ))) as_command = xstrdup("as");
268         }
269 
270         if (force_pointer_size)
271         {
272             const char *args = (target_platform == PLATFORM_APPLE) ?
273                 ((force_pointer_size == 8) ? " -arch x86_64" : " -arch i386") :
274                 ((force_pointer_size == 8) ? " --64" : " --32");
275             as_command = xrealloc( as_command, strlen(as_command) + strlen(args) + 1 );
276             strcat( as_command, args );
277         }
278     }
279     return as_command;
280 }
281 
282 const char *get_ld_command(void)
283 {
284     if (!ld_command)
285     {
286         if (target_alias)
287         {
288             ld_command = xmalloc( strlen(target_alias) + sizeof("-ld") );
289             strcpy( ld_command, target_alias );
290             strcat( ld_command, "-ld" );
291         }
292         else
293         {
294             static const char * const commands[] = { "ld", "gld", NULL };
295             if (!(ld_command = find_tool( commands ))) ld_command = xstrdup("ld");
296         }
297 
298         if (force_pointer_size)
299         {
300             const char *args;
301 
302             switch (target_platform)
303             {
304             case PLATFORM_APPLE:
305                 args = (force_pointer_size == 8) ? " -arch x86_64" : " -arch i386";
306                 break;
307             case PLATFORM_FREEBSD:
308                 args = (force_pointer_size == 8) ? " -m elf_x86_64" : " -m elf_i386_fbsd";
309                 break;
310             default:
311                 args = (force_pointer_size == 8) ? " -m elf_x86_64" : " -m elf_i386";
312                 break;
313             }
314             ld_command = xrealloc( ld_command, strlen(ld_command) + strlen(args) + 1 );
315             strcat( ld_command, args );
316         }
317     }
318     return ld_command;
319 }
320 
321 const char *get_nm_command(void)
322 {
323     if (!nm_command)
324     {
325         if (target_alias)
326         {
327             nm_command = xmalloc( strlen(target_alias) + sizeof("-nm") );
328             strcpy( nm_command, target_alias );
329             strcat( nm_command, "-nm" );
330         }
331         else
332         {
333             static const char * const commands[] = { "nm", "gnm", NULL };
334             if (!(nm_command = find_tool( commands ))) nm_command = xstrdup("nm");
335         }
336     }
337     return nm_command;
338 }
339 
340 const char *get_windres_command(void)
341 {
342     static char *windres_command;
343 
344     if (!windres_command)
345     {
346         if (target_alias)
347         {
348             windres_command = xmalloc( strlen(target_alias) + sizeof("-windres") );
349             strcpy( windres_command, target_alias );
350             strcat( windres_command, "-windres" );
351         }
352         else
353         {
354             static const char * const commands[] = { "windres", NULL };
355             if (!(windres_command = find_tool( commands ))) windres_command = xstrdup("windres");
356         }
357     }
358     return windres_command;
359 }
360 
361 /* get a name for a temp file, automatically cleaned up on exit */
362 char *get_temp_file_name( const char *prefix, const char *suffix )
363 {
364     char *name;
365     const char *ext;
366     int fd;
367 
368     assert( nb_tmp_files < MAX_TMP_FILES );
369     if (!nb_tmp_files && !save_temps) atexit( cleanup_tmp_files );
370 
371     if (!prefix || !prefix[0]) prefix = "winebuild";
372     if (!suffix) suffix = "";
373     if (!(ext = strchr( prefix, '.' ))) ext = prefix + strlen(prefix);
374     name = xmalloc( sizeof("/tmp/") + (ext - prefix) + sizeof(".XXXXXX") + strlen(suffix) );
375     strcpy( name, "/tmp/" );
376     memcpy( name + 5, prefix, ext - prefix );
377     strcpy( name + 5 + (ext - prefix), ".XXXXXX" );
378     strcat( name, suffix );
379 
380     /* first try without the /tmp/ prefix */
381     if ((fd = mkstemps( name + 5, strlen(suffix) )) != -1)
382         name += 5;
383     else if ((fd = mkstemps( name, strlen(suffix) )) == -1)
384         fatal_error( "could not generate a temp file\n" );
385 
386     close( fd );
387     tmp_files[nb_tmp_files++] = name;
388     return name;
389 }
390 
391 /*******************************************************************
392  *         buffer management
393  *
394  * Function for reading from/writing to a memory buffer.
395  */
396 
397 int byte_swapped = 0;
398 const char *input_buffer_filename;
399 const unsigned char *input_buffer;
400 size_t input_buffer_pos;
401 size_t input_buffer_size;
402 unsigned char *output_buffer;
403 size_t output_buffer_pos;
404 size_t output_buffer_size;
405 
406 static void check_output_buffer_space( size_t size )
407 {
408     if (output_buffer_pos + size >= output_buffer_size)
409     {
410         output_buffer_size = max( output_buffer_size * 2, output_buffer_pos + size );
411         output_buffer = xrealloc( output_buffer, output_buffer_size );
412     }
413 }
414 
415 void init_input_buffer( const char *file )
416 {
417     int fd;
418     struct stat st;
419 
420     if ((fd = open( file, O_RDONLY | O_BINARY )) == -1) fatal_perror( "Cannot open %s", file );
421     if ((fstat( fd, &st ) == -1)) fatal_perror( "Cannot stat %s", file );
422     if (!st.st_size) fatal_error( "%s is an empty file\n", file );
423 #ifdef  HAVE_MMAP
424     if ((input_buffer = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
425 #endif
426     {
427         unsigned char *buffer = xmalloc( st.st_size );
428         if (read( fd, buffer, st.st_size ) != st.st_size) fatal_error( "Cannot read %s\n", file );
429         input_buffer = buffer;
430     }
431     close( fd );
432     input_buffer_filename = xstrdup( file );
433     input_buffer_size = st.st_size;
434     input_buffer_pos = 0;
435     byte_swapped = 0;
436 }
437 
438 void init_output_buffer(void)
439 {
440     output_buffer_size = 1024;
441     output_buffer_pos = 0;
442     output_buffer = xmalloc( output_buffer_size );
443 }
444 
445 void flush_output_buffer(void)
446 {
447     if (fwrite( output_buffer, 1, output_buffer_pos, output_file ) != output_buffer_pos)
448         fatal_error( "Error writing to %s\n", output_file_name );
449     free( output_buffer );
450 }
451 
452 unsigned char get_byte(void)
453 {
454     if (input_buffer_pos >= input_buffer_size)
455         fatal_error( "%s is a truncated file\n", input_buffer_filename );
456     return input_buffer[input_buffer_pos++];
457 }
458 
459 unsigned short get_word(void)
460 {
461     unsigned short ret;
462 
463     if (input_buffer_pos + sizeof(ret) > input_buffer_size)
464         fatal_error( "%s is a truncated file\n", input_buffer_filename );
465     memcpy( &ret, input_buffer + input_buffer_pos, sizeof(ret) );
466     if (byte_swapped) ret = (ret << 8) | (ret >> 8);
467     input_buffer_pos += sizeof(ret);
468     return ret;
469 }
470 
471 unsigned int get_dword(void)
472 {
473     unsigned int ret;
474 
475     if (input_buffer_pos + sizeof(ret) > input_buffer_size)
476         fatal_error( "%s is a truncated file\n", input_buffer_filename );
477     memcpy( &ret, input_buffer + input_buffer_pos, sizeof(ret) );
478     if (byte_swapped)
479         ret = ((ret << 24) | ((ret << 8) & 0x00ff0000) | ((ret >> 8) & 0x0000ff00) | (ret >> 24));
480     input_buffer_pos += sizeof(ret);
481     return ret;
482 }
483 
484 void put_data( const void *data, size_t size )
485 {
486     check_output_buffer_space( size );
487     memcpy( output_buffer + output_buffer_pos, data, size );
488     output_buffer_pos += size;
489 }
490 
491 void put_byte( unsigned char val )
492 {
493     check_output_buffer_space( 1 );
494     output_buffer[output_buffer_pos++] = val;
495 }
496 
497 void put_word( unsigned short val )
498 {
499     if (byte_swapped) val = (val << 8) | (val >> 8);
500     put_data( &val, sizeof(val) );
501 }
502 
503 void put_dword( unsigned int val )
504 {
505     if (byte_swapped)
506         val = ((val << 24) | ((val << 8) & 0x00ff0000) | ((val >> 8) & 0x0000ff00) | (val >> 24));
507     put_data( &val, sizeof(val) );
508 }
509 
510 void put_qword( unsigned int val )
511 {
512     if (byte_swapped)
513     {
514         put_dword( 0 );
515         put_dword( val );
516     }
517     else
518     {
519         put_dword( val );
520         put_dword( 0 );
521     }
522 }
523 
524 /* pointer-sized word */
525 void put_pword( unsigned int val )
526 {
527     if (get_ptr_size() == 8) put_qword( val );
528     else put_dword( val );
529 }
530 
531 void align_output( unsigned int align )
532 {
533     size_t size = align - (output_buffer_pos % align);
534 
535     if (size == align) return;
536     check_output_buffer_space( size );
537     memset( output_buffer + output_buffer_pos, 0, size );
538     output_buffer_pos += size;
539 }
540 
541 /* output a standard header for generated files */
542 void output_standard_file_header(void)
543 {
544     if (spec_file_name)
545         output( "/* File generated automatically from %s; do not edit! */\n", spec_file_name );
546     else
547         output( "/* File generated automatically; do not edit! */\n" );
548     output( "/* This file can be copied, modified and distributed without restriction. */\n\n" );
549 }
550 
551 /* dump a byte stream into the assembly code */
552 void dump_bytes( const void *buffer, unsigned int size )
553 {
554     unsigned int i;
555     const unsigned char *ptr = buffer;
556 
557     if (!size) return;
558     output( "\t.byte " );
559     for (i = 0; i < size - 1; i++, ptr++)
560     {
561         if ((i % 16) == 15) output( "0x%02x\n\t.byte ", *ptr );
562         else output( "0x%02x,", *ptr );
563     }
564     output( "0x%02x\n", *ptr );
565 }
566 
567 
568 /*******************************************************************
569  *         open_input_file
570  *
571  * Open a file in the given srcdir and set the input_file_name global variable.
572  */
573 FILE *open_input_file( const char *srcdir, const char *name )
574 {
575     char *fullname;
576     FILE *file = fopen( name, "r" );
577 
578     if (!file && srcdir)
579     {
580         fullname = xmalloc( strlen(srcdir) + strlen(name) + 2 );
581         strcpy( fullname, srcdir );
582         strcat( fullname, "/" );
583         strcat( fullname, name );
584         file = fopen( fullname, "r" );
585     }
586     else fullname = xstrdup( name );
587 
588     if (!file) fatal_error( "Cannot open file '%s'\n", fullname );
589     input_file_name = fullname;
590     current_line = 1;
591     return file;
592 }
593 
594 
595 /*******************************************************************
596  *         close_input_file
597  *
598  * Close the current input file (must have been opened with open_input_file).
599  */
600 void close_input_file( FILE *file )
601 {
602     fclose( file );
603     free( input_file_name );
604     input_file_name = NULL;
605     current_line = 0;
606 }
607 
608 
609 /*******************************************************************
610  *         remove_stdcall_decoration
611  *
612  * Remove a possible @xx suffix from a function name.
613  * Return the numerical value of the suffix, or -1 if none.
614  */
615 int remove_stdcall_decoration( char *name )
616 {
617     char *p, *end = strrchr( name, '@' );
618     if (!end || !end[1] || end == name) return -1;
619     /* make sure all the rest is digits */
620     for (p = end + 1; *p; p++) if (!isdigit(*p)) return -1;
621     *end = 0;
622     return atoi( end + 1 );
623 }
624 
625 
626 /*******************************************************************
627  *         assemble_file
628  *
629  * Run a file through the assembler.
630  */
631 void assemble_file( const char *src_file, const char *obj_file )
632 {
633     const char *prog = get_as_command();
634     char *cmd;
635     int err;
636 
637     cmd = xmalloc( strlen(prog) + strlen(obj_file) + strlen(src_file) + 6 );
638     sprintf( cmd, "%s -o %s %s", prog, obj_file, src_file );
639     if (verbose) fprintf( stderr, "%s\n", cmd );
640     err = system( cmd );
641     if (err) fatal_error( "%s failed with status %d\n", prog, err );
642     free( cmd );
643 }
644 
645 
646 /*******************************************************************
647  *         alloc_dll_spec
648  *
649  * Create a new dll spec file descriptor
650  */
651 DLLSPEC *alloc_dll_spec(void)
652 {
653     DLLSPEC *spec;
654 
655     spec = xmalloc( sizeof(*spec) );
656     spec->file_name          = NULL;
657     spec->dll_name           = NULL;
658     spec->init_func          = NULL;
659     spec->main_module        = NULL;
660     spec->type               = SPEC_WIN32;
661     spec->base               = MAX_ORDINALS;
662     spec->limit              = 0;
663     spec->stack_size         = 0;
664     spec->heap_size          = 0;
665     spec->nb_entry_points    = 0;
666     spec->alloc_entry_points = 0;
667     spec->nb_names           = 0;
668     spec->nb_resources       = 0;
669     spec->characteristics    = IMAGE_FILE_EXECUTABLE_IMAGE;
670     if (get_ptr_size() > 4)
671         spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
672     else
673         spec->characteristics |= IMAGE_FILE_32BIT_MACHINE;
674     spec->dll_characteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
675     spec->subsystem          = 0;
676     spec->subsystem_major    = 4;
677     spec->subsystem_minor    = 0;
678     spec->entry_points       = NULL;
679     spec->names              = NULL;
680     spec->ordinals           = NULL;
681     spec->resources          = NULL;
682     return spec;
683 }
684 
685 
686 /*******************************************************************
687  *         free_dll_spec
688  *
689  * Free dll spec file descriptor
690  */
691 void free_dll_spec( DLLSPEC *spec )
692 {
693     int i;
694 
695     for (i = 0; i < spec->nb_entry_points; i++)
696     {
697         ORDDEF *odp = &spec->entry_points[i];
698         free( odp->name );
699         free( odp->export_name );
700         free( odp->link_name );
701     }
702     free( spec->file_name );
703     free( spec->dll_name );
704     free( spec->init_func );
705     free( spec->entry_points );
706     free( spec->names );
707     free( spec->ordinals );
708     free( spec->resources );
709     free( spec );
710 }
711 
712 
713 /*******************************************************************
714  *         make_c_identifier
715  *
716  * Map a string to a valid C identifier.
717  */
718 const char *make_c_identifier( const char *str )
719 {
720     static char buffer[256];
721     char *p;
722 
723     for (p = buffer; *str && p < buffer+sizeof(buffer)-1; p++, str++)
724     {
725         if (isalnum(*str)) *p = *str;
726         else *p = '_';
727     }
728     *p = 0;
729     return buffer;
730 }
731 
732 
733 /*******************************************************************
734  *         get_stub_name
735  *
736  * Generate an internal name for a stub entry point.
737  */
738 const char *get_stub_name( const ORDDEF *odp, const DLLSPEC *spec )
739 {
740     static char buffer[256];
741     if (odp->name || odp->export_name)
742     {
743         char *p;
744         sprintf( buffer, "__wine_stub_%s", odp->name ? odp->name : odp->export_name );
745         /* make sure name is a legal C identifier */
746         for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
747         if (!*p) return buffer;
748     }
749     sprintf( buffer, "__wine_stub_%s_%d", make_c_identifier(spec->file_name), odp->ordinal );
750     return buffer;
751 }
752 
753 /* parse a cpu name and return the corresponding value */
754 enum target_cpu get_cpu_from_name( const char *name )
755 {
756     unsigned int i;
757 
758     for (i = 0; i < sizeof(cpu_names)/sizeof(cpu_names[0]); i++)
759         if (!strcmp( cpu_names[i].name, name )) return cpu_names[i].cpu;
760     return -1;
761 }
762 
763 /*****************************************************************
764  *  Function:    get_alignment
765  *
766  *  Description:
767  *    According to the info page for gas, the .align directive behaves
768  * differently on different systems.  On some architectures, the
769  * argument of a .align directive is the number of bytes to pad to, so
770  * to align on an 8-byte boundary you'd say
771  *     .align 8
772  * On other systems, the argument is "the number of low-order zero bits
773  * that the location counter must have after advancement."  So to
774  * align on an 8-byte boundary you'd say
775  *     .align 3
776  *
777  * The reason gas is written this way is that it's trying to mimick
778  * native assemblers for the various architectures it runs on.  gas
779  * provides other directives that work consistently across
780  * architectures, but of course we want to work on all arches with or
781  * without gas.  Hence this function.
782  *
783  *
784  *  Parameters:
785  *    align  --  the number of bytes to align to. Must be a power of 2.
786  */
787 unsigned int get_alignment(unsigned int align)
788 {
789     unsigned int n;
790 
791     assert( !(align & (align - 1)) );
792 
793     switch(target_cpu)
794     {
795     case CPU_x86:
796     case CPU_x86_64:
797     case CPU_SPARC:
798         if (target_platform != PLATFORM_APPLE) return align;
799         /* fall through */
800     case CPU_POWERPC:
801     case CPU_ALPHA:
802         n = 0;
803         while ((1u << n) != align) n++;
804         return n;
805     }
806     /* unreached */
807     assert(0);
808     return 0;
809 }
810 
811 /* return the page size for the target CPU */
812 unsigned int get_page_size(void)
813 {
814     switch(target_cpu)
815     {
816     case CPU_x86:     return 4096;
817     case CPU_x86_64:  return 4096;
818     case CPU_POWERPC: return 4096;
819     case CPU_SPARC:   return 8192;
820     case CPU_ALPHA:   return 8192;
821     }
822     /* unreached */
823     assert(0);
824     return 0;
825 }
826 
827 /* return the size of a pointer on the target CPU */
828 unsigned int get_ptr_size(void)
829 {
830     switch(target_cpu)
831     {
832     case CPU_x86:
833     case CPU_POWERPC:
834     case CPU_SPARC:
835     case CPU_ALPHA:
836         return 4;
837     case CPU_x86_64:
838         return 8;
839     }
840     /* unreached */
841     assert(0);
842     return 0;
843 }
844 
845 /* return the assembly name for a C symbol */
846 const char *asm_name( const char *sym )
847 {
848     static char buffer[256];
849 
850     switch (target_platform)
851     {
852     case PLATFORM_APPLE:
853     case PLATFORM_WINDOWS:
854         if (sym[0] == '.' && sym[1] == 'L') return sym;
855         buffer[0] = '_';
856         strcpy( buffer + 1, sym );
857         return buffer;
858     default:
859         return sym;
860     }
861 }
862 
863 /* return an assembly function declaration for a C function name */
864 const char *func_declaration( const char *func )
865 {
866     static char buffer[256];
867 
868     switch (target_platform)
869     {
870     case PLATFORM_APPLE:
871         return "";
872     case PLATFORM_WINDOWS:
873         sprintf( buffer, ".def _%s; .scl 2; .type 32; .endef", func );
874         break;
875     default:
876         sprintf( buffer, ".type %s,@function", func );
877         break;
878     }
879     return buffer;
880 }
881 
882 /* output a size declaration for an assembly function */
883 void output_function_size( const char *name )
884 {
885     switch (target_platform)
886     {
887     case PLATFORM_APPLE:
888     case PLATFORM_WINDOWS:
889         break;
890     default:
891         output( "\t.size %s, .-%s\n", name, name );
892         break;
893     }
894 }
895 
896 /* output the GNU note for non-exec stack */
897 void output_gnu_stack_note(void)
898 {
899     switch (target_platform)
900     {
901     case PLATFORM_WINDOWS:
902     case PLATFORM_APPLE:
903         break;
904     default:
905         output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
906         break;
907     }
908 }
909 
910 /* return a global symbol declaration for an assembly symbol */
911 const char *asm_globl( const char *func )
912 {
913     static char buffer[256];
914 
915     switch (target_platform)
916     {
917     case PLATFORM_APPLE:
918         sprintf( buffer, "\t.globl _%s\n\t.private_extern _%s\n_%s:", func, func, func );
919         return buffer;
920     case PLATFORM_WINDOWS:
921         sprintf( buffer, "\t.globl _%s\n_%s:", func, func );
922         return buffer;
923     default:
924         sprintf( buffer, "\t.globl %s\n\t.hidden %s\n%s:", func, func, func );
925         return buffer;
926     }
927 }
928 
929 const char *get_asm_ptr_keyword(void)
930 {
931     switch(get_ptr_size())
932     {
933     case 4: return ".long";
934     case 8: return ".quad";
935     }
936     assert(0);
937     return NULL;
938 }
939 
940 const char *get_asm_string_keyword(void)
941 {
942     switch (target_platform)
943     {
944     case PLATFORM_APPLE:
945         return ".asciz";
946     default:
947         return ".string";
948     }
949 }
950 
951 const char *get_asm_short_keyword(void)
952 {
953     switch (target_platform)
954     {
955     default:            return ".short";
956     }
957 }
958 
959 const char *get_asm_rodata_section(void)
960 {
961     switch (target_platform)
962     {
963     case PLATFORM_APPLE: return ".const";
964     default:             return ".section .rodata";
965     }
966 }
967 
968 const char *get_asm_string_section(void)
969 {
970     switch (target_platform)
971     {
972     case PLATFORM_APPLE: return ".cstring";
973     default:             return ".section .rodata";
974     }
975 }
976 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.