Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | ******************************************************************************* |
michael@0 | 3 | * |
michael@0 | 4 | * Copyright (C) 1999-2013, International Business Machines |
michael@0 | 5 | * Corporation and others. All Rights Reserved. |
michael@0 | 6 | * |
michael@0 | 7 | ******************************************************************************* |
michael@0 | 8 | * file name: toolutil.c |
michael@0 | 9 | * encoding: US-ASCII |
michael@0 | 10 | * tab size: 8 (not used) |
michael@0 | 11 | * indentation:4 |
michael@0 | 12 | * |
michael@0 | 13 | * created on: 1999nov19 |
michael@0 | 14 | * created by: Markus W. Scherer |
michael@0 | 15 | * |
michael@0 | 16 | * 6/25/08 - Added Cygwin specific code in uprv_mkdir - Brian Rower |
michael@0 | 17 | * |
michael@0 | 18 | * This file contains utility functions for ICU tools like genccode. |
michael@0 | 19 | */ |
michael@0 | 20 | |
michael@0 | 21 | #if U_PLATFORM == U_PF_MINGW |
michael@0 | 22 | // *cough* - for struct stat |
michael@0 | 23 | #ifdef __STRICT_ANSI__ |
michael@0 | 24 | #undef __STRICT_ANSI__ |
michael@0 | 25 | #endif |
michael@0 | 26 | #endif |
michael@0 | 27 | |
michael@0 | 28 | #include <stdio.h> |
michael@0 | 29 | #include <sys/stat.h> |
michael@0 | 30 | #include "unicode/utypes.h" |
michael@0 | 31 | |
michael@0 | 32 | #ifndef U_TOOLUTIL_IMPLEMENTATION |
michael@0 | 33 | #error U_TOOLUTIL_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu |
michael@0 | 34 | #endif |
michael@0 | 35 | |
michael@0 | 36 | #if U_PLATFORM_USES_ONLY_WIN32_API |
michael@0 | 37 | # define VC_EXTRALEAN |
michael@0 | 38 | # define WIN32_LEAN_AND_MEAN |
michael@0 | 39 | # define NOUSER |
michael@0 | 40 | # define NOSERVICE |
michael@0 | 41 | # define NOIME |
michael@0 | 42 | # define NOMCX |
michael@0 | 43 | # if U_PLATFORM == U_PF_MINGW |
michael@0 | 44 | # define __NO_MINGW_LFS /* gets around missing 'off64_t' */ |
michael@0 | 45 | # endif |
michael@0 | 46 | # include <windows.h> |
michael@0 | 47 | # include <direct.h> |
michael@0 | 48 | #else |
michael@0 | 49 | # include <sys/stat.h> |
michael@0 | 50 | # include <sys/types.h> |
michael@0 | 51 | #endif |
michael@0 | 52 | |
michael@0 | 53 | /* In MinGW environment, io.h needs to be included for _mkdir() */ |
michael@0 | 54 | #if U_PLATFORM == U_PF_MINGW |
michael@0 | 55 | #include <io.h> |
michael@0 | 56 | #endif |
michael@0 | 57 | |
michael@0 | 58 | #include <errno.h> |
michael@0 | 59 | |
michael@0 | 60 | #include "unicode/errorcode.h" |
michael@0 | 61 | #include "unicode/putil.h" |
michael@0 | 62 | #include "cmemory.h" |
michael@0 | 63 | #include "cstring.h" |
michael@0 | 64 | #include "toolutil.h" |
michael@0 | 65 | #include "unicode/ucal.h" |
michael@0 | 66 | |
michael@0 | 67 | U_NAMESPACE_BEGIN |
michael@0 | 68 | |
michael@0 | 69 | IcuToolErrorCode::~IcuToolErrorCode() { |
michael@0 | 70 | // Safe because our handleFailure() does not throw exceptions. |
michael@0 | 71 | if(isFailure()) { handleFailure(); } |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | void IcuToolErrorCode::handleFailure() const { |
michael@0 | 75 | fprintf(stderr, "error at %s: %s\n", location, errorName()); |
michael@0 | 76 | exit(errorCode); |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | U_NAMESPACE_END |
michael@0 | 80 | |
michael@0 | 81 | static int32_t currentYear = -1; |
michael@0 | 82 | |
michael@0 | 83 | U_CAPI int32_t U_EXPORT2 getCurrentYear() { |
michael@0 | 84 | #if !UCONFIG_NO_FORMATTING |
michael@0 | 85 | UErrorCode status=U_ZERO_ERROR; |
michael@0 | 86 | UCalendar *cal = NULL; |
michael@0 | 87 | |
michael@0 | 88 | if(currentYear == -1) { |
michael@0 | 89 | cal = ucal_open(NULL, -1, NULL, UCAL_TRADITIONAL, &status); |
michael@0 | 90 | ucal_setMillis(cal, ucal_getNow(), &status); |
michael@0 | 91 | currentYear = ucal_get(cal, UCAL_YEAR, &status); |
michael@0 | 92 | ucal_close(cal); |
michael@0 | 93 | } |
michael@0 | 94 | #else |
michael@0 | 95 | /* No formatting- no way to set the current year. */ |
michael@0 | 96 | #endif |
michael@0 | 97 | return currentYear; |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | |
michael@0 | 101 | U_CAPI const char * U_EXPORT2 |
michael@0 | 102 | getLongPathname(const char *pathname) { |
michael@0 | 103 | #if U_PLATFORM_USES_ONLY_WIN32_API |
michael@0 | 104 | /* anticipate problems with "short" pathnames */ |
michael@0 | 105 | static WIN32_FIND_DATAA info; |
michael@0 | 106 | HANDLE file=FindFirstFileA(pathname, &info); |
michael@0 | 107 | if(file!=INVALID_HANDLE_VALUE) { |
michael@0 | 108 | if(info.cAlternateFileName[0]!=0) { |
michael@0 | 109 | /* this file has a short name, get and use the long one */ |
michael@0 | 110 | const char *basename=findBasename(pathname); |
michael@0 | 111 | if(basename!=pathname) { |
michael@0 | 112 | /* prepend the long filename with the original path */ |
michael@0 | 113 | uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1); |
michael@0 | 114 | uprv_memcpy(info.cFileName, pathname, basename-pathname); |
michael@0 | 115 | } |
michael@0 | 116 | pathname=info.cFileName; |
michael@0 | 117 | } |
michael@0 | 118 | FindClose(file); |
michael@0 | 119 | } |
michael@0 | 120 | #endif |
michael@0 | 121 | return pathname; |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | U_CAPI const char * U_EXPORT2 |
michael@0 | 125 | findDirname(const char *path, char *buffer, int32_t bufLen, UErrorCode* status) { |
michael@0 | 126 | if(U_FAILURE(*status)) return NULL; |
michael@0 | 127 | const char *resultPtr = NULL; |
michael@0 | 128 | int32_t resultLen = 0; |
michael@0 | 129 | |
michael@0 | 130 | const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR); |
michael@0 | 131 | #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR |
michael@0 | 132 | const char *basenameAlt=uprv_strrchr(path, U_FILE_ALT_SEP_CHAR); |
michael@0 | 133 | if(basenameAlt && (!basename || basename<basenameAlt)) { |
michael@0 | 134 | basename = basenameAlt; |
michael@0 | 135 | } |
michael@0 | 136 | #endif |
michael@0 | 137 | if(!basename) { |
michael@0 | 138 | /* no basename - return ''. */ |
michael@0 | 139 | resultPtr = ""; |
michael@0 | 140 | resultLen = 0; |
michael@0 | 141 | } else { |
michael@0 | 142 | resultPtr = path; |
michael@0 | 143 | resultLen = basename - path; |
michael@0 | 144 | if(resultLen<1) { |
michael@0 | 145 | resultLen = 1; /* '/' or '/a' -> '/' */ |
michael@0 | 146 | } |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | if((resultLen+1) <= bufLen) { |
michael@0 | 150 | uprv_strncpy(buffer, resultPtr, resultLen); |
michael@0 | 151 | buffer[resultLen]=0; |
michael@0 | 152 | return buffer; |
michael@0 | 153 | } else { |
michael@0 | 154 | *status = U_BUFFER_OVERFLOW_ERROR; |
michael@0 | 155 | return NULL; |
michael@0 | 156 | } |
michael@0 | 157 | } |
michael@0 | 158 | |
michael@0 | 159 | U_CAPI const char * U_EXPORT2 |
michael@0 | 160 | findBasename(const char *filename) { |
michael@0 | 161 | const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR); |
michael@0 | 162 | |
michael@0 | 163 | #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR |
michael@0 | 164 | if(basename==NULL) { |
michael@0 | 165 | /* Use lenient matching on Windows, which can accept either \ or / |
michael@0 | 166 | This is useful for environments like Win32+CygWin which have both. |
michael@0 | 167 | */ |
michael@0 | 168 | basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR); |
michael@0 | 169 | } |
michael@0 | 170 | #endif |
michael@0 | 171 | |
michael@0 | 172 | if(basename!=NULL) { |
michael@0 | 173 | return basename+1; |
michael@0 | 174 | } else { |
michael@0 | 175 | return filename; |
michael@0 | 176 | } |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | U_CAPI void U_EXPORT2 |
michael@0 | 180 | uprv_mkdir(const char *pathname, UErrorCode *status) { |
michael@0 | 181 | |
michael@0 | 182 | int retVal = 0; |
michael@0 | 183 | #if U_PLATFORM_USES_ONLY_WIN32_API |
michael@0 | 184 | retVal = _mkdir(pathname); |
michael@0 | 185 | #else |
michael@0 | 186 | retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH)); |
michael@0 | 187 | #endif |
michael@0 | 188 | if (retVal && errno != EEXIST) { |
michael@0 | 189 | #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN |
michael@0 | 190 | /*if using Cygwin and the mkdir says it failed...check if the directory already exists..*/ |
michael@0 | 191 | /* if it does...don't give the error, if it does not...give the error - Brian Rower - 6/25/08 */ |
michael@0 | 192 | struct stat st; |
michael@0 | 193 | |
michael@0 | 194 | if(stat(pathname,&st) != 0) |
michael@0 | 195 | { |
michael@0 | 196 | *status = U_FILE_ACCESS_ERROR; |
michael@0 | 197 | } |
michael@0 | 198 | #else |
michael@0 | 199 | *status = U_FILE_ACCESS_ERROR; |
michael@0 | 200 | #endif |
michael@0 | 201 | } |
michael@0 | 202 | } |
michael@0 | 203 | |
michael@0 | 204 | #if !UCONFIG_NO_FILE_IO |
michael@0 | 205 | U_CAPI UBool U_EXPORT2 |
michael@0 | 206 | uprv_fileExists(const char *file) { |
michael@0 | 207 | struct stat stat_buf; |
michael@0 | 208 | if (stat(file, &stat_buf) == 0) { |
michael@0 | 209 | return TRUE; |
michael@0 | 210 | } else { |
michael@0 | 211 | return FALSE; |
michael@0 | 212 | } |
michael@0 | 213 | } |
michael@0 | 214 | #endif |
michael@0 | 215 | |
michael@0 | 216 | /*U_CAPI UDate U_EXPORT2 |
michael@0 | 217 | uprv_getModificationDate(const char *pathname, UErrorCode *status) |
michael@0 | 218 | { |
michael@0 | 219 | if(U_FAILURE(*status)) { |
michael@0 | 220 | return; |
michael@0 | 221 | } |
michael@0 | 222 | // TODO: handle case where stat is not available |
michael@0 | 223 | struct stat st; |
michael@0 | 224 | |
michael@0 | 225 | if(stat(pathname,&st) != 0) |
michael@0 | 226 | { |
michael@0 | 227 | *status = U_FILE_ACCESS_ERROR; |
michael@0 | 228 | } else { |
michael@0 | 229 | return st.st_mtime; |
michael@0 | 230 | } |
michael@0 | 231 | } |
michael@0 | 232 | */ |
michael@0 | 233 | |
michael@0 | 234 | /* tool memory helper ------------------------------------------------------- */ |
michael@0 | 235 | |
michael@0 | 236 | struct UToolMemory { |
michael@0 | 237 | char name[64]; |
michael@0 | 238 | int32_t capacity, maxCapacity, size, idx; |
michael@0 | 239 | void *array; |
michael@0 | 240 | UAlignedMemory staticArray[1]; |
michael@0 | 241 | }; |
michael@0 | 242 | |
michael@0 | 243 | U_CAPI UToolMemory * U_EXPORT2 |
michael@0 | 244 | utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) { |
michael@0 | 245 | UToolMemory *mem; |
michael@0 | 246 | |
michael@0 | 247 | if(maxCapacity<initialCapacity) { |
michael@0 | 248 | maxCapacity=initialCapacity; |
michael@0 | 249 | } |
michael@0 | 250 | |
michael@0 | 251 | mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size); |
michael@0 | 252 | if(mem==NULL) { |
michael@0 | 253 | fprintf(stderr, "error: %s - out of memory\n", name); |
michael@0 | 254 | exit(U_MEMORY_ALLOCATION_ERROR); |
michael@0 | 255 | } |
michael@0 | 256 | mem->array=mem->staticArray; |
michael@0 | 257 | |
michael@0 | 258 | uprv_strcpy(mem->name, name); |
michael@0 | 259 | mem->capacity=initialCapacity; |
michael@0 | 260 | mem->maxCapacity=maxCapacity; |
michael@0 | 261 | mem->size=size; |
michael@0 | 262 | mem->idx=0; |
michael@0 | 263 | return mem; |
michael@0 | 264 | } |
michael@0 | 265 | |
michael@0 | 266 | U_CAPI void U_EXPORT2 |
michael@0 | 267 | utm_close(UToolMemory *mem) { |
michael@0 | 268 | if(mem!=NULL) { |
michael@0 | 269 | if(mem->array!=mem->staticArray) { |
michael@0 | 270 | uprv_free(mem->array); |
michael@0 | 271 | } |
michael@0 | 272 | uprv_free(mem); |
michael@0 | 273 | } |
michael@0 | 274 | } |
michael@0 | 275 | |
michael@0 | 276 | |
michael@0 | 277 | U_CAPI void * U_EXPORT2 |
michael@0 | 278 | utm_getStart(UToolMemory *mem) { |
michael@0 | 279 | return (char *)mem->array; |
michael@0 | 280 | } |
michael@0 | 281 | |
michael@0 | 282 | U_CAPI int32_t U_EXPORT2 |
michael@0 | 283 | utm_countItems(UToolMemory *mem) { |
michael@0 | 284 | return mem->idx; |
michael@0 | 285 | } |
michael@0 | 286 | |
michael@0 | 287 | |
michael@0 | 288 | static UBool |
michael@0 | 289 | utm_hasCapacity(UToolMemory *mem, int32_t capacity) { |
michael@0 | 290 | if(mem->capacity<capacity) { |
michael@0 | 291 | int32_t newCapacity; |
michael@0 | 292 | |
michael@0 | 293 | if(mem->maxCapacity<capacity) { |
michael@0 | 294 | fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n", |
michael@0 | 295 | mem->name, (long)mem->maxCapacity); |
michael@0 | 296 | exit(U_MEMORY_ALLOCATION_ERROR); |
michael@0 | 297 | } |
michael@0 | 298 | |
michael@0 | 299 | /* try to allocate a larger array */ |
michael@0 | 300 | if(capacity>=2*mem->capacity) { |
michael@0 | 301 | newCapacity=capacity; |
michael@0 | 302 | } else if(mem->capacity<=mem->maxCapacity/3) { |
michael@0 | 303 | newCapacity=2*mem->capacity; |
michael@0 | 304 | } else { |
michael@0 | 305 | newCapacity=mem->maxCapacity; |
michael@0 | 306 | } |
michael@0 | 307 | |
michael@0 | 308 | if(mem->array==mem->staticArray) { |
michael@0 | 309 | mem->array=uprv_malloc(newCapacity*mem->size); |
michael@0 | 310 | if(mem->array!=NULL) { |
michael@0 | 311 | uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size); |
michael@0 | 312 | } |
michael@0 | 313 | } else { |
michael@0 | 314 | mem->array=uprv_realloc(mem->array, newCapacity*mem->size); |
michael@0 | 315 | } |
michael@0 | 316 | |
michael@0 | 317 | if(mem->array==NULL) { |
michael@0 | 318 | fprintf(stderr, "error: %s - out of memory\n", mem->name); |
michael@0 | 319 | exit(U_MEMORY_ALLOCATION_ERROR); |
michael@0 | 320 | } |
michael@0 | 321 | mem->capacity=newCapacity; |
michael@0 | 322 | } |
michael@0 | 323 | |
michael@0 | 324 | return TRUE; |
michael@0 | 325 | } |
michael@0 | 326 | |
michael@0 | 327 | U_CAPI void * U_EXPORT2 |
michael@0 | 328 | utm_alloc(UToolMemory *mem) { |
michael@0 | 329 | char *p=NULL; |
michael@0 | 330 | int32_t oldIndex=mem->idx; |
michael@0 | 331 | int32_t newIndex=oldIndex+1; |
michael@0 | 332 | if(utm_hasCapacity(mem, newIndex)) { |
michael@0 | 333 | p=(char *)mem->array+oldIndex*mem->size; |
michael@0 | 334 | mem->idx=newIndex; |
michael@0 | 335 | uprv_memset(p, 0, mem->size); |
michael@0 | 336 | } |
michael@0 | 337 | return p; |
michael@0 | 338 | } |
michael@0 | 339 | |
michael@0 | 340 | U_CAPI void * U_EXPORT2 |
michael@0 | 341 | utm_allocN(UToolMemory *mem, int32_t n) { |
michael@0 | 342 | char *p=NULL; |
michael@0 | 343 | int32_t oldIndex=mem->idx; |
michael@0 | 344 | int32_t newIndex=oldIndex+n; |
michael@0 | 345 | if(utm_hasCapacity(mem, newIndex)) { |
michael@0 | 346 | p=(char *)mem->array+oldIndex*mem->size; |
michael@0 | 347 | mem->idx=newIndex; |
michael@0 | 348 | uprv_memset(p, 0, n*mem->size); |
michael@0 | 349 | } |
michael@0 | 350 | return p; |
michael@0 | 351 | } |