toolutil.cpp revision 27f654740f2a26ad62a5c155af9199af9e69b889
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 53U_NAMESPACE_BEGIN 54 55IcuToolErrorCode::~IcuToolErrorCode() { 56 // Safe because our handleFailure() does not throw exceptions. 57 if(isFailure()) { handleFailure(); } 58} 59 60void IcuToolErrorCode::handleFailure() const { 61 fprintf(stderr, "error at %s: %s\n", location, errorName()); 62 exit(errorCode); 63} 64 65U_NAMESPACE_END 66 67static int32_t currentYear = -1; 68 69U_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 87U_CAPI const char * U_EXPORT2 88getLongPathname(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 110U_CAPI const char * U_EXPORT2 111findDirname(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 145U_CAPI const char * U_EXPORT2 146findBasename(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 165U_CAPI void U_EXPORT2 166uprv_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 directory 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 191uprv_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 210struct UToolMemory { 211 char name[64]; 212 int32_t capacity, maxCapacity, size, idx; 213 void *array; 214 UAlignedMemory staticArray[1]; 215}; 216 217U_CAPI UToolMemory * U_EXPORT2 218utm_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 240U_CAPI void U_EXPORT2 241utm_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 251U_CAPI void * U_EXPORT2 252utm_getStart(UToolMemory *mem) { 253 return (char *)mem->array; 254} 255 256U_CAPI int32_t U_EXPORT2 257utm_countItems(UToolMemory *mem) { 258 return mem->idx; 259} 260 261 262static UBool 263utm_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 301U_CAPI void * U_EXPORT2 302utm_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 314U_CAPI void * U_EXPORT2 315utm_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} 326