|  | /* | 
|  | * Small utility functions for winebuild | 
|  | * | 
|  | * Copyright 2000 Alexandre Julliard | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  | #include "wine/port.h" | 
|  |  | 
|  | #include <ctype.h> | 
|  | #include <stdarg.h> | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include "build.h" | 
|  |  | 
|  | void *xmalloc (size_t size) | 
|  | { | 
|  | void *res; | 
|  |  | 
|  | res = malloc (size ? size : 1); | 
|  | if (res == NULL) | 
|  | { | 
|  | fprintf (stderr, "Virtual memory exhausted.\n"); | 
|  | exit (1); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | void *xrealloc (void *ptr, size_t size) | 
|  | { | 
|  | void *res = realloc (ptr, size); | 
|  | if (res == NULL) | 
|  | { | 
|  | fprintf (stderr, "Virtual memory exhausted.\n"); | 
|  | exit (1); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | char *xstrdup( const char *str ) | 
|  | { | 
|  | char *res = strdup( str ); | 
|  | if (!res) | 
|  | { | 
|  | fprintf (stderr, "Virtual memory exhausted.\n"); | 
|  | exit (1); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | char *strupper(char *s) | 
|  | { | 
|  | char *p; | 
|  | for (p = s; *p; p++) *p = toupper(*p); | 
|  | return s; | 
|  | } | 
|  |  | 
|  | void fatal_error( const char *msg, ... ) | 
|  | { | 
|  | va_list valist; | 
|  | va_start( valist, msg ); | 
|  | if (input_file_name) | 
|  | { | 
|  | fprintf( stderr, "%s:", input_file_name ); | 
|  | if (current_line) | 
|  | fprintf( stderr, "%d:", current_line ); | 
|  | fputc( ' ', stderr ); | 
|  | } | 
|  | vfprintf( stderr, msg, valist ); | 
|  | va_end( valist ); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | void fatal_perror( const char *msg, ... ) | 
|  | { | 
|  | va_list valist; | 
|  | va_start( valist, msg ); | 
|  | if (input_file_name) | 
|  | { | 
|  | fprintf( stderr, "%s:", input_file_name ); | 
|  | if (current_line) | 
|  | fprintf( stderr, "%d:", current_line ); | 
|  | fputc( ' ', stderr ); | 
|  | } | 
|  | vfprintf( stderr, msg, valist ); | 
|  | perror( " " ); | 
|  | va_end( valist ); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | void warning( const char *msg, ... ) | 
|  | { | 
|  | va_list valist; | 
|  |  | 
|  | if (!display_warnings) return; | 
|  | va_start( valist, msg ); | 
|  | if (input_file_name) | 
|  | { | 
|  | fprintf( stderr, "%s:", input_file_name ); | 
|  | if (current_line) | 
|  | fprintf( stderr, "%d:", current_line ); | 
|  | fputc( ' ', stderr ); | 
|  | } | 
|  | fprintf( stderr, "warning: " ); | 
|  | vfprintf( stderr, msg, valist ); | 
|  | va_end( valist ); | 
|  | } | 
|  |  | 
|  | /* output a standard header for generated files */ | 
|  | void output_standard_file_header( FILE *outfile ) | 
|  | { | 
|  | if (input_file_name) | 
|  | fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n", | 
|  | input_file_name ); | 
|  | else | 
|  | fprintf( outfile, "/* File generated automatically; do not edit! */\n" ); | 
|  | fprintf( outfile, | 
|  | "/* This file can be copied, modified and distributed without restriction. */\n\n" ); | 
|  | } | 
|  |  | 
|  | /* dump a byte stream into the assembly code */ | 
|  | void dump_bytes( FILE *outfile, const unsigned char *data, int len, | 
|  | const char *label, int constant ) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | fprintf( outfile, "\nstatic %sunsigned char %s[%d] = {", | 
|  | constant ? "const " : "", label, len ); | 
|  | for (i = 0; i < len; i++) | 
|  | { | 
|  | if (!(i & 7)) fprintf( outfile, "\n  " ); | 
|  | fprintf( outfile, "0x%02x", *data++ ); | 
|  | if (i < len - 1) fprintf( outfile, "," ); | 
|  | } | 
|  | fprintf( outfile, "\n};\n" ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /******************************************************************* | 
|  | *         open_input_file | 
|  | * | 
|  | * Open a file in the given srcdir and set the input_file_name global variable. | 
|  | */ | 
|  | FILE *open_input_file( const char *srcdir, const char *name ) | 
|  | { | 
|  | char *fullname; | 
|  | FILE *file; | 
|  |  | 
|  | if (srcdir) | 
|  | { | 
|  | fullname = xmalloc( strlen(srcdir) + strlen(name) + 2 ); | 
|  | strcpy( fullname, srcdir ); | 
|  | strcat( fullname, "/" ); | 
|  | strcat( fullname, name ); | 
|  | } | 
|  | else fullname = xstrdup( name ); | 
|  |  | 
|  | if (!(file = fopen( fullname, "r" ))) fatal_error( "Cannot open file '%s'\n", fullname ); | 
|  | input_file_name = fullname; | 
|  | current_line = 1; | 
|  | return file; | 
|  | } | 
|  |  | 
|  |  | 
|  | /******************************************************************* | 
|  | *         close_input_file | 
|  | * | 
|  | * Close the current input file (must have been opened with open_input_file). | 
|  | */ | 
|  | void close_input_file( FILE *file ) | 
|  | { | 
|  | fclose( file ); | 
|  | free( input_file_name ); | 
|  | input_file_name = NULL; | 
|  | current_line = 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /******************************************************************* | 
|  | *         make_c_identifier | 
|  | * | 
|  | * Map a string to a valid C identifier. | 
|  | */ | 
|  | const char *make_c_identifier( const char *str ) | 
|  | { | 
|  | static char buffer[256]; | 
|  | char *p; | 
|  |  | 
|  | for (p = buffer; *str && p < buffer+sizeof(buffer)-1; p++, str++) | 
|  | { | 
|  | if (isalnum(*str)) *p = *str; | 
|  | else *p = '_'; | 
|  | } | 
|  | *p = 0; | 
|  | return buffer; | 
|  | } | 
|  |  | 
|  |  | 
|  | /***************************************************************** | 
|  | *  Function:    get_alignment | 
|  | * | 
|  | *  Description: | 
|  | *    According to the info page for gas, the .align directive behaves | 
|  | * differently on different systems.  On some architectures, the | 
|  | * argument of a .align directive is the number of bytes to pad to, so | 
|  | * to align on an 8-byte boundary you'd say | 
|  | *     .align 8 | 
|  | * On other systems, the argument is "the number of low-order zero bits | 
|  | * that the location counter must have after advancement."  So to | 
|  | * align on an 8-byte boundary you'd say | 
|  | *     .align 3 | 
|  | * | 
|  | * The reason gas is written this way is that it's trying to mimick | 
|  | * native assemblers for the various architectures it runs on.  gas | 
|  | * provides other directives that work consistantly across | 
|  | * architectures, but of course we want to work on all arches with or | 
|  | * without gas.  Hence this function. | 
|  | * | 
|  | * | 
|  | *  Parameters: | 
|  | *                alignBoundary  --  the number of bytes to align to. | 
|  | *                                   If we're on an architecture where | 
|  | *                                   the assembler requires a 'number | 
|  | *                                   of low-order zero bits' as a | 
|  | *                                   .align argument, then this number | 
|  | *                                   must be a power of 2. | 
|  | * | 
|  | */ | 
|  | int get_alignment(int alignBoundary) | 
|  | { | 
|  | #ifdef __PPC__ | 
|  |  | 
|  | int n = 0; | 
|  |  | 
|  | switch(alignBoundary) | 
|  | { | 
|  | case 2: | 
|  | n = 1; | 
|  | break; | 
|  | case 4: | 
|  | n = 2; | 
|  | break; | 
|  | case 8: | 
|  | n = 3; | 
|  | break; | 
|  | case 16: | 
|  | n = 4; | 
|  | break; | 
|  | case 32: | 
|  | n = 5; | 
|  | break; | 
|  | case 64: | 
|  | n = 6; | 
|  | break; | 
|  | case 128: | 
|  | n = 7; | 
|  | break; | 
|  | case 256: | 
|  | n = 8; | 
|  | break; | 
|  | case 512: | 
|  | n = 9; | 
|  | break; | 
|  | case 1024: | 
|  | n = 10; | 
|  | break; | 
|  | case 2048: | 
|  | n = 11; | 
|  | break; | 
|  | case 4096: | 
|  | n = 12; | 
|  | break; | 
|  | case 8192: | 
|  | n = 13; | 
|  | break; | 
|  | case 16384: | 
|  | n = 14; | 
|  | break; | 
|  | case 32768: | 
|  | n = 15; | 
|  | break; | 
|  | case 65536: | 
|  | n = 16; | 
|  | break; | 
|  | default: | 
|  | fatal_error("Alignment to %d-byte boundary not supported on this architecture.\n", | 
|  | alignBoundary); | 
|  | } | 
|  | return n; | 
|  |  | 
|  | #elif defined(__i386__) || defined(__sparc__) | 
|  |  | 
|  | return alignBoundary; | 
|  |  | 
|  | #else | 
|  | #error "How does the '.align' assembler directive work on your architecture?" | 
|  | #endif | 
|  | } |