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 45static int32_t currentYear = -1; 46 47U_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 65U_CAPI const char * U_EXPORT2 66getLongPathname(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 88U_CAPI const char * U_EXPORT2 89findBasename(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 108U_CAPI void U_EXPORT2 109uprv_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 134uprv_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 153struct UToolMemory { 154 char name[64]; 155 int32_t capacity, maxCapacity, size, idx; 156 void *array; 157 UAlignedMemory staticArray[1]; 158}; 159 160U_CAPI UToolMemory * U_EXPORT2 161utm_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 183U_CAPI void U_EXPORT2 184utm_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 194U_CAPI void * U_EXPORT2 195utm_getStart(UToolMemory *mem) { 196 return (char *)mem->array; 197} 198 199U_CAPI int32_t U_EXPORT2 200utm_countItems(UToolMemory *mem) { 201 return mem->idx; 202} 203 204 205static UBool 206utm_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 243U_CAPI void * U_EXPORT2 244utm_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 254U_CAPI void * U_EXPORT2 255utm_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