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