1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/tools/toolutil/toolutil.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,351 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* 1.7 +* Copyright (C) 1999-2013, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +******************************************************************************* 1.11 +* file name: toolutil.c 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* created on: 1999nov19 1.17 +* created by: Markus W. Scherer 1.18 +* 1.19 +* 6/25/08 - Added Cygwin specific code in uprv_mkdir - Brian Rower 1.20 +* 1.21 +* This file contains utility functions for ICU tools like genccode. 1.22 +*/ 1.23 + 1.24 +#if U_PLATFORM == U_PF_MINGW 1.25 +// *cough* - for struct stat 1.26 +#ifdef __STRICT_ANSI__ 1.27 +#undef __STRICT_ANSI__ 1.28 +#endif 1.29 +#endif 1.30 + 1.31 +#include <stdio.h> 1.32 +#include <sys/stat.h> 1.33 +#include "unicode/utypes.h" 1.34 + 1.35 +#ifndef U_TOOLUTIL_IMPLEMENTATION 1.36 +#error U_TOOLUTIL_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu 1.37 +#endif 1.38 + 1.39 +#if U_PLATFORM_USES_ONLY_WIN32_API 1.40 +# define VC_EXTRALEAN 1.41 +# define WIN32_LEAN_AND_MEAN 1.42 +# define NOUSER 1.43 +# define NOSERVICE 1.44 +# define NOIME 1.45 +# define NOMCX 1.46 +# if U_PLATFORM == U_PF_MINGW 1.47 +# define __NO_MINGW_LFS /* gets around missing 'off64_t' */ 1.48 +# endif 1.49 +# include <windows.h> 1.50 +# include <direct.h> 1.51 +#else 1.52 +# include <sys/stat.h> 1.53 +# include <sys/types.h> 1.54 +#endif 1.55 + 1.56 +/* In MinGW environment, io.h needs to be included for _mkdir() */ 1.57 +#if U_PLATFORM == U_PF_MINGW 1.58 +#include <io.h> 1.59 +#endif 1.60 + 1.61 +#include <errno.h> 1.62 + 1.63 +#include "unicode/errorcode.h" 1.64 +#include "unicode/putil.h" 1.65 +#include "cmemory.h" 1.66 +#include "cstring.h" 1.67 +#include "toolutil.h" 1.68 +#include "unicode/ucal.h" 1.69 + 1.70 +U_NAMESPACE_BEGIN 1.71 + 1.72 +IcuToolErrorCode::~IcuToolErrorCode() { 1.73 + // Safe because our handleFailure() does not throw exceptions. 1.74 + if(isFailure()) { handleFailure(); } 1.75 +} 1.76 + 1.77 +void IcuToolErrorCode::handleFailure() const { 1.78 + fprintf(stderr, "error at %s: %s\n", location, errorName()); 1.79 + exit(errorCode); 1.80 +} 1.81 + 1.82 +U_NAMESPACE_END 1.83 + 1.84 +static int32_t currentYear = -1; 1.85 + 1.86 +U_CAPI int32_t U_EXPORT2 getCurrentYear() { 1.87 +#if !UCONFIG_NO_FORMATTING 1.88 + UErrorCode status=U_ZERO_ERROR; 1.89 + UCalendar *cal = NULL; 1.90 + 1.91 + if(currentYear == -1) { 1.92 + cal = ucal_open(NULL, -1, NULL, UCAL_TRADITIONAL, &status); 1.93 + ucal_setMillis(cal, ucal_getNow(), &status); 1.94 + currentYear = ucal_get(cal, UCAL_YEAR, &status); 1.95 + ucal_close(cal); 1.96 + } 1.97 +#else 1.98 + /* No formatting- no way to set the current year. */ 1.99 +#endif 1.100 + return currentYear; 1.101 +} 1.102 + 1.103 + 1.104 +U_CAPI const char * U_EXPORT2 1.105 +getLongPathname(const char *pathname) { 1.106 +#if U_PLATFORM_USES_ONLY_WIN32_API 1.107 + /* anticipate problems with "short" pathnames */ 1.108 + static WIN32_FIND_DATAA info; 1.109 + HANDLE file=FindFirstFileA(pathname, &info); 1.110 + if(file!=INVALID_HANDLE_VALUE) { 1.111 + if(info.cAlternateFileName[0]!=0) { 1.112 + /* this file has a short name, get and use the long one */ 1.113 + const char *basename=findBasename(pathname); 1.114 + if(basename!=pathname) { 1.115 + /* prepend the long filename with the original path */ 1.116 + uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1); 1.117 + uprv_memcpy(info.cFileName, pathname, basename-pathname); 1.118 + } 1.119 + pathname=info.cFileName; 1.120 + } 1.121 + FindClose(file); 1.122 + } 1.123 +#endif 1.124 + return pathname; 1.125 +} 1.126 + 1.127 +U_CAPI const char * U_EXPORT2 1.128 +findDirname(const char *path, char *buffer, int32_t bufLen, UErrorCode* status) { 1.129 + if(U_FAILURE(*status)) return NULL; 1.130 + const char *resultPtr = NULL; 1.131 + int32_t resultLen = 0; 1.132 + 1.133 + const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR); 1.134 +#if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR 1.135 + const char *basenameAlt=uprv_strrchr(path, U_FILE_ALT_SEP_CHAR); 1.136 + if(basenameAlt && (!basename || basename<basenameAlt)) { 1.137 + basename = basenameAlt; 1.138 + } 1.139 +#endif 1.140 + if(!basename) { 1.141 + /* no basename - return ''. */ 1.142 + resultPtr = ""; 1.143 + resultLen = 0; 1.144 + } else { 1.145 + resultPtr = path; 1.146 + resultLen = basename - path; 1.147 + if(resultLen<1) { 1.148 + resultLen = 1; /* '/' or '/a' -> '/' */ 1.149 + } 1.150 + } 1.151 + 1.152 + if((resultLen+1) <= bufLen) { 1.153 + uprv_strncpy(buffer, resultPtr, resultLen); 1.154 + buffer[resultLen]=0; 1.155 + return buffer; 1.156 + } else { 1.157 + *status = U_BUFFER_OVERFLOW_ERROR; 1.158 + return NULL; 1.159 + } 1.160 +} 1.161 + 1.162 +U_CAPI const char * U_EXPORT2 1.163 +findBasename(const char *filename) { 1.164 + const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR); 1.165 + 1.166 +#if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR 1.167 + if(basename==NULL) { 1.168 + /* Use lenient matching on Windows, which can accept either \ or / 1.169 + This is useful for environments like Win32+CygWin which have both. 1.170 + */ 1.171 + basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR); 1.172 + } 1.173 +#endif 1.174 + 1.175 + if(basename!=NULL) { 1.176 + return basename+1; 1.177 + } else { 1.178 + return filename; 1.179 + } 1.180 +} 1.181 + 1.182 +U_CAPI void U_EXPORT2 1.183 +uprv_mkdir(const char *pathname, UErrorCode *status) { 1.184 + 1.185 + int retVal = 0; 1.186 +#if U_PLATFORM_USES_ONLY_WIN32_API 1.187 + retVal = _mkdir(pathname); 1.188 +#else 1.189 + retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH)); 1.190 +#endif 1.191 + if (retVal && errno != EEXIST) { 1.192 +#if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN 1.193 + /*if using Cygwin and the mkdir says it failed...check if the directory already exists..*/ 1.194 + /* if it does...don't give the error, if it does not...give the error - Brian Rower - 6/25/08 */ 1.195 + struct stat st; 1.196 + 1.197 + if(stat(pathname,&st) != 0) 1.198 + { 1.199 + *status = U_FILE_ACCESS_ERROR; 1.200 + } 1.201 +#else 1.202 + *status = U_FILE_ACCESS_ERROR; 1.203 +#endif 1.204 + } 1.205 +} 1.206 + 1.207 +#if !UCONFIG_NO_FILE_IO 1.208 +U_CAPI UBool U_EXPORT2 1.209 +uprv_fileExists(const char *file) { 1.210 + struct stat stat_buf; 1.211 + if (stat(file, &stat_buf) == 0) { 1.212 + return TRUE; 1.213 + } else { 1.214 + return FALSE; 1.215 + } 1.216 +} 1.217 +#endif 1.218 + 1.219 +/*U_CAPI UDate U_EXPORT2 1.220 +uprv_getModificationDate(const char *pathname, UErrorCode *status) 1.221 +{ 1.222 + if(U_FAILURE(*status)) { 1.223 + return; 1.224 + } 1.225 + // TODO: handle case where stat is not available 1.226 + struct stat st; 1.227 + 1.228 + if(stat(pathname,&st) != 0) 1.229 + { 1.230 + *status = U_FILE_ACCESS_ERROR; 1.231 + } else { 1.232 + return st.st_mtime; 1.233 + } 1.234 +} 1.235 +*/ 1.236 + 1.237 +/* tool memory helper ------------------------------------------------------- */ 1.238 + 1.239 +struct UToolMemory { 1.240 + char name[64]; 1.241 + int32_t capacity, maxCapacity, size, idx; 1.242 + void *array; 1.243 + UAlignedMemory staticArray[1]; 1.244 +}; 1.245 + 1.246 +U_CAPI UToolMemory * U_EXPORT2 1.247 +utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) { 1.248 + UToolMemory *mem; 1.249 + 1.250 + if(maxCapacity<initialCapacity) { 1.251 + maxCapacity=initialCapacity; 1.252 + } 1.253 + 1.254 + mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size); 1.255 + if(mem==NULL) { 1.256 + fprintf(stderr, "error: %s - out of memory\n", name); 1.257 + exit(U_MEMORY_ALLOCATION_ERROR); 1.258 + } 1.259 + mem->array=mem->staticArray; 1.260 + 1.261 + uprv_strcpy(mem->name, name); 1.262 + mem->capacity=initialCapacity; 1.263 + mem->maxCapacity=maxCapacity; 1.264 + mem->size=size; 1.265 + mem->idx=0; 1.266 + return mem; 1.267 +} 1.268 + 1.269 +U_CAPI void U_EXPORT2 1.270 +utm_close(UToolMemory *mem) { 1.271 + if(mem!=NULL) { 1.272 + if(mem->array!=mem->staticArray) { 1.273 + uprv_free(mem->array); 1.274 + } 1.275 + uprv_free(mem); 1.276 + } 1.277 +} 1.278 + 1.279 + 1.280 +U_CAPI void * U_EXPORT2 1.281 +utm_getStart(UToolMemory *mem) { 1.282 + return (char *)mem->array; 1.283 +} 1.284 + 1.285 +U_CAPI int32_t U_EXPORT2 1.286 +utm_countItems(UToolMemory *mem) { 1.287 + return mem->idx; 1.288 +} 1.289 + 1.290 + 1.291 +static UBool 1.292 +utm_hasCapacity(UToolMemory *mem, int32_t capacity) { 1.293 + if(mem->capacity<capacity) { 1.294 + int32_t newCapacity; 1.295 + 1.296 + if(mem->maxCapacity<capacity) { 1.297 + fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n", 1.298 + mem->name, (long)mem->maxCapacity); 1.299 + exit(U_MEMORY_ALLOCATION_ERROR); 1.300 + } 1.301 + 1.302 + /* try to allocate a larger array */ 1.303 + if(capacity>=2*mem->capacity) { 1.304 + newCapacity=capacity; 1.305 + } else if(mem->capacity<=mem->maxCapacity/3) { 1.306 + newCapacity=2*mem->capacity; 1.307 + } else { 1.308 + newCapacity=mem->maxCapacity; 1.309 + } 1.310 + 1.311 + if(mem->array==mem->staticArray) { 1.312 + mem->array=uprv_malloc(newCapacity*mem->size); 1.313 + if(mem->array!=NULL) { 1.314 + uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size); 1.315 + } 1.316 + } else { 1.317 + mem->array=uprv_realloc(mem->array, newCapacity*mem->size); 1.318 + } 1.319 + 1.320 + if(mem->array==NULL) { 1.321 + fprintf(stderr, "error: %s - out of memory\n", mem->name); 1.322 + exit(U_MEMORY_ALLOCATION_ERROR); 1.323 + } 1.324 + mem->capacity=newCapacity; 1.325 + } 1.326 + 1.327 + return TRUE; 1.328 +} 1.329 + 1.330 +U_CAPI void * U_EXPORT2 1.331 +utm_alloc(UToolMemory *mem) { 1.332 + char *p=NULL; 1.333 + int32_t oldIndex=mem->idx; 1.334 + int32_t newIndex=oldIndex+1; 1.335 + if(utm_hasCapacity(mem, newIndex)) { 1.336 + p=(char *)mem->array+oldIndex*mem->size; 1.337 + mem->idx=newIndex; 1.338 + uprv_memset(p, 0, mem->size); 1.339 + } 1.340 + return p; 1.341 +} 1.342 + 1.343 +U_CAPI void * U_EXPORT2 1.344 +utm_allocN(UToolMemory *mem, int32_t n) { 1.345 + char *p=NULL; 1.346 + int32_t oldIndex=mem->idx; 1.347 + int32_t newIndex=oldIndex+n; 1.348 + if(utm_hasCapacity(mem, newIndex)) { 1.349 + p=(char *)mem->array+oldIndex*mem->size; 1.350 + mem->idx=newIndex; 1.351 + uprv_memset(p, 0, n*mem->size); 1.352 + } 1.353 + return p; 1.354 +}