]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
3 | * | |
729e4ab9 | 4 | * Copyright (C) 1999-2010, International Business Machines |
b75a7d8f A |
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 | * | |
729e4ab9 A |
16 | * 6/25/08 - Added Cygwin specific code in uprv_mkdir - Brian Rower |
17 | * | |
b75a7d8f A |
18 | * This file contains utility functions for ICU tools like genccode. |
19 | */ | |
20 | ||
73c04bcf | 21 | #include <stdio.h> |
729e4ab9 | 22 | #include <sys/stat.h> |
73c04bcf | 23 | #include "unicode/utypes.h" |
73c04bcf A |
24 | |
25 | #ifdef U_WINDOWS | |
b75a7d8f A |
26 | # define VC_EXTRALEAN |
27 | # define WIN32_LEAN_AND_MEAN | |
b75a7d8f A |
28 | # define NOUSER |
29 | # define NOSERVICE | |
30 | # define NOIME | |
31 | # define NOMCX | |
32 | # include <windows.h> | |
73c04bcf A |
33 | # include <direct.h> |
34 | #else | |
35 | # include <sys/stat.h> | |
36 | # include <sys/types.h> | |
b75a7d8f | 37 | #endif |
729e4ab9 A |
38 | |
39 | /* In MinGW environment, io.h needs to be included for _mkdir() */ | |
40 | #ifdef __MINGW32__ | |
41 | #include <io.h> | |
42 | #endif | |
43 | ||
73c04bcf | 44 | #include <errno.h> |
b75a7d8f | 45 | |
729e4ab9 A |
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 | ||
46f4442e A |
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 | } | |
46f4442e | 80 | #else |
729e4ab9 | 81 | /* No formatting- no way to set the current year. */ |
46f4442e | 82 | #endif |
729e4ab9 | 83 | return currentYear; |
46f4442e A |
84 | } |
85 | ||
86 | ||
b75a7d8f A |
87 | U_CAPI const char * U_EXPORT2 |
88 | getLongPathname(const char *pathname) { | |
73c04bcf | 89 | #ifdef U_WINDOWS |
b75a7d8f | 90 | /* anticipate problems with "short" pathnames */ |
729e4ab9 | 91 | static WIN32_FIND_DATAA info; |
46f4442e | 92 | HANDLE file=FindFirstFileA(pathname, &info); |
b75a7d8f A |
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 | ||
729e4ab9 A |
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 | ||
b75a7d8f A |
145 | U_CAPI const char * U_EXPORT2 |
146 | findBasename(const char *filename) { | |
147 | const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR); | |
374ca955 A |
148 | |
149 | #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR | |
150 | if(basename==NULL) { | |
b75a7d8f | 151 | /* Use lenient matching on Windows, which can accept either \ or / |
374ca955 | 152 | This is useful for environments like Win32+CygWin which have both. |
b75a7d8f | 153 | */ |
374ca955 A |
154 | basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR); |
155 | } | |
b75a7d8f | 156 | #endif |
374ca955 A |
157 | |
158 | if(basename!=NULL) { | |
159 | return basename+1; | |
160 | } else { | |
b75a7d8f A |
161 | return filename; |
162 | } | |
163 | } | |
374ca955 | 164 | |
73c04bcf A |
165 | U_CAPI void U_EXPORT2 |
166 | uprv_mkdir(const char *pathname, UErrorCode *status) { | |
729e4ab9 | 167 | |
73c04bcf | 168 | int retVal = 0; |
729e4ab9 | 169 | #if defined(U_WINDOWS) || defined(__MINGW32__) |
73c04bcf A |
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) { | |
729e4ab9 A |
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 | |
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 | { | |
73c04bcf | 201 | *status = U_FILE_ACCESS_ERROR; |
729e4ab9 A |
202 | } else { |
203 | return st.st_mtime; | |
73c04bcf A |
204 | } |
205 | } | |
729e4ab9 | 206 | */ |
73c04bcf | 207 | |
374ca955 A |
208 | /* tool memory helper ------------------------------------------------------- */ |
209 | ||
210 | struct UToolMemory { | |
211 | char name[64]; | |
729e4ab9 | 212 | int32_t capacity, maxCapacity, size, idx; |
374ca955 A |
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; | |
729e4ab9 | 236 | mem->idx=0; |
374ca955 A |
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) { | |
729e4ab9 | 258 | return mem->idx; |
374ca955 A |
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) { | |
729e4ab9 | 285 | uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size); |
374ca955 A |
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 | } | |
729e4ab9 | 295 | mem->capacity=newCapacity; |
374ca955 A |
296 | } |
297 | ||
298 | return TRUE; | |
299 | } | |
300 | ||
301 | U_CAPI void * U_EXPORT2 | |
302 | utm_alloc(UToolMemory *mem) { | |
729e4ab9 A |
303 | char *p=NULL; |
304 | int32_t oldIndex=mem->idx; | |
305 | int32_t newIndex=oldIndex+1; | |
374ca955 | 306 | if(utm_hasCapacity(mem, newIndex)) { |
729e4ab9 A |
307 | p=(char *)mem->array+oldIndex*mem->size; |
308 | mem->idx=newIndex; | |
374ca955 A |
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) { | |
729e4ab9 A |
316 | char *p=NULL; |
317 | int32_t oldIndex=mem->idx; | |
318 | int32_t newIndex=oldIndex+n; | |
374ca955 | 319 | if(utm_hasCapacity(mem, newIndex)) { |
729e4ab9 A |
320 | p=(char *)mem->array+oldIndex*mem->size; |
321 | mem->idx=newIndex; | |
374ca955 A |
322 | uprv_memset(p, 0, n*mem->size); |
323 | } | |
324 | return p; | |
325 | } |