1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1999-2009, 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 #include "unicode/putil.h" 25 #include "cmemory.h" 26 #include "cstring.h" 27 #include "toolutil.h" 28 #include "unicode/ucal.h" 29 30 #ifdef U_WINDOWS 31 # define VC_EXTRALEAN 32 # define WIN32_LEAN_AND_MEAN 33 # define NOUSER 34 # define NOSERVICE 35 # define NOIME 36 # define NOMCX 37 # include <windows.h> 38 # include <direct.h> 39 #else 40 # include <sys/stat.h> 41 # include <sys/types.h> 42 #endif 43 #include <errno.h> 44 45 static int32_t currentYear = -1; 46 47 U_CAPI int32_t U_EXPORT2 getCurrentYear() { 48 #if !UCONFIG_NO_FORMATTING 49 UErrorCode status=U_ZERO_ERROR; 50 UCalendar *cal = NULL; 51 52 if(currentYear == -1) { 53 cal = ucal_open(NULL, -1, NULL, UCAL_TRADITIONAL, &status); 54 ucal_setMillis(cal, ucal_getNow(), &status); 55 currentYear = ucal_get(cal, UCAL_YEAR, &status); 56 ucal_close(cal); 57 } 58 return currentYear; 59 #else 60 return 2008; 61 #endif 62 } 63 64 65 U_CAPI const char * U_EXPORT2 66 getLongPathname(const char *pathname) { 67 #ifdef U_WINDOWS 68 /* anticipate problems with "short" pathnames */ 69 static WIN32_FIND_DATAA info; 70 HANDLE file=FindFirstFileA(pathname, &info); 71 if(file!=INVALID_HANDLE_VALUE) { 72 if(info.cAlternateFileName[0]!=0) { 73 /* this file has a short name, get and use the long one */ 74 const char *basename=findBasename(pathname); 75 if(basename!=pathname) { 76 /* prepend the long filename with the original path */ 77 uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1); 78 uprv_memcpy(info.cFileName, pathname, basename-pathname); 79 } 80 pathname=info.cFileName; 81 } 82 FindClose(file); 83 } 84 #endif 85 return pathname; 86 } 87 88 U_CAPI const char * U_EXPORT2 89 findBasename(const char *filename) { 90 const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR); 91 92 #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR 93 if(basename==NULL) { 94 /* Use lenient matching on Windows, which can accept either \ or / 95 This is useful for environments like Win32+CygWin which have both. 96 */ 97 basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR); 98 } 99 #endif 100 101 if(basename!=NULL) { 102 return basename+1; 103 } else { 104 return filename; 105 } 106 } 107 108 U_CAPI void U_EXPORT2 109 uprv_mkdir(const char *pathname, UErrorCode *status) { 110 111 int retVal = 0; 112 #if defined(U_WINDOWS) 113 retVal = _mkdir(pathname); 114 #else 115 retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH)); 116 #endif 117 if (retVal && errno != EEXIST) { 118 #if defined(U_CYGWIN) 119 /*if using Cygwin and the mkdir says it failed...check if the directory already exists..*/ 120 /* if it does...don't give the error, if it does not...give the error - Brian Rower - 6/25/08 */ 121 struct stat st; 122 123 if(stat(pathname,&st) != 0) 124 { 125 *status = U_FILE_ACCESS_ERROR; 126 } 127 #else 128 *status = U_FILE_ACCESS_ERROR; 129 #endif 130 } 131 } 132 133 /*U_CAPI UDate U_EXPORT2 134 uprv_getModificationDate(const char *pathname, UErrorCode *status) 135 { 136 if(U_FAILURE(*status)) { 137 return; 138 } 139 // TODO: handle case where stat is not available 140 struct stat st; 141 142 if(stat(pathname,&st) != 0) 143 { 144 *status = U_FILE_ACCESS_ERROR; 145 } else { 146 return st.st_mtime; 147 } 148 } 149 */ 150 151 /* tool memory helper ------------------------------------------------------- */ 152 153 struct UToolMemory { 154 char name[64]; 155 int32_t capacity, maxCapacity, size, idx; 156 void *array; 157 UAlignedMemory staticArray[1]; 158 }; 159 160 U_CAPI UToolMemory * U_EXPORT2 161 utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) { 162 UToolMemory *mem; 163 164 if(maxCapacity<initialCapacity) { 165 maxCapacity=initialCapacity; 166 } 167 168 mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size); 169 if(mem==NULL) { 170 fprintf(stderr, "error: %s - out of memory\n", name); 171 exit(U_MEMORY_ALLOCATION_ERROR); 172 } 173 mem->array=mem->staticArray; 174 175 uprv_strcpy(mem->name, name); 176 mem->capacity=initialCapacity; 177 mem->maxCapacity=maxCapacity; 178 mem->size=size; 179 mem->idx=0; 180 return mem; 181 } 182 183 U_CAPI void U_EXPORT2 184 utm_close(UToolMemory *mem) { 185 if(mem!=NULL) { 186 if(mem->array!=mem->staticArray) { 187 uprv_free(mem->array); 188 } 189 uprv_free(mem); 190 } 191 } 192 193 194 U_CAPI void * U_EXPORT2 195 utm_getStart(UToolMemory *mem) { 196 return (char *)mem->array; 197 } 198 199 U_CAPI int32_t U_EXPORT2 200 utm_countItems(UToolMemory *mem) { 201 return mem->idx; 202 } 203 204 205 static UBool 206 utm_hasCapacity(UToolMemory *mem, int32_t capacity) { 207 if(mem->capacity<capacity) { 208 int32_t newCapacity; 209 210 if(mem->maxCapacity<capacity) { 211 fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n", 212 mem->name, (long)mem->maxCapacity); 213 exit(U_MEMORY_ALLOCATION_ERROR); 214 } 215 216 /* try to allocate a larger array */ 217 if(capacity>=2*mem->capacity) { 218 newCapacity=capacity; 219 } else if(mem->capacity<=mem->maxCapacity/3) { 220 newCapacity=2*mem->capacity; 221 } else { 222 newCapacity=mem->maxCapacity; 223 } 224 225 if(mem->array==mem->staticArray) { 226 mem->array=uprv_malloc(newCapacity*mem->size); 227 if(mem->array!=NULL) { 228 uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size); 229 } 230 } else { 231 mem->array=uprv_realloc(mem->array, newCapacity*mem->size); 232 } 233 234 if(mem->array==NULL) { 235 fprintf(stderr, "error: %s - out of memory\n", mem->name); 236 exit(U_MEMORY_ALLOCATION_ERROR); 237 } 238 } 239 240 return TRUE; 241 } 242 243 U_CAPI void * U_EXPORT2 244 utm_alloc(UToolMemory *mem) { 245 char *p=(char *)mem->array+mem->idx*mem->size; 246 int32_t newIndex=mem->idx+1; 247 if(utm_hasCapacity(mem, newIndex)) { 248 mem->idx=newIndex; 249 uprv_memset(p, 0, mem->size); 250 } 251 return p; 252 } 253 254 U_CAPI void * U_EXPORT2 255 utm_allocN(UToolMemory *mem, int32_t n) { 256 char *p=(char *)mem->array+mem->idx*mem->size; 257 int32_t newIndex=mem->idx+n; 258 if(utm_hasCapacity(mem, newIndex)) { 259 mem->idx=newIndex; 260 uprv_memset(p, 0, n*mem->size); 261 } 262 return p; 263 } 264