X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/46f4442e9a5a4f3b98b7c1083586332f6a8a99a4..f59164e3d128c7675a4d3934206346a3384e53a5:/icuSources/tools/genccode/genccode.c diff --git a/icuSources/tools/genccode/genccode.c b/icuSources/tools/genccode/genccode.c index 291ca229..58f5c2e8 100644 --- a/icuSources/tools/genccode/genccode.c +++ b/icuSources/tools/genccode/genccode.c @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 1999-2007, International Business Machines + * Copyright (C) 1999-2016, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* * file name: gennames.c @@ -19,7 +19,7 @@ #include "unicode/utypes.h" -#ifdef U_WINDOWS +#if U_PLATFORM_HAS_WIN32_API # define VC_EXTRALEAN # define WIN32_LEAN_AND_MEAN # define NOUSER @@ -30,7 +30,7 @@ #include #endif -#ifdef U_LINUX +#if U_PLATFORM_IS_LINUX_BASED && U_HAVE_ELF_H # define U_ELF #endif @@ -55,44 +55,9 @@ #include "toolutil.h" #include "unicode/uclean.h" #include "uoptions.h" +#include "pkg_genc.h" -#define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU)) - -static uint32_t column=MAX_COLUMN; - -#if defined(U_WINDOWS) || defined(U_ELF) -#define CAN_GENERATE_OBJECTS -#endif - -/* prototypes --------------------------------------------------------------- */ - -static void -writeCCode(const char *filename, const char *destdir); - -static void -writeAssemblyCode(const char *filename, const char *destdir); - -#ifdef CAN_GENERATE_OBJECTS -static void -writeObjectCode(const char *filename, const char *destdir); -#endif - -static void -getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix); - -static void -write8(FileStream *out, uint8_t byte); - -static void -write32(FileStream *out, uint32_t byte); - -#ifdef OS400 -static void -write8str(FileStream *out, uint8_t byte); -#endif -/* -------------------------------------------------------------------------- */ - -enum { +enum { kOptHelpH = 0, kOptHelpQuestionMark, kOptDestDir, @@ -106,128 +71,6 @@ enum { kOptAssembly }; -/* -Creating Template Files for New Platforms - -Let the cc compiler help you get started. -Compile this program - const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16}; -with the -S option to produce assembly output. - -For example, this will generate array.s: -gcc -S array.c - -This will produce a .s file that may look like this: - - .file "array.c" - .version "01.01" -gcc2_compiled.: - .globl x - .section .rodata - .align 4 - .type x,@object - .size x,20 -x: - .long 1 - .long 2 - .long -559038737 - .long -1 - .long 16 - .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)" - -which gives a starting point that will compile, and can be transformed -to become the template, generally with some consulting of as docs and -some experimentation. - -If you want ICU to automatically use this assembly, you should -specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file, -where the name is the compiler or platform that you used in this -assemblyHeader data structure. -*/ -static const struct AssemblyType { - const char *name; - const char *header; - const char *beginLine; -} assemblyHeader[] = { - {"gcc", - ".globl %s\n" - "\t.section .note.GNU-stack,\"\",@progbits\n" - "\t.section .rodata\n" - "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */ - "\t.type %s,@object\n" - "%s:\n\n", - - ".long " - }, - {"gcc-darwin", - /*"\t.section __TEXT,__text,regular,pure_instructions\n" - "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/ - ".globl _%s\n" - "\t.data\n" - "\t.const\n" - "\t.align 4\n" /* 1<<4 = 16 */ - "_%s:\n\n", - - ".long " - }, - {"gcc-cygwin", - ".globl _%s\n" - "\t.section .rodata\n" - "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */ - "_%s:\n\n", - - ".long " - }, - {"sun", - "\t.section \".rodata\"\n" - "\t.align 8\n" - ".globl %s\n" - "%s:\n", - - ".word " - }, - {"sun-x86", - "Drodata.rodata:\n" - "\t.type Drodata.rodata,@object\n" - "\t.size Drodata.rodata,0\n" - "\t.globl %s\n" - "\t.align 8\n" - "%s:\n", - - ".4byte " - }, - {"xlc", - ".globl %s{RO}\n" - "\t.toc\n" - "%s:\n" - "\t.csect %s{RO}, 4\n", - - ".long " - }, - {"aCC-ia64", - "\t.file \"%s.s\"\n" - "\t.type %s,@object\n" - "\t.global %s\n" - "\t.secalias .abe$0.rodata, \".rodata\"\n" - "\t.section .abe$0.rodata = \"a\", \"progbits\"\n" - "\t.align 16\n" - "%s::\t", - - "data4 " - }, - {"aCC-parisc", - "\t.SPACE $TEXT$\n" - "\t.SUBSPA $LIT$\n" - "%s\n" - "\t.EXPORT %s\n" - "\t.ALIGN 16\n", - - ".WORD " - } -}; - -static int32_t assemblyHeaderIndex = -1; - static UOption options[]={ /*0*/UOPTION_HELP_H, UOPTION_HELP_QUESTION_MARK, @@ -242,17 +85,20 @@ static UOption options[]={ UOPTION_DEF("assembly", 'a', UOPT_REQUIRES_ARG) }; +#define CALL_WRITECCODE 'c' +#define CALL_WRITEASSEMBLY 'a' +#define CALL_WRITEOBJECT 'o' extern int main(int argc, char* argv[]) { UBool verbose = TRUE; - int32_t idx; + char writeCode; U_MAIN_INIT_ARGS(argc, argv); options[kOptDestDir].value = "."; /* read command line options */ - argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); + argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options); /* error handling, printing usage message */ if(argc<0) { @@ -282,26 +128,17 @@ main(int argc, char* argv[]) { "\t-f or --filename Specify an alternate base filename. (default: symbolname_typ)\n" "\t-a or --assembly Create assembly file. (possible values are: "); - fprintf(stderr, "%s", assemblyHeader[0].name); - for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) { - fprintf(stderr, ", %s", assemblyHeader[idx].name); - } - fprintf(stderr, - ")\n"); + printAssemblyHeadersToStdErr(); } else { const char *message, *filename; - void (*writeCode)(const char *, const char *); + /* TODO: remove void (*writeCode)(const char *, const char *); */ if(options[kOptAssembly].doesOccur) { message="generating assembly code for %s\n"; - writeCode=&writeAssemblyCode; - for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) { - if (uprv_strcmp(options[kOptAssembly].value, assemblyHeader[idx].name) == 0) { - assemblyHeaderIndex = idx; - break; - } - } - if (assemblyHeaderIndex < 0) { + writeCode = CALL_WRITEASSEMBLY; + /* TODO: remove writeCode=&writeAssemblyCode; */ + + if (!checkAssemblyHeaderName(options[kOptAssembly].value)) { fprintf(stderr, "Assembly type \"%s\" is unknown.\n", options[kOptAssembly].value); return -1; @@ -310,918 +147,51 @@ main(int argc, char* argv[]) { #ifdef CAN_GENERATE_OBJECTS else if(options[kOptObject].doesOccur) { message="generating object code for %s\n"; - writeCode=&writeObjectCode; + writeCode = CALL_WRITEOBJECT; + /* TODO: remove writeCode=&writeObjectCode; */ } #endif else { message="generating C code for %s\n"; - writeCode=&writeCCode; + writeCode = CALL_WRITECCODE; + /* TODO: remove writeCode=&writeCCode; */ } while(--argc) { filename=getLongPathname(argv[argc]); if (verbose) { fprintf(stdout, message, filename); } - column=MAX_COLUMN; - writeCode(filename, options[kOptDestDir].value); - } - } - - return 0; -} - -static void -writeAssemblyCode(const char *filename, const char *destdir) { - char entry[64]; - uint32_t buffer[1024]; - char *bufferStr = (char *)buffer; - FileStream *in, *out; - size_t i, length; - - in=T_FileStream_open(filename, "rb"); - if(in==NULL) { - fprintf(stderr, "genccode: unable to open input file %s\n", filename); - exit(U_FILE_ACCESS_ERROR); - } - - getOutFilename(filename, destdir, bufferStr, entry, ".s"); - out=T_FileStream_open(bufferStr, "w"); - if(out==NULL) { - fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr); - exit(U_FILE_ACCESS_ERROR); - } - - if(options[kOptEntryPoint].doesOccur) { - uprv_strcpy(entry, options[kOptEntryPoint].value); - uprv_strcat(entry, "_dat"); - } - - /* turn dashes or dots in the entry name into underscores */ - length=uprv_strlen(entry); - for(i=0; ie_ident[0]!=ELFMAG0 || - pHeader32->e_ident[1]!=ELFMAG1 || - pHeader32->e_ident[2]!=ELFMAG2 || - pHeader32->e_ident[3]!=ELFMAG3 || - pHeader32->e_ident[EI_CLASS]e_ident[EI_CLASS]>ELFCLASS64 - ) { - fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename); - exit(U_UNSUPPORTED_ERROR); - } - - *pBits= pHeader32->e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */ -#ifdef U_ELF64 - if(*pBits!=32 && *pBits!=64) { - fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n"); - exit(U_UNSUPPORTED_ERROR); - } -#else - if(*pBits!=32) { - fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n"); - exit(U_UNSUPPORTED_ERROR); - } -#endif - - *pIsBigEndian=(UBool)(pHeader32->e_ident[EI_DATA]==ELFDATA2MSB); - if(*pIsBigEndian!=U_IS_BIG_ENDIAN) { - fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n"); - exit(U_UNSUPPORTED_ERROR); - } - /* TODO: Support byte swapping */ - - *pCPU=pHeader32->e_machine; -#elif defined(U_WINDOWS) - if(lengthMachine; - /* - * The number of bits is implicit with the Machine value. - * *pBits is ignored in the calling code, so this need not be precise. - */ - *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64; - /* Windows always runs on little-endian CPUs. */ - *pIsBigEndian=FALSE; -#else -# error "Unknown platform for CAN_GENERATE_OBJECTS." -#endif - - T_FileStream_close(in); -} - -static void -writeObjectCode(const char *filename, const char *destdir) { - /* common variables */ - char buffer[4096], entry[40]={ 0 }; - FileStream *in, *out; - const char *newSuffix; - int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0; - - uint16_t cpu, bits; - UBool makeBigEndian; - - /* platform-specific variables and initialization code */ -#ifdef U_ELF - /* 32-bit Elf file header */ - static Elf32_Ehdr header32={ - { - /* e_ident[] */ - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - ELFCLASS32, - U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB, - EV_CURRENT /* EI_VERSION */ - }, - ET_REL, - EM_386, - EV_CURRENT, /* e_version */ - 0, /* e_entry */ - 0, /* e_phoff */ - (Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */ - 0, /* e_flags */ - (Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */ - 0, /* e_phentsize */ - 0, /* e_phnum */ - (Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */ - 5, /* e_shnum */ - 2 /* e_shstrndx */ - }; - - /* 32-bit Elf section header table */ - static Elf32_Shdr sectionHeaders32[5]={ - { /* SHN_UNDEF */ - 0 - }, - { /* .symtab */ - 1, /* sh_name */ - SHT_SYMTAB, - 0, /* sh_flags */ - 0, /* sh_addr */ - (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */ - (Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */ - 3, /* sh_link=sect hdr index of .strtab */ - 1, /* sh_info=One greater than the symbol table index of the last - * local symbol (with STB_LOCAL). */ - 4, /* sh_addralign */ - (Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */ - }, - { /* .shstrtab */ - 9, /* sh_name */ - SHT_STRTAB, - 0, /* sh_flags */ - 0, /* sh_addr */ - (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */ - 40, /* sh_size */ - 0, /* sh_link */ - 0, /* sh_info */ - 1, /* sh_addralign */ - 0 /* sh_entsize */ - }, - { /* .strtab */ - 19, /* sh_name */ - SHT_STRTAB, - 0, /* sh_flags */ - 0, /* sh_addr */ - (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */ - (Elf32_Word)sizeof(entry), /* sh_size */ - 0, /* sh_link */ - 0, /* sh_info */ - 1, /* sh_addralign */ - 0 /* sh_entsize */ - }, - { /* .rodata */ - 27, /* sh_name */ - SHT_PROGBITS, - SHF_ALLOC, /* sh_flags */ - 0, /* sh_addr */ - (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */ - 0, /* sh_size */ - 0, /* sh_link */ - 0, /* sh_info */ - 16, /* sh_addralign */ - 0 /* sh_entsize */ - } - }; - - /* symbol table */ - static Elf32_Sym symbols32[2]={ - { /* STN_UNDEF */ - 0 - }, - { /* data entry point */ - 1, /* st_name */ - 0, /* st_value */ - 0, /* st_size */ - ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), - 0, /* st_other */ - 4 /* st_shndx=index of related section table entry */ - } - }; - - /* section header string table, with decimal string offsets */ - static const char sectionStrings[40]= - /* 0 */ "\0" - /* 1 */ ".symtab\0" - /* 9 */ ".shstrtab\0" - /* 19 */ ".strtab\0" - /* 27 */ ".rodata\0" - /* 35 */ "\0\0\0\0"; /* contains terminating NUL */ - /* 40: padded to multiple of 8 bytes */ - - /* - * Use entry[] for the string table which will contain only the - * entry point name. - * entry[0] must be 0 (NUL) - * The entry point name can be up to 38 characters long (sizeof(entry)-2). - */ - - /* 16-align .rodata in the .o file, just in case */ - static const char padding[16]={ 0 }; - int32_t paddingSize; - -#ifdef U_ELF64 - /* 64-bit Elf file header */ - static Elf64_Ehdr header64={ - { - /* e_ident[] */ - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - ELFCLASS64, - U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB, - EV_CURRENT /* EI_VERSION */ - }, - ET_REL, - EM_X86_64, - EV_CURRENT, /* e_version */ - 0, /* e_entry */ - 0, /* e_phoff */ - (Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */ - 0, /* e_flags */ - (Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */ - 0, /* e_phentsize */ - 0, /* e_phnum */ - (Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */ - 5, /* e_shnum */ - 2 /* e_shstrndx */ - }; - - /* 64-bit Elf section header table */ - static Elf64_Shdr sectionHeaders64[5]={ - { /* SHN_UNDEF */ - 0 - }, - { /* .symtab */ - 1, /* sh_name */ - SHT_SYMTAB, - 0, /* sh_flags */ - 0, /* sh_addr */ - (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */ - (Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */ - 3, /* sh_link=sect hdr index of .strtab */ - 1, /* sh_info=One greater than the symbol table index of the last - * local symbol (with STB_LOCAL). */ - 4, /* sh_addralign */ - (Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */ - }, - { /* .shstrtab */ - 9, /* sh_name */ - SHT_STRTAB, - 0, /* sh_flags */ - 0, /* sh_addr */ - (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */ - 40, /* sh_size */ - 0, /* sh_link */ - 0, /* sh_info */ - 1, /* sh_addralign */ - 0 /* sh_entsize */ - }, - { /* .strtab */ - 19, /* sh_name */ - SHT_STRTAB, - 0, /* sh_flags */ - 0, /* sh_addr */ - (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */ - (Elf64_Xword)sizeof(entry), /* sh_size */ - 0, /* sh_link */ - 0, /* sh_info */ - 1, /* sh_addralign */ - 0 /* sh_entsize */ - }, - { /* .rodata */ - 27, /* sh_name */ - SHT_PROGBITS, - SHF_ALLOC, /* sh_flags */ - 0, /* sh_addr */ - (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */ - 0, /* sh_size */ - 0, /* sh_link */ - 0, /* sh_info */ - 16, /* sh_addralign */ - 0 /* sh_entsize */ - } - }; - - /* - * 64-bit symbol table - * careful: different order of items compared with Elf32_sym! - */ - static Elf64_Sym symbols64[2]={ - { /* STN_UNDEF */ - 0 - }, - { /* data entry point */ - 1, /* st_name */ - ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT), - 0, /* st_other */ - 4, /* st_shndx=index of related section table entry */ - 0, /* st_value */ - 0 /* st_size */ - } - }; - -#endif /* U_ELF64 */ - - /* entry[] have a leading NUL */ - entryOffset=1; - - /* in the common code, count entryLength from after the NUL */ - entryLengthOffset=1; - - newSuffix=".o"; - -#elif defined(U_WINDOWS) - struct { - IMAGE_FILE_HEADER fileHeader; - IMAGE_SECTION_HEADER sections[2]; - char linkerOptions[100]; - } objHeader; - IMAGE_SYMBOL symbols[1]; - struct { - DWORD sizeofLongNames; - char longNames[100]; - } symbolNames; - - /* - * entry sometimes have a leading '_' - * overwritten if entryOffset==0 depending on the target platform - * see check for cpu below - */ - entry[0]='_'; - - newSuffix=".obj"; -#else -# error "Unknown platform for CAN_GENERATE_OBJECTS." -#endif - - /* deal with options, files and the entry point name */ - getArchitecture(&cpu, &bits, &makeBigEndian); - printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%hu\n", cpu, bits, makeBigEndian); -#ifdef U_WINDOWS - if(cpu==IMAGE_FILE_MACHINE_I386) { - entryOffset=1; - } -#endif - - in=T_FileStream_open(filename, "rb"); - if(in==NULL) { - fprintf(stderr, "genccode: unable to open input file %s\n", filename); - exit(U_FILE_ACCESS_ERROR); - } - size=T_FileStream_size(in); - - getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix); - - if(options[kOptEntryPoint].doesOccur) { - uprv_strcpy(entry+entryOffset, options[kOptEntryPoint].value); - uprv_strcat(entry+entryOffset, "_dat"); - } - /* turn dashes in the entry name into underscores */ - entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset); - for(i=0; i= 0 ; i--) -#endif - { - uint8_t value = ptrIdx[i]; - if (value || seenNonZero) { - *(s++)=hexToStr[value>>4]; - *(s++)=hexToStr[value&0xF]; - seenNonZero = 1; - } - } - } - - *(s++)=0; - T_FileStream_writeLine(out, bitFieldStr); -} - -static void -write8(FileStream *out, uint8_t byte) { - char s[4]; - int i=0; - - /* convert the byte value to a string */ - if(byte>=100) { - s[i++]=(char)('0'+byte/100); - byte%=100; - } - if(i>0 || byte>=10) { - s[i++]=(char)('0'+byte/10); - byte%=10; - } - s[i++]=(char)('0'+byte); - s[i]=0; - /* write the value, possibly with comma and newline */ - if(column==MAX_COLUMN) { - /* first byte */ - column=1; - } else if(column<16) { - T_FileStream_writeLine(out, ","); - ++column; - } else { - T_FileStream_writeLine(out, ",\n"); - column=1; - } - T_FileStream_writeLine(out, s); -} - -#ifdef OS400 -static void -write8str(FileStream *out, uint8_t byte) { - char s[8]; - - if (byte > 7) - sprintf(s, "\\x%X", byte); - else - sprintf(s, "\\%X", byte); - - /* write the value, possibly with comma and newline */ - if(column==MAX_COLUMN) { - /* first byte */ - column=1; - T_FileStream_writeLine(out, "\""); - } else if(column<24) { - ++column; - } else { - T_FileStream_writeLine(out, "\"\n\""); - column=1; - } - T_FileStream_writeLine(out, s); + return 0; } -#endif