ICU-3933 Move flag parsing code to toolutil. Add file modification time functionality to toolutil. Update pkgdata to reflect these changes and to test mod time to see if a new library needs to be built.

X-SVN-Rev: 25228
This commit is contained in:
Michael Ow 2009-01-09 22:30:44 +00:00
parent 04c57ff523
commit 7cbb428511
7 changed files with 331 additions and 106 deletions

View file

@ -49,6 +49,8 @@
#include "pkg_icu.h"
#include "pkg_genc.h"
#include "pkg_gencmn.h"
#include "flagparser.h"
#include "filestat.h"
#if U_HAVE_POPEN
@ -72,6 +74,9 @@ U_CDECL_END
#if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX)
#define BUILD_DATA_WITHOUT_ASSEMBLY
#endif
#if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
#define CAN_WRITE_OBJ_CODE
#endif
#define LARGE_BUFFER_MAX_SIZE 2048
#define SMALL_BUFFER_MAX_SIZE 512
@ -185,7 +190,7 @@ enum {
INSTALL_CMD,
PKGDATA_FLAGS_SIZE
};
static char pkgDataFlags[PKGDATA_FLAGS_SIZE][SMALL_BUFFER_MAX_SIZE];
static char **pkgDataFlags = NULL;
enum {
LIB_FILE,
@ -199,8 +204,6 @@ enum {
};
static char libFileNames[LIB_FILENAMES_SIZE][256];
static int32_t pkg_readInFlags(const char* fileName);
static void pkg_checkFlag(UPKGOptions *o);
const char options_help[][320]={
@ -464,6 +467,15 @@ main(int argc, char* argv[]) {
result = pkg_executeOptions(&o);
if (pkgDataFlags != NULL) {
for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
if (pkgDataFlags[i] != NULL) {
uprv_free(pkgDataFlags[i]);
}
}
uprv_free(pkgDataFlags);
}
if (o.cShortName != NULL) {
uprv_free((char *)o.cShortName);
}
@ -491,6 +503,7 @@ main(int argc, char* argv[]) {
#define MODE_FILES 'f'
static int32_t pkg_executeOptions(UPKGOptions *o) {
UErrorCode status = U_ZERO_ERROR;
int32_t result = 0;
const char mode = o->mode[0];
char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
@ -546,12 +559,32 @@ static int32_t pkg_executeOptions(UPKGOptions *o) {
char version_major[10] = "";
UBool reverseExt = FALSE;
if (pkg_readInFlags(o->options) != 0) {
fprintf(stderr,"Unable to open or read \"%s\" option file.\n", o->options);
UBool failedFlagsAllocation = FALSE;
/* Allocate memory for pkgDataFlags and initialize it. */
pkgDataFlags = (char **)uprv_malloc(sizeof(char *) * PKGDATA_FLAGS_SIZE);
if (pkgDataFlags != NULL) {
for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
pkgDataFlags[i] = (char *)uprv_malloc(sizeof(char) * SMALL_BUFFER_MAX_SIZE);
if (pkgDataFlags[i] == NULL) {
fprintf(stderr,"Unable to allocated memory for pkgDataFlags.\n");
failedFlagsAllocation = TRUE;
} else {
pkgDataFlags[i][0] = 0;
}
}
}
if (pkgDataFlags == NULL || failedFlagsAllocation) {
fprintf(stderr,"Unable to allocated memory for pkgDataFlags.\n");
return -1;
}
#ifndef WINDOWS_WITH_MSVC
parseFlagsFile(o->options, pkgDataFlags, SMALL_BUFFER_MAX_SIZE, (int32_t)PKGDATA_FLAGS_SIZE, &status);
if (U_FAILURE(status)) {
fprintf(stderr,"Unable to open or read \"%s\" option file.\n", o->options);
return -1;
}
/* Get the version major number. */
if (o->version != NULL) {
for (uint32_t i = 0;i < sizeof(version_major);i++) {
@ -574,14 +607,16 @@ static int32_t pkg_executeOptions(UPKGOptions *o) {
createFileNames(version_major, o->version, o->libName, reverseExt);
if (o->version != NULL) {
/* Check to see if a previous built data library file exists */
/* Check to see if a previous built data library file exists and check if it is the latest. */
sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION_TMP]);
if (T_FileStream_file_exists(checkLibFile)) {
if (o->install != NULL) {
uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
result = pkg_installLibrary(o->install, targetDir);
if (isFileModTimeLater(checkLibFile, o->srcDir)) {
if (o->install != NULL) {
uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
result = pkg_installLibrary(o->install, targetDir);
}
return result;
}
return result;
}
}
@ -614,11 +649,11 @@ static int32_t pkg_executeOptions(UPKGOptions *o) {
return -1;
}
} else {
#if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
#ifdef CAN_WRITE_OBJ_CODE
writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
#ifdef U_LINUX
result = pkg_generateLibraryFile(targetDir, mode, gencFilePath, NULL);
#else /* WINDOWS_WITH_MSVC */
#elif defined(WINDOWS_WITH_MSVC)
return pkg_createWindowsDLL(mode, gencFilePath, o);
#endif
#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
@ -906,6 +941,13 @@ static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetD
char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
if (list == NULL || listNames == NULL) {
/* list and listNames should never be NULL since we are looping through the CharList with
* the given size.
*/
return -1;
}
cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE);
buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE);
@ -913,13 +955,6 @@ static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetD
const char *file ;
const char *name;
if (list == NULL || listNames == NULL) {
/* list and listNames should never be NULL since we are looping through the CharList with
* the given size.
*/
result = -1;
break;
}
if (i == 0) {
/* The first iteration calls the gencmn function and initailizes the buffer. */
createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
@ -1058,56 +1093,6 @@ static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, U
}
#endif
/*
* Get the position after the '=' character.
*/
static int32_t flagOffset(const char *buffer, int32_t bufferSize) {
int32_t offset = 0;
for (offset = 0; offset < bufferSize;offset++) {
if (buffer[offset] == '=') {
offset++;
break;
}
}
if (offset == bufferSize || (offset - 1) == bufferSize) {
offset = 0;
}
return offset;
}
/*
* Extract the setting after the '=' and store it in flag excluding the newline character.
*/
static void extractFlag(char* buffer, int32_t bufferSize, char* flag) {
char *pBuffer;
int32_t offset;
UBool bufferWritten = FALSE;
if (buffer[0] != 0) {
/* Get the offset (i.e. position after the '=') */
offset = flagOffset(buffer, bufferSize);
pBuffer = buffer+offset;
for(int32_t i = 0;;i++) {
if (pBuffer[i+1] == 0) {
/* Indicates a new line character. End here. */
flag[i] = 0;
break;
}
flag[i] = pBuffer[i];
if (i == 0) {
bufferWritten = TRUE;
}
}
}
if (!bufferWritten) {
flag[0] = 0;
}
}
static void pkg_checkFlag(UPKGOptions *o) {
#ifdef U_AIX
char *flag = NULL;
@ -1194,41 +1179,6 @@ static void pkg_checkFlag(UPKGOptions *o) {
#endif
}
/*
* Opens the given fileName and reads in the information storing the data in pkgDataFlags.
*/
static int32_t pkg_readInFlags(const char *fileName) {
int32_t result = 0;
#ifdef WINDOWS_WITH_MSVC
/* Zero out the flags since it is not being used. */
for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
pkgDataFlags[i][0] = 0;
}
#else
char buffer[LARGE_BUFFER_MAX_SIZE];
FileStream *f = T_FileStream_open(fileName, "r");
if (f == NULL) {
return -1;
}
for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
if (T_FileStream_readLine(f, buffer, LARGE_BUFFER_MAX_SIZE) == NULL) {
result = -1;
break;
}
extractFlag(buffer, LARGE_BUFFER_MAX_SIZE, pkgDataFlags[i]);
}
T_FileStream_close(f);
#endif
return result;
}
#if 0
{
rc = system(cmd);

View file

@ -1,6 +1,6 @@
#******************************************************************************
#
# Copyright (C) 1999-2008, International Business Machines
# Copyright (C) 1999-2009, International Business Machines
# Corporation and others. All Rights Reserved.
#
#******************************************************************************
@ -53,7 +53,8 @@ LIBS = $(LIBICUI18N) $(LIBICUUC) $(DEFAULT_LIBS)
OBJECTS = filestrm.o package.o pkgitems.o swapimpl.o toolutil.o unewdata.o \
ucm.o ucmstate.o uoptions.o uparse.o \
ucbuf.o xmlparser.o writesrc.o pkg_icu.o pkg_genc.o pkg_gencmn.o
ucbuf.o xmlparser.o writesrc.o \
pkg_icu.o pkg_genc.o pkg_gencmn.o flagparser.o filestat.o
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))

View file

@ -0,0 +1,107 @@
/******************************************************************************
* Copyright (C) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
#include "filestat.h"
#include "cstring.h"
#include "unicode/putil.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#if U_HAVE_DIRENT_H
#include <dirent.h>
typedef struct dirent DIRENT;
#define MAX_PATH_SIZE PATH_MAX /* Set the limit for the size of the path. */
#define MAX_READ_SIZE 512
#define SKIP1 "."
#define SKIP2 ".."
#endif
typedef struct stat STAT;
static int32_t whichFileModTimeIsLater(const char *file1, const char *file2);
/*
* Goes through the given directory recursive to compare each file's modification time with that of the file given.
*/
U_CAPI UBool U_EXPORT2
isFileModTimeLater(const char *filePath, const char *dirToCheckAgainst) {
UBool isLatest = TRUE;
if (filePath == NULL || dirToCheckAgainst == NULL) {
return FALSE;
}
#if U_HAVE_DIRENT_H
DIR *pDir = NULL;
if ((pDir= opendir(dirToCheckAgainst)) != NULL) {
DIR *subDirp = NULL;
DIRENT *dirEntry = NULL;
while ((dirEntry = readdir(pDir)) != NULL) {
if (uprv_strcmp(dirEntry->d_name, SKIP1) != 0 && uprv_strcmp(dirEntry->d_name, SKIP2) != 0) {
char newpath[MAX_PATH_SIZE] = "";
uprv_strcpy(newpath, dirToCheckAgainst);
uprv_strcat(newpath, U_FILE_SEP_STRING);
uprv_strcat(newpath, dirEntry->d_name);
if ((subDirp = opendir(newpath)) != NULL) {
/* If this new path is a directory, make a recursive call with the newpath. */
closedir(subDirp);
isLatest = isFileModTimeLater(filePath, newpath);
if (!isLatest) {
break;
}
} else {
int32_t latest = whichFileModTimeIsLater(filePath, newpath);
if (latest < 0 || latest == 2) {
isLatest = FALSE;
break;
}
}
}
}
closedir(pDir);
} else {
fprintf(stderr, "Unable to open directory: %s\n", dirToCheckAgainst);
return FALSE;
}
#endif
return isLatest;
}
/* Compares the mod time of both files returning a number indicating which one is later. -1 if error ocurs. */
static int32_t whichFileModTimeIsLater(const char *file1, const char *file2) {
int32_t result = 0;
STAT stbuf1, stbuf2;
if (stat(file1, &stbuf1) == 0 && stat(file2, &stbuf2) == 0) {
time_t modtime1, modtime2;
double diff;
modtime1 = stbuf1.st_mtim.tv_sec;
modtime2 = stbuf2.st_mtim.tv_sec;
diff = difftime(modtime1, modtime2);
if (diff < 0.0) {
result = 2;
} else if (diff > 0.0) {
result = 1;
}
} else {
fprintf(stderr, "Unable to get stats from file: %s or %s\n", file1, file2);
result = -1;
}
return result;
}

View file

@ -0,0 +1,30 @@
/*
*******************************************************************************
*
* Copyright (C) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: flagparser.h
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2009jan09
* created by: Michael Ow
*
* Compares modification times on specified files using ICU and intended for use in ICU tests and in build tools.
* Not suitable for production use. Not supported.
* Not conformant. Not efficient.
* But very small.
*/
#ifndef __FILESTAT_H__
#define __FILESTAT_H__
#include "unicode/utypes.h"
U_CAPI UBool U_EXPORT2
isFileModTimeLater(const char *filePath, const char *dirToCheckAgainst);
#endif

View file

@ -0,0 +1,91 @@
/******************************************************************************
* Copyright (C) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
#include "flagparser.h"
#include "filestrm.h"
#define LARGE_BUFFER_MAX_SIZE 2048
static void extractFlag(char* buffer, int32_t bufferSize, char* flag);
static int32_t getFlagOffset(const char *buffer, int32_t bufferSize);
/*
* Opens the given fileName and reads in the information storing the data in flagBuffer.
*/
U_CAPI void U_EXPORT2
parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, int32_t numOfFlags, UErrorCode *status) {
char buffer[LARGE_BUFFER_MAX_SIZE];
int32_t i;
FileStream *f = T_FileStream_open(fileName, "r");
if (f == NULL) {
*status = U_FILE_ACCESS_ERROR;
}
for (i = 0; i < numOfFlags; i++) {
if (T_FileStream_readLine(f, buffer, LARGE_BUFFER_MAX_SIZE) == NULL) {
*status = U_FILE_ACCESS_ERROR;
break;
}
extractFlag(buffer, LARGE_BUFFER_MAX_SIZE, flagBuffer[i]);
}
T_FileStream_close(f);
}
/*
* Extract the setting after the '=' and store it in flag excluding the newline character.
*/
static void extractFlag(char* buffer, int32_t bufferSize, char* flag) {
int32_t i;
char *pBuffer;
int32_t offset;
UBool bufferWritten = FALSE;
if (buffer[0] != 0) {
/* Get the offset (i.e. position after the '=') */
offset = getFlagOffset(buffer, bufferSize);
pBuffer = buffer+offset;
for(i = 0;;i++) {
if (pBuffer[i+1] == 0) {
/* Indicates a new line character. End here. */
flag[i] = 0;
break;
}
flag[i] = pBuffer[i];
if (i == 0) {
bufferWritten = TRUE;
}
}
}
if (!bufferWritten) {
flag[0] = 0;
}
}
/*
* Get the position after the '=' character.
*/
static int32_t getFlagOffset(const char *buffer, int32_t bufferSize) {
int32_t offset = 0;
for (offset = 0; offset < bufferSize;offset++) {
if (buffer[offset] == '=') {
offset++;
break;
}
}
if (offset == bufferSize || (offset - 1) == bufferSize) {
offset = 0;
}
return offset;
}

View file

@ -0,0 +1,30 @@
/*
*******************************************************************************
*
* Copyright (C) 2009, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
* file name: flagparser.h
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2009jan08
* created by: Michael Ow
*
* Tiny flag file parser using ICU and intended for use in ICU tests and in build tools.
* Not suitable for production use. Not supported.
* Not conformant. Not efficient.
* But very small.
*/
#ifndef __FLAGPARSER_H__
#define __FLAGPARSER_H__
#include "unicode/utypes.h"
U_CAPI void U_EXPORT2
parseFlagsFile(const char *fileName, char **flagBuffer, int32_t flagBufferSize, int32_t numOfFlags, UErrorCode *status);
#endif

View file

@ -412,10 +412,18 @@
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
<File
RelativePath=".\filestat.c"
>
</File>
<File
RelativePath=".\filestrm.c"
>
</File>
<File
RelativePath=".\flagparser.cpp"
>
</File>
<File
RelativePath=".\package.cpp"
>
@ -577,10 +585,18 @@
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
<File
RelativePath=".\filestat.h"
>
</File>
<File
RelativePath=".\filestrm.h"
>
</File>
<File
RelativePath=".\flagparser.h"
>
</File>
<File
RelativePath=".\package.h"
>