void writeCmnRules(UPKGOptions *o, FileStream *makefile) { char tmp[1024]; CharList *infiles; infiles = o->filePaths; sprintf(tmp, "\"$(TARGETDIR)\\$(CMNTARGET)\" : $(DATAFILEPATHS)\n\t@\"$(GENCMN)\" -C \"%s\" -d \"%s\" -n \"$(NAME)\" 0 <<\n", o->comment, o->targetDir); T_FileStream_writeLine(makefile, tmp); pkg_writeCharList(makefile, infiles, "\n", -1); /* for(;infiles;infiles = infiles->next) { if(infiles->str[0] != '"' && infiles->str[uprv_strlen(infiles->str)-1] != '"') { sprintf(tmp, "\"%s\"\n", infiles->str); } else { sprintf(tmp, "%s\n", infiles->str); } T_FileStream_writeLine(makefile, tmp); } */ sprintf(tmp, "\n<<\n"); T_FileStream_writeLine(makefile, tmp); }
void pkg_mode_common(UPKGOptions *o, FileStream *makefile, UErrorCode *status) { char tmp[1024]; CharList *tail = NULL; uprv_strcpy(tmp, UDATA_CMN_PREFIX); uprv_strcat(tmp, o->shortName); uprv_strcat(tmp, UDATA_CMN_SUFFIX); if(!uprv_strcmp(o->mode, "common")) { /* If we're not the main mode.. don't change the output file list */ /* We should be the only item. So we don't care about the order. */ o->outFiles = pkg_appendToList(o->outFiles, &tail, uprv_strdup(tmp)); if(o->nooutput || o->verbose) { fprintf(stdout, "# Output file: %s%s%s\n", o->targetDir, U_FILE_SEP_STRING, tmp); } if(o->nooutput) { *status = U_ZERO_ERROR; return; } sprintf(tmp, "# File to make:\nTARGET=%s%s%s\n\nTARGETNAME=%s\n", o->targetDir, U_FILE_SEP_STRING, o->outFiles->str, o->outFiles->str); T_FileStream_writeLine(makefile, tmp); } else { /* We're in another mode. but, set the target so they can find us.. */ T_FileStream_writeLine(makefile, "TARGET="); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "\n\n"); } /* end [check to make sure we are in mode 'common' ] */ sprintf(tmp, "# List file for gencmn:\n" "CMNLIST=%s%s%s_common.lst\n\n", o->tmpDir, U_FILE_SEP_STRING, o->shortName); T_FileStream_writeLine(makefile, tmp); sprintf(tmp, "all: $(TARGET)\n\n"); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "$(TARGET): $(CMNLIST) $(DATAFILEPATHS)\n" "\t$(INVOKE) $(GENCMN) -n $(CNAME) -c -s $(SRCDIR) -d $(TARGETDIR) 0 $(CMNLIST)\n\n"); if(o->hadStdin == FALSE) { /* shortcut */ T_FileStream_writeLine(makefile, "$(CMNLIST): $(LISTFILES)\n" "\tcat $(LISTFILES) > $(CMNLIST)\n\n"); } else { T_FileStream_writeLine(makefile, "$(CMNLIST): \n" "\t@echo \"generating $@ (list of data files)\"\n" "\t@-$(RMV) $@\n" "\t@for file in $(DATAFILEPATHS); do \\\n" "\t echo $$file >> $@; \\\n" "\tdone;\n\n"); } if(!uprv_strcmp(o->mode, "common")) { /* only install/clean in our own mode */ T_FileStream_writeLine(makefile, "CLEANFILES= $(CMNLIST) $(TARGET)\n\nclean:\n\t-$(RMV) $(CLEANFILES) $(MAKEFILE)"); T_FileStream_writeLine(makefile, "\n\n"); sprintf(tmp, "install: $(TARGET)\n" "\t$(INSTALL_DATA) $(TARGET) $(INSTALLTO)%s$(TARGETNAME)\n\n", U_FILE_SEP_STRING); T_FileStream_writeLine(makefile, tmp); } }
static void TestFileStream(void){ int32_t c = 0; int32_t c1=0; UErrorCode status = U_ZERO_ERROR; const char* testdatapath = loadTestData(&status); char* fileName = (char*) malloc(uprv_strlen(testdatapath) +10); FileStream* stream = NULL; /* these should not be closed */ FileStream* pStdin = T_FileStream_stdin(); FileStream* pStdout = T_FileStream_stdout(); FileStream* pStderr = T_FileStream_stderr(); const char* testline = "This is a test line"; int32_t bufLen = (int32_t)strlen(testline)+10; char* buf = (char*) malloc(bufLen); int32_t retLen = 0; if(pStdin==NULL){ log_err("failed to get T_FileStream_stdin()"); } if(pStdout==NULL){ log_err("failed to get T_FileStream_stdout()"); } if(pStderr==NULL){ log_err("failed to get T_FileStream_stderr()"); } uprv_strcpy(fileName,testdatapath); uprv_strcat(fileName,".dat"); stream = T_FileStream_open(fileName, "r"); if(stream==NULL){ log_data_err("T_FileStream_open failed to open %s\n",fileName); } else { if(!T_FileStream_file_exists(fileName)){ log_data_err("T_FileStream_file_exists failed to verify existence of %s \n",fileName); } retLen=T_FileStream_read(stream,&c,1); if(retLen==0){ log_data_err("T_FileStream_read failed to read from %s \n",fileName); } retLen=0; T_FileStream_rewind(stream); T_FileStream_read(stream,&c1,1); if(c!=c1){ log_data_err("T_FileStream_rewind failed to rewind %s \n",fileName); } T_FileStream_rewind(stream); c1 = T_FileStream_peek(stream); if(c!=c1){ log_data_err("T_FileStream_peek failed to peekd %s \n",fileName); } c = T_FileStream_getc(stream); T_FileStream_ungetc(c,stream); if(c!= T_FileStream_getc(stream)){ log_data_err("T_FileStream_ungetc failed to d %s \n",fileName); } if(T_FileStream_size(stream)<=0){ log_data_err("T_FileStream_size failed to d %s \n",fileName); } if(T_FileStream_error(stream)){ log_data_err("T_FileStream_error shouldn't have an error %s\n",fileName); } if(!T_FileStream_error(NULL)){ log_err("T_FileStream_error didn't get an error %s\n",fileName); } T_FileStream_putc(stream, 0x20); if(!T_FileStream_error(stream)){ /* Warning writing to a read-only file may not consistently fail on all platforms (e.g. HP-UX, FreeBSD, MacOSX) */ log_verbose("T_FileStream_error didn't get an error when writing to a readonly file %s\n",fileName); } T_FileStream_close(stream); } /* test writing function */ stream=NULL; uprv_strcpy(fileName,testdatapath); uprv_strcat(fileName,".tmp"); stream = T_FileStream_open(fileName,"w+"); if(stream == NULL){ log_data_err("Could not open %s for writing\n",fileName); } else { c= '$'; T_FileStream_putc(stream,c); T_FileStream_rewind(stream); if(c != T_FileStream_getc(stream)){ log_data_err("T_FileStream_putc failed %s\n",fileName); } T_FileStream_rewind(stream); T_FileStream_writeLine(stream,testline); T_FileStream_rewind(stream); T_FileStream_readLine(stream,buf,bufLen); if(uprv_strncmp(testline, buf,uprv_strlen(buf))!=0){ log_data_err("T_FileStream_writeLine failed %s\n",fileName); } T_FileStream_rewind(stream); T_FileStream_write(stream,testline,(int32_t)strlen(testline)); T_FileStream_rewind(stream); retLen = T_FileStream_read(stream, buf, bufLen); if(uprv_strncmp(testline, buf,retLen)!=0){ log_data_err("T_FileStream_write failed %s\n",fileName); } T_FileStream_close(stream); } if(!T_FileStream_remove(fileName)){ log_data_err("T_FileStream_remove failed to delete %s\n",fileName); } free(fileName); free(buf); }
U_CAPI void U_EXPORT2 writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) { uint32_t column = MAX_COLUMN; char buffer[4096], entry[64]; 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); } if(optName != NULL) { /* prepend 'icudt28_' */ strcpy(entry, optName); strcat(entry, "_"); } else { entry[0] = 0; } getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename); if (outFilePath != NULL) { uprv_strcpy(outFilePath, buffer); } out=T_FileStream_open(buffer, "w"); if(out==NULL) { fprintf(stderr, "genccode: unable to open output file %s\n", buffer); exit(U_FILE_ACCESS_ERROR); } /* turn dashes or dots in the entry name into underscores */ length=uprv_strlen(entry); for(i=0; i<length; ++i) { if(entry[i]=='-' || entry[i]=='.') { entry[i]='_'; } } #if U_PLATFORM == U_PF_OS400 /* TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c This is here because this platform can't currently put const data into the read-only pages of an object or shared library (service program). Only strings are allowed in read-only pages, so we use char * strings to store the data. In order to prevent the beginning of the data from ever matching the magic numbers we must still use the initial double. [grhoten 4/24/2003] */ sprintf(buffer, "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" "#include \"unicode/umachine.h\"\n" "#endif\n" "U_CDECL_BEGIN\n" "const struct {\n" " double bogus;\n" " const char *bytes; \n" "} %s={ 0.0, \n", entry); T_FileStream_writeLine(out, buffer); for(;;) { length=T_FileStream_read(in, buffer, sizeof(buffer)); if(length==0) { break; } for(i=0; i<length; ++i) { column = write8str(out, (uint8_t)buffer[i], column); } } T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n"); #else /* Function renaming shouldn't be done in data */ sprintf(buffer, "#ifndef IN_GENERATED_CCODE\n" "#define IN_GENERATED_CCODE\n" "#define U_DISABLE_RENAMING 1\n" "#include \"unicode/umachine.h\"\n" "#endif\n" "U_CDECL_BEGIN\n" "const struct {\n" " double bogus;\n" " uint8_t bytes[%ld]; \n" "} %s={ 0.0, {\n", (long)T_FileStream_size(in), entry); T_FileStream_writeLine(out, buffer); for(;;) { length=T_FileStream_read(in, buffer, sizeof(buffer)); if(length==0) { break; } for(i=0; i<length; ++i) { column = write8(out, (uint8_t)buffer[i], column); } } T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n"); #endif if(T_FileStream_error(in)) { fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } if(T_FileStream_error(out)) { fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } T_FileStream_close(out); T_FileStream_close(in); }
U_CAPI void U_EXPORT2 writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) { uint32_t column = MAX_COLUMN; 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", optFilename); 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 (outFilePath != NULL) { uprv_strcpy(outFilePath, bufferStr); } #ifdef WINDOWS_WITH_GNUC /* Need to fix the file seperator character when using MinGW. */ swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/'); #endif if(optEntryPoint != NULL) { uprv_strcpy(entry, optEntryPoint); uprv_strcat(entry, "_dat"); } /* turn dashes or dots in the entry name into underscores */ length=uprv_strlen(entry); for(i=0; i<length; ++i) { if(entry[i]=='-' || entry[i]=='.') { entry[i]='_'; } } sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header, entry, entry, entry, entry, entry, entry, entry, entry); T_FileStream_writeLine(out, bufferStr); T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine); for(;;) { length=T_FileStream_read(in, buffer, sizeof(buffer)); if(length==0) { break; } if (length != sizeof(buffer)) { /* pad with extra 0's when at the end of the file */ for(i=0; i < (length % sizeof(uint32_t)); ++i) { buffer[length+i] = 0; } } for(i=0; i<(length/sizeof(buffer[0])); i++) { column = write32(out, buffer[i], column); } } T_FileStream_writeLine(out, "\n"); sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer, entry, entry, entry, entry, entry, entry, entry, entry); T_FileStream_writeLine(out, bufferStr); if(T_FileStream_error(in)) { fprintf(stderr, "genccode: file read error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } if(T_FileStream_error(out)) { fprintf(stderr, "genccode: file write error while generating from file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } T_FileStream_close(out); T_FileStream_close(in); }
extern int main(int argc, char *argv[]) { const char *pname, *sourcePath, *destPath, *inFilename, *outFilename, *outComment; char outType; UBool isHelp, isModified, isPackage; int result = 0; Package *pkg, *listPkg, *addListPkg; U_MAIN_INIT_ARGS(argc, argv); /* get the program basename */ pname=findBasename(argv[0]); argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options); isHelp=options[OPT_HELP_H].doesOccur || options[OPT_HELP_QUESTION_MARK].doesOccur; if(isHelp) { printUsage(pname, TRUE); return U_ZERO_ERROR; } pkg=new Package; if(pkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); return U_MEMORY_ALLOCATION_ERROR; } isModified=FALSE; int autoPrefix=0; if(options[OPT_AUTO_TOC_PREFIX].doesOccur) { pkg->setAutoPrefix(); ++autoPrefix; } if(options[OPT_AUTO_TOC_PREFIX_WITH_TYPE].doesOccur) { if(options[OPT_TOC_PREFIX].doesOccur) { fprintf(stderr, "icupkg: --auto_toc_prefix_with_type and also --toc_prefix\n"); printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } pkg->setAutoPrefixWithType(); ++autoPrefix; } if(argc<2 || 3<argc || autoPrefix>1) { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } if(options[OPT_SOURCEDIR].doesOccur) { sourcePath=options[OPT_SOURCEDIR].value; } else { // work relative to the current working directory sourcePath=NULL; } if(options[OPT_DESTDIR].doesOccur) { destPath=options[OPT_DESTDIR].value; } else { // work relative to the current working directory destPath=NULL; } if(0==strcmp(argv[1], "new")) { if(autoPrefix) { fprintf(stderr, "icupkg: --auto_toc_prefix[_with_type] but no input package\n"); printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } inFilename=NULL; isPackage=TRUE; } else { inFilename=argv[1]; if(isPackageName(inFilename)) { pkg->readPackage(inFilename); isPackage=TRUE; } else { /* swap a single file (icuswap replacement) rather than work on a package */ pkg->addFile(sourcePath, inFilename); isPackage=FALSE; } } if(argc>=3) { outFilename=argv[2]; if(0!=strcmp(argv[1], argv[2])) { isModified=TRUE; } } else if(isPackage) { outFilename=NULL; } else /* !isPackage */ { outFilename=inFilename; isModified=(UBool)(sourcePath!=destPath); } /* parse the output type option */ if(options[OPT_OUT_TYPE].doesOccur) { const char *type=options[OPT_OUT_TYPE].value; if(type[0]==0 || type[1]!=0) { /* the type must be exactly one letter */ printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } outType=type[0]; switch(outType) { case 'l': case 'b': case 'e': break; default: printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } /* * Set the isModified flag if the output type differs from the * input package type. * If we swap a single file, just assume that we are modifying it. * The Package class does not give us access to the item and its type. */ isModified|=(UBool)(!isPackage || outType!=pkg->getInType()); } else if(isPackage) { outType=pkg->getInType(); // default to input type } else /* !isPackage: swap single file */ { outType=0; /* tells extractItem() to not swap */ } if(options[OPT_WRITEPKG].doesOccur) { isModified=TRUE; } if(!isPackage) { /* * icuswap tool replacement: Only swap a single file. * Check that irrelevant options are not set. */ if( options[OPT_COMMENT].doesOccur || options[OPT_COPYRIGHT].doesOccur || options[OPT_MATCHMODE].doesOccur || options[OPT_REMOVE_LIST].doesOccur || options[OPT_ADD_LIST].doesOccur || options[OPT_EXTRACT_LIST].doesOccur || options[OPT_LIST_ITEMS].doesOccur ) { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } if(isModified) { pkg->extractItem(destPath, outFilename, 0, outType); } delete pkg; return result; } /* Work with a package. */ if(options[OPT_COMMENT].doesOccur) { outComment=options[OPT_COMMENT].value; } else if(options[OPT_COPYRIGHT].doesOccur) { outComment=U_COPYRIGHT_STRING; } else { outComment=NULL; } if(options[OPT_MATCHMODE].doesOccur) { if(0==strcmp(options[OPT_MATCHMODE].value, "noslash")) { pkg->setMatchMode(Package::MATCH_NOSLASH); } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* remove items */ if(options[OPT_REMOVE_LIST].doesOccur) { listPkg=new Package(); if(listPkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); exit(U_MEMORY_ALLOCATION_ERROR); } if(readList(NULL, options[OPT_REMOVE_LIST].value, FALSE, listPkg)) { pkg->removeItems(*listPkg); delete listPkg; isModified=TRUE; } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* * add items * use a separate Package so that its memory and items stay around * as long as the main Package */ addListPkg=NULL; if(options[OPT_ADD_LIST].doesOccur) { addListPkg=new Package(); if(addListPkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); exit(U_MEMORY_ALLOCATION_ERROR); } if(readList(sourcePath, options[OPT_ADD_LIST].value, TRUE, addListPkg)) { pkg->addItems(*addListPkg); // delete addListPkg; deferred until after writePackage() isModified=TRUE; } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* extract items */ if(options[OPT_EXTRACT_LIST].doesOccur) { listPkg=new Package(); if(listPkg==NULL) { fprintf(stderr, "icupkg: not enough memory\n"); exit(U_MEMORY_ALLOCATION_ERROR); } if(readList(NULL, options[OPT_EXTRACT_LIST].value, FALSE, listPkg)) { pkg->extractItems(destPath, *listPkg, outType); delete listPkg; } else { printUsage(pname, FALSE); return U_ILLEGAL_ARGUMENT_ERROR; } } /* list items */ if(options[OPT_LIST_ITEMS].doesOccur) { int32_t i; if (options[OPT_LIST_FILE].doesOccur) { FileStream *out; out = T_FileStream_open(options[OPT_LIST_FILE].value, "w"); if (out != NULL) { for(i=0; i<pkg->getItemCount(); ++i) { T_FileStream_writeLine(out, pkg->getItem(i)->name); T_FileStream_writeLine(out, "\n"); } T_FileStream_close(out); } else { return U_ILLEGAL_ARGUMENT_ERROR; } } else { for(i=0; i<pkg->getItemCount(); ++i) { fprintf(stdout, "%s\n", pkg->getItem(i)->name); } } } /* check dependencies between items */ if(!pkg->checkDependencies()) { /* some dependencies are not fulfilled */ return U_MISSING_RESOURCE_ERROR; } /* write the output .dat package if there are any modifications */ if(isModified) { char outFilenameBuffer[1024]; // for auto-generated output filename, if necessary if(outFilename==NULL || outFilename[0]==0) { if(inFilename==NULL || inFilename[0]==0) { fprintf(stderr, "icupkg: unable to auto-generate an output filename if there is no input filename\n"); exit(U_ILLEGAL_ARGUMENT_ERROR); } /* * auto-generate a filename: * copy the inFilename, * and if the last basename character matches the input file's type, * then replace it with the output file's type */ char suffix[6]="?.dat"; char *s; suffix[0]=pkg->getInType(); strcpy(outFilenameBuffer, inFilename); s=strchr(outFilenameBuffer, 0); if((s-outFilenameBuffer)>5 && 0==memcmp(s-5, suffix, 5)) { *(s-5)=outType; } outFilename=outFilenameBuffer; } if(options[OPT_TOC_PREFIX].doesOccur) { pkg->setPrefix(options[OPT_TOC_PREFIX].value); } result = writePackageDatFile(outFilename, outComment, NULL, NULL, pkg, outType); } delete addListPkg; delete pkg; return result; }
U_CAPI void U_EXPORT2 createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight, const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName) { static char buffer[4096]; char *line; char *linePtr; char *s = NULL; UErrorCode errorCode=U_ZERO_ERROR; uint32_t i, fileOffset, basenameOffset, length, nread; FileStream *in, *file; line = (char *)uprv_malloc(sizeof(char) * LINE_BUFFER_SIZE); if (line == NULL) { fprintf(stderr, "gencmn: unable to allocate memory for line buffer of size %d\n", LINE_BUFFER_SIZE); exit(U_MEMORY_ALLOCATION_ERROR); } linePtr = line; maxSize = max_size; if (destDir == NULL) { destDir = u_getDataDirectory(); } if (name == NULL) { name = COMMON_DATA_NAME; } if (type == NULL) { type = DATA_TYPE; } if (source == NULL) { source = "."; } if (dataFile == NULL) { in = T_FileStream_stdin(); } else { in = T_FileStream_open(dataFile, "r"); if(in == NULL) { fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile); exit(U_FILE_ACCESS_ERROR); } } if (verbose) { if(sourceTOC) { printf("generating %s_%s.c (table of contents source file)\n", name, type); } else { printf("generating %s.%s (common data file with table of contents)\n", name, type); } } /* read the list of files and get their lengths */ while((s != NULL && *s != 0) || (s=T_FileStream_readLine(in, (line=linePtr), LINE_BUFFER_SIZE))!=NULL) { /* remove trailing newline characters and parse space separated items */ if (s != NULL && *s != 0) { line=s; } else { s=line; } while(*s!=0) { if(*s==' ') { *s=0; ++s; break; } else if(*s=='\r' || *s=='\n') { *s=0; break; } ++s; } /* check for comment */ if (*line == '#') { continue; } /* add the file */ #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) { char *t; while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) { *t = U_FILE_SEP_CHAR; } } #endif addFile(getLongPathname(line), name, source, sourceTOC, verbose); } uprv_free(linePtr); if(in!=T_FileStream_stdin()) { T_FileStream_close(in); } if(fileCount==0) { fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == NULL ? "<stdin>" : dataFile); return; } /* sort the files by basename */ qsort(files, fileCount, sizeof(File), compareFiles); if(!sourceTOC) { UNewDataMemory *out; /* determine the offsets of all basenames and files in this common one */ basenameOffset=4+8*fileCount; fileOffset=(basenameOffset+(basenameTotal+15))&~0xf; for(i=0; i<fileCount; ++i) { files[i].fileOffset=fileOffset; fileOffset+=(files[i].fileSize+15)&~0xf; files[i].basenameOffset=basenameOffset; basenameOffset+=files[i].basenameLength; } /* create the output file */ out=udata_create(destDir, type, name, &dataInfo, copyRight == NULL ? U_COPYRIGHT_STRING : copyRight, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n", destDir, name, type, u_errorName(errorCode)); exit(errorCode); } /* write the table of contents */ udata_write32(out, fileCount); for(i=0; i<fileCount; ++i) { udata_write32(out, files[i].basenameOffset); udata_write32(out, files[i].fileOffset); } /* write the basenames */ for(i=0; i<fileCount; ++i) { udata_writeString(out, files[i].basename, files[i].basenameLength); } length=4+8*fileCount+basenameTotal; /* copy the files */ for(i=0; i<fileCount; ++i) { /* pad to 16-align the next file */ length&=0xf; if(length!=0) { udata_writePadding(out, 16-length); } if (verbose) { printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s"); } /* copy the next file */ file=T_FileStream_open(files[i].pathname, "rb"); if(file==NULL) { fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname); exit(U_FILE_ACCESS_ERROR); } for(nread = 0;;) { length=T_FileStream_read(file, buffer, sizeof(buffer)); if(length <= 0) { break; } nread += length; udata_writeBlock(out, buffer, length); } T_FileStream_close(file); length=files[i].fileSize; if (nread != files[i].fileSize) { fprintf(stderr, "gencmn: unable to read %s properly (got %ld/%ld byte%s)\n", files[i].pathname, (long)nread, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s"); exit(U_FILE_ACCESS_ERROR); } } /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */ length&=0xf; if(length!=0) { udata_writePadding(out, 16-length); } /* finish */ udata_finish(out, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode)); exit(errorCode); } } else { /* write a .c source file with the table of contents */ char *filename; FileStream *out; /* create the output filename */ filename=s=buffer; uprv_strcpy(filename, destDir); s=filename+uprv_strlen(filename); if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) { *s++=U_FILE_SEP_CHAR; } uprv_strcpy(s, name); if(*(type)!=0) { s+=uprv_strlen(s); *s++='_'; uprv_strcpy(s, type); } s+=uprv_strlen(s); uprv_strcpy(s, ".c"); /* open the output file */ out=T_FileStream_open(filename, "w"); if (gencmnFileName != NULL) { uprv_strcpy(gencmnFileName, filename); } if(out==NULL) { fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } /* write the source file */ sprintf(buffer, "/*\n" " * ICU common data table of contents for %s.%s\n" " * Automatically generated by icu/source/tools/gencmn/gencmn .\n" " */\n\n" "#include \"unicode/utypes.h\"\n" "#include \"unicode/udata.h\"\n" "\n" "/* external symbol declarations for data (%d files) */\n", name, type, fileCount); T_FileStream_writeLine(out, buffer); sprintf(buffer, "extern const char\n %s%s[]", symPrefix?symPrefix:"", files[0].pathname); T_FileStream_writeLine(out, buffer); for(i=1; i<fileCount; ++i) { sprintf(buffer, ",\n %s%s[]", symPrefix?symPrefix:"", files[i].pathname); T_FileStream_writeLine(out, buffer); } T_FileStream_writeLine(out, ";\n\n"); sprintf( buffer, "U_EXPORT struct {\n" " uint16_t headerSize;\n" " uint8_t magic1, magic2;\n" " UDataInfo info;\n" " char padding[%lu];\n" " uint32_t count, reserved;\n" " struct {\n" " const char *name;\n" " const void *data;\n" " } toc[%lu];\n" "} U_EXPORT2 %s_dat = {\n" " 32, 0xda, 0x27, {\n" " %lu, 0,\n" " %u, %u, %u, 0,\n" " {0x54, 0x6f, 0x43, 0x50},\n" " {1, 0, 0, 0},\n" " {0, 0, 0, 0}\n" " },\n" " \"\", %lu, 0, {\n", (unsigned long)32-4-sizeof(UDataInfo), (unsigned long)fileCount, entrypointName, (unsigned long)sizeof(UDataInfo), U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, U_SIZEOF_UCHAR, (unsigned long)fileCount ); T_FileStream_writeLine(out, buffer); sprintf(buffer, " { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname); T_FileStream_writeLine(out, buffer); for(i=1; i<fileCount; ++i) { sprintf(buffer, ",\n { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname); T_FileStream_writeLine(out, buffer); } T_FileStream_writeLine(out, "\n }\n};\n"); T_FileStream_close(out); uprv_free(symPrefix); } }
void pkg_mode_windows(UPKGOptions *o, FileStream *makefile, UErrorCode *status) { char tmp[1024]; char tmp2[1024]; const char *separator = o->icuroot[uprv_strlen(o->icuroot)-1]=='\\'?"":"\\"; UBool isDll = (UBool)(uprv_strcmp(o->mode, "dll") == 0); UBool isStatic = (UBool)(uprv_strcmp(o->mode, "static") == 0); if(U_FAILURE(*status)) { return; } sprintf(tmp2, "ICUROOT=%s\n\n", o->icuroot); T_FileStream_writeLine(makefile, tmp2); sprintf(tmp2, "GENCMN = $(ICUROOT)%sbin\\gencmn.exe\n", separator); T_FileStream_writeLine(makefile, tmp2); if(isDll) { uprv_strcpy(tmp, LIB_PREFIX); uprv_strcat(tmp, o->cShortName); uprv_strcat(tmp, UDATA_SO_SUFFIX); if(o->nooutput || o->verbose) { fprintf(stdout, "# Output %s file: %s%s%s\n", UDATA_SO_SUFFIX, o->targetDir, U_FILE_SEP_STRING, tmp); } if(o->nooutput) { *status = U_ZERO_ERROR; return; } sprintf(tmp2, "# DLL file to make:\nDLLTARGET=%s\n\n", tmp); T_FileStream_writeLine(makefile, tmp2); sprintf(tmp2, "LINK32 = link.exe\n" "LINK32_FLAGS = /nologo /out:\"$(TARGETDIR)\\$(DLLTARGET)\" /DLL /NOENTRY /base:\"0x4ad00000\" /implib:\"$(TARGETDIR)\\$(ENTRYPOINT).lib\" /comment:\"%s\"\n", o->comment ); T_FileStream_writeLine(makefile, tmp2); sprintf(tmp2, "GENCCODE = $(ICUROOT)%sbin\\genccode.exe\n", separator); T_FileStream_writeLine(makefile, tmp2); T_FileStream_writeLine(makefile, "\n" "# Windows specific DLL version information.\n" "!IF EXISTS(\".\\$(NAME)_icudata.res\")\n" "DATA_VER_INFO=\".\\$(NAME)_icudata.res\"\n" "!ELSE\n" "DATA_VER_INFO=\n" "!ENDIF\n\n"); uprv_strcpy(tmp, UDATA_CMN_PREFIX "$(NAME)" UDATA_CMN_INTERMEDIATE_SUFFIX OBJ_SUFFIX); sprintf(tmp2, "# intermediate obj file:\nCMNOBJTARGET=%s\n\n", tmp); T_FileStream_writeLine(makefile, tmp2); } else if (isStatic) { uprv_strcpy(tmp, LIB_PREFIX); uprv_strcat(tmp, o->cShortName); uprv_strcat(tmp, UDATA_LIB_SUFFIX); pkg_sttc_writeReadme(o, tmp, status); if(U_FAILURE(*status)) { return; } if(o->nooutput || o->verbose) { fprintf(stdout, "# Output %s file: %s%s%s\n", UDATA_SO_SUFFIX, o->targetDir, U_FILE_SEP_STRING, tmp); } if(o->nooutput) { *status = U_ZERO_ERROR; return; } sprintf(tmp2, "# LIB file to make:\nDLLTARGET=%s\n\n", tmp); T_FileStream_writeLine(makefile, tmp2); sprintf(tmp2, "LINK32 = LIB.exe\n" "LINK32_FLAGS = /nologo /out:\"$(TARGETDIR)\\$(DLLTARGET)\" /EXPORT:\"%s\"\n", o->cShortName ); T_FileStream_writeLine(makefile, tmp2); sprintf(tmp2, "GENCCODE = $(ICUROOT)%sbin\\genccode.exe\n", separator); T_FileStream_writeLine(makefile, tmp2); T_FileStream_writeLine(makefile, "\n" "# Windows specific LIB version information.\n" "!IF EXISTS(\".\\$(NAME)_icudata.res\")\n" "DATA_VER_INFO=\".\\$(NAME)_icudata.res\"\n" "!ELSE\n" "DATA_VER_INFO=\n" "!ENDIF\n\n"); uprv_strcpy(tmp, UDATA_CMN_PREFIX "$(NAME)" UDATA_CMN_INTERMEDIATE_SUFFIX OBJ_SUFFIX); sprintf(tmp2, "# intermediate obj file:\nCMNOBJTARGET=%s\n\n", tmp); T_FileStream_writeLine(makefile, tmp2); } uprv_strcpy(tmp, UDATA_CMN_PREFIX); uprv_strcat(tmp, o->cShortName); uprv_strcat(tmp, UDATA_CMN_SUFFIX); if(o->nooutput || o->verbose) { fprintf(stdout, "# Output file: %s%s%s\n", o->targetDir, U_FILE_SEP_STRING, tmp); } if(o->nooutput) { *status = U_ZERO_ERROR; return; } sprintf(tmp2, "# common file to make:\nCMNTARGET=%s\n\n", tmp); T_FileStream_writeLine(makefile, tmp2); if(isDll || isStatic) { sprintf(tmp, "all: \"$(TARGETDIR)\\$(DLLTARGET)\"\n\n"); T_FileStream_writeLine(makefile, tmp); sprintf(tmp, "\"$(TARGETDIR)\\$(DLLTARGET)\": \"$(TARGETDIR)\\$(CMNOBJTARGET)\"\n" "\t$(LINK32) $(LINK32_FLAGS) \"$(TARGETDIR)\\$(CMNOBJTARGET)\" $(DATA_VER_INFO)\n\n"); T_FileStream_writeLine(makefile, tmp); sprintf(tmp, "\"$(TARGETDIR)\\$(CMNOBJTARGET)\": \"$(TARGETDIR)\\$(CMNTARGET)\"\n" "\t@\"$(GENCCODE)\" $(GENCOPTIONS) -e $(ENTRYPOINT) -o -d \"$(TARGETDIR)\" \"$(TARGETDIR)\\$(CMNTARGET)\"\n\n"); T_FileStream_writeLine(makefile, tmp); sprintf(tmp2, "clean:\n" "\t-@erase \"$(TARGETDIR)\\$(DLLTARGET)\"\n" "\t-@erase \"$(TARGETDIR)\\$(CMNOBJTARGET)\"\n" "\t-@erase \"$(TARGETDIR)\\$(CMNTARGET)\"\n\n"); T_FileStream_writeLine(makefile, tmp2); } else { /* common */ sprintf(tmp, "all: \"$(TARGETDIR)\\$(CMNTARGET)\"\n\n"); T_FileStream_writeLine(makefile, tmp); sprintf(tmp2, "clean:\n" "\t-@erase \"$(TARGETDIR)\\$(CMNTARGET)\"\n\n"); T_FileStream_writeLine(makefile, tmp2); } sprintf(tmp2, "rebuild: clean all\n\n"); T_FileStream_writeLine(makefile, tmp2); /* Write compile rules */ writeCmnRules(o, makefile); }
void pkg_sttc_writeReadme(struct UPKGOptions_ *o, const char *libName, UErrorCode *status) { char tmp[1024]; FileStream *out; if(U_FAILURE(*status)) { return; } /* Makefile pathname */ uprv_strcpy(tmp, o->targetDir); uprv_strcat(tmp, U_FILE_SEP_STRING "README_"); uprv_strcat(tmp, o->shortName); uprv_strcat(tmp, ".txt"); out = T_FileStream_open(tmp, "w"); if (!out) { fprintf(stderr, "err: couldn't create README file %s\n", tmp); *status = U_FILE_ACCESS_ERROR; return; } sprintf(tmp, "## README for \"%s\"'s static data (%s)\n" "## created by pkgdata, ICU Version %s\n", o->shortName, libName, U_ICU_VERSION); T_FileStream_writeLine(out, tmp); sprintf(tmp, "\n\nTo use this data in your application:\n\n" "1. At the top of your source file, add the following lines:\n" "\n" " #include \"unicode/utypes.h\"\n" " #include \"unicode/udata.h\"\n" " U_CFUNC char %s_dat[];\n", o->cShortName); T_FileStream_writeLine(out, tmp); sprintf(tmp, "2. *Early* in your application, call the following function:\n" "\n" " UErrorCode myError = U_ZERO_ERROR;\n" " udata_setAppData( \"%s\", (const void*) %s_dat, &myError);\n" " if(U_FAILURE(myError))\n" " {\n" " handle error condition ...\n" " }\n" "\n", o->cShortName, o->cShortName); T_FileStream_writeLine(out, tmp); sprintf(tmp, "3. Link your application against %s\n" "\n\n" "4. Now, you may access this data with a 'path' of \"%s\" as in the following example:\n" "\n" " ... ures_open( \"%s\", \"%s\", &err ); \n", libName, o->shortName, o->shortName, uloc_getDefault()); T_FileStream_writeLine(out, tmp); T_FileStream_close(out); }
void pkg_mode_static(UPKGOptions *o, FileStream *makefile, UErrorCode *status) { char tmp[1024]; CharList *tail = NULL; CharList *objects = NULL; if(U_FAILURE(*status)) { return; } uprv_strcpy(tmp, LIB_STATIC_PREFIX); uprv_strcat(tmp, o->libName); uprv_strcat(tmp, UDATA_LIB_SUFFIX); o->outFiles = pkg_appendToList(o->outFiles, &tail, uprv_strdup(tmp)); if (!o->quiet) { pkg_sttc_writeReadme(o, tmp, status); } if(U_FAILURE(*status)) { return; } if(o->nooutput || o->verbose) { fprintf(stdout, "# Output file: %s%s%s\n", o->targetDir, U_FILE_SEP_STRING, tmp); } if(o->nooutput) { *status = U_ZERO_ERROR; return; } /* begin writing makefile ========================= */ T_FileStream_writeLine(makefile, "# Version numbers:\nVERSIONED="); if (o->version) { sprintf(tmp, ".%s", o->version); if (!uprv_strchr(o->version, '.')) { uprv_strcat(tmp, ".0"); } T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "\nDLL_LDFLAGS=$(LD_SONAME) $(RPATH_LDFLAGS)\n"); } else { T_FileStream_writeLine(makefile, "\nDLL_LDFLAGS=$(BIR_LDFLAGS)\n"); } T_FileStream_writeLine(makefile, "\n"); sprintf(tmp, "# File to make:\nTARGET=%s\n\n", o->outFiles->str); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "LIB_TARGET=$(TARGET)\n"); uprv_strcpy(tmp, "all: $(TARG_PATH)$(LIB_TARGET)"); uprv_strcat(tmp, "\n\n"); T_FileStream_writeLine(makefile, tmp); #ifdef OS400 /* New for iSeries: All packaged data in one .c */ sprintf(tmp, "# Create a file which contains all .c data files/structures\n" "$(TEMP_DIR)/$(NAME)all.c: $(CMNLIST)\n\n"); T_FileStream_writeLine(makefile, tmp); #endif /* Write compile rules */ pkg_mak_writeObjRules(o, makefile, &objects, ".$(STATIC_O)"); /* use special .o suffix */ sprintf(tmp, "# List file for gencmn:\n" "CMNLIST=%s%s$(NAME)_static.lst\n\n", o->tmpDir, U_FILE_SEP_STRING); T_FileStream_writeLine(makefile, tmp); if(o->hadStdin == FALSE) { /* shortcut */ T_FileStream_writeLine(makefile, "$(CMNLIST): $(LISTFILES)\n" "\tcat $(LISTFILES) > $(CMNLIST)\n\n"); } else { T_FileStream_writeLine(makefile, "$(CMNLIST): \n" "\t@echo \"generating $@ (list of data files)\"\n" "\t@-$(RMV) $@\n" "\t@for file in $(DATAFILEPATHS); do \\\n" "\t echo $$file >> $@; \\\n" "\tdone;\n\n"); } pkg_mak_writeAssemblyHeader(makefile, o); sprintf(tmp,"$(TEMP_PATH)$(NAME)_dat.$(STATIC_O) : $(TEMP_PATH)$(NAME)_dat.c\n" "\t$(COMPILE.c) -o $@ $<\n\n"); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "# 'TOCOBJ' contains C Table of Contents objects [if any]\n"); if(!o->embed) { sprintf(tmp, "$(TEMP_PATH)$(NAME)_dat.c: $(CMNLIST)\n" "\t$(INVOKE) $(GENCMN) -e $(ENTRYPOINT) -n $(NAME) -S -s $(SRCDIR) -d $(TEMP_DIR) 0 $(CMNLIST)\n\n"); } else { sprintf(tmp, "$(TEMP_PATH)$(NAME)_dat.c: $(CMNLIST)\n" "\t$(INVOKE) $(GENCMN) -e $(ENTRYPOINT) -n $(NAME) -S -E -d $(TEMP_DIR) 0 $(CMNLIST)\n\n"); } T_FileStream_writeLine(makefile, tmp); sprintf(tmp, "TOCOBJ= $(NAME)_dat%s \n\n", OBJ_SUFFIX); T_FileStream_writeLine(makefile, tmp); #ifdef OS400 /* New for iSeries: All packaged data in one .c */ sprintf(tmp,"$(TEMP_PATH)$(NAME)all.$(STATIC_O) : $(TEMP_PATH)$(NAME)all.c\n" "\t$(COMPILE.c) -o $@ $<\n\n"); T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "# 'ALLDATAOBJ' contains all .c data structures\n"); sprintf(tmp, "ALLDATAOBJ= $(NAME)all%s \n\n", OBJ_SUFFIX); T_FileStream_writeLine(makefile, tmp); #endif sprintf(tmp, "TOCSYM= $(ENTRYPOINT)_dat \n\n"); /* entrypoint not always shortname! */ T_FileStream_writeLine(makefile, tmp); T_FileStream_writeLine(makefile, "BASE_OBJECTS= $(TOCOBJ) "); #ifdef OS400 T_FileStream_writeLine(makefile, "$(ALLDATAOBJ) "); #else pkg_writeCharListWrap(makefile, objects, " ", " \\\n",0); #endif pkg_mak_writeAssemblyFooter(makefile, o); T_FileStream_writeLine(makefile, "\n\n"); T_FileStream_writeLine(makefile, "OBJECTS=$(BASE_OBJECTS:%=$(TEMP_PATH)%)\n\n"); T_FileStream_writeLine(makefile,"$(TEMP_PATH)%.$(STATIC_O): $(TEMP_PATH)%.c\n\t $(COMPILE.c) -o $@ $<\n\n"); #if NO_IMPLICIT_AR T_FileStream_writeLine(makefile, "$(TARG_PATH)$(LIB_TARGET):$(TARG_PATH)$(LIB_TARGET) $(OBJECTS) $(LISTFILES)\n" "\t$(AR) $(ARFLAGS) $(TARG_PATH)$(LIB_TARGET) $(OBJECTS)\n" "\t$(RANLIB) $@\n\n"); #else T_FileStream_writeLine(makefile, "$(TARG_PATH)$(LIB_TARGET):$(TARG_PATH)$(LIB_TARGET)($(OBJECTS)) $(LISTFILES)\n" "\t$(RANLIB) $@\n\n"); #endif T_FileStream_writeLine(makefile, "CLEANFILES= $(CMNLIST) $(OBJECTS) $(TARG_PATH)$(LIB_TARGET) $(TARG_PATH)$(MIDDLE_STATIC_LIB_TARGET) $(TARG_PATH)$(TARGET)\n\nclean:\n\t-$(RMV) $(CLEANFILES) $(MAKEFILE)"); T_FileStream_writeLine(makefile, "\n\n"); T_FileStream_writeLine(makefile, "# static mode shouldn't need to be installed, but we will install the header and static library for them.\n"); T_FileStream_writeLine(makefile, "install: $(TARG_PATH)$(LIB_TARGET)\n" "\t$(INSTALL-L) $(TARG_PATH)$(LIB_TARGET) $(INSTALLTO)/$(LIB_TARGET)\n"); T_FileStream_writeLine(makefile, "\t$(RANLIB) $(INSTALLTO)/$(LIB_TARGET)\n"); if (o->version) { T_FileStream_writeLine(makefile, "\tcd $(INSTALLTO) && $(RM) $(MIDDLE_STATIC_LIB_TARGET) && ln -s $(LIB_TARGET) $(MIDDLE_STATIC_LIB_TARGET)\n\tcd $(INSTALLTO) && $(RM) $(STATIC_LIB_TARGET) && ln -s $(LIB_TARGET) $(STATIC_LIB_TARGET)\n"); T_FileStream_writeLine(makefile, "\t$(RANLIB) $(INSTALLTO)/$(STATIC_LIB_TARGET)\n\n"); } *status = U_ZERO_ERROR; }
extern int main(int argc, char* argv[]) { static char buffer[4096]; char line[512]; FileStream *in, *file; char *s; UErrorCode errorCode=U_ZERO_ERROR; uint32_t i, fileOffset, basenameOffset, length, nread; UBool sourceTOC, verbose; const char *entrypointName = NULL; U_MAIN_INIT_ARGS(argc, argv); /* preset then read command line options */ options[4].value=u_getDataDirectory(); options[6].value=COMMON_DATA_NAME; options[7].value=DATA_TYPE; options[10].value="."; 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]); } else if(argc<2) { argc=-1; } if(argc<0 || options[0].doesOccur || options[1].doesOccur) { FILE *where = argc < 0 ? stderr : stdout; /* * Broken into chucks because the C89 standard says the minimum * required supported string length is 509 bytes. */ fprintf(where, "%csage: %s [ -h, -?, --help ] [ -v, --verbose ] [ -c, --copyright ] [ -C, --comment comment ] [ -d, --destdir dir ] [ -n, --name filename ] [ -t, --type filetype ] [ -S, --source tocfile ] [ -e, --entrypoint name ] maxsize listfile\n", argc < 0 ? 'u' : 'U', *argv); if (options[0].doesOccur || options[1].doesOccur) { fprintf(where, "\n" "Read the list file (default: standard input) and create a common data\n" "file from specified files. Omit any files larger than maxsize, if maxsize > 0.\n"); fprintf(where, "\n" "Options:\n" "\t-h, -?, --help this usage text\n" "\t-v, --verbose verbose output\n" "\t-c, --copyright include the ICU copyright notice\n" "\t-C, --comment comment include a comment string\n" "\t-d, --destdir dir destination directory\n"); fprintf(where, "\t-n, --name filename output filename, without .type extension\n" "\t (default: " COMMON_DATA_NAME ")\n" "\t-t, --type filetype type of the destination file\n" "\t (default: \"" DATA_TYPE "\")\n" "\t-S, --source tocfile write a .c source file with the table of\n" "\t contents\n" "\t-e, --entrypoint name override the c entrypoint name\n" "\t (default: \"<name>_<type>\")\n"); } return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; } sourceTOC=options[8].doesOccur; verbose = options[2].doesOccur; maxSize=(uint32_t)uprv_strtoul(argv[1], NULL, 0); if(argc==2) { in=T_FileStream_stdin(); } else { in=T_FileStream_open(argv[2], "r"); if(in==NULL) { fprintf(stderr, "gencmn: unable to open input file %s\n", argv[2]); exit(U_FILE_ACCESS_ERROR); } } if (verbose) { if(sourceTOC) { printf("generating %s_%s.c (table of contents source file)\n", options[6].value, options[7].value); } else { printf("generating %s.%s (common data file with table of contents)\n", options[6].value, options[7].value); } } /* read the list of files and get their lengths */ while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* remove trailing newline characters */ s=line; while(*s!=0) { if(*s=='\r' || *s=='\n') { *s=0; break; } ++s; } /* check for comment */ if (*line == '#') { continue; } /* add the file */ #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) { char *t; while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) { *t = U_FILE_SEP_CHAR; } } #endif addFile(getLongPathname(line), sourceTOC, verbose); } if(in!=T_FileStream_stdin()) { T_FileStream_close(in); } if(fileCount==0) { fprintf(stderr, "gencmn: no files listed in %s\n", argc==2 ? "<stdin>" : argv[2]); return 0; } /* sort the files by basename */ qsort(files, fileCount, sizeof(File), compareFiles); if(!sourceTOC) { UNewDataMemory *out; /* determine the offsets of all basenames and files in this common one */ basenameOffset=4+8*fileCount; fileOffset=(basenameOffset+(basenameTotal+15))&~0xf; for(i=0; i<fileCount; ++i) { files[i].fileOffset=fileOffset; fileOffset+=(files[i].fileSize+15)&~0xf; files[i].basenameOffset=basenameOffset; basenameOffset+=files[i].basenameLength; } /* create the output file */ out=udata_create(options[4].value, options[7].value, options[6].value, &dataInfo, options[3].doesOccur ? U_COPYRIGHT_STRING : options[5].value, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n", options[4].value, options[6].value, options[7].value, u_errorName(errorCode)); exit(errorCode); } /* write the table of contents */ udata_write32(out, fileCount); for(i=0; i<fileCount; ++i) { udata_write32(out, files[i].basenameOffset); udata_write32(out, files[i].fileOffset); } /* write the basenames */ for(i=0; i<fileCount; ++i) { udata_writeString(out, files[i].basename, files[i].basenameLength); } length=4+8*fileCount+basenameTotal; /* copy the files */ for(i=0; i<fileCount; ++i) { /* pad to 16-align the next file */ length&=0xf; if(length!=0) { udata_writePadding(out, 16-length); } if (verbose) { printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s"); } /* copy the next file */ file=T_FileStream_open(files[i].pathname, "rb"); if(file==NULL) { fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname); exit(U_FILE_ACCESS_ERROR); } for(nread = 0;;) { length=T_FileStream_read(file, buffer, sizeof(buffer)); if(length <= 0) { break; } nread += length; udata_writeBlock(out, buffer, length); } T_FileStream_close(file); length=files[i].fileSize; if (nread != files[i].fileSize) { fprintf(stderr, "gencmn: unable to read %s properly (got %ld/%ld byte%s)\n", files[i].pathname, (long)nread, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s"); exit(U_FILE_ACCESS_ERROR); } } /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */ length&=0xf; if(length!=0) { udata_writePadding(out, 16-length); } /* finish */ udata_finish(out, &errorCode); if(U_FAILURE(errorCode)) { fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode)); exit(errorCode); } } else { /* write a .c source file with the table of contents */ char *filename; FileStream *out; /* create the output filename */ filename=s=buffer; uprv_strcpy(filename, options[4].value); s=filename+uprv_strlen(filename); if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) { *s++=U_FILE_SEP_CHAR; } uprv_strcpy(s, options[6].value); if(*(options[7].value)!=0) { s+=uprv_strlen(s); *s++='_'; uprv_strcpy(s, options[7].value); } s+=uprv_strlen(s); uprv_strcpy(s, ".c"); /* open the output file */ out=T_FileStream_open(filename, "w"); if(out==NULL) { fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename); exit(U_FILE_ACCESS_ERROR); } /* If an entrypoint is specified, use it. */ if(options[9].doesOccur) { entrypointName = options[9].value; } else { entrypointName = options[6].value; } /* write the source file */ sprintf(buffer, "/*\n" " * ICU common data table of contents for %s.%s ,\n" " * Automatically generated by icu/source/tools/gencmn/gencmn .\n" " */\n\n" "#include \"unicode/utypes.h\"\n" "#include \"unicode/udata.h\"\n" "\n" "/* external symbol declarations for data */\n", options[6].value, options[7].value); T_FileStream_writeLine(out, buffer); sprintf(buffer, "extern const char\n %s%s[]", symPrefix?symPrefix:"", files[0].pathname); T_FileStream_writeLine(out, buffer); for(i=1; i<fileCount; ++i) { sprintf(buffer, ",\n %s%s[]", symPrefix?symPrefix:"", files[i].pathname); T_FileStream_writeLine(out, buffer); } T_FileStream_writeLine(out, ";\n\n"); sprintf( buffer, "U_EXPORT struct {\n" " uint16_t headerSize;\n" " uint8_t magic1, magic2;\n" " UDataInfo info;\n" " char padding[%lu];\n" " uint32_t count, reserved;\n" " struct {\n" " const char *name;\n" " const void *data;\n" " } toc[%lu];\n" "} U_EXPORT2 %s_dat = {\n" " 32, 0xda, 0x27, {\n" " %lu, 0,\n" " %u, %u, %u, 0,\n" " {0x54, 0x6f, 0x43, 0x50},\n" " {1, 0, 0, 0},\n" " {0, 0, 0, 0}\n" " },\n" " \"\", %lu, 0, {\n", (unsigned long)32-4-sizeof(UDataInfo), (unsigned long)fileCount, entrypointName, (unsigned long)sizeof(UDataInfo), U_IS_BIG_ENDIAN, U_CHARSET_FAMILY, U_SIZEOF_UCHAR, (unsigned long)fileCount ); T_FileStream_writeLine(out, buffer); sprintf(buffer, " { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname); T_FileStream_writeLine(out, buffer); for(i=1; i<fileCount; ++i) { sprintf(buffer, ",\n { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname); T_FileStream_writeLine(out, buffer); } T_FileStream_writeLine(out, "\n }\n};\n"); T_FileStream_close(out); uprv_free(symPrefix); } return 0; }