/* ******************************************************************************* * * Copyright (C) 1999-2004, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: gennames.c * encoding: US-ASCII * tab size: 8 (not used) * indentation:4 * * created on: 1999nov01 * created by: Markus W. Scherer * * This program reads a binary file and creates a C source code file * with a byte array that contains the data of the binary file. * * 12/09/1999 weiv Added multiple file handling */ #ifdef WIN32 # define VC_EXTRALEAN # define WIN32_LEAN_AND_MEAN # define NOGDI # define NOUSER # define NOSERVICE # define NOIME # define NOMCX #include #include /* _M_IA64 should be defined in windows.h */ #if defined(_M_IA64) # define ICU_OBJECT_MACHINE_TYPE IMAGE_FILE_MACHINE_IA64 # define ICU_ENTRY_OFFSET 0 #elif defined(_M_AMD64) # define ICU_OBJECT_MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64 # define ICU_ENTRY_OFFSET 0 #else # define ICU_OBJECT_MACHINE_TYPE IMAGE_FILE_MACHINE_I386 # define ICU_ENTRY_OFFSET 1 #endif #endif #include #include #include "unicode/utypes.h" #include "unicode/putil.h" #include "cmemory.h" #include "cstring.h" #include "filestrm.h" #include "toolutil.h" #include "unicode/uclean.h" #include "uoptions.h" #define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU)) static uint32_t column=MAX_COLUMN; #ifdef WIN32 #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 { kOptHelpH = 0, kOptHelpQuestionMark, kOptDestDir, kOptName, kOptEntryPoint, #ifdef CAN_GENERATE_OBJECTS kOptObject, #endif kOptFilename, 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 .rodata\n" "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */ "%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 " }, {"xlc", ".globl %s{RO}\n" "\t.toc\n" "%s:\n" "\t.csect %s{RO}, 4\n", ".long " }, {"aCC", "\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, UOPTION_DESTDIR, UOPTION_DEF("name", 'n', UOPT_REQUIRES_ARG), UOPTION_DEF("entrypoint", 'e', UOPT_REQUIRES_ARG), #ifdef CAN_GENERATE_OBJECTS /*5*/UOPTION_DEF("object", 'o', UOPT_NO_ARG), #endif UOPTION_DEF("filename", 'f', UOPT_REQUIRES_ARG), UOPTION_DEF("assembly", 'a', UOPT_REQUIRES_ARG) }; extern int main(int argc, char* argv[]) { UBool verbose = TRUE; int32_t idx; U_MAIN_INIT_ARGS(argc, argv); options[kOptDestDir].value = "."; /* read command line options */ argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options); /* error handling, printing usage message */ if(argc<0) { fprintf(stderr, "error in command line argument \"%s\"\n", argv[-argc]); } if(argc<0 || options[kOptHelpH].doesOccur || options[kOptHelpQuestionMark].doesOccur) { fprintf(stderr, "usage: %s [-options] filename1 filename2 ...\n" "\tread each binary input file and \n" "\tcreate a .c file with a byte array that contains the input file's data\n" "options:\n" "\t-h or -? or --help this usage text\n" "\t-d or --destdir destination directory, followed by the path\n" "\t-n or --name symbol prefix, followed by the prefix\n" "\t-e or --entrypoint entry point name, followed by the name\n" "\t-r or --revision Specify a version\n" #ifdef CAN_GENERATE_OBJECTS "\t-o or --object write a .obj file instead of .c\n" #endif "\t-f or --filename Specify an alternate base filename. (default: symbolname_typ)\n" , argv[0]); fprintf(stderr, "\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"); } else { const char *message, *filename; 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) { fprintf(stderr, "Assembly type \"%s\" is unknown.\n", options[kOptAssembly].value); return -1; } } #ifdef CAN_GENERATE_OBJECTS else if(options[kOptObject].doesOccur) { message="generating object code for %s\n"; writeCode=&writeObjectCode; } #endif else { message="generating C code for %s\n"; 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; 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); } #endif